📄 funcs.fdo
字号:
; File : $FUNCS.FDO$
;
; 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$;
; ENDLOG
; General function include module for FDOS.A86
BDOS_CODE cseg
public fdos_entry
;==========
fdos_entry: ; FDOS module entry point
;==========
; On Entry:
; DS:DX -> parameter block
; On exit:
; AX = BX = return code
; (DS/ES corrupted)
; entry: DS:DX = argument
;
; exit: AX,BX = return code
mov si,dx
lodsw ; AX = FDOS number
sub ax,39h ; base it at zero
jc fd_error ; stop if too low
cmp ax,FDOS_MAX ; check if function in range
jae fd_error ; yes, continue
push ds ; save parameter segment
push dx ; save parameter offset
push ax ; save sub-function
mov bp,sp ; SS:BP -> working variables
mov bx,ax
add bx,ax
add bx,ax
call fdos_tbl[bx]
add sp,3*WORD ; clean up stack
mov ax,bx
ret
fd_error:
mov ax,ED_FUNCTION ; return "invalid function"
mov bx,ax
ret
fdos_tbl dw fdos_mkdir ; 39-make directory
db 2
dw fdos_rmdir ; 3A-remove directory
db 2
dw fdos_chdir ; 3B-change directory
db 2
dw fdos_creat ; 3C-create file
db 4
dw fdos_open ; 3D-open file
db 4
dw fdos_close ; 3E-close file
db 1
dw fdos_read ; 3F-read from file
db 4
dw fdos_write ; 40-write to file
db 4
dw fdos_unlink ; 41-delete file
db 4
dw fdos_lseek ; 42-set file pointer
db 4
dw fdos_chmod ; 43-get/set file attributes
db 6
dw fdos_ioctl ; 44-IOCTL emulation
db 3
dw fdos_dup ; 45-duplicate handle
db 2
dw fdos_fdup ; 46-force duplicate handle
db 2
dw fdos_curdir ; 47-get current directory
db 3
dw fdos_getdpb ;*48*disk information
db 4
dw fdos_flush ;*49*flush buffers
db 0
dw fdos_select ;*4A*drive select
db 1
dw fdos_exec ;*4B*create child PSP
db 1
dw fdos_exit ;*4C*close child PSP
db 0
dw fdos_fcb ;*4D*generic FCB call
db 5
dw fdos_first ; 4E-find first matching file
db 4
dw fdos_next ; 4F-find next matching file
db 0
dw fdos_commit ;*50*commit file
db 1
dw fdos_mknew ;*51*make new file
db 4
dw fdos_lock ;*52*lock/unlock block
db 6
dw fdos_mkddsc ; 53 build DDSC from BPB
db 4
dw fdos_ddio ;*54*Int 25/26 emulation
db 6
dw fdos_expand ;*55*expand file name
db 6
dw fdos_move ; 56-rename file
db 6
dw fdos_dattim ; 57-get/set file name
db 4
dw fdos_reopen_fcb ; 58-FCB reopen support function
db 5
FDOS_MAX equ (offset $ - offset fdos_tbl) / 3
Public local_disk
local_disk: ; continue execution within MXdisk semaphore
;----------
; This function will make local copies of the parameters
; and continue
callf ss:lock_tables
pop fdos_addr ; return address
add sp,2*WORD ; discard return from call fdos_tbl[bx]
; and function #
pop si ; get parameter offset
pop ax ; get parameter segment
mov sp_save,sp ; save for re-entry/errors
mov ds,ax ; DS:SI -> paremeter block
fdos_reenter:
push ss ! pop es ; ES = local data segment
mov di,offset fdos_pb ; ES:DI -> local parameter block copy
lodsw ! stosw ; load subfunction number
mov es:fdos_info,si ; save it for BDOS return
mov es:fdos_info+WORD,ds ; save parameter segment for return
mov bx,ax
add bx,ax
add bx,ax ; BX = function # * 3
mov cl,byte ptr fdos_tbl-(39h*(WORD+BYTE))+WORD[bx]
mov ch,0
; get table of # of parameters
mov es:fdos_info+2*WORD,cx ; save the parameter count
rep movsw ; copy parameter block
push es ! pop ds ; DS = SYSDAT
mov ioexerr,0FFh ; assume default error code
mov rwmode,0
mov finddfcb_mask,DA_VOLUME*256
xor ax,ax
mov fdos_ret,ax ; assume success unless proven otherwise
call fdos_addr ; call code following "call local_disk"
mov ax,fdos_ret ; get return code, fall thru to exit
Public fdos_error
fdos_error:
;----------
; AX = return code
mov sp,sp_save ; stack to entry value (for errors)
mov si,offset fdos_pb+2 ; get local copy
les di,dword ptr fdos_info ; get parameter block address
mov cx,fdos_info+2*WORD ; get parameter block size
rep movsw ; copy return values
mov bx,ax
callf ss:unlock_tables
ret ; return to BDOS, which copies BX to AX
Public fdos_restart
fdos_restart: ; we want to restart the function after an error
;------------ ; we already have MXdisk
;
mov sp,sp_save ; break out from low levels
lds si,dword ptr fdos_info
dec si ! dec si ; DS:SI -> parameter block
jmps fdos_reenter ; try from scratch
fdos_ED_ROOM:
;-----------
mov ax,ED_ROOM ; no more files
jmps fdos_error
fdos_ED_DRIVE:
;-----------
mov ax,ED_DRIVE ; bad drive
jmps fdos_error
fdos_ED_PATH:
mov ax,ED_PATH ; invalid path or drive
jmps fdos_error
fdos_ED_PROTECT:
mov ax,ED_PROTECT ; write protect error
jmps fdos_error
Public fdos_ED_ACCESS
fdos_ED_ACCESS:
mov ax,ED_ACCESS ; access denied error
jmps fdos_error
eject
; MAKE DIRECTORY (MKDIR)
; +----+----+----+----+----+----+
; | 39 | name |
; +----+----+----+----+----+----+
; entry:
; ------
; name: segmented address of ASCIIZ name
; exit:
; -----
; AX: 0000 or error code ( < 0)
fdos_mkdir:
;----------
call redir_asciiz_offer
call local_disk ; get MXdisk, switch stack
call path_prep_chk ; parse path, walk down the tree
call finddfcbf ; find matching FCB
jnz mkdir_access ; file/dir exists, "access denied"
call allocdir ; allocate a directory entry
push ax ; save pointer to directory entry
lea si,info_fcb+1 ; SI -> file name
xchg ax,di ; DI -> DNAME
mov cx,11
rep movsb ; copy file name into directory buffer
; lea di,DATTS[si]
mov al,DA_DIR
stosb ; mark it as a directory
xor ax,ax
mov cx,(32-12)
rep stosb ; zero remainder of new FCB
pop si ; SI -> directory
call stamp_dir_entry ; set time and date in FCB
xor ax,ax
call alloc_cluster ; Allocate a block
jc mkdir_err ; Report Error(no room on disk)
mov si,dirp
mov DBLOCK1[si],ax ; Initialize 1st block of fcb
push ax ; save block
call update_fat ; Write the fat to disk
call update_dir ; Write the directory to disk
pop ax ; now initialise the sub-directory
call mkdir_init ; '.' and '..' entries
call update_dir ; update directory entry
mov ax,5 ; return a magic value for some
mov fdos_ret,ax ; PD expansion program
ret
mkdir_err:
;---------
mov bx,dirp ; can't make dir, no data space
mov DNAME[bx],0E5h ; so release our directory entry
call update_dir ; release this entry
mkdir_access:
jmp fdos_ED_ACCESS ; return "access denied" error
chk_no_dot: ; reject "." and ".." names
cmp info_fcb+1,'.'
je mkdir_access
ret
eject
; REMOVE DIRECTORY (RMDIR)
; +----+----+----+----+----+----+
; | 3A | name |
; +----+----+----+----+----+----+
; entry:
; ------
; name: segmented address of ASCIIZ name
; exit:
; -----
; AX: 0000 or error code ( < 0)
fdos_rmdir:
;----------
call redir_asciiz_offer
call local_disk ; get MXdisk, switch stack
call path_prep_chk ; parse path to bottom level
call finddfcbf ; try to locate directory entry
jz fdos_rmdir20 ; skip if we can't find it
test DATTS[bx],DA_DIR ; check directory attribute
jz fdos_rmdir30 ; O.K. if a directory
call chkcds ; make sure no-where current
jnc fdos_rmdir40
call path_prep ; redo as rmdir_ok may destroy info
call finddfcbf ; find the entry again
call rmdir_ok ; make sure not in use
call finddfcbf ; find the entry again
if PASSWORD
call check_pwd_any
endif
kill_entry:
call kill_file ; actually delete entry
update_dir_fat:
call update_dir ; update directory entry
jmp update_fat ; update file allocation table
fdos_rmdir20:
jmp fdos_ED_PATH ; "invalid path"
fdos_rmdir30:
jmp fdos_ED_ACCESS ; "access denied"
fdos_rmdir40:
mov ax,ED_DIR
jmp fdos_error
eject
; CHANGE DIRECTORY (CHDIR)
; +----+----+----+----+----+----+
; | 3B | name |
; +----+----+----+----+----+----+
; entry:
; ------
; name: segmented address of ASCIIZ name
; exit:
; -----
; AX: 0000 or error code ( < 0)
chdir_ED_PATH:
jmp fdos_ED_PATH ; all logical errors give "no path"
chdir_ED_DRIVE:
mov ax,ED_DRIVE ; bad drive error message
chdir_err:
jmp fdos_error
fdos_chdir:
;----------
call redir_asciiz_offer
call local_disk ; get MXdisk, switch stack
fdos_move_chdir:
;---------------
mov orig_drive,0FFFFh ; set drive to invalid
les di,dword ptr fdos_pb+2 ; get string address
call get_path_drive ; from asciiz or default
jc chdir_ED_DRIVE ; continue if drive A: - Z:
call islocal ; reject networked drives
jc chdir_ED_DRIVE ; as bad drives
call path_prep_cont ; continue if drive legal
jc chdir_err ; return error to application
call chk_no_dev ; no devices allowed
call chk_no_wild ; no wild cards allowed here
cmp orig_drive,0FFFFh ; check if assign to specified drive
jne chdir10 ; skip drive specified
mov ax,path_drive ; else same as path drive
mov orig_drive,ax
chdir10:
if JOIN
call offer_join ; are we opening a JOIN'd drive ?
jnc chdir30 ; if so move to it and skip open_dir
endif
call chk_for_root ; check if we are in the root
je chdir30 ; if so, just skip the open_dir
call finddfcbf ; try to locate directory entry
jz chdir_ED_PATH ; skip if no valid directory
test DATTS[bx],DA_DIR ; check directory attribute
jz chdir_ED_PATH ; return if not a directory
if PASSWORD
call check_pwd_any ; check if PW prot'd & wrong PW
endif
call open_dir ; else open last directory
jc chdir_ED_PATH ; return an error if we can't
chdir30:
mov ax,orig_drive ; get logical drive
call get_ldt ; ES:BX -> LDT_
jc chdir10 ; no LDT_, must be init time...
mov si,es:LDT_FLAGS[bx] ; normally we inherit parents
mov cx,es:LDT_ROOTLEN[bx] ; root block and drive
mov dx,es:word ptr LDT_NAME[bx]
mov bx,es:LDT_ROOT[bx] ; if it's a "SUBST I: C:\PATH" form
cmp ax,path_drive ; we pick up new root and drive
je chdir50 ; like this
mov ax,path_drive ; ASCII drive from path drive
mov dx,'A'+256*':' ; make it into ASCII "C:"
add dx,ax ; in case LDT does not exist
call get_ldt ; get LDT_ in case it's subst'd
jc chdir40
mov dx,es:word ptr LDT_NAME[bx]
chdir40:
mov bx,fdos_hds_blk ; root block from fdos_hds
chdir50:
mov di,offset pri_pathname ; build new LDT_ here
or si,LFLG_PHYSICAL ; drive is always physical
mov LDT_FLAGS[di],si
mov LDT_ROOTLEN[di],cx ; inherit rootlen from parent
mov LDT_ROOT[di],bx ; root as above
mov ax,fdos_hds_blk ; current block from HDS
mov LDT_BLK[di],ax
mov al,fdos_hds_drv ; current drive we from HDS
mov LDT_DRV[di],al
mov ax,word ptr current_ddsc
mov word ptr LDT_PDT[di],ax
mov ax,word ptr current_ddsc+WORD
mov word ptr LDT_PDT+WORD[di],ax
push ss ! pop es ; now build ASCII path
; lea di,LDT_NAME[di] ; ES:DI -> name
xchg ax,dx
stosw ; plant 'A:'
mov ax,'\'
stosw ; make that 'A:\',0
dec di ; point at NUL
mov fdos_hds_root,0 ; we want to go back to root
mov fdos_pb+6,di ; rebuild into LDT_ at the address
mov fdos_pb+8,es
push ds ! pop es
chdir60:
call hdsblk ; get current block
if JOIN
jnz chdir65 ; if not at root unparse
call check_join ; check if drive is joined to another
jz chdir80 ; at root, unJOIN'd, so exit
; we are at the root of this drive
xchg al,fdos_hds_drv ; update HDS drive so we can force
push es ; an exit next time round
call get_ldt ; now copy the JOIN'd name
push ds ! push es ! pop ds ! pop es
lea si,LDT_NAME+3[bx] ; point to my JOIN data
mov di,offset save_area
call copy_asciiz
push es ! pop ds
pop es
jmps chdir70 ; copy this into place
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -