📄 utils.fdo
字号:
; File : $UTILS.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$
; UTILS.FDO 1.39 94/11/30 13:39:18
; added share_delay function
; UTILS.FDO 1.37 94/07/13 15:42:01
; Change to rename/delete of file open in compatibility modes
; UTILS.FDO 1.36 94/06/28 11:10:10
; Limit ddsc allocation to 1st 255
; UTILS.FDO 1.34 94/04/25 19:33:04
; Reject blank names (ie. all spaces) when parsing path
; We used to die in rebuild_ldt_curdir (GATEWAY problem)
; UTILS.FDO 1.33 93/12/16 13:57:06
; Fix path_prep bug when dir in path doesn't exist
; UTILS.FDO 1.32 93/12/09 23:56:10
; Move non-inherited bit to correct place in file handle
; UTILS.FDO 1.31 93/12/08 03:30:03
; Add extra check to offer_join: consider JOIN B: \FRED, SUBST L: \FRED\FRED
; A CD L:\ would see FRED at the root of B: and change into it, so we
; would end up at \FRED, so we only check if ROOTLEN=2
; UTILS.FDO 1.27 93/11/19 17:45:14
; Fix for SERVER print queue viewing problem
; UTILS.FDO 1.26 93/11/08 16:30:12
; Get dat/time on device handle returns current date/time
; UTILS.FDO 1.25 93/09/14 20:03:42
; Trust LFLG_PHYSICAL
; UTILS.FDO 1.23 93/09/03 20:26:09
; Add "no critical errors" support (int 21/6C)
; UTILS.FDO 1.22 93/07/26 18:11:00
; re-arrange DHNDL_DCNTHI for the benefit of Geoworks
; UTILS.FDO 1.21 93/07/20 22:43:48
; Even fewer checks on int 25/26
; ENDLOG
; General utility include module for FDOS.A86
select_pb2:
;----------
call get_pb2_drive ; get drive from parameter block
; jmp select_unique ; select drive, make HDS unique
select_unique:
;-------------
; entry: AL = drive to select (0-15)
mov byte ptr path_drive,al ; save logical drive
jmp select_logical_drv ; select the drive
logical2physical:
;----------------
; On Entry:
; AL = drive to select
; On Exit:
; AL = appropriate physical drive to select
;
; This routine is called by low level routines (func_ddio, func_getdpb)
; and bypasses the checks for networked/joined drives together with the
; normal media change checks. It does however handle SUBST'd drives.
;
call get_ldt_raw ; ES:BX -> LDT for our drive
jc logical2physical10 ; if we don't have one must be physical
test es:LDT_FLAGS[bx],LFLG_JOINED
jnz logical2physical10 ; joined drive - treat as physical
test es:LDT_FLAGS[bx],LFLG_SUBST
jz logical2physical10 ; as long as we aren't SUBST'd it OK
mov al,es:LDT_NAME[bx] ; get the drive from the ascii name
and al,1fh ; as the drive may require rebuilding
dec ax ; make it zero based
logical2physical10:
ret
Public dbcs_lead
dbcs_lead:
;---------
; Return true if given byte is the first of a double byte character.
; Entry
; al = byte to be tested
; Exit
; Z Flag = 1 - byte is a DBCS lead
; 0 - byte is not a DBCS lead
; Lost
; no registers changed
if KANJI
push si
push bx
push ax
; First get a pointer to the double byte lead table in the COUNTRY info.
mov si, offset DBCS_tbl+2 ; ds:si -> double byte table
; Examine each entry in the table to see if it defines a range that includes
; the given character.
mov bl, al ; bl = byte to be tested
dbcs_loop:
lods ss:ax ; al/ah = start/end of range
test ax, ax ; end of table?
jz dbcs_no ; yes - exit (not in table)
cmp al, bl ; start <= bl?
ja dbcs_loop ; no - try next range
cmp ah, bl ; bl <= end?
jb dbcs_loop ; no - try next range
cmp al, al ; return with Z flag set
jmp dbcs_exit
dbcs_no:
cmp al, 1 ; return with Z flag reset
dbcs_exit:
pop ax
pop bx
pop si
ret
else
test al, al ; force non-0 condition
ret
endif
kanji_eos:
;---------
; entry: ES:DI -> string to find the end of
; exit: ES:DI -> character before NUL byte
mov dx,di ; in case string is empty
kanji_eos1:
mov al,es:[di] ; get next character
test al,al ; is it the final NUL byte
jz kanji_eos9 ; return if NUL found
mov dx,di
inc di ; move to next character
if KANJI
call dbcs_lead ; is this first half of 16-bit char?
jne kanji_eos1 ; skip if normal character
inc di ; else skip 2nd half (should really check)
endif
jmps kanji_eos1 ; loop back for next character
kanji_eos9:
mov di,dx ; ES:DI -> last character
ret ; end of string found
path_chop:
;---------
; entry: ES:DI -> path = "d:\level1\level2\"
; exit: path = "d:\level1\"
mov al,es:[di] ; get next character
test al,al ; end of string?
jz path_chop2 ; yes, string scanned
inc di ; next character
if KANJI
call dbcs_lead ; lead-in of 16-bit character?
jne path_chop1 ; no, normal 8-bit
inc di ; skip hi-byte (should really check)
jmps path_chop ; try again
path_chop1:
endif
call check_slash ; is this a path character
jne path_chop ; loop back if not path character
mov dx,cx ; last but one '/' = last '/'
mov cx,di ; last '/' = current '/'
jmps path_chop ; repeat
path_chop2:
mov di,dx ; ES:DI -> last but one slash + 1
sub ax,ax ; get a NUL byte
stosb ; chop off the last level
ret
Public rebuild_ldt_root
rebuild_ldt_root:
;----------------
; On Entry:
; ES:BX -> LDT_ to rebuild
; fdos_hds = physical root for this drive
; On Exit:
; ES:BX preserved
; LDT_ROOT rebuilt from ASCII LDT_NAME
;
push ds
push es ! pop ds ; DS:BX -> LDT_
push ss ! pop es
mov di,offset temp_ldt ; ES:DI -> temp LDT_
lea si,LDT_NAME+3[bx] ; point to start of pathname
mov cx,LDT_ROOTLEN[bx] ; CX = end of root portion
xor ax,ax ; assume we want root block
sub cx,3 ; skip the 'D:\'
jbe rebuild_ldt_root10 ; nothing to do unless SUBST'd
rep movsb ; copy the root portion of the name
call select_dir ; select this directory
jnc rebuild_ldt_root10
xor ax,ax
mov LDT_ROOTLEN[bx],2 ; force ourselves into the root
mov LDT_NAME+3[bx],al ; as the media has changed
rebuild_ldt_root10:
push ds ! pop es ; ES:BX -> LDT_
pop ds
mov ax,fdos_hds_blk
mov es:LDT_ROOT[bx],ax ; update our root block
if JOIN
mov al,fdos_hds_drv ; and the physical drive
mov es:LDT_DRV[bx],al
endif
ret
rebuild_ldt_curdir:
;------------------
; On Entry:
; ES:BX -> LDT_ to rebuild
; fdos_hds = logical root of this drive
; On Exit:
; ES:BX preserved
; LDT_DRV and LDT_BLK rebuilt from ASCII LDT_NAME
;
push ds
push es ! pop ds ; DS:BX -> LDT_
push ss ! pop es
mov di,offset temp_ldt ; ES:DI -> temp LDT_
mov si,LDT_ROOTLEN[bx] ; SI = end of root portion
lea si,LDT_NAME[bx+si] ; point to subdir entry
lodsb ; get 1st char
call check_slash ; is it a leading '\' ?
je rebuild_ldt_curdir10 ; yes, discard it
dec si ; else leave it alone
rebuild_ldt_curdir10:
test al,al ; anything to do?
jz rebuild_ldt_curdir40 ; no, we are already there
rebuild_ldt_curdir20:
lodsb ! stosb ; copy the string
test al,al ; until we hit the terminating NUL
jnz rebuild_ldt_curdir20
dec di
call select_dir ; select this directory
jnc rebuild_ldt_curdir40
mov si,LDT_ROOTLEN[bx] ; SI = end of root portion
cmp si,3 ; is root real root or a subdir ?
ja rebuild_ldt_curdir30
mov si,3 ; real root, leave '\' alone
rebuild_ldt_curdir30:
mov LDT_NAME[bx+si],0 ; move ASCII to root
rebuild_ldt_curdir40:
push ds ! pop es ; ES:BX -> LDT_
pop ds
mov ax,fdos_hds_blk
mov es:LDT_BLK[bx],ax ; update our curdir block
if JOIN
mov al,fdos_hds_drv ; and the physical drive
mov es:LDT_DRV[bx],al
endif
ret
select_dir:
;----------
; On Entry:
; DS:BX -> LDT
; ES:DI -> end of ASCII path
; temp_ldt contains dir to select
; On Exit:
; DS:BX preserved
; CY set on error, root of original drive reselected
;
mov ax,'.\' ; append a "\." in case it's the root
stosw ; (and so a NULL path)
xor ax,ax
stosb
push ds ! push bx ; make sure LDT survives
push ss ! pop ds ; DS back to SYSDAT
mov si,offset temp_ldt ; ES:SI -> directory to select
call path_prep_next ; try to move into it
if JOIN
call offer_join ; are we opening a JOIN'd drive ?
jnc select_dir20
endif
call finddfcbf ; find the directory entry
jz select_dir10 ; stop if we can't
test DATTS[bx],DA_DIR ; check if directory
jz select_dir10 ; fail if this is a file
push ds ! pop es
lea di,DNAME[bx] ; ES:DI -> ASCII name to open
mov cx,8+3
mov al,' '
repe scasb ; is it all spaces ?
je select_dir10 ; if so reject it
call open_dir
jnc select_dir20
select_dir10:
mov ax,fdos_hds_root ; move to the virtual root
mov fdos_hds_blk,ax
stc ; return error
select_dir20:
pop bx ! pop ds
ret
eject
; Run down the path and parse final name
; exit: ds:dx -> info_fcb parsed at path end
; cf = 1, and al = code on any error
path_prep:
les di,dword ptr fdos_pb+2 ; es:di -> path name
path_prep_ptr:
call path_prep_check ; try to prepare path
jnc path_prep_good ; skip if success
jmp fdos_error ; return error to application
path_prep_drive_error:
; stc ; return CY set
mov ax,ED_DRIVE ; with correct error code
path_prep_good:
ret
path_prep_check:
call get_path_drive ; from asciiz or default
jc path_prep_drive_error ; continue if drive A: - Z:
path_prep_cont:
push di ; DX = drive code (0-15)
push es ; save string address
push ds ! pop es ; ES = SYSDAT
call select_unique ; select the drive and
pop es
pop si ; es:si -> past drive
lods es:al ; get first character
call check_slash ; if '\' or '/' then start at root
jne path_prep_curdir ; else select current directory
push es
call path_prep_root ; fake a '.' entry for the root
pop es
lods es:al ; get next char
dec si ; forget we looked
test al,al ; if just a '\' stop now
jz path_prep_done
call check_slash
jne path_prep_next ; otherwise start processing from root
mov ax,ED_ACCESS ; get correct error code
stc ; and return if \\
ret
path_prep_curdir:
; We need to select the current directory as a start for our operations
dec si ; forget about char we looked at
push es ! push si ; and save position in name
mov al,logical_drv ; get the current logical drive
call get_ldt ; and hence the LDT structures
jc path_prep_curdir30 ; no LDT, leave at physical root
if JOIN
mov al,fdos_hds_drv ; are we on a known drive ?
sub al,es:LDT_DRV[bx] ; (we may be on joined drive)
jne path_prep_curdir10 ; if not better rebuild
cbw ! dec ax ; AX = FFFF
else
mov ax,0FFFFh
endif
cmp ax,es:LDT_BLK[bx] ; do we need to do a rebuild
jne path_prep_curdir20 ; or can we trust the media ?
path_prep_curdir10:
call rebuild_ldt_curdir ; better reselect current dir
path_prep_curdir20:
mov ax,es:LDT_BLK[bx] ; move to current directory block
mov fdos_hds_blk,ax
path_prep_curdir30:
pop si ! pop es ; ES:SI -> name again
path_prep_next:
;--------------
; Called by disk change code to rebuild an HDS_ for a drive after
; media change detected.
; On Entry:
; ES:SI -> pathname to rebuild
; fdos_hds = HDS_ to rebuild
; On Exit:
; CY set if problem (AX=error code)
; ES=DS
;
cmp es:byte ptr [si],0 ; can't have trailing '/' or '\'
je path_prep_error ; return this as an error
mov ax,path_drive
inc ax ; al = drive (one based)
call parse_path ; set up the info_fcb
jc path_prep_error ; skip on any parse error
test al,al ; AL = delimiter
jz path_prep_done ; are we at the end ?
cmp word ptr info_fcb+1,' .'
je path_prep_next ; CHDIR (".") => stay where we are
call check_no_wild ; no wilds cards in path's
je path_prep_error ; skip if wild cards found
if JOIN
push es
push si
call offer_join ; are we opening a JOIN'd drive ?
pop si
pop es
jnc path_prep_next ; if so move on to next stage
endif
push es
push si ; save string address
push ds ! pop es ; ES = local segment
call finddfcbf ; locate the directory entry
pop si
pop es ; restore string address
jz path_prep_error ; no, missing directory in path
test DATTS[bx],DA_DIR ; check if directory
jz path_prep_error ; fail if this is a file
push es ! push si ; save string address
push ds ! pop es ; ES = local segment
if PASSWORD
call check_pwd_any ; check if PW req'd & supplied
endif
call open_dir ; go down one level
pop si ! pop es ; restore string address
jnc path_prep_next ; if open is good, repeat
path_prep_error:
mov ax,ED_PATH ; return code in case of error
stc ; indicate error to caller
ret
path_prep_done:
cmp info_fcb+1,'.' ; is it '.' or '..' ?
jne path_prep_exit ; if so get its full name
if JOIN
call offer_join ; are we opening a JOIN'd drive ?
jnc path_prep_root ; if so move into the dir
endif
call finddfcbf ; find the directory entry
jz path_prep_exit ; stop if we can't
call open_dir ; move into the directory
jc path_prep_error ; stop if we can't
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -