From 80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 Mon Sep 17 00:00:00 2001 From: Rich Turner Date: Fri, 12 Aug 1983 17:53:34 -0700 Subject: MS-DOS v2.0 Release --- v2.0/source/DIR.ASM | 1084 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1084 insertions(+) create mode 100644 v2.0/source/DIR.ASM (limited to 'v2.0/source/DIR.ASM') diff --git a/v2.0/source/DIR.ASM b/v2.0/source/DIR.ASM new file mode 100644 index 0000000..d0bb84f --- /dev/null +++ b/v2.0/source/DIR.ASM @@ -0,0 +1,1084 @@ +; +; 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 + +; +; Input: [Attrib] = attribute to search for +; CH = found attribute +; Output: JZ +; JNZ +; + 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 or JZ +; + POP AX + return +MatchAttributes ENDP + +do_ext + +CODE ENDS + END + \ No newline at end of file -- cgit v1.2.3