📄 funcs.fdo
字号:
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 + -