📄 fcbs.a86
字号:
title 'FCB - DOS file system FCB support'
; File : $FCBS.A86$
;
; Description :
;
; Original Author : DIGITAL RESEARCH
;
; Last Edited By : $CALDERA$
;
;-----------------------------------------------------------------------;
; Copyright Work of Caldera, Inc. All Rights Reserved.
;
; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
; CIVIL LIABILITY.
;-----------------------------------------------------------------------;
;
; *** Current Edit History ***
; *** End of Current Edit History ***
; $Log$
; FCBS.A86 1.10 93/11/11 15:38:14
; Chart Master fix - fcb_readblk over > 64k is truncated to 64k and
; error 2 (Segment boundry overlap) is returned
; FCBS.A86 1.9 93/10/18 17:37:06
; fix for >255 open files (PNW Server)
; ENDLOG
eject ! include i:fdos.equ
eject ! include i:msdos.equ
eject ! include i:mserror.equ
eject ! include i:doshndl.def ; DOS Handle Structures
eject
BDOS_DATA dseg word
BDOS_CODE cseg
extrn ifn2dhndl:near
extrn parse_one:near
extrn fdos_entry:near
Public fdos_exit
eject
; TERMINATE CHILD (EXIT)
; +----+----+
; | 24 |
; +----+----+
; entry:
; ------
; -none-
; exit:
; -----
; -none-
; Close down all FCB handles associated with the current PSP
;
fdos_exit:
;---------
push ds
push ss ! pop ds ; DS -> PCM_DSEG
sub ax,ax ; start with first DHNDL_
fdos_exit10:
call ifn2dhndl ; get DHNDL_
jc fdos_exit40 ; stop if we have run out
mov fcb_pb+2,ax ; we may close this IFN
push ax
mov cx,es:DHNDL_COUNT[bx] ; get the open count
jcxz fdos_exit30 ; skip if nothing to do
mov ax,current_psp ; get current PSP
cmp ax,es:DHNDL_PSP[bx] ; does it belong to this PSP
jne fdos_exit30
mov ax,ss:machine_id ; get current process
cmp ax,es:DHNDL_UID[bx]
jne fdos_exit30
test es:DHNDL_MODE[bx],DHM_FCB
jz fdos_exit20 ; skip close if not FCB
push es
push bx ; save the DHNDL
mov ax,MS_X_CLOSE
call fcb_fdos ; make the FDOS do the work
pop bx
pop es ; recover the DHNDL
fdos_exit20:
mov es:DHNDL_COUNT[bx],0 ; always free the handle if it's ours
fdos_exit30:
pop ax
inc al ; onto next IFN
jnz fdos_exit10
fdos_exit40:
pop ds
ret
Public fdos_fcb
eject
; GENERIC FCB FUNCTION (FCB)
; +----+----+----+----+----+----+----+----+
; | 22 | fcbadr | count |
; +----+----+----+----+----+----+----+----+
; | func |
; +----+----+
; entry:
; ------
; fcbadr: FCB address
; count: multi-sector count for read/write
; func: FCB sub-function
; exit:
; -----
; AX: return code or error code ( < 0)
fdos_fcb:
;--------
mov bx,2[bp] ; BX -> parameter block
mov bx,8[bx] ; get subfunction code
shl bx,1 ; make it word index
sub bl,15*WORD ; adjust to base address
jc fcb_error ; reject if too low
cmp bl,FCB_MAX1 ; is it in 1st block
jb fdos_fcb10
sub bl,(33-24)*WORD ; adjust for gap
jc fcb_error
cmp bl,FCB_MAX2 ; is it in 2nd block
jb fdos_fcb10
sub bl,(39-37)*WORD ; adjust for gap
jc fcb_error
fdos_fcb10:
cmp bx,FCB_MAX3 ; check the range
jae fcb_error ; skip if invalid function
jmp fcb_table[bx] ; call the right function
fcb_error:
mov bx,ED_FUNCTION
ret
fcb_table dw fcb_open ; 15-open file
dw fcb_close ; 16-close file
dw fcb_first ; 17-find first
dw fcb_next ; 18-find next
dw fcb_delete ; 19-delete file
dw fcb_read ; 20-read from file
dw fcb_write ; 21-write to file
dw fcb_make ; 22-make file
dw fcb_rename ; 23-rename file
FCB_MAX1 equ (offset $ - offset fcb_table)
dw fcb_readrand ; 33-read from file
dw fcb_writerand ; 34-write to file
dw fcb_size ; 35-compute file size
dw fcb_setrecord ; 36-set relative record
FCB_MAX2 equ (offset $ - offset fcb_table)
dw fcb_readblk ; 39-read from file
dw fcb_writeblk ; 40-write to file
FCB_MAX3 equ (offset $ - offset fcb_table)
fcb_make:
;--------
call fcb_path_prep ; build pathname
mov ax,MS_X_CREAT
jmps fcb_open_make_common
fcb_open:
;--------
call fcb_path_prep ; build pathname
mov ax,MS_X_OPEN
fcb_open_make_common:
mov fcb_pb+6,DHM_RW+DHM_FCB ; open as an FCB for read/write
call fcb_fdos ; lets try and open the file
jnc fcb_open10 ; skip if we can't
ret
fcb_open10:
call ifn2dhndl ; ES:BX -> DHNDL_ we have opened
push ds
push es ! push bx ; save DHNDL_
call fcb_point ; ES:BX = FCB
pop si ! pop ds ; DS:SI -> DHNDL_
mov es:MSF_IFN[bx],al ; store IFN away
mov es:MSF_BLOCK[bx],0 ; current block number
mov es:MSF_RECSIZE[bx],128 ; current logical record size
call fcb_update ; update misc changing fields
mov ax,ds:DHNDL_DEVOFF[si]
mov es:word ptr MSF_DEVPTR[bx],ax
mov ax,ds:DHNDL_DEVSEG[si]
mov es:word ptr MSF_DEVPTR+2[bx],ax
mov ax,ds:DHNDL_BLK1[si]
mov es:MSF_BLOCK1[bx],ax
mov al,ds:DHNDL_ATTR[si]
mov es:MSF_IOCTL[bx],al
mov al,es:MSF_DRIVE[bx] ; get drive from FCB
dec al ; was absolute drive specified ?
jns fcb_open20 ; if so use it
mov al,ss:current_dsk ; else use default drive
fcb_open20:
inc al ; make drive 1 rather than 0 based
mov es:MSF_DRIVE[bx],al ; drive code
if 0
test ds:DHNDL_DATRB[si],DA_VOLUME
else
test ss:fcb_pb+8,DA_VOLUME
endif
pop ds
jnz fcb_close ; don't leave VOL label's open
xor bx,bx ; no errors !
ret
fcb_update:
;----------
; On Entry:
; DS:SI -> DHNDL_
; ES:BX -> FCB
; On Exit:
; DATE/TIME/SIZE/DBLK/DCNT fields updated
;
mov ax,ds:DHNDL_TIME[si]
mov es:MSF_TIME[bx],ax
mov ax,ds:DHNDL_DATE[si]
mov es:MSF_DATE[bx],ax
mov ax,ds:DHNDL_SIZELO[si]
mov es:MSF_SIZE[bx],ax
mov ax,ds:DHNDL_SIZEHI[si]
mov es:MSF_SIZE+2[bx],ax
mov ax,ds:DHNDL_DBLK[si]
mov es:MSF_DBLK[bx],ax
mov al,ds:DHNDL_DCNTLO[si]
mov ah,ds:DHNDL_DCNTHI[si]
mov es:MSF_DCNT[bx],ax
ret
fcb_close:
;---------
; close file (DOS function 10h)
call fcb_point ; ES:BX -> FCB
mov al,0FFh
cmp al,es:MSF_IFN[bx] ; is it a multiple close ?
je fcb_fdos_common10 ; don't re-open for this...
call fcb_handle_vfy ; verify we have a sensible handle
mov es:MSF_IFN[bx],al ; mark FCB as closed (it will be)
mov ax,MS_X_CLOSE ; now close it
; jmps fcb_fdos_common
fcb_fdos_common:
;---------------
call fcb_fdos ; make the FDOS do the work
jc fcb_fdos_common20 ; return any error codes
fcb_fdos_common10:
xor bx,bx ; else return zero
fcb_fdos_common20:
ret
fcb_rename:
;----------
call fcb_path_prep
call fcb_path2_prep
mov ax,MS_X_RENAME ; it's a rename
jmps fcb_fdos_common
fcb_delete:
;----------
call fcb_path_prep
mov ax,MS_X_UNLINK ; it's a delete
jmps fcb_fdos_common
fcb_first:
;---------
call fcb_path_prep ; prepare pathname
mov ax,MS_X_FIRST ; we want to search 1st
jmps fcb_search_common
fcb_next:
;--------
call fcb_restore_search_state
mov ax,MS_X_NEXT
fcb_search_common:
call fcb_search ; 0 of OK, otherwise ED_..
jc fcb_search_common10
call fcb_save_search_state ; save sucessful state
xor bx,bx ; return code in BX
fcb_search_common10:
ret
fcb_setrecord:
;-------------
call fcb_point ; ES:BX -> FCB
mov ax,128 ; multiply current block by 128
mul es:MSF_BLOCK[bx] ; to give current record number
xor cx,cx
mov cl,es:MSF_CR[bx] ; Add in the current record
add ax,cx ; to DX:AX to give the
adc dx,0 ; relative record
mov es:MSF_RR[bx],ax ; save the result
mov es:MSF_RR2[bx],dl
xor bx,bx ; we did OK
ret
fcb_write:
;---------
mov ax,MS_X_WRITE ; make it a write
jmps fcb_seq_rw
fcb_read:
;--------
mov ax,MS_X_READ ; make it a read
fcb_seq_rw:
call fcb_handle_vfy ; verify we have a sensible handle
push ax ; save the operation
call fcb_get_count ; AX = bytes to read
push ax ; save byte count
call fcb_seek_seq ; Seek to position in the file
pop cx ; recover byte to xfer
pop ax ; and the Operation Code
jc fcb_seq_rw10
call fcb_rw ; do the Op
jc fcb_seq_rw10
push bx ; save the error code
call fcb_update_seq ; update FCB filepos
pop bx ; recover error
fcb_seq_rw10:
ret
fcb_rw:
; On Entry:
; AX = operation code
; CX = count
; fcb_pb+2 = IFN
; On Exit:
; BX = error code
les dx,ss:dword ptr dma_offset
add cx,dx ; see if we overflow
jc fcb_rw20
sub cx,dx ; count back to normal
push cx ; save target count
mov fcb_pb+4,dx
mov fcb_pb+6,es ; setup buffer address
mov fcb_pb+8,cx ; and target count
call fcb_fdos ; ask the FDOS to do the read/write
jc fcb_rw10 ; we got a real error...
push ds
push es
mov ax,fcb_pb+2 ; get IFN
call ifn2dhndl ; ES:BX -> DHNDL_ we have open
push es ! push bx ; save DHNDL_
call fcb_point ; ES:BX = FCB
pop si ! pop ds ; DS:SI -> DHNDL_
call fcb_update ; update file size/time-stamp
pop es
pop ds
pop ax ; recover target count
mov cx,fcb_pb+8 ; we xfered this much
cmp cx,ax ; did we xfer enough
jb fcb_rw30 ; nope..
xor bx,bx ; xfer went OK
ret
fcb_rw10:
pop ax ; discard target count
ret
fcb_rw20:
; Our DTA is too small - return 2
mov bx,2 ; indicate the DTA is too small
; stc ; error - don't update FCB
ret
fcb_rw30:
; We have some form of EOF - lets look into it
call fcb_point ; ES:BX = FCB
mov bx,es:MSF_RECSIZE[bx] ; BX = record size
mov ax,cx
xor dx,dx ; DX:AX = bytes xfer'd
div bx ; did we xfer a complete
test dx,dx ; number of records ?
jz fcb_rw40 ; if so return 1
; Partial data was read - fill out with zero's and return 3
inc ax ; allow for incomplete record
push ax ; save rounded up xfer count
les di,ss:dword ptr dma_offset
add di,cx ; point to 1st byte after xfer
mov cx,bx ; this many in a record
sub cx,dx ; so this many weren't xfer'd
xor ax,ax ; fill them with zero's
rep stosb ; zap the bytes we didn't xfer to
pop ax ; recover xfer count
mul bx ; and work out # bytes xfered
xchg ax,cx ; return bytes in CX
mov bx,3 ; indicate EOF (partial read)
; clc ; update FCB
ret
fcb_rw40:
; No Data was xfered - return 1
mov bx,1 ; indicate EOF (no data read)
; clc ; update FCB
ret
fcb_writerand:
;-------------
mov ax,MS_X_WRITE ; make it a write
jmps fcb_random_rw
fcb_readrand:
;------------
mov ax,MS_X_READ ; make it a read
fcb_random_rw:
call fcb_handle_vfy ; check the handle is OK
push ax ; save the code
call fcb_get_count ; AX = bytes to read
push ax ; save byte count
xor cx,cx ; cause update of seq posn from
call fcb_update_rr ; random record position
call fcb_seek_rr ; Seek to position in the file
pop cx ; recover byte to xfer
pop ax ; and the Operation Code
jc fcb_random_rw10
call fcb_rw ; do the Op
fcb_random_rw10:
ret
fcb_writeblk:
;------------
mov ax,MS_X_WRITE ; make it a write
jmps fcb_block_rw
fcb_readblk:
;-----------
mov ax,MS_X_READ ; make it a read
fcb_block_rw:
call fcb_handle_vfy ; check the handle is OK
push ax ; save the code
call fcb_get_count ; AX = bytes per record, CX = # records
xchg ax,cx ; CX = bytes per record
mul cx ; AX = bytes to xfer
test dx,dx ; more than 64K ?
jz fcb_block_rw10 ; then we should truncate it
mov ax,15 ; AX = handy mask
cwd ; DX = 0
and ax,ss:dma_offset ; get dma offset for para
not ax ; DX/AX = maximum bytes we can xfer
div cx ; AX = maximum blocks we can xfer
mul cx ; AX = bytes to xfer (now < 64K)
fcb_block_rw10:
push ax ; save byte count
call fcb_seek_rr ; Seek to position in the file
pop cx ; recover byte to xfer
pop ax ; and the Operation Code
jc fcb_block_rw20
call fcb_rw ; do the Op
jc fcb_block_rw20
push bx ; save the error code
call fcb_update_rr ; update FCB filepos, get records xferd
mov bx,2[bp] ; BX -> parameter block
xchg cx,6[bx] ; update amount xfered
sub cx,6[bx] ; CX = # we didn't xfer (normally 0)
pop bx ; recover (possible) error
jcxz fcb_block_rw20 ; skip if we read all we wanted to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -