⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utils.fdo

📁 一个dos操作系统DRDOS的源码
💻 FDO
📖 第 1 页 / 共 5 页
字号:
;    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 + -