MS-DOS/v2.0/source/DIR.ASM

1084 lines
29 KiB
NASM
Raw Permalink Normal View History

1983-08-13 01:53:34 +01:00
;
; Directory routines for MSDOS
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
TITLE DIR - Directory and path cracking
NAME Dir
i_need NoSetDir,BYTE
i_need EntFree,WORD
i_need DirStart,WORD
i_need LastEnt,WORD
i_need ClusNum,WORD
i_need CurBuf,DWORD
i_need ThisFCB,DWORD
i_need Attrib,BYTE
i_need DelAll,BYTE
i_need VolID,BYTE
i_need Name1,BYTE
i_need ThisDPB,DWORD
i_need EntLast,WORD
i_need Creating,BYTE
i_need SecClusPos,BYTE
i_need ClusFac,BYTE
i_need NxtClusNum,WORD
i_need DirSec,WORD
i_need DriveSpec,BYTE
i_need Device_availability,BYTE
i_need RootStart,BYTE
i_need DevString,BYTE
i_need DevStrLen,BYTE
SUBTTL BUILDDIR,NEWDIR -- ALLOCATE DIRECTORIES
PAGE
procedure BUILDDIR,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; ES:BP Points to DPB
; [THISFCB] Set if using NEWDIR entry point
; [LASTENT] current last valid entry number in directory if no free
; entries
; Function:
; Grow directory if no free entries and not root
; Outputs:
; CARRY SET IF FAILURE
; ELSE
; AX entry number of new entry
; If a new dir [DIRSTART],[CLUSFAC],[CLUSNUM],[DIRSEC] set
; AX = first entry of new dir
; GETENT should be called to set [LASTENT]
MOV AX,[ENTFREE]
CMP AX,-1
JNZ GOTRET
CMP [DIRSTART],0
JNZ NEWDIR
STC
return ; Can't grow root
entry NEWDIR
MOV BX,[DIRSTART]
OR BX,BX
JZ NULLDIR
invoke GETEOF
NULLDIR:
MOV CX,1
invoke ALLOCATE
retc
MOV DX,[DIRSTART]
OR DX,DX
JNZ ADDINGDIR
call SETDIRSRCH
MOV [LASTENT],-1
JMP SHORT GOTDIRREC
ADDINGDIR:
CMP [CLUSNUM],0FF8H
JB NOTFIRSTGROW
MOV [CLUSNUM],BX
NOTFIRSTGROW:
MOV DX,BX
XOR BL,BL
invoke FIGREC
GOTDIRREC:
MOV CL,ES:[BP.dpb_cluster_mask]
INC CL
XOR CH,CH
ZERODIR:
PUSH CX
MOV AL,0FFH
invoke GETBUFFR
MOV CX,ES:[BP.dpb_sector_size]
PUSH ES
LES DI,[CURBUF]
PUSH DI
ADD DI,BUFINSIZ
XOR AX,AX
SHR CX,1
REP STOSW
JNC EVENZ
STOSB
EVENZ:
POP DI
INC AL
MOV ES:[DI.BUFDIRTY],AL
POP ES
POP CX
INC DX
LOOP ZERODIR
MOV AX,[LASTENT]
INC AX
GOTRET:
CLC
return
BUILDDIR ENDP
;
; set up a . and .. directory entry for a directory
;
procedure SETDOTENT,NEAR
ASSUME DS:DOSGROUP
MOV CX,4
MOV AX,2020H
REP STOSW
STOSB
MOV SI,WORD PTR [THISFCB]
MOV AL,attr_directory
STOSB
ADD DI,10
MOV AX,[SI.fcb_FTIME]
STOSW
MOV AX,[SI.fcb_FDATE]
STOSW
MOV AX,DX
STOSW
XOR AX,AX
STOSW
STOSW
return
SETDOTENT ENDP
SUBTTL GETFILE, GETNAME, FINDNAME -- LOOK FOR A FILE
PAGE
procedure SEARCH,near
entry GETFILE
ASSUME DS:NOTHING,ES:NOTHING
; Same as GETNAME except ES:DI points to FCB on successful return
invoke MOVNAME
retc
PUSH DX
PUSH DS
CALL FINDNAME
POP ES
POP DI
return
entry GETNAME
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS,DX point to FCB
; Function:
; Find file name in disk directory. First byte is
; drive number (0=current disk). "?" matches any
; character.
; Outputs:
; Carry set if file not found
; ELSE
; Zero set if attributes match (always except when creating)
; AH = Device ID (bit 7 set if not disk)
; [THISDPB] = Base of drive parameters
; DS = DOSGROUP
; ES = DOSGROUP
; [CURBUF+2]:BX = Pointer into directory buffer
; [CURBUF+2]:SI = Pointer to First Cluster field in directory entry
; [CURBUF] has directory record with match
; [NAME1] has file name
; All other registers destroyed.
invoke MOVNAME
ASSUME ES:DOSGROUP
retc ; Bad file name?
entry FINDNAME
PUSH SS
POP DS
ASSUME DS:DOSGROUP
invoke DEVNAME
JC FindEntry
invoke BUILDFCB
return
ASSUME ES:NOTHING
; NOTE THE FALL THROUGH
SUBTTL FINDENTRY -- LOOK FOR AN ENTRY
PAGE
entry FindEntry
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; [THISDPB] set
; [SECCLUSPOS] = 0
; [DIRSEC] = Starting directory sector number
; [CLUSNUM] = Next cluster of directory
; [CLUSFAC] = Sectors/Cluster
; [NAME1] = Name to look for
; Function:
; Find file name in disk directory.
; "?" matches any character.
; Outputs:
; Carry set if name not found
; ELSE
; Zero set if attributes match (always except when creating)
; AH = Device ID (bit 7 set if not disk)
; [THISDPB] = Base of drive parameters
; DS = DOSGROUP
; ES = DOSGROUP
; [CURBUF+2]:BX = Pointer into directory buffer
; [CURBUF+2]:SI = Pointer to First Cluster field in directory entry
; [CURBUF] has directory record with match
; [NAME1] has file name
; [LASTENT] is entry number of the entry
; All other registers destroyed.
CALL STARTSRCH
CMP BYTE PTR [ATTRIB],attr_volume_id
; Looking for vol ID only ?
JNZ NOTVOLSRCH ; No
CALL SETROOTSRCH ; Yes force search of root
NOTVOLSRCH:
CALL GETENTRY
entry Srch
PUSH DS
MOV DS,WORD PTR [CURBUF+2]
ASSUME DS:NOTHING
MOV AH,BYTE PTR [BX]
OR AH,AH ; End of directory?
JZ FREE
CMP AH,BYTE PTR [DELALL] ; Free entry?
JZ FREE
TEST BYTE PTR [BX+11],attr_volume_id
; Volume ID file?
JZ CHKFNAM ; NO
INC BYTE PTR [VOLID]
CHKFNAM:
MOV SI,BX
PUSH SS
POP ES
ASSUME ES:DOSGROUP
MOV DI,OFFSET DOSGROUP:NAME1
MOV CX,11
WILDCRD:
REPE CMPSB
JZ FOUND
CMP BYTE PTR ES:[DI-1],"?"
JZ WILDCRD
POP DS
ASSUME DS:DOSGROUP
entry NEXTENT
LES BP,[THISDPB]
ASSUME ES:NOTHING
CALL NEXTENTRY
JNC SRCH
JMP SHORT SETESRET
FREE:
POP DS
ASSUME DS:DOSGROUP
MOV CX,[LASTENT]
CMP CX,[ENTFREE]
JAE TSTALL
MOV [ENTFREE],CX
TSTALL:
CMP AH,BYTE PTR [DELALL] ; At end of directory?
JZ NEXTENT ; No - continue search
MOV [ENTLAST],CX
STC
JMP SHORT SETESRET
FOUND:
;
; We have a file with a matching name. We must now consider
; the attributes:
; ATTRIB Action
; ------ ------
; Volume_ID Is Volume_ID in test?
; Otherwise If no create then Is ATTRIB+extra superset of test?
; If create then Is ATTRIB equal to test?
;
MOV CH,[SI] ; Attributes of file
POP DS
ASSUME DS:DOSGROUP
MOV AH,BYTE PTR [ATTRIB] ; Attributes of search
TEST CH,attr_volume_id ; Volume ID file?
JZ check_one_volume_id ; Nope check other attributes
TEST AH,attr_volume_id ; Can we find Volume ID?
JZ NEXTENT ; Nope, (not even $FCB_CREATE)
XOR AH,AH ; Set zero flag for $FCB_CREATE
JMP SHORT RETF ; Found Volume ID
check_one_volume_id:
CMP AH,attr_volume_id ; Looking only for Volume ID?
JZ NEXTENT ; Yes, continue search
ADD SI,15
CALL MatchAttributes
JZ RETF
TEST BYTE PTR [CREATING],-1 ; Pass back mismatch if creating
JZ NEXTENT ; Otherwise continue searching
RETF:
LES BP,[THISDPB]
MOV AH,ES:[BP.dpb_drive]
SETESRET:
PUSH SS
POP ES
return
SUBTTL GETENTRY, NEXTENTRY, GETENT -- STEP THROUGH DIRECTORY
PAGE
entry GETENTRY
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; [LASTENT] has directory entry
; ES:BP points to drive parameters
; Function:
; Locates directory entry in preparation for search
; GETENT provides entry for passing desired entry in AX
; A valid search environment MUST exist
; ENDENT,ENTLAST,ENTFREE
; Outputs:
; [CURBUF+2]:BX = Pointer to next directory entry in CURBUF
; [CURBUF+2]:DX = Pointer to first byte after end of CURBUF
; [LASTENT] = New directory entry number
MOV AX,[LASTENT]
entry GETENT
MOV [LASTENT],AX
MOV CL,4
SHL AX,CL
XOR DX,DX
SHL AX,1
RCL DX,1 ; Account for overflow in last shift
MOV BX,ES:[BP.dpb_sector_size]
AND BL,255-31 ; Must be multiple of 32
DIV BX
MOV BX,DX ; Position within sector
PUSH BX
invoke DIRREAD
POP BX
SETENTRY:
MOV DX,WORD PTR [CURBUF]
ADD DX,BUFINSIZ
ADD BX,DX
ADD DX,ES:[BP.dpb_sector_size] ; Always clears carry
return
entry NEXTENTRY
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; Same as outputs of GETENTRY, above
; Function:
; Update BX, and [LASTENT] for next directory entry.
; Carry set if no more.
MOV AX,[LASTENT]
CMP AX,[ENTLAST]
JZ NONE
INC AX
ADD BX,32
CMP BX,DX
JB HAVIT
MOV BL,BYTE PTR [SECCLUSPOS]
INC BL
CMP BL,BYTE PTR [CLUSFAC]
JB SAMECLUS
MOV BX,[NXTCLUSNUM]
CMP BX,0FF8H
JAE NONE
CMP BX,2
JB NONE
JMP GETENT
NONE:
STC
return
HAVIT:
MOV [LASTENT],AX
CLC
return
SAMECLUS:
MOV BYTE PTR [SECCLUSPOS],BL
MOV [LASTENT],AX
PUSH DS
LDS DI,[CURBUF]
ASSUME DS:NOTHING
MOV DX,[DI.BUFSECNO]
INC DX
POP DS
ASSUME DS:DOSGROUP
invoke FIRSTCLUSTER
XOR BX,BX
JMP SETENTRY
Search ENDP
SUBTTL GETCURRDIR -- GET CURRENT DIRECTORY
PAGE
procedure Dir_search,NEAR
entry GETCURRDIR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; ES:BP Points to DPB
; FATREAD should be called before this routine
; Function:
; Find current directory for drive
; If path is bad set current directory to the root
; Outputs:
; DS = DOSGROUP
; [SECCLUSPOS] = 0
; [DIRSTART] = Cluster # of first cluster of directory ( 0 if root)
; [DIRSEC] Set to phys sec # of first sector first cluster of directory
; [CLUSNUM] Set to next cluster
; [CLUSFAC] Sectors/cluster
; Destroys all registers
MOV BX,ES:[BP.dpb_current_dir]
OR BX,BX
JZ SETROOTSRCH
CMP BX,0FF8H
JB SETDIRSRCH
PUSH ES
POP DS
LEA SI,[BP.dpb_dir_text]
CALL ROOTPATH
ASSUME DS:DOSGROUP
JNC SETCURR
MOV ES:[BP.dpb_current_dir],0
SETROOTSRCH:
ASSUME DS:NOTHING,ES:NOTHING
PUSH SS
POP DS
ASSUME DS:DOSGROUP
XOR AX,AX
MOV [DIRSTART],AX
MOV BYTE PTR [SECCLUSPOS],AL
DEC AX
MOV [CLUSNUM],AX
MOV AX,ES:[BP.dpb_first_sector]
MOV DX,ES:[BP.dpb_dir_sector]
SUB AX,DX
MOV BYTE PTR [CLUSFAC],AL
MOV [DIRSEC],DX
return
SETCURR:
ASSUME DS:DOSGROUP
MOV AX,[DIRSTART]
MOV ES:[BP.dpb_current_dir],AX
return
entry SETDIRSRCH
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; BX cluster number of start of directory
; ES:BP Points to DPB
; Function:
; Set up a directory search
; Outputs:
; DS = DOSGROUP
; [DIRSTART] = BX
; [CLUSFAC],[CLUSNUM],[SECCLUSPOS],[DIRSEC] set
; destroys AX,DX
OR BX,BX
JZ SETROOTSRCH
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV [DIRSTART],BX
MOV AL,ES:[BP.dpb_cluster_mask]
INC AL
MOV BYTE PTR [CLUSFAC],AL
invoke UNPACK
MOV [CLUSNUM],DI
MOV DX,BX
XOR BL,BL
MOV BYTE PTR [SECCLUSPOS],BL
invoke FIGREC
MOV [DIRSEC],DX
return
Dir_search ENDP
SUBTTL MAKENODE -- CREATE A NEW NODE
PAGE
procedure MakeNode,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL - attribute to create
; DS:SI Points to asciz path
; [THISFCB] Points to an empty FCB
; Function:
; Make a new node
; Outputs:
; DS=DOSGROUP
; ES:BP Points to DPB
; AX = 0 Success
; AX = 1 A node by this name exists and is a directory
; AX = 2 A new node could not be created error
; AX = 3 A node by this name exists and is a file error
; AX = 4 Bad Path error
; AX = 5 Attribute mismatch error
; CARRY SET IF ERROR
; ELSE
; [DIRSTART],[DIRSEC],[CLUSFAC],[CLUSNUM] set to directory
; containing new node.
; [CURBUF+2]:BX Points to entry
; [CURBUF+2]:SI Points to entry.fcb_firclus
; [ThisFCB] is filled in
; If this is a new entry zero is set and
; Attribute byte in entry is directory
; else a file existed by this name and:
; [NAME1] has name
; entry is not changed in any way
; Destroys all registers
PUSH AX
CALL GetPath
MOV DL,CL ; Save CL info
POP CX
MOV BYTE PTR [ATTRIB],CL
MOV CX,AX
JNC make_exists ; File existed
JNZ make_err_4 ; Path bad
OR DL,DL ; Check "CL" return from GETPATH
JNZ make_type ; Name simply not found
make_err_4:
MOV AL,4 ; case 1 bad path
make_err_ret:
STC
return
make_type:
XOR AL,AL ; nothing exists... assume 0
STC
JMP SHORT make_save
make_exists:
JZ make_exists_dir
MOV AL,3 ; file exists type 3
TEST BYTE PTR [ATTRIB],(attr_volume_id+attr_directory)
JNZ make_err_ret_5 ; but we wanted a volid or dir
OR CH,CH
JS make_dev ; No furthur checks if device
PUSH CX
MOV DS,WORD PTR [CURBUF+2]
MOV CH,[BX+dir_attr] ; Get file attributes
TEST CH,attr_read_only
JNZ make_err_ret_5P ; Cannot create on read only files
CALL MatchAttributes
make_err_ret_5P:
POP CX
JZ make_dev ; Attributes ok
make_err_ret_5:
MOV AL,5 ; Attribute mismatch
JMP SHORT make_err_ret
make_dev:
XOR AL,AL ; Make sure zero set(atts match), carry clear(exists)
MOV AL,3 ; Restore correct value
JMP SHORT make_save
make_exists_dir:
MOV AL,1 ; directory exists
TEST BYTE PTR [ATTRIB],attr_directory
JZ make_err_ret ; we didn't want a directory
CLC
return ; just return
make_save:
PUSH AX
;
; set up for call to NewEntry - it is in the middle of FCB_CREATE
; so we must also pre-push two registers. They will be popped off
; by FCB_CREATE
;
PUSH SS
POP DS
ASSUME DS:DOSGROUP
PUSHF ;Save state of flags
CMP BYTE PTR [NAME1],'.' ;Detect attempt to make '.' or '..'
JNZ NOTLDOT ; Needed because no '.' or '..' in root
POPF
MOV AL,1 ;Force type 2 error
JMP SHORT SET2ERR
NOTLDOT:
POPF
PUSH ES
LES DI,[ThisFCB]
PUSH DS
PUSH DI
PUSH ES
MOV AX,CX
invoke NewEntry
POP DS
POP ES
SET2ERR:
OR AL,AL
POP AX
JZ make_set_fcb
MOV AL,2 ; create failed case 2
STC
return
make_set_fcb:
ASSUME DS:DOSGROUP
PUSH ES
LES DI,[THISFCB]
INC DI
PUSH DS
PUSH SI
MOV DS,WORD PTR [CURBUF+2]
ASSUME DS:NOTHING
MOV SI,BX
MOV CX,11
REP MOVSB
POP SI
POP DS
ASSUME DS:DOSGROUP
POP ES
CMP AL,1
JA make_errors
OR AL,AL
CLC
return
make_errors:
STC
return
MakeNode ENDP
SUBTTL GETPATH -- PARSE AN asciz PATH
PAGE
procedure GETPATH,near
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:SI Points to asciz path
; Function:
; Crack the path
; Outputs:
; [DRIVESPEC] is non zero if a drive was specified
; [ROOTSTART] is non zero if a / started the path
; [ATTRIB] set to attr_directory+attr_hidden+attr_system
; Same as FINDPATH except if path specifies a device in which case
; bit 7 of AH will be set and SI and BX will point DOSGROUP relative
; Destroys all registers
XOR AX,AX
MOV WORD PTR [DRIVESPEC],AX
MOV BYTE PTR [ATTRIB],attr_directory+attr_system+attr_hidden
LODSB
invoke PATHCHRCMP
JZ DEFAULTROOT
MOV AH,AL
LODSB
CMP AL,':'
JZ DRVSPEC
DEC SI
DEC SI
PUSH DS
PUSH SI
PUSH SS
POP ES
CMP BYTE PTR [device_availability],0
JZ NOWDEV
CALL GOTPRESTRING2
JNC BUILDFCBJ ; If no carry then we have a device
NOWDEV:
CALL DEFPATH
GOFIND:
MOV AL,[NoSetDir]
PUSH AX
MOV [NoSetDir],0
CALL GETCURRDIR
POP AX
MOV [NoSetDir],AL
POP SI
POP DS
JMP FINDPATH
DEFPATH:
XOR AL,AL
DRVPATH:
invoke GETTHISDRV
retc ; Bad drive
PUSH SS
POP DS
invoke FATREAD
CLC
return
DEFAULTROOT:
PUSH DS
PUSH SI
CALL DEFPATH
POP SI
POP DS
ROOTSRCH:
INC BYTE PTR [ROOTSTART]
CMP BYTE PTR [SI],0
JZ PATHISNULL
PUSH DS
PUSH SI
PUSH ES ; Save pointer to DPB
CALL CHKDEV
POP ES
JNC BUILDFCBJ
POP SI
POP DS
JMP ROOTPATH
BUILDFCBJ:
POP AX
POP AX
context es
invoke BUILDFCB ; Clears carry sets zero
INC AL ; reset zero
return
DRVSPEC:
INC [DRIVESPEC]
MOV AL,AH
OR AL,20H ; Convert to lower case
SUB AL,60H ; Make A=1
PUSH DS
PUSH SI
PUSH AX
context es
CALL GotPreString2
ASSUME ES:NOTHING
POP AX
JNC BuildFCBJ
CALL DRVPATH
POP SI
POP DS
retc ; Bad drive
LODSB
invoke PATHCHRCMP
JZ ROOTSRCH
DEC SI
PUSH DS
PUSH SI
JMP GOFIND
PATHISNULL:
CALL SETROOTSRCH
ASSUME DS:DOSGROUP
XOR AL,AL ; Set zero (directory) clear carry
return
CHKDEV:
ASSUME DS:NOTHING
PUSH SS
POP ES
MOV DI,OFFSET DOSGROUP:DEVSTRING
XOR CX,CX
MOV CL,DEVSTRLEN
CHKPRESTRING:
REPE CMPSB
JZ GOTPRESTRING
DEC SI
invoke GETLET ; Try convert to upper case
CMP AL,ES:[DI-1]
JZ CHKPRESTRING
NOPRESTRING:
STC
return
GOTPRESTRING:
LODSB
invoke PATHCHRCMP
JNZ NOPRESTRING
GOTPRESTRING2:
MOV DI,OFFSET DOSGROUP:NAME1
MOV CX,9
TESTLOOP:
invoke GETLET
CMP AL,'.'
JZ TESTDEVICE
invoke PATHCHRCMP
JZ NOTDEV
OR AL,AL
JZ TESTDEVICE
STOSB
LOOP TESTLOOP
NOTDEV:
STC
return
TESTDEVICE:
ADD CX,2
MOV AL,' '
REP STOSB
PUSH SS
POP DS
invoke DEVNAME
return
GETPATH ENDP
SUBTTL ROOTPATH, FINDPATH -- PARSE A PATH
PAGE
procedure ROOTPATH,near
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; ES:BP Points to DPB
; FATREAD should be called before this routine
; DS:SI Points to asciz string of path which is assumed to start at
; the root (no leading '/').
; Function:
; Search from root for path
; Outputs:
; Same as FINDPATH
; Destroys all registers
PUSH DS
CALL SETROOTSRCH
POP DS
; NOTE FALL THROUGH
entry FINDPATH
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; ES:BP Points to DPB
; DS:SI Points to asciz string of path (no leading '/').
; [SECCLUSPOS] = 0
; [DIRSEC] = Phys sec # of first sector of directory
; [CLUSNUM] = Cluster # of next cluster
; [CLUSFAC] = Sectors per cluster
; Validate_path should be called before this routine is used,
; unless it is KNOWN the path is good.
; Function:
; Parse path name
; Outputs:
; ES:BP Points to DPB
; Carry set if bad path
; DS:SI Points to path element causing failure
; Zero set
; [DIRSTART],[DIRSEC],[CLUSNUM], and [CLUSFAC] are set up to
; start a search on the last directory
; CL is zero if there is a bad name in the path
; CL is non-zero if the name was simply not found
; [ENTFREE] may have free spot in directory
; [NAME1] is the name.
; CL = 81H if '*'s or '?' in name 1, 80H otherwise
; Zero reset
; File in middle of path or bad name in path
; or path too long or malformed path
; ELSE
; DS = DOSGROUP
; AH = device ID
; [CURBUF] contains directory record with match
; [CURBUF+2]:BX Points into [CURBUF] to start of entry
; [CURBUF+2]:SI Points to fcb_FIRCLUS field for entry
; [NAME1] Has entry name
; If last element is a directory zero is set and:
; [DIRSTART],[SECCLUSPOS],[DIRSEC],[CLUSNUM], and [CLUSFAC]
; are set up to start a search on it.
; If last element is a file zero is reset
; Destroys all registers
PUSH ES
PUSH SI
invoke NAMETRANS
MOV CL,AL
OR CL,80H
POP DI
POP ES
CMP SI,DI
JNZ check_device
JMP BADPATH
check_device:
PUSH DS
PUSH SI
MOV AL,BYTE PTR [SI]
;
; can we see all devices
;
context DS
CMP BYTE PTR [device_availability],0
JZ FindFile
;
; check name1 to see if we have a device...
;
PUSH ES
context ES
invoke DevName ; blast BX
POP ES
ASSUME ES:NOTHING
JC FindFile
OR AL,AL
JNZ FileInPath
POP SI
POP SI
context ES
invoke BuildFCB
INC AL
return
FindFile:
ASSUME ES:NOTHING
PUSH DI ; Start of this element
PUSH ES
PUSH CX
CALL FINDENTRY
POP CX
POP ES
POP DI
JC BADPATHPOP
LDS DI,[CURBUF]
ASSUME DS:NOTHING
TEST BYTE PTR [BX+dir_attr],attr_directory
JZ FileInPath
;
; if we are not setting the directory, then
; check for end of string
;
CMP BYTE PTR [NoSetDir],0
JZ SetDir
MOV DX,DI
MOV AX,DS
POP DI
POP DS
CMP BYTE PTR [DI],0
JZ SetRet
PUSH DS
PUSH DI
MOV DI,DX
MOV DS,AX
SetDir:
MOV DX,[SI]
SUB BX,DI
SUB SI,DI
PUSH BX
PUSH AX
PUSH SI
PUSH CX
PUSH [DI.BUFSECNO]
MOV BX,DX
CALL SETDIRSRCH
ASSUME DS:DOSGROUP
POP DX
XOR AL,AL
invoke GETBUFFR
POP CX
POP SI
POP AX
POP BX
MOV DI,WORD PTR [CURBUF]
ADD SI,DI
ADD BX,DI
POP DI
POP DS
ASSUME DS:NOTHING
MOV AL,[DI]
OR AL,AL
JZ SETRET
INC DI
MOV SI,DI
invoke PATHCHRCMP
JNZ find_bad_name
JMP FINDPATH
find_bad_name:
DEC SI
BADPATH:
XOR CL,CL ; Set zero
STC
return
FILEINPATH:
POP DI
POP DS
MOV AL,[DI]
OR AL,AL
JZ INCRET
MOV SI,DI ; Path too long
STC
return
INCRET:
INC AL ; Reset zero
SETRET:
PUSH SS
POP DS
return
BADPATHPOP:
POP SI
POP DS
MOV AL,[SI]
MOV SI,DI ; Start of bad element
OR AL,AL ; zero if bad element is last, non-zero if path too long
STC
return
ROOTPATH ENDP
SUBTTL STARTSRCH -- INITIATE DIRECTORY SEARCH
PAGE
procedure StartSrch,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; [THISDPB] Set
; Function:
; Set up a search for GETENTRY and NEXTENTRY
; Outputs:
; ES:BP = Drive parameters
; Sets up LASTENT, ENDENT, ENTFREE=ENTLAST=-1, VOLID=0
; Destroys all registers (via FATREAD)
LES BP,[THISDPB]
XOR AX,AX
MOV [LASTENT],AX
MOV BYTE PTR [VOLID],AL ; No volume ID found
DEC AX
MOV [ENTFREE],AX
MOV [ENTLAST],AX
return
StartSrch ENDP
BREAK <MatchAttributes - the final check for attribute matching>
;
; Input: [Attrib] = attribute to search for
; CH = found attribute
; Output: JZ <match>
; JNZ <nomatch>
;
procedure MatchAttributes,near
ASSUME DS:NOTHING,ES:NOTHING
PUSH AX
MOV AL,[Attrib] ; AL <- SearchSet
NOT AL ; AL <- SearchSet'
AND AL,CH ; AL <- SearchSet' and FoundSet
AND AL,attr_all ; AL <- SearchSet' and FoundSet and Important
;
; the result is non-zero if an attribute is not in the search set
; and in the found set and in the important set. This means that we do not
; have a match. Do a JNZ <nomatch> or JZ <match>
;
POP AX
return
MatchAttributes ENDP
do_ext
CODE ENDS
END