⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 funcs.fdo

📁 一个dos操作系统DRDOS的源码
💻 FDO
📖 第 1 页 / 共 5 页
字号:
chdir65:
else
	 jz	chdir80			; if at root, we're done
endif
	call	parent2save_area	; parental name written in save_area
chdir70:
	dec	di			; DI -> '\0' at end
	mov	al,'\' ! stosb		; add a trailing backslash
	sub	di,offset save_area+1
	mov	dx,di			; DX = length of name

	push	es			; insert name into user buffer
	les	di,dword ptr fdos_pb+6
	mov	al,0 ! scasb		; check if first directory
	 je	chdir75			; if not 1st in path
	inc	dx			; we need space for '\'
chdir75:
	dec	di			; adjust for scan
	call	mkspace_parent		; move ES:DI up by DX bytes
	mov	di,fdos_pb+6		; ES:DI -> user buffer
	rep	movsb			; copy directory into user buffer
	pop	es			; ES = local segment again
	jmp	chdir60			; try again til root

chdir80:				; arrive here when root reached
	mov	ax,orig_drive		; get logical drive
	call	get_ldt			; ES:BX -> LDT_
	 jc	chdir85			; no LDT_, what happended ?
	push	ds
	mov	di,bx			; ES:DI -> destination LDT_
	push ss ! pop ds
	mov	si,offset pri_pathname	; DS:SI -> new LDT_ we just built
	mov	cx,LDT_LEN
	rep	movsb			; copy the new LDT_ into place
	pop	ds
	cmp	ax,path_drive		; if the drive's are same
	 je	chdir85			;  "CD" or "SUBST d:=d:path"
	or	es:LDT_FLAGS[bx],LFLG_SUBST
	lea	di,LDT_NAME[bx]		; ES:DI -> name
	xor	ax,ax
	mov	cx,LDT_FLAGS-LDT_NAME	; name can be this long
	repne	scasb			; look for terminating NUL
	sub	di,bx			; get # chars skipped
	dec	di			; forget the NUL
	cmp	di,3			; root is special case again !
	 jbe	chdir85
	mov	es:LDT_ROOTLEN[bx],di	; set new root position
chdir85:
	ret

eject
;	CREATE FILE (CREAT)

;	+----+----+----+----+----+----+----+----+----+----+
;	|    3C   |        name       |  mode   |  attrib |
;	+----+----+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	name:	segmented address of ASCIIZ name
;	mode:	open mode for handle
;   attrib: attribute for file

;	exit:
;	-----
;	AX:	file handle or error code ( < 0)

fdos_creat:
;----------
	call	redir_asciiz_dev_offer	; offer it as a network device
	call	asciiz_dev_offer	; offer it as a local device
	call	redir_asciiz_file_offer	; offer it as a network file
	call	local_disk		; get MXdisk, switch stack
	call	mustbe_free_handle	; make sure we have spare handle
	call	path_prep		; parse path, walk down the tree
	call	check_device		; is it a device ?
	 jc	creat_disk
	jmp	open_dev		; open as a device handle
creat_disk:
	call	chk_no_dot_or_wild
	test	byte ptr fdos_pb+8,DA_VOLUME
	 jz	creat_nolbl		; skip if not volume label
	call	mustbe_nolbl		; do we have an existing label ?
	jmps	creat_new_file		; no, create one
creat_nolbl:
	call	finddfcbf		; find entry, ignore labels
	 jz	creat_new_file		; skip if it doesn't exist yet

	call	check_no_dir		; make sure not a directory
	call	check_ro		; check if file is read/only
	call	close_if_open		; make sure not open by any process
if PASSWORD
	call	check_pwd_d		; check if PW req'd & supplied	
endif
	mov	bx,dirp
	mov	ax,DBLOCK1[bx]		; release all blocks of the file
	call	delfat			; so it is truncated to zero size
	call	update_fat		; update file allocation table
	jmps	creat2			; reinitialize directory entry

creat_new_file:				; create new file - shared by MKNEW
	call	allocdir		; allocate a directory entry
creat2:
	mov	bx,dirp			; BX -> directory entry
	lea	di,DNAME[bx]		; DI -> name offset in dir buffer
	mov	si,offset info_fcb+1	; SI -> name offset in FCB
	mov	cx,11
	rep	movsb			; copy name into directory
	mov	ax,fdos_pb+8		; get creation file attribute
	mov	dx,fdos_pb+6		; open in r/w, compatibilty mode
	test	al,not (DA_RO+DA_SYSTEM+DA_HIDDEN+DA_ARCHIVE)
	 jz	creat5			; allow r/o, hidden, system, archive
	test	al,DA_VOLUME		; failure as file, creating a label?
	 jz	creat_access_err	;  no, then it's really a problem
	mov	dl,DHM_RO+DHM_LOCAL	; open in compatibility mode
creat5:
	or	al,DA_ARCHIVE		; always create as new file
	stosb				; update directory attributes
	sub	ax,ax			; zero out remainder of entry
	mov	cx,32-12
	rep	stosb			; zero remainder of entry

	push	bx			; save dirp
	push	dx			; save the open mode
	call	stamp_dir_entry		; set time and date in FCB
	call	update_dir		; update directory
	pop	ax			; restore open mode
	pop	bx			; restore dirp
	jmp	creat_handle		; now allocate file handle

creat_access_err:
	jmp	fdos_ED_ACCESS		; return "access denied"


eject
;	OPEN FILE (OPEN)

;	+----+----+----+----+----+----+----+----+----+----+
;	|    3D   |        name       |  mode   |  attrib |
;	+----+----+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	name:	segmented address of ASCIIZ name
;   mode:   open mode 
;	attrib:	file attrib for search (default = 16h)

;	exit:
;	-----
;	AX:	file handle or error code ( < 0)

fdos_open:
;---------
	call	redir_asciiz_dev_offer	; offer it as a network device
	call	asciiz_dev_offer	; offer it as a local device
	call	redir_asciiz_file_offer	; offer it as a network file
	call	local_disk		; get MXdisk, switch stack
	call	mustbe_free_handle	; make sure we have spare handle
	call	path_prep		; parse the path, go to bottom level
	call	check_device
	 jc	open_disk
	jmp	open_dev		; open as a device
open_disk:
	call	chk_no_wild		; we don't allow no wild cards here
	call	finddfcbf		; search by name
	 jz	open8			; bail out if not found
	mov	al,byte ptr fdos_pb+8	; check requested attributes
if PASSWORD
	cmp	word ptr DPWD[bx],0
	 je	open1
	or	al,DA_HIDDEN
open1:
endif
	not	al
	and	al,DA_HIDDEN+DA_SYSTEM
	or	al,DA_DIR+DA_VOLUME
	test	DATTS[bx],al
	 jnz	open9			; error if attrib not as requested
	mov	ax,fdos_pb+6		; determine open mode
if PASSWORD
	sub	dx,dx			; assume no PW conflicts
endif
	test	al,DHM_RW+DHM_WO	; test if read/only access
	 jz	open2
if PASSWORD				; if write or r/w check writes
	or	dx,PWM_W		;  check for write password
endif
;	mov	bx,dirp			; get directory pointer
	test	DATTS[bx],DA_RO		; read/only file?
	 jz	open2			;  no, skip FCB check
	test	ax,DHM_FCB		; if FCB open of read-only file
	 jz	open9			; allow it, but adjust to read-only
	and	al,not DHM_RWMSK	;  open mode and proceed
open2:
if PASSWORD
	test	al,DHM_WO		; will we try to read?
	 jnz	open3			; skip if not open for reading
	or	dx,PWM_R + PWM_E	; else check for read/exec password
open3:
	push	ax			; save the open mode
	xchg	ax,dx			; AX = password modes to check for
	call	check_pwd		; check for r/w passwords
	pop	ax
endif
	jmp	open_handle		; now allocate file handle

open8:
	jmp	fdos_ED_FILE		; "file not found"
open9:
	jmp	fdos_ED_ACCESS		; return "access denied" error


eject
;	CLOSE FILE (CLOSE)

;	+----+----+----+----+
;	|    3E   |  handle |
;	+----+----+----+----+

;	entry:
;	------
;	handle:	open file handle to be closed

;	exit:
;	-----
;	AX:	3Exx (where xx = # time it was open) or error code ( < 0)

fdos_close:
;----------
	call	vfy_dhndl_ptr		; check file handle #
	call	redir_dhndl_offer
	call	local_disk		; get MXdisk, switch stack
	call	check_handle		; check if legal file handle
	mov	ax,es:DHNDL_COUNT[bx]	; return # times file WAS open
	mov	ah,3Eh			; AH = MS_X_CLOSE
    mov fdos_ret,ax     ; return 3Exx if successful
	 jc	close20			; skip if character device close
close_dhndl:
	call	release_handle		; release file handle into pool
	callf	ss:share_stub+S_CLOSE	; call the fdos stub routine
	dec	es:DHNDL_COUNT[bx]	; one less XFN refers to this IFN
	test	es:DHNDL_WATTR[bx],DHAT_REMOTE+DHAT_CLEAN
	 jnz	close10			; skip update if not dirty local file
	call	select_handle		; select the disk
	call	file_update		; update directory & FAT if written
close10:
	ret

close20:				; handle refers to character device
	jmp	close_dev		; close the device handle

eject
;	READ FROM FILE (READ)

;	+----+----+----+----+----+----+----+----+----+----+
;	|    3F   |  handle |       buffer      |  count  |
;	+----+----+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	handle:	open file handle
;	buffer:	buffer to read into
;	count:	max. number of bytes to read

;	exit:
;	-----
;	AX:	byte count or error code ( < 0)

fdos_read:
;---------
	call	vfy_dhndl_ptr		; check file handle #
	test	es:DHNDL_MODE[bx],DHM_WO
	 jnz	rw_ED_ACCESS		; fail if open write only
	call	redir_dhndl_offer
	test	es:DHNDL_WATTR[bx],DHAT_DEV
	 jnz	fdos_read_dev		; skip if character device
	call	local_disk		; get MXdisk, switch stack
	call	verify_handle		; check if legal file handle
	mov	cx,fdos_pb+8		; get requested transfer length
	mov	ax,es:DHNDL_POSLO[bx]	; If we get an error we want to have
	mov	dx,es:DHNDL_POSHI[bx]	; xfer len adjusted for EOF (CopyIIpc)
	sub	ax,es:DHNDL_SIZELO[bx]	; are we beyond EOF ?
	sbb	dx,es:DHNDL_SIZEHI[bx]
;	 jb	read2			; beyond EOF already, no action required
;	 ja	read2			; more the 64K to go, no problems
	 jnz	read2
	cmp	ax,cx			; do we want more than there is?
	 jae	read2			; yes, shorten the fdos_pb count
	sub	fdos_pb+8,ax		;  in case of a critical error
read2:
	mov	fdrwflg,1		; we're reading
	les	di,dword ptr fdos_pb+4	; get disk transfer address
	call	fdosrw			; read from file
	xor	ax,ax			; return OK
	xchg	ax,fdos_ret		; get returned byte count
	mov	fdos_pb+8,ax		; return in requested count
	ret

fdos_read_dev:
	jmp	read_dev		; read from character device

rw_ED_ACCESS:
	mov	bx,ED_ACCESS		; return access denied
	ret

eject
;	WRITE TO FILE (WRITE)

;	+----+----+----+----+----+----+----+----+----+----+
;	|    40   |  handle |       buffer      |  count  |
;	+----+----+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	handle:	open file handle
;	buffer:	buffer to be wriiten
;	count:	max. number of bytes to write

;	exit:
;	-----
;	AX:	byte count or error code ( < 0)

fdos_write:
;----------
	call	vfy_dhndl_ptr		; check file handle #
	test	es:DHNDL_MODE[bx],DHM_WO+DHM_RW
	 jz	rw_ED_ACCESS		; fail if not open in r/w or w mode?
	call	redir_dhndl_offer
	test	es:DHNDL_WATTR[bx],DHAT_DEV
	 jnz	fdos_write_dev		; skip if not character device
	call	local_disk		; get MXdisk, switch stack
	call	verify_handle		; check if legal file handle
	mov	fdrwflg,0		; we're writing
	les	di,dword ptr fdos_pb+4	; get disk transfer address
	mov	cx,fdos_pb+8		; get requested transfer length
	call	fdosrw			; write to file file

	xor	ax,ax			; return OK
	xchg	ax,fdos_ret		; get returned byte count
	mov	fdos_pb+8,ax		; return in requested count
	ret

fdos_write_dev:
	jmp	write_dev		; write to character device
	
eject
;	DELETE FILE (UNLINK)

;	+----+----+----+----+----+----+----+----+----+----+
;	|    41   |        name       |  *****  |  attrib |
;	+----+----+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	name:	segmented address of ASCIIZ name
;	attrib:	delete mask (FCB only..)

;	exit:
;	-----
;	AX:	0000 or error code ( < 0)


fdos_unlink:
;-----------
	call	redir_asciiz_offer
	call	local_disk		; get MXdisk, switch stack
	call	path_prep		; parse the path, go to bottom level
	call	chk_no_dev		; can't be a device
					; look to see is the call is a remote
	cmp	ss:remote_call,0	;  a 21/5D00 one or a local FCB one
	 jz	unlink1			; neither, no wild cards allowed
	 jns	unlink2			; if it's an FCB call we need to check
	test	fdos_pb+8,DA_VOLUME	;  for deleting a VOLUME label
	 jz	unlink2
	call	find_labelf		; lets find the volume label
	 jz	unlink4			;  reporting error if we don't match
	jmp	kill_entry		; found it - delete it

unlink4:
	jmp	fdos_ED_FILE		; return "file not found"

unlink1:
	call	chk_no_wild		; make sure not a wild card
unlink2:
	call	setenddir		; search from the start

; We now skip any labels/dirs, returning ED_FILE if no other matches
unlink3:
	call	finddfcb		; try to locate directory entry
	 jz	unlink4			;  returning an error on failure
	test	DATTS[bx],DA_DIR+DA_VOLUME
	 jnz	unlink3			; make sure it isn't a label/directory

unlink5:
; we have a match, so return ED_ACCESS if we can't find a file we can delete
	call	unlink_attribs		; AL = attribs we can't delete
	 jz	unlink7			; yes, go for it
	call	finddfcb		; look for another entry
	 jnz	unlink5			;  try this one instead
	jmp	fdos_ED_ACCESS		; "access denied" if nothing deleted
					;  since we found at least 1 file

; we will delete at least one file, so now we succeed
unlink6:
	call	unlink_attribs		; AL = attribs we can't delete
	 jnz	unlink8			; yes, go for it
unlink7:
	call	close_if_same_psp	; make sure not open by any process
if PASSWORD
	call	check_pwd_d		; check for password
endif
	call	kill_file		; delete file
unlink8:
	call	finddfcb		; look for another entry
	 jnz	unlink6			;  try and delete it if we find one
	jmp	update_dir_fat		; write out dirty directories/FAT


unlink_attribs:
; On Entry:
;	BX -> directory entry
; On Exit:
;	AL = attribute mask which prevents deletion
;	ZF = 1 if delete OK, ZF = 0 if file should be skipped
;
	mov	al,byte ptr fdos_pb+8	; check attributes
if PASSWORD
	cmp	word ptr DPWD[bx],0
	 je	unlink_attribs10
	or	al,DA_HIDDEN
unlink_attribs10:
endif
	not	al
	and	al,DA_HIDDEN+DA_SYSTEM+DA_RO
    or  al,DA_DIR+DA_VOLUME 
	test	DATTS[bx],al		; should we delete this entry ?
	ret


eject
;	GET/SET FILE POSITION (LSEEK)

;	+----+----+----+----+----+----+----+----+----+----+
;	|    42   |  handle |       offset      !  method |
;	+----+----+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	handle:	open file handle
;	offset:	long integer offset
;	method:	0 = begin, 1 = current, 2 = end of file

;	exit:
;	-----
;	AX:	0000 or error code ( < 0)
;	offset:	new offset

fdos_lseek:
;----------
	call	vfy_dhndl_ptr		; check file handle #
	call	redir_dhndl_offer
	test	es:DHNDL_ATTR[bx],DHAT_DEV
	 jnz	lseek_dev		; skip if character device
	call	local_disk		; get MXdisk, switch stack

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -