📄 funcs.fdo
字号:
pop dx
xchg adrive,dl
call discard_all ; discard all buffers
xchg adrive,dl
inc dx ; onto next drive
cmp dl,phys_drv
jb fdos_flush10
mov al,0FFh ; AL = all drives
jmp hshdscrd ; forget about our hashing
; ret
eject
; SELECT DRIVE
; +----+----+----+----+
; | 4A | drive |
; +----+----+----+----+
; entry:
; ------
; drive: drive (zero based) to select as default drive
; exit:
; -----
; current_dsk: drive (if legal)
fdos_select:
;-----------
call local_disk ; cheap way to get MX
mov ax,fdos_pb+WORD ; AL = drive
call get_ldt ; ES:BX -> LDT for drive A
mov dx,ax ; DL = logical drive
jc fdos_select10 ; no LDT, treat as physical=logical
mov ax,es:LDT_FLAGS[bx] ; get the LDT_FLAGS
test ax,LFLG_NETWRKD ; NETWORK drives are OK, but we must
jnz fdos_select20 ; skip physical selection bit
test ax,LFLG_PHYSICAL
jz fdos_select30 ; skip physical selection bit
if JOIN
test ax,LFLG_JOINED ; JOINed drives are bad news
jnz fdos_select30 ; so don't select one
endif
mov al,es:LDT_NAME[bx] ; get ASCII drive letter
call toupper ; it was ascii
sub al,'A' ; make it zero based
fdos_select10:
call get_ddsc ; ES:BX -> DDSC_ for drive
jc fdos_select30 ; no, don't select
fdos_select20:
mov ss:current_dsk,dl ; new logical disk selected
fdos_select30:
ret
eject
; EXECUTE CHILD (EXEC)
; +----+----+----+----+
; | 4B | pspseg |
; +----+----+----+----+
; entry:
; ------
; pspseg: segment of child PSP
; exit:
; -----
; AX: 0000h
fdos_exec:
;---------
call local_disk ; get MXdisk, switch stack
mov cx,fdos_pb+2
jcxz exec30 ; no duplicate handles if no new PSP
mov di,offset PSP_XFT
mov es,cx ; get child PSP
mov cx,XFNMAX ; get # of handles in child PSP
mov PSP_XFNMAX,cx
mov PSP_XFTOFF,di
mov PSP_XFTSEG,es
mov al,0FFh ; assume all handles closed
rep stosb
xor si,si ; start with XFN 0
exec10:
call get_xftptr ; ES:DI -> XFN table
jc exec30 ; stop if none
add di,si
mov al,es:[di] ; get IFN of old handle
call ifn2dhndl ; ES:BX -> DHNDL_
jc exec20
mov cx,es:DHNDL_COUNT[bx] ; skip files that aren't open
jcxz exec20
test es:byte ptr DHNDL_WATTR+1[bx],DHAT_LOCAL/100h
jnz exec20 ; don't inherit private files
test es:byte ptr DHNDL_MODE+1[bx],DHM_FCB/100h
jnz exec20 ; don't inherit FCB's
inc cx
mov es:DHNDL_COUNT[bx],cx ; increment in-use count
push ax
call dup_dev ; inform device driver it's happened
pop ax
mov es,fdos_pb+2 ; get child PSP
mov es:PSP_XFT[si],al ; inherit this IFN
exec20:
inc si ; next file handle
cmp si,XFNMAX
jb exec10 ; inherit all file handles
exec30:
ret
eject
; FIND FIRST FILE
; +----+----+----+----+----+----+----+----+----+----+
; | 4E | name | ***** | attrib |
; +----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; name: pointer to ASCIIZ file name
; attrib: attribute to be used in search
; nb. API addition - attrib bit 7 set returns starting cluster
;
; exit:
; -----
; AX: 0000 or error code ( < 0)
; Note: This call returns matching files in
; the current DMA address and also saves
; the BDOS state in the there.
;
fdos_first:
;----------
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 path_prep ; parse path, walk down the tree
call check_device ; if it a device
jnc fdos_first10
mov ax,fdos_pb+8 ; get search attribute
mov attributes,al ; set for attribute match
mov dcnt,0FFFFh ; search from beginning
jmps search_next ; find next matching file
fdos_first10:
jmp first_dev ; return device name
next_deverr: ; NEXT after FIRST on device:
mov bx,ED_FILE ; "no more files"
ret
eject
; FIND NEXT FILE
; +----+----+
; | 4F |
; +----+----+
; entry:
; ------
;
; exit:
; -----
; AX: 0000 or error code ( < 0)
; Note: This call returns matching files in
; the current DMA address and also saves
; the BDOS state in the there.
;
fdos_next:
;---------
push ds
call lds_si_dmaptr ; DS:SI -> users DMA address
lodsw
xchg ax,dx ; DH = local drive
pop ds
cmp dh,0FFh ; check if FIRST was character device
je next_deverr ; "no more files" if device
call redir_snext_offer
call local_disk ; get MXdisk, switch stack
call select_from_DTA ; prepare for the search
; jmp search_next ; now go and look for next file
search_next:
;-----------
mov chdblk,0 ; don't assume sequential access
mov al,attributes ; are we looking for a VOL label?
test al,DA_DIR+DA_SYSTEM+DA_HIDDEN
jnz search_n10 ; these bits take precedence
test al,DA_VOLUME ; searching for label?
jz search_n10 ; search for directory label only
if UNDELETE
cmp al,DA_DELWATCH+DA_VOLUME
jne search_vol ; searching for pending delete entries?
call find_pending_delete ; did we find it ?
jz search_next_err ; No, then skip
jmps search_n30 ; save search state for user
search_vol:
endif
call find_label ; did we find it ?
jnz search_n30 ; save search state for user
search_next_err:
jmp fdos_ED_ROOM ; else end of directory
search_n10:
call finddfcb ; find next matching entry
jz search_next_err ; if not found
mov al,attributes ; get attributes that we support
if PASSWORD
cmp word ptr DPWD[bx],0 ; does it have a password?
jz search_n20 ; skip if not
or al,DA_HIDDEN ; else include hidden files
search_n20:
endif
not al ; attributes we don't support
and al,DA_DIR+DA_HIDDEN+DA_SYSTEM+DA_VOLUME
test DATTS[bx],al ; any attributes we don't support
jnz search_n10 ; then don't count this one
search_n30:
push ss ! pop es
mov di,offset srch_buf ; ES:DI -> DMA search address
push di ; save for later
if JOIN
mov al,fdos_hds_drv ; save the PHYSICAL drive
else
mov al,byte ptr path_drive ; save the specified drive
endif
inc al
stosb
mov dx,di ; remember start of name field
mov si,offset info_fcb+1 ; point at search FCB
mov cx,11
rep movsb ; save name for search
mov al,attributes ; get search attribute
stosb
mov ax,dcnt
stosw ; save directory count
mov ax,fdos_hds_blk ; get the directory block
stosw ; save the current block
add di,4 ; skip 4 reserved bytes
mov si,dirp ; point to directory name
test attributes,DA_CLUSTER ; is the caller requesting
jz search_n35 ; the starting cluster ?
mov ax,DBLOCK1[si] ; pick it up from dir entry
dec di ; and return at offset 13h
dec di ; in DTA (WARNING - Lantastic
stosw ; server uses these bytes too..)
search_n35:
mov cx,32/WORD
rep movsw ; location (also used by FCB search)
pop si ; SI = offset srch_buf
call les_di_dmaptr ; ES:DI -> DMA address
push ss ! pop ds ; DS:SI -> srch_buf
mov cx,21
rep movsb ; copy from buffer to user DMA
mov bx,dirp ; BX -> matching entry
mov al,DATTS[bx]
stosb ; return directory attribute
lea si,DTIME[bx]
movsw ! movsw ; return time, date
inc si
inc si ; skip starting cluster
movsw ! movsw ; return file size
jmp unparse ; return file name
eject
; COMMIT FILE (COMMIT)
; +----+----+----+----+
; | 50 | handle |
; +----+----+----+----+
; entry:
; ------
; handle: open file handle to be flushed
; exit:
; -----
; AX: 0000 or error code ( < 0)
file_updt20: ; NO-OP for clean files
commit_dev: ; NO-OP on character devices
ret
fdos_commit:
;-----------
call vfy_dhndl_ptr ; check file handle
call redir_dhndl_offer
call local_disk ; get MXdisk, switch stack
call verify_handle ; check if legal file handle
jc commit_dev
; jmp file_update ; update directory & FAT if written
; Update directory & File Allocation Table (partial close)
; entry: ES:BX -> DHNDL_
; exit: ES:BX preserved
Public file_update
file_update:
;-----------
test es:DHNDL_ATTR[bx],DHAT_CLEAN
jnz file_updt20 ; skip if file is clean
mov al,es:DHNDL_DCNTLO[bx] ; get directory count
mov ah,es:DHNDL_DCNTHI[bx]
dec ax
mov dcnt,ax ; set search position
xor cx,cx ; find any entry
mov chdblk,cx ; non-sequential access
push es ! push bx
call getdir ; read the directory entry
pop bx ! pop es
test ax,ax ; did we find something?
jz file_updt10 ; skip if directory entry lost
xchg ax,di ; DI -> directory entry in buffer
or DATTS[di],DA_ARCHIVE ; mark file as modified
;;; call timestamp_dhndl ; record the current time
mov ax,es:DHNDL_BLK1[bx] ; AX = 1st block in file
lea di,DTIME[di] ; DI -> [time,date,block1,size]
push es ! push bx
push ds
lea si,DHNDL_TIME[bx]
push ds ! push es
pop ds ! pop es ; swap ES and DS
movsw ! movsw ; copy time then date
stosw ; now 1st cluster
movsw ! movsw ; finally file size
pop ds
call update_dir ; update directory
call update_fat ; flush dirty FAT
call update_dat ; flush all dirty data buffers
pop bx ! pop es
or es:DHNDL_ATTR[bx],DHAT_CLEAN
ret ; only mark as clean AFTER it's written
file_updt10:
mov ax,ED_H_MATCH ; can't find open file
mov fdos_ret,ax ; save error code
ret
eject
; CREATE NEW FILE
; +----+----+----+----+----+----+----+----+
; | 51 | name | mode |
; +----+----+----+----+----+----+----+----+
; entry:
; ------
; name: segmented address of ASCIIZ name
; mode: attribute for file
; exit:
; -----
; AX: file handle or error code ( < 0)
; Note: The function is identical to CREATE FILE
; with the exception that an error is returned
; if the specified file already exists.
fdos_mknew:
;----------
call redir_asciiz_offer
call local_disk ; get MXdisk, switch stack
call mustbe_free_handle ; make sure we have spare handle
call path_prep_chk ; parse path, walk down the tree
call finddfcbf ; check if we can find this one
jnz mknew10
test byte ptr fdos_pb+8,DA_VOLUME
jz mknew_nolbl ; skip if not volume label
call mustbe_nolbl ; do we have an existing label ?
mknew_nolbl:
jmp creat_new_file ; go ahead and create the file
mknew10:
mov ax,ED_EXISTS
jmp fdos_error
eject
; LOCK/UNLOCK FILE DATA (LOCK/UNLOCK)
; +----+----+----+----+----+----+----+----+
; | 52 | handle | offset |
; +----+----+----+----+----+----+----+----+
; | length | lock |
; +----+----+----+----+----+----+
; entry:
; ------
; handle: open file handle
; offset: long integer offset
; length: long integer byte count
; lock: 0 = lock, 1 = unlock
; exit:
; -----
; AX: byte count or error code ( < 0)
fdos_lock:
;---------
call vfy_dhndl_ptr ; check file handle #
test es:DHNDL_WATTR[bx],DHAT_DEV
jnz lock_dev ; skip if character device
call redir_dhndl_offer
call local_disk ; get MXdisk, switch stack
call check_handle ; check if legal file handle
mov ax,ED_ACCESS ; assume a problem
jc lock_error ; can't lock/unlock device handles
mov di,offset fdos_pb
callf ss:share_stub+S_LOCKS ; call the stub routine
jnc lock_ret ; return error if we got one
lock_error:
jmp fdos_error ; can't do locking
lock_dev:
mov bx,ED_ACCESS
lock_ret:
ret
eject
; BUILD DDSC FROM BPB
; +----+----+----+----+----+----+----+----+----+----+
; | 53 | bpbptr ! ddscptr |
; +----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; bpbptr: address of BPB
; ddscptr: address of DDSC to be built
; exit:
; -----
; 0000 or error code ( < 0)
fdos_mkddsc:
;-----------
push ds
mov si,2[bp] ; SI -> parameter block
les di,6[si] ; ES:DI -> DDSC
lds si,2[si] ; DS:SI -> BPB
call bpb2ddsc ; convert BPB to DDSC
xor bx,bx ; no error
pop ds ; restore segment register
ret
bpb2ddsc:
;--------
; build a DDSC from a BPB, leavinf UNIT, RUNIT, DEVICE, FIRST, and LINK fields
; unchanged
; On Entry:
; DS:SI -> source BPB
; ES:DI -> destination DDSC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -