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

📄 dkopen.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	TITLE	DKOPEN - DISK OPEN routines
;***
; DKOPEN - Disk open and other utility routines
;
;	Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;
;	The routines in this module are used while opening files
;	in all modes (disk and device files).
;
;******************************************************************************
	INCLUDE switch.inc
	INCLUDE rmacros.inc	; general runtime macros

	UseSeg	_BSS
	UseSeg	RT_TEXT
	UseSeg	ER_TEXT
	UseSeg	NH_TEXT 	
	UseSeg	DV_TEXT 	
	UseSeg	_DATA		

	INCLUDE seg.inc 	; Segment definitions

	INCLUDE baslibma.inc
	INCLUDE files.inc
	INCLUDE devdef.inc
	INCLUDE rtps.inc	; constants shared with QBI
	INCLUDE nhutil.inc	
	INCLUDE string.inc	
	INCLUDE idmac.inc	

	.xall
	.radix	10

;************************************************************************
;
sBegin	_BSS

externB b$FILMOD		
externB b$PATHNAM		
externW b$Buf2			
PATH_LEN EQU b$Buf2		

globalW b$CLOS_HANDLE,0		; file handle for B$TEST_CLOSE to close
globalW b$CLOS_FDB,0		; FDB for B$TEST_CLOSE to close the file
				; and deallocate the FDB.

externB b$LOCKTYPE
externB b$ACCESS

sEnd	_BSS
;
;************************************************************************


;************************************************************************
;
sBegin	ER_TEXT
externNP	B$ERR_AFE	
externNP	B$ERR_BFM	
externNP	B$ERR_FNF
externNP	B$ERR_ACD
externNP	B$ERR_TMF
externNP	B$ERR_IOE
externNP	B$ERR_FAO
externNP	B$ERR_PNF	

sEnd	ER_TEXT
;
;************************************************************************

;************************************************************************
;
sBegin	NH_TEXT 			
	externNP	B$LHALC_CPCT	; compact LH and allocate entry
	externNP	B$LHDALC	; deallocate FDB
	externNP	B$STDALCTMP	
sEnd	NH_TEXT 			

sBegin	DV_TEXT 			
	externNP	B$DOS3CHECK	
	externNP	B$OPENIT	
sEnd	DV_TEXT 			

sBegin	RT_TEXT

externNP	B$GETEXTERR	; Get extended error, if available
externNP	B$CLOSE
externNP	B$LHNXTFIL	
externNP	B$FILESIZE
externNP	B$SeekFromStart 
externNP	B$DISK_SINP	
externNP	B$OpenErr	
;
;************************************************************************

assumes cs,RT_TEXT

	SUBTTL	disk OPEN
	page

;***
;  B$DISKOPEN - DISK device-dependent OPEN routine.
;
;Purpose:
;	This routine does the actual opening of the files.
;	It tries to open the file in the mode specified and
;	if that fails it will then try to reopen the file
;	in some of the other modes. (The reopen does not
;	happen if the first try was for READ_ONLY).
;	It also checks to see if it opened a character
;	device and if so sets the appropriate fields in the
;	FDB to reflect this. If the open is in the append mode
;	it seeks to the end of the file and backs up over the
;	first CTRL Z.
;
;Entry:
;
;	AX = output from B$GET_PATHNAME
;	BX = file number
;	CX = record size
;	DX = file name string descriptor (ignored)
;
;Exit:
;	File opened and FDB filled in OR
;	appropriate error message given.
;
;Uses:
;	AX, BX, CX, DX
;
;****


cProc	B$DISKOPEN,<NEAR,PUBLIC>,<ES,DI>
cBegin

	PUSH	DS		; ES = DS
	POP	ES

;	First, allocate FDB with extra space for all disk files and
;	space for the field buffer for random files.

	INC	CX		; LEN specified?
	LOOP	LEN_SPEC	; brif so -- use specified record length
	MOV	CX,REC_LENGTH	; CX = default random record length
	TEST	b$FILMOD,MD_RND ; random mode?
	JNZ	LEN_SPEC	; brif so -- use random default
	MOV	CX,SEQ_BUF_LEN	; use default sequential buffer length
LEN_SPEC:			
	TEST	b$FILMOD,MD_BIN ; BINARY mode?
	JZ	NOT_BIN		; brif not -- keep specified buffer size
	MOV	CX,1		; buffer size = 1
NOT_BIN:			
	PUSH	CX		; save buffer size
	PUSH	BX		; save file number
	PUSH	AX		; save output from B$GET_PATHNAME
	MOV	DI,OFFSET DGROUP:b$PATHNAM ; DI = pathname address for
				; B$CHKFOPEN
	XOR	SI,SI		; clear SI for B$AnalyzeErr, so it doesn't
				; try to access a non-existing FDB.

;	If the file is not random or sequential input, check if
;	the file has been already opened in BASCOM.  If CF = 1, then
;	give FILE ALREADY OPEN error.

	TEST	b$FILMOD,MD_RND+MD_SQI+MD_BIN ; random or binary or seqin?
	JNZ	DOPEN_NOCHK	;if so, then jump
	cCALL	B$CHKFOPEN	; check if already open -- give
				;  "file already open" error if so
DOPEN_NOCHK:

;	Determine the initial file access for the open.  The accesses
;	attempted are based on the file mode and ACCESS clause type:

;	[b$FILMOD] = MD_SQI (sequential input)
;	    [b$ACCESS] = ACCESS_NONE	read
;	    [b$ACCESS] = ACCESS_READ	read

;	[b$FILMOD] = MD_SQO (sequential output)
;	    [b$ACCESS] = ACCESS_NONE	write
;	    [b$ACCESS] = ACCESS_WRITE	write

;	[b$FILMOD] = MD_RND OR MD_BIN (random or binary)	[13]
;	    [b$ACCESS] = ACCESS_NONE	read/write, write, read
;	    [b$ACCESS] = ACCESS_READ	read
;	    [b$ACCESS] = ACCESS_WRITE	write
;	    [b$ACCESS] = ACCESS_READ_WRITE	read/write

;	[b$FILMOD] = MD_APP (append)
;	    [b$ACCESS] = ACCESS_NONE	read/write, write
;	    [b$ACCESS] = ACCESS_WRITE	write

	XOR	BX,BX		;assume 0 for OPEN read
	CMP	[b$ACCESS],ACCESS_READ ;test if ACCESS READ
	JE	DOPEN_OPEN	;if so, jump to open file
	CMP	b$FILMOD,MD_SQI ; test if input sequential
	JE	DOPEN_OPEN	;if so, jump to open file
	INC	BX		;assume 1 for OPEN write
	CMP	[b$ACCESS],ACCESS_WRITE ;test if ACCESS WRITE
	JE	DOPEN_OPEN	;if so, jump to open file
	CMP	b$FILMOD,MD_SQO ; test if output sequential
	JE	DOPEN_OPEN	;if so, jump to open file
	INC	BX		;otherwise, read/write file
				;  The file is opened with the mode in BX.	It is either
;	opened initially in the mode computed above, or reopened
;	in the next mode determined from the above table after
;	an open failure.

;
;		File
;-----------------------------------------------
;    |	doesn't  |      exists     |  OpenFlag
;    |	exist	 |		   |	in HEX
;-----------------------------------------------
;sqi |	fail	 |	open file  |	01
;sqo |	create	 |	replace    |	12
;rnd |	create	 |	open file  |	11
;-----------------------------------------------
;

DOPEN_OPEN:

	MOV	DI,BX		;save mode for possible reopen
	CALL	DiskOpenHelper	; open file with mode in BX
				; AX = error code if error
				; BX = file handle
	JC	OPEN_FAILED	; brif open failed

;	The OPEN succeeded.  The only error condition that could
;	occur is if a file is to be appended with only a write
;	access.  If this is so, close the file and fake a
;	PATH/FILE ACCESS ERROR.

	CMP	b$FILMOD,MD_APP ; test if append mode
	JNE	JMP_DOPEN_PROCESS ; brif not -- process open
	CMP	DI,1		;test if WRITE access
	JNE	JMP_DOPEN_PROCESS ; brif not -- process open
	CALL	DO_CLOSE	; file is append with write mode and
				;exists cannot be accessed...
	JMP	SHORT ERCACD	; path/file access error

;	The OPEN failed.  If mode was sequential input, either give
;	correct access error (PERMISSION DENIED if sharing conflict
;	or PATH/FILE ACCESS ERROR if directory access conflict) or
;	FILE NOT FOUND.

OPEN_FAILED:			
	CMP	AX,ERRPNF	;test if PATH NOT FOUND error
	JE	ERCPNF		;if so, then report it
	CMP	b$FILMOD,MD_SQI ; test if input sequential
	JNE	DOPEN_NOT_SQI_FAIL ;if not, then jump
	CMP	AX,ERRACD	; test if access error
	JE	DOPEN_ACCESS_ERROR ;if so, jump to process it
ERCFNF:				
	JMP	B$ERR_FNF	;jump to FILE NOT FOUND

ERCPNF:				
	JMP	B$ERR_PNF	; jump to PATH NOT FOUND

DOPEN_NOT_SQI_FAIL:
	CMP	AX,ERRFNF	; test if FILE NOT FOUND
	JNE	DOPEN_NEXT_ACCESS ;else error forces next one
	MOV	DX,OFFSET DGROUP:b$PATHNAM ; address of file pathname
	XOR	CX,CX		;attributes - none
	MOV	AH,C_CREAT	;create file function
	CALLOS			;and make the DOS call
				; AX = error code or handle
	JC	DOPEN_CREATE_ERROR ; if creation error, jump
	XCHG	BX,AX		; get handle in BX
	CALL	DO_CLOSE	; close the file
	MOV	BX,DI		;get the same access type
	CALL	DiskOpenHelper	; and reopen the file
				; AX = error code if CF
				; BX = file handle
	JNC	DOPEN_PROCESS	;jump if success

;	The OPEN failed with the current access.  If an access
;	failure occurred and the OPEN is allowed to retry using
;	another access ([b$ACCESS]=ACCESS_NONE), determine the
;	new access and retry the OPEN.

DOPEN_NEXT_ACCESS:
	CMP	AX,ERRACD	; test if access error
	JNE	DOPEN_NOT_ACCESS_ERROR ;if not, then branch
	CMP	[b$ACCESS],ACCESS_NONE ;is a retry possible?
	JNE	DOPEN_ACCESS_ERROR ;if not, just process error
	TEST	b$FILMOD,MD_RND+MD_BIN ; test for random or binary modes
	JE	DOPEN_TRY_APPEND_RETRY ; if not, then jump
	OR	DI,DI		;is access READ?
	JE	DOPEN_ACCESS_ERROR ;if so, then jump
	MOV	BX,DI		;get access code
	DEC	BX		;r/w->write or write->read
	JMP	DOPEN_OPEN	;retry random OPEN now

JMP_DOPEN_PROCESS:		; Code is too big and ugly for relative
	JMP	SHORT DOPEN_PROCESS ; jumps to DOPEN_PROCESS.

DOPEN_TRY_APPEND_RETRY:
	CMP	b$FILMOD,MD_APP ; test for append mode
	JNE	DOPEN_ACCESS_ERROR ;jump if not
	CMP	DI,2		;test if read/write
	JNE	DOPEN_ACCESS_ERROR ;jump if not
	MOV	BX,1		;make access WRITE
	JMP	DOPEN_OPEN	;retry append OPEN now

;	OPEN failed with error code 5 (carry set).  Use extended error
;	call (if DOS 3 or later) to determine reported error.
;	"PATH/FILE ACCESS ERROR" is reported when failure is due to
;	directory restriction.	"PERMISSION DENIED" is for DOS 2 or
;	OPEN access conflict.

DOPEN_ACCESS_ERROR:
	JMP	B$OpenErr	; give proper error message, with SI <> FDB.
				; (FL_CHAR bit of FD_FLAGS always clear)

;	Error not access-related.

DOPEN_NOT_ACCESS_ERROR:
	CMP	AX,ERRFNF	; error was FILE NOT FOUND?
	JE	ERCFNF		; brif so
	CMP	b$FILMOD,MD_SQO ; interpreter compatability
	JE	ERCTMF		; brif sequential output -- too many files
ERCACD:				
	JMP	B$ERR_ACD

DOPEN_CREATE_ERROR:		
	CMP	AX,ERRACD	; test if access error
	JNE	DOPEN_NOT_ACCESS_ERROR ; if not, then branch
	CALL	B$GETEXTERR	; get extended error after creation
	JC	ERCTMF		; if DOS 2, then give too many files
	CMP	AX,52H		; test if directory entry creation failed
	JNE	ERCACD		; if not, then path/access error

ERCTMF:				
	JMP	B$ERR_TMF	; too many files

;	OPEN has been completed.  Finish details needed for BASCOM.
;	BX = file handle

DOPEN_PROCESS:
	POP	AX		; AX = output from B$GET_PATHNAME
	POP	DX		; DX = file number
	POP	CX		; restore buffer size
	XCHG	DX,BX		; BX = file #, DX = file handle
	PUSH	DX		; save file handle

				; allocate the FDB, and fill some fields
	PUSH	CX		; save buffer size
	ADD	CX,PATH_LEN	; add extra space for pathname
	MOV	DL,255 		; (DL) = width
				; fields
	MOV	AH,255		; (AH) = all file modes legal
	CALL	B$DEVOPN 	; Allocate file block, set up some fields
	FDB_PTR ES,SI,SI	; (ES:)SI = *FDB
	POP	CX		; get back buffer size
	MOV	FileDB.FD_VRECL,CX  ; set record length/buffer size

	LEA	DI,FileDB.FD_BUFFER ; ES:DI = address to put pathname in the
	ADD	DI,CX		;		FDB (after I/O buffer)
	MOV	CX,PATH_LEN	; CX = length of pathname (including null)
	PUSH	SI		; save FDB address
	MOV	SI,OFFSET DGROUP:b$PATHNAM ; DS:SI = pathname address
	REP	MOVSB		; and copy pathname into FDB
	POP	SI		; SI = FDB address
	POP	BX		; BX = file handle

	MOV	FileDB.FD_HANDLE,BX ; save file handle
	OR	FileDB.FD_FLAGS,FL_NEOF ;set flag for no EOF
	mov	al,0
	callos	ioctl		;discover whether character device
	mov	al,dl
	test	al,fl_char	;Is it a device?
	jz	nochar		;Brif not a character device

	AND	AL,FL_CHAR+FL_CONOUT+FL_CONINP ; Clean all bits except
				; FL_CHAR, FL_CONINP, and FL_CONOUT
	OR	FileDB.FD_FLAGS,AL  ;update FDB flags

	mov	al,1
	or	dx,32		; set raw - preserve bits
	mov	dh,0		; Must set high byte to zero !
	CALLOS	IOCTL,ERCIOE	; set raw mode -- I/O error upon failure

				;Don't make CON out RAW if DOS 2.+
	TEST	b$FILMOD,MD_RND+MD_BIN ; random or binary char device?
	JNZ	NOCHAR		; brif so -- these files have a buffer size
	MOV	FileDB.FD_VRECL,1 ;yes, set block size to one
	CMP	b$FILMOD,MD_APP ; if append, convert to MD_SQO
	jne	nochar
	MOV	b$FILMOD,MD_SQO 

nochar:
	MOV	AL,b$FILMOD	
	mov	FileDB.FD_MODE,al ;set mode
	TEST	FileDB.FD_FLAGS,FL_CHAR ; char device?
	JNZ	NoTruncate	; brif so -- don't truncate file
	TEST	AL,MD_SQO	; output?
	JZ	NoTruncate	; brif not -- don't truncate file
	OR	FileDB.FD_FLAGS,FL_TRUNC ; truncate file upon first write
NoTruncate:			
	cmp	al,MD_APP	; is it append?
	JNE	OpenExit	; brif not -- exit
	cCall	B$FILESIZE	; seek to end of file [DX|AX] = file size/pos
	MOV	CX,AX		; [DX|CX] = file size
	OR	AX,DX		; empty file?
	JZ	EmptyApp	; brif so -- don't seek back

;	An empty file opened by BASCOM10 has a 1A (^Z) at the begining of
;	a block of 128 characters which constitutes the file. Before this
;	change the SEEK routine ]was seeking to one past the end of 128
;	characters thereby retaining a ^Z at the beginning.  The new
;	algorithm first seeks to the LAST BLOCK of 128 characters and
;	then searches for the first available ^Z or end of file as the
;	case may be and starts appending from that point.

	SUB	CX,128		; get the last block of 128
	SBB	DX,0		; characters
	JNB	appfi1		;brif file is more than 128 chars
	XOR	CX,CX		; set postion to zero
	XOR	DX,DX		
appfi1:				; [DX|CX] = new position
	CALL	B$SeekFromStart ; position file pointer ([DX|AX] = result)
	XCHG	AX,CX		; [DX|CX] = file position

	MOV	b$CLOS_FDB,SI	; deallocate FDB and close file if error
	CALL	B$DISK_SINP	; read a char.  Destroys AX.
	MOV	b$CLOS_FDB,0	; finished with critical section

	JB	appfi2		; brif got a ctrl z
	ADD	CX,1		; check the next guy
	ADC	DX,0		
	JMP	SHORT appfi1	; loop around

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -