1 ; SCCSID = @(#)macro2.asm 1.2 85/07/23
2 TITLE MACRO2
- Pathname
and macro related internal routines
8 ; TransPathNoSet Written
12 ; CopyComponent written
22 ; Created: MZ 4 April 1983
23 ; MZ 18 April 1983 Make TransFCB handle extended FCBs
24 ; AR 2 June 1983 Define/Delete macro for NET redir.
25 ; MZ 3 Nov 83 Fix InitCDS to reset length to 2
26 ; MZ 4 Nov 83 Fix NetAssign to use STRLEN only
27 ; MZ 18 Nov 83 Rewrite string processing for subtree
29 ; BAS 3 Jan 85 ScanPathChar to search for path separator
30 ; in null terminated string.
32 ; MSDOS performs several types of name translation. First, we maintain for
33 ; each valid drive letter the text of the current directory on that drive.
34 ; For invalid drive letters, there is no current directory so we pretend to
35 ; be at the root. A current directory is either the raw local directory
36 ; (consisting of drive:\path) or a local network directory (consisting of
37 ; \\machine\path. There is a limit on the point to which a .. is allowed.
39 ; Given a path, MSDOS will transform this into a real from-the-root path
40 ; without . or .. entries. Any component that is > 8.3 is truncated to
41 ; this and all * are expanded into ?'s.
43 ; The second part of name translation involves subtree aliasing. A list of
44 ; subtree pairs is maintained by the external utility SUBST. The results of
45 ; the previous 'canonicalization' are then examined to see if any of the
46 ; subtree pairs is a prefix of the user path. If so, then this prefix is
47 ; replaced with the other subtree in the pair.
49 ; A third part involves mapping this "real" path into a "physical" path. A
50 ; list of drive/subtree pairs are maintained by the external utility JOIN.
51 ; The output of the previous translation is examined to see if any of the
52 ; subtrees in this list are a prefix of the string. If so, then the prefix
53 ; is replaced by the appropriate drive letter. In this manner, we can
54 ; 'mount' one device under another.
56 ; The final form of name translation involves the mapping of a user's
57 ; logical drive number into the internal physical drive. This is
58 ; accomplished by converting the drive number into letter:CON, performing
59 ; the above translation and then converting the character back into a drive
63 ; curdir_text DB DIRSTRLEN DUP (?) ; text of assignment and curdir
64 ; curdir_flags DW ? ; various flags
65 ; curdir_devptr DD ? ; local pointer to DPB or net device
66 ; curdir_ID DW ? ; cluster of current dir (net ID)
68 ; curdir_end DW ? ; end of assignment
70 ; curdir_netID EQU DWORD PTR curdir_ID
72 ; curdir_isnet EQU 1000000000000000B
73 ; curdir_inuse EQU 0100000000000000B
76 ; There are two main entry points: TransPath and TransFCB. TransPath will
77 ; take a path and form the real text of the pathname with all . and ..
78 ; removed. TransFCB will translate an FCB into a path and then invoke
81 ; Implementation note: CURDIR_End field points to the point in the text
82 ; string where the user may back up to via .. It is the location of a
83 ; separator character. For the root, it points at the leading /. For net
84 ; assignments it points at the end (nul) of the initial assignment:
85 ; A:/ \\foo\bar \\foo\bar\blech\bozo
87 ; A: -> d: /path/ path/ text
89 ; A000 version 4.00 Jan. 1988
93 ; get the appropriate segment definitions
97 CODE SEGMENT BYTE PUBLIC 'CODE'
98 ASSUME
SS:DOSGroup
,CS:DOSGroup
109 I_need Splices
,BYTE ; TRUE => splices are being done.
110 I_need WFP_Start
,WORD ; pointer to beginning of expansion
111 I_need Curr_Dir_End
,WORD ; offset to end of current dir
112 I_need ThisCDS
,DWORD ; pointer to CDS used
113 I_need ThisDPB
,DWORD ; pointer to DPB used
114 I_need NAME1
,11 ; Parse output of NameTrans
115 I_need OpenBuf
,128 ; ususal destination of strings
116 I_need ExtFCB
,BYTE ; flag for extended FCBs
117 I_need Sattrib
,BYTE ; attribute of search
118 I_need fSplice
,BYTE ; TRUE => do splice after canonicalize
119 I_need fSharing
,BYTE ; TRUE => no redirection allowed
120 I_Need NoSetDir
,BYTE ; TRUE => syscall is interested in
121 ; entry, not contents. We splice only
123 I_Need cMeta
,BYTE ; count of meta chars in path
124 I_Need Temp_Var
,WORD ;AN000; variable for temporary use 3/31/KK
125 I_Need DOS34_FLAG
,WORD ;AN000; variable for dos34
126 I_Need NO_FILTER_PATH
,DWORD ;AN000; pointer to orignal path
131 BREAK <TransFCB
- convert an FCB
into a path
, doing substitution
>
134 ; TransFCB - Copy an FCB from DS:DX into a reserved area doing all of the
135 ; gritty substitution.
137 ; Inputs: DS:DX - pointer to FCB
138 ; ES:DI - point to destination
139 ; Outputs: Carry Set - invalid path in final map
140 ; Carry Clear - FCB has been mapped into ES:DI
141 ; Sattrib is set from possibly extended FCB
142 ; ExtFCB set if extended FCB found
143 ; Registers modified: most
145 Procedure TransFCB
,NEAR
146 ASSUME
CS:DOSGroup
,DS:NOTHING
,ES:NOTHING
,SS:DOSGroup
147 PUBLIC MACRO001S
,MACRO001E
152 Context
ES ; get DOSGroup addressability
153 SaveReg
<ES,DI> ; save away final destination
154 LEA DI,FCBTmp
; point to FCB temp area
155 MOV [ExtFCB
],0 ; no extended FCB found
156 MOV [Sattrib
],0 ; default search attributes
157 invoke GetExtended
; get FCB, extended or not
158 JZ GetDrive
; not an extended FCB, get drive
159 MOV AL,[SI-1] ; get attributes
160 MOV [SAttrib
],AL ; store search attributes
161 MOV [ExtFCB
],-1 ; signal extended FCB
163 LODSB ; get drive byte
166 CALL TextFromDrive
; convert 0-based drive to text
168 ; Scan the source to see if there are any illegal chars
170 MOV BX,OFFSET DOSGroup
:CharType
172 ;----------------------------- Start of DBCS 2/13/KK
173 SaveReg
<SI> ;AN000;; back over name, ext
174 MOV CX,8 ;AN000;; 8 chars in main part of name
175 FCBScan:LODSB ;AN000;; get a byte
176 invoke testkanj
;AN000;
179 JCXZ VolidChck
;AN000;; Kanji half char screw up
180 LODSB ;AN000;; second kanji byte
181 jmp short Nextch
;AN000;
183 TEST [SAttrib
],attr_volume_id
;AN000;; volume id ?
184 JZ Badpack
;AN000;; no, error
185 OR [DOS34_FLAG
],DBCS_VOLID
;AN000;; no, error
186 DEC CX ;AN000;; cx=-1
187 INC SI ;AN000;; next char
188 JMP SHORT FCBScango
;AN000;
190 XLAT ES:CharType
;AN000;;get bits
196 ADD CX,3 ;AN000;; Three chars in extension
199 invoke testkanj
;AN000;
202 JCXZ BadPack
;AN000;; Kanji half char problem
203 LODSB ;AN000;; second kanji byte
204 jmp short NextChE
;AN000;
206 XLAT ES:CharType
;AN000;; get bits
210 LOOP FCBScanE
;AN000;
211 ;----------------------------- End of DBCS 2/13/KK
215 SaveReg
<SI> ; back over name, ext
216 FCBScan:LODSB ; get a byte
217 XLAT ES:CharType
; get bits
224 invoke PackName
; crunch the path
225 RestoreReg
<DI,ES> ; get original destination
226 Context
DS ; get DS addressability
227 LEA SI,FCBTmp
; point at new pathname
231 CALL TransPathSet
; convert the path
233 JNC FCBRet
; bye with transPath error code
236 MOV AL,error_path_not_found
239 EndProc TransFCB
,NoCheck
241 BREAK <TransPath
- copy a path
, do string
sub and put
in current dir
>
244 ; TransPath - copy a path from DS:SI to ES:DI, performing component string
245 ; substitution, insertion of current directory and fixing . and ..
246 ; entries. Perform splicing. Allow input string to match splice
249 ; TransPathSet - Same as above except No splicing is performed if input path
252 ; TransPathNoSet - No splicing/local using is performed at all.
254 ; The following anomalous behaviour is required:
256 ; Drive letters on devices are ignored. (set up DummyCDS)
257 ; Paths on devices are ignored. (truncate to 0-length)
258 ; Raw net I/O sets ThisCDS => NULL.
259 ; fSharing => dummyCDS and no subst/splice. Only canonicalize.
264 ; FatRead done on local CDS.
265 ; ValidateCDS done on local CDS.
270 ; set up DummyCDS (ThisCDS)
271 ; canonicalize (sets cMeta)
275 ; if \\ or d:\\ lead then
276 ; set up null CDS (ThisCDS)
277 ; canonicalize (sets cMeta)
280 ; set up dummyCDS (ThisCDS)
281 ; canonicalize (sets cMeta)
284 ; getCDS (sets (ThisCDS) from name)
285 ; validateCDS (may reset current dir)
287 ; canonicalize (set cMeta)
289 ; generate correct CDS (ThisCDS)
294 ; Inputs: DS:SI - point to ASCIZ string path
295 ; DI - point to buffer in DOSGroup
296 ; Outputs: Carry Set - invalid path specification: too many .., bad
297 ; syntax, etc. or user FAILed to I 24.
298 ; WFP_Start - points to beginning of buffer
299 ; Curr_Dir_End - points to end of current dir in path
301 ; Registers modified: most
303 Procedure TransPath
,NEAR
304 ASSUME
CS:DOSGroup
,DS:NOTHING
,ES:NOTHING
,SS:DOSGroup
310 MOV NoSetDir
,AL ; NoSetDir = !fExact;
313 MOV WORD PTR [NO_FILTER_PATH
],SI ;AN000;;IFS. save old path for IFS
314 MOV WORD PTR [NO_FILTER_PATH
+2],DS ;AN000;;IFS.
316 MOV fSplice
,AL ; fSplice = TRUE;
319 MOV Curr_Dir_End
,-1 ; crack from start
321 LEA BP,[DI+TEMPLEN
] ; end of buffer
323 ; if this is through the server dos call, fsharing is set. We set up a
324 ; dummy cds and let the operation go.
326 TEST fSharing
,-1 ; if no sharing
327 JZ CheckUNC
; skip to UNC check
329 ; ES:DI point to buffer
331 CALL DriveFromText
; get drive and advance DS:SI
332 invoke GetThisDrv
; Set ThisCDS and convert to 0-based
334 CALL TextFromDrive
; drop in new
335 LEA BX,[DI+1] ; backup limit
336 CALL Canonicalize
; copy and canonicalize
339 ; Perform splices for net guys.
342 MOV SI,wfp_Start
; point to name
347 Context
DS ; for FATREAD
348 LES DI,ThisCDS
; for fatread
353 MOV AL,error_path_not_found
; Set up for possible bad path error
354 return
; any errors are in Carry flag
357 ; Let the network decide if the name is for a spooled device. It will map
361 MOV WORD PTR ThisCDS
,-1 ; NULL thisCDS
362 CallInstall NetSpoolCheck
,multNet
,35
365 ; At this point the name is either a UNC-style name (prefixed with two leading
366 ; \\s) or is a local file/device. Remember that if a net-spooled device was
367 ; input, then the name has been changed to the remote spooler by the above net
368 ; call. Also, there may be a drive in front of the \\.
371 CALL DriveFromText
; eat drive letter
373 MOV AX,WORD PTR [SI] ; get first two bytes of path
374 Invoke PathChrCmp
; convert to normal form
375 XCHG AH,AL ; swap for second byte
376 Invoke PathChrCmp
; convert to normal form
377 JNZ CheckDevice
; not a path char
378 CMP AH,AL ; are they same?
379 JNZ CheckDevice
; nope
381 ; We have a UNC request. We must copy the string up to the beginning of the
382 ; local machine root path
386 MOVSW ; get the lead \\
387 UNCCpy: LODSB ; get a byte
389 ;----------------------------- Start of DBCS 2/23/KK
390 invoke testkanj
;AN000;
395 JZ UNCTerm
;AN000;; Ignore half kanji error for now
399 ;----------------------------- End of DBCS 2/23/KK
401 invoke UCase
;AN000;; convert the char
403 JZ UNCTerm
; end of string. All done.
404 Invoke PathChrCmp
; is it a path char?
405 MOV BX,DI ; backup position
407 JNZ UNCCpy
; no, go copy
408 CALL Canonicalize
; wham (and set cMeta)
412 ;----------------------------- Start of DBCS 2/23/KK
413 retc
;AN000; Return if error from Canonicalize
415 ; Although Cononicalize has done lots of good things for us it may also have
416 ; done e5 to 05 conversion on the fisrt char following a path sep char which is
417 ; not wanted on a UNC request as this should be left for the remote station.
418 ; The simplest thing to do is check for such conversions and convert them back
420 ; This check loop is also called from the DoFile section of TransPath if the
421 ; file is a remote file. Entry point when called is TP_check05 with the
422 ; inputs/outputs as follows;
423 ; Inputs : ES:DI = Buffer to check for re-conversion
428 MOV DI,WFP_start
;AN000;; ES:DI points to converted string
430 MOV AL,BYTE PTR ES:[DI] ;AN000;; Get character from path
431 OR AL,AL ;AN000;; End of null terminated path?
432 JZ TP_end05
;AN000;; Finished, CF =0 from OR (ret success)
433 invoke testkanj
;AN000;; Kanji lead character?
434 JZ TP_notK
;AN000;; Check for path seperator if not
435 INC DI ;AN000;; Bypass Kanji second byte
436 JMP TP_nxt05
;AN000;; Go to check next character
438 invoke PathChrCmp
;AN000;; Is it a path seperator char?
439 JNZ TP_nxt05
;AN000;; Check next character if not
440 CMP BYTE PTR ES:[DI+1],05 ;AN000;; 05 following path sep char?
441 JNZ TP_nxt05
;AN000;; Check next character if not
442 MOV BYTE PTR ES:[DI+1],0E5h ;AN000;; Convert 05 back to E5
444 INC DI ;AN000;; Point to next char in path
445 JMP TP_check05
;AN000;; Test all chars in path
447 ;----------------------------- End of DBCS 2/23/KK
449 return
; return error code
458 ; Check DS:SI for device. First eat any path stuff
460 POP AX ; retrieve drive info
461 CMP BYTE PTR DS:[SI],0 ; check for null file
463 MOV AL,error_file_not_found
; bad file error
464 STC ; signal error on null input
467 SaveReg
<AX,BP> ; save drive number
468 Invoke CheckThisDevice
; snoop for device
469 RestoreReg
<BP,AX> ; get drive letter back
470 JNC DoFile
; yes we have a file.
472 ; We have a device. AX has drive letter. At this point we may fake a CDS ala
473 ; sharing DOS call. We know by getting here that we are NOT in a sharing DOS
476 MOV fSharing
,-1 ; simulate sharing dos call
477 invoke GetThisDrv
; set ThisCDS and init DUMMYCDS
480 ; Now that we have noted that we have a device, we put it into a form that
481 ; getpath can understand. Normally getpath requires d:\ to begin the input
482 ; string. We relax this to state that if the d:\ is present then the path
483 ; may be a file. If D:/ (note the forward slash) is present then we have
487 MOV AL,'/' ; path sep.
489 invoke StrCpy
; move remainder of string
491 Context
DS ; remainder of OK stuff
494 ; We have a file. Get the raw CDS.
498 invoke GetVisDrv
; get proper CDS
499 MOV AL,error_path_not_found
; Set up for possible bad file error
500 retc
; CARRY set -> bogus drive/spliced
502 ; ThisCDS has correct CDS. DS:SI advanced to point to beginning of path/file.
503 ; Make sure that CDS has valid directory; ValidateCDS requires a temp buffer
504 ; Use the one that we are going to use (ES:DI).
506 SaveReg
<DS,SI,ES,DI> ; save all string pointers.
507 invoke ValidateCDS
; poke CDS amd make everything OK
508 RestoreReg
<DI,ES,SI,DS> ; get back pointers
509 MOV AL,error_path_not_found
; Set up for possible bad path error
510 retc
; someone failed an operation
512 ; ThisCDS points to correct CDS. It contains the correct text of the
513 ; current directory. Copy it in.
516 LDS SI,ThisCDS
; point to CDS
517 MOV BX,DI ; point to destination
518 ADD BX,[SI].curdir_end
; point to backup limit
519 ; LEA SI,[SI].curdir_text ; point to text
520 LEA BP,[DI+TEMPLEN
] ; regenerate end of buffer
522 ;------------------------ Start of DBCS 2/13/KK
525 invoke TestKanj
;AN000;
529 CMP BYTE PTR [SI],0 ;AN000;
533 JMP SHORT GetOrig ;AN000;
538 DEC DI ;AN000;; point to NUL byte
540 ;------------------------ End of DBCS 2/13/KK
542 invoke FStrCpy ; copy string. ES:DI point to end
543 DEC DI ; point to NUL byte
546 ; Make sure that there is a path char at end.
553 ; Now get original string.
556 DEC DI ; point to path char
559 ; BX points to the end of the root part of the CDS (at where a path char
560 ; should be) . Now, we decide whether we use this root or extend it with the
561 ; current directory. See if the input string begins with a leading \
563 CALL PathSep
; is DS:SI a path sep?
564 JNZ PathAssure
; no, DI is correct. Assure a path char
565 OR AL,AL ; end of string?
566 JZ DoCanon
; yes, skip.
568 ; The string does begin with a \. Reset the beginning of the canonicalization
569 ; to this root. Make sure that there is a path char there and advance the
570 ; source string over all leading \'s.
572 MOV DI,BX ; back up to root point.
581 ; DS:SI start at some file name. ES:DI points at some path char. Drop one in
588 ; ES:DI point to the correct spot for canonicalization to begin.
589 ; BP is the max extent to advance DI
590 ; BX is the backup limit for ..
593 CALL Canonicalize ; wham.
594 retc ; badly formatted path.
596 ;--------------------- Start of DBCS 2/13/KK
597 ; Although Cononicalize has done lots of good things for us it may also have
598 ; done e5 to 05 conversion on the fisrt char following a path sep char which is
599 ; not wanted if this a remote file as this should be left for the remote
600 ; station. Check for a leading \\ in the path buffer and call TP_check05 to
601 ; reconvert if found.
603 MOV DI,WFP_start ;AN000;; ES:DI points to string
604 MOV AX,WORD PTR ES:[DI] ;AN000;; Get leading 2 chars from path buffer
605 invoke PathChrCmp ;AN000;; First char a path char?
606 JNZ TP_notremote ;AN000;; Not remote if not.
607 invoke PathChrCmp ;AN000;; Second char a path char?
608 JNZ TP_notremote ;AN000;; Not remote if not
609 CALL TP_check05 ;AN000;; Remote so convert 05 back to e5
610 TP_notremote: ;AN000;
611 ;--------------------- End of DBCS 2/13/KK
614 ; The string has been moved to ES:DI. Reset world to DOS context, pointers
615 ; to wfp_start and do string substitution. BP is still the max position in
619 MOV DI,wfp_start ; DS:SI point to string
620 LDS SI,ThisCDS ; point to CDS
622 ; LEA SI,[SI].curdir_text ; point to text
623 CALL PathPref ; is there a prefix?
624 JNZ DoSplice ; no, do splice
626 ; We have a match. Check to see if we ended in a path char.
629 ;---------------------------- Start of DBCS 2/13/KK
632 MOV SI,WORD PTR ThisCDS ;AN000;; point to CDS
634 MOV AL,BYTE PTR [SI] ;AN000;
635 invoke TESTKANJ ;AN000;
641 POP BX ;AN000;; Last char was KANJI, don't look back
642 JMP SHORT Pathline ;AN000;; for path sep, there isn't one.
649 ;------------------------ End of DBCS 2/13/KK
651 MOV AL,DS:[SI-1] ; last char to match
652 Invoke PathChrCmp ; did we end on a path char? (root)
653 JZ DoSplice ; yes, no current dir here.
655 CMP BYTE PTR ES:[DI],0 ; end at NUL?
657 INC DI ; point to after current path char
658 MOV Curr_Dir_End,DI ; point to correct spot
663 Context DS ; back to DOSGROUP
664 MOV SI,wfp_Start ; point to beginning of string
668 CALL Splice ; replaces in place.
672 ; The final thing is to assure ourselves that a FATREAD is done on the local
676 LES DI,ThisCDS ; point to correct drive
677 TEST ES:[DI].curdir_flags,curdir_isnet
678 retnz ; net, no fatread necessary
683 MOV AL,error_path_not_found ; Set up for possible bad path error
684 Done: return ; any errors in carry flag.
687 BREAK <Canonicalize - copy a path and remove . and .. entries>
690 ; Canonicalize - copy path removing . and .. entries.
692 ; Inputs: DS:SI - point to ASCIZ string path
693 ; ES:DI - point to buffer
694 ; BX - backup limit (offset from ES) points to slash
696 ; Outputs: Carry Set - invalid path specification: too many .., bad
699 ; DS:DI - advanced to end of string
700 ; ES:DI - advanced to end of canonicalized form after nul
701 ; Registers modified: AX CX DX (in addition to those above)
703 Procedure Canonicalize,NEAR
704 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
706 ; We copy all leading path separators.
708 LODSB ; while (PathChr (*s))
711 JNZ CanonDec0 ; 2/19/KK
715 CMP DI,BP ; if (d > dlim)
716 JAE CanonBad ; goto error;
718 JMP Canonicalize ; *d++ = *s++;
720 CanonDec0: ;AN000; 2/19/KK
721 ; mov cs:Temp_Var,di ;AN000; 3/31/KK
726 ; Main canonicalization loop. We come here with DS:SI pointing to a textual
727 ; component (no leading path separators) and ES:DI being the destination
732 ; If we are at the end of the source string, then we need to check to see that
733 ; a potential drive specifier is correctly terminated with a path sep char.
734 ; Otherwise, do nothing
737 CMP [SI],AL ; if (*s == 0) {
740 call chk_last_colon ;AN000; 2/18/KK
742 CMP BYTE PTR ES:[DI-1],':' ; if (d[-1] == ':')
745 MOV AL,'\' ; *d++ = '\';
753 ;---------------- Start of DBCS 2/18/KK
754 chk_last_colon proc
;AN000;
758 mov si,[WFP_START
] ;AN000;;PTM. for cd .. use beginning of buf
759 cmp si,di ;AN000;; no data stored ?
760 jb CLC02
;AN000;;PTM. for cd ..
761 inc si ;AN000;; make NZ flag
762 JMP SHORT CLC09
;AN000;
771 CMP BYTE PTR ES:[DI-1],':' ;AN000;; if (d[-1] == ':')
774 mov al,es:[si] ;AN000;
776 invoke testkanj
;AN000;
785 chk_last_colon endp
;AN000;
786 ;---------------- Endt of DBCS 2/18/KK
790 CALL ScanPathChar
; check for path chars in rest of string
791 MOV AL,error_path_not_found
; Set up for bad path error
792 JZ PathEnc
; path character encountered in string
793 MOV AL,error_file_not_found
; Set bad file error
798 ; We have a textual component that we must copy. We uppercase it and truncate
802 CALL CopyComponent
; if (!CopyComponent (s, d))
805 ; We special case the . and .. cases. These will be backed up.
807 CMP WORD PTR ES:[DI],'.' + (0 SHL 8)
809 CMP WORD PTR ES:[DI],'..'
812 Skip1: CALL SkipBack
; SkipBack ();
813 MOV AL,error_path_not_found
; Set up for possible bad path error
817 ; We have a normal path. Advance destination pointer over it.
822 ; We have successfully copied a component. We are now pointing at a path
823 ; sep char or are pointing at a nul or are pointing at something else.
824 ; If we point at something else, then we have an error.
828 JNZ CanonBad
; something else...
830 ; Copy the first path char we see.
833 Invoke PathChrCmp
; is it path char?
834 JNZ CanonDec
; no, go test for nul
835 CMP DI,BP ; beyond buffer end?
836 JAE CanonBad
; yep, error.
837 STOSB ; copy the one byte
839 ; Skip all remaining path chars
842 LODSB ; get next byte
843 Invoke PathChrCmp
; path char again?
844 JZ CanonPathLoop
; yep, grab another
846 JMP CanonLoop
; go copy component
849 BREAK <PathSep
- determine
if char is a path separator
>
852 ; PathSep - look at DS:SI and see if char is / \ or NUL
853 ; Inputs: DS:SI - point to a char
854 ; Outputs: AL has char from DS:SI (/ => \)
855 ; Zero set if AL is / \ or NUL
856 ; Zero reset otherwise
857 ; Registers modified: AL
859 Procedure PathSep
,NEAR
860 ASSUME
CS:DOSGroup
,DS:NOTHING
,ES:NOTHING
,SS:DOSGroup
861 MOV AL,[SI] ; get the character
862 entry PathSepGotCh
; already have character
863 OR AL,AL ; test for zero
864 retz
; return if equal to zero (NUL)
865 invoke PathChrCmp
; check for path character
866 return
; and return HIS determination
869 BREAK <SkipBack
- move backwards to a path separator
>
872 ; SkipBack - look at ES:DI and backup until it points to a / \
873 ; Inputs: ES:DI - point to a char
874 ; BX has current directory back up limit (point to a / \)
875 ; Outputs: ES:DI backed up to point to a path char
876 ; AL has char from output ES:DI (path sep if carry clear)
877 ; Carry set if illegal backup
879 ; Registers modified: DI,AL
881 Procedure SkipBack
,NEAR
882 ASSUME
CS:DOSGroup
,DS:NOTHING
,ES:NOTHING
,SS:DOSGroup
884 ;-------------------------- Start of DBCS 2/13/KK
890 MOV SI,BX ;AN000;; DS:SI -> start of ES:DI string
891 MOV CX,DI ;AN000;; Limit of forward scan is input DI
893 invoke PathChrCmp
;AN000;
894 JNZ SkipBadP
;AN000;; Backup limit MUST be path char
897 MOV DI,BX ;AN000;; Init backup point to backup limit
900 JAE SkipOK
;AN000;; Done, DI is correct backup point
902 invoke Testkanj
;AN000;
904 lodsb ;AN000;; Skip over second kanji byte
907 invoke PathChrCmp
;AN000;
908 JNZ Skiplp
;AN000;; New backup point
909 MOV DI,SI ;AN000;; DI point to path sep
913 MOV AL,ES:[DI] ;AN000;; Set output AL
914 CLC ;AN000;; return (0);
924 ;-------------------------- End of DBCS 2/13/KK
926 CMP DI,BX ; while (TRUE) {
927 JB SkipBad
; if (d < dlim)
929 MOV AL,ES:[DI] ; if (pathchr (*--d))
930 invoke PathChrCmp
; break;
936 MOV AL,error_path_not_found
; bad path error
941 Break <CopyComponent
- copy
out a
file path component
>
944 ; CopyComponent - copy a file component from a path string (DS:SI) into ES:DI
946 ; Inputs: DS:SI - source path
947 ; ES:DI - destination
948 ; ES:BP - end of buffer
949 ; Outputs: Carry Set - too long
950 ; Carry Clear - DS:SI moved past component
951 ; CX has length of destination
952 ; Registers modified: AX,CX,DX
954 Procedure CopyComponent
,NEAR
955 ASSUME
CS:DOSGroup
,DS:NOTHING
,ES:NOTHING
,SS:DOSGroup
956 CopyBP EQU
WORD PTR [BP]
957 CopyD EQU
DWORD PTR [BP+2]
958 CopyDoff EQU
WORD PTR [BP+2]
959 CopyS EQU
DWORD PTR [BP+6]
960 CopySoff EQU
WORD PTR [BP+6]
961 CopyTemp EQU
BYTE PTR [BP+10]
962 SUB SP,14 ; room for temp buffer
963 SaveReg
<DS,SI,ES,DI,BP>
968 CMP AL,AH ; if ((*d++=*s++) == '.') {
970 CALL PathSep
; if (!pathsep(*s))
973 LODSB ; if ((*d++=*s++) != '.'
978 JNZ CopyBad
; || !pathsep (*s))
979 NulTerm: ; return -1;
980 XOR AL,AL ; *d++ = 0;
983 JMP SHORT GoodRet
; }
986 Invoke NameTrans
; s = NameTrans (s, Name1);
987 CMP SI,CopySOff
; if (s == CopySOff)
988 JZ CopyBad
; return (-1);
989 TEST fSharing
,-1 ; if (!fSharing) {
991 AND DL,1 ; cMeta += fMeta;
992 ADD cMeta
,DL ; if (cMeta > 0)
993 JG CopyBad
; return (-1);
995 OR DL,DL ; if (cMeta == 0 && fMeta == 0)
996 JZ CopyBadPath
; return (-1);
1000 MOV SI,OFFSET DOSGroup
:NAME1
1003 Invoke PackName
; PackName (Name1, temp);
1005 Invoke StrLen
; if (strlen(temp)+d > bp)
1009 JAE CopyBad
; return (-1);
1010 MOV SI,DI ; strcpy (d, temp);
1015 JMP SHORT CopyEnd
; return 0;
1018 CALL ScanPathChar
; check for path chars in rest of string
1019 MOV AL,error_file_not_found
; Set up for bad file error
1023 MOV AL,error_path_not_found
; Set bad path error
1025 RestoreReg
<BP,DI,ES,SI,DS>
1027 ADD SP,14 ; reclaim temp buffer
1032 EndProc CopyComponent
,NoCheck
1034 Break <Splice
- pseudo mount by string substitution
>
1037 ; Splice - take a string and substitute a prefix if one exists. Change
1038 ; ThisCDS to point to physical drive CDS.
1039 ; Inputs: DS:SI point to string
1040 ; NoSetDir = TRUE => exact matches with splice fail
1041 ; Outputs: DS:SI points to thisCDS
1042 ; ES:DI points to DPB
1043 ; String at DS:SI may be reduced in length by removing prefix
1044 ; and substituting drive letter.
1045 ; CX = 0 If no splice done
1047 ; ThisCDS points to proper CDS if spliced, otherwise it is
1049 ; ThisDPB points to proper DPB
1050 ; Registers modified: DS:SI, ES:DI, BX,AX,CX
1052 Procedure Splice
,NEAR
1053 ASSUME
CS:DOSGroup
,DS:NOTHING
,ES:NOTHING
,SS:DOSGroup
1056 SaveReg
<<WORD PTR ThisCDS
>,<WORD PTR ThisCDS
+2>> ; TmpCDS = ThisCDS
1059 XOR AX,AX ; for (i=1; s = GetCDSFromDrv (i); i++)
1061 invoke GetCDSFromDrv
1064 TEST [SI.curdir_flags
],curdir_splice
1065 JZ SpliceScan
; if ( Spliced (i) ) {
1067 CALL PathPref
; if (!PathPref (s, d))
1071 JMP SpliceScan
; continue;
1073 CMP BYTE PTR ES:[DI],0 ; if (*s || NoSetDir) {
1078 MOV SI,DI ; p = src + strlen (p);
1081 CALL TextFromDrive1
; src = TextFromDrive1(src,i);
1085 ADD AX,DI ; curdirend += src-p;
1089 CMP BYTE PTR [SI],0 ; if (*p)
1090 JNZ SpliceCopy
; *src++ = '\\';
1093 SpliceCopy: ; strcpy (src, p);
1095 ADD SP,4 ; throw away saved stuff
1096 OR CL,1 ; signal splice done.
1097 JMP SHORT DoSet ; return;
1099 ASSUME DS:NOTHING ; ThisCDS = TmpCDS;
1100 RestoreReg <<WORD PTR ThisCDS+2>,<WORD PTR ThisCDS>>
1104 LDS SI,ThisCDS ; ThisDPB = ThisCDS->devptr;
1105 LES DI,[SI].curdir_devptr
1106 MOV WORD PTR ThisDPB,DI
1107 MOV WORD PTR ThisDPB+2,ES
1111 Break <$NameTrans - partially process a name>
1114 ; $NameTrans - allow users to see what names get mapped to. This call
1115 ; performs only string substitution and canonicalization, not splicing. Due
1116 ; to Transpath playing games with devices, we need to insure that the output
1117 ; has drive letter and : in it.
1119 ; Inputs: DS:SI - source string for translation
1120 ; ES:DI - pointer to buffer
1123 ; Buffer at ES:DI is filled in with data
1124 ; ES:DI point byte after nul byte at end of dest string in buffer
1126 ; AX = error_path_not_found
1127 ; Registers modified: all
1129 Procedure $NameTrans,Near
1130 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
1131 SaveReg <DS,SI,ES,DI>
1132 MOV DI,OFFSET DOSGroup:OpenBuf
1133 CALL TransPath ; to translation (everything)
1134 RestoreReg <DI,ES,SI,DS>
1136 transfer SYS_Ret_Err
1138 MOV SI,OFFSET DOSGroup:OpenBuf
1145 Break <DriveFromText - return drive number from a text string>
1148 ; DriveFromText - examine DS:SI and remove a drive letter, advancing the
1151 ; Inputs: DS:SI point to a text string
1152 ; Outputs: AL has drive number
1154 ; Registers modified: AX,SI.
1156 Procedure DriveFromText,NEAR
1157 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
1158 XOR AL,AL ; drive = 0;
1159 CMP BYTE PTR [SI],0 ; if (*s &&
1161 CMP BYTE PTR [SI+1],':' ; s[1] == ':') {
1164 ;--------------------- Start of DBCS 2/18/KK
1167 invoke testkanj ;AN000;
1170 ;--------------------- End of DBCS 2/18/KK
1172 LODSW ; drive = (*s | 020) - 'a'+1;
1174 SUB AL,'a'-1 ; s += 2;
1176 MOV AL,-1 ; nuke AL...
1178 EndProc DriveFromText
1180 Break <TextFromDrive - convert a drive number to a text string>
1183 ; TextFromDrive - turn AL into a drive letter: and put it at es:di with
1184 ; trailing :. TextFromDrive1 takes a 1-based number.
1186 ; Inputs: AL has 0-based drive number
1187 ; Outputs: ES:DI advanced
1188 ; Registers modified: AX
1190 Procedure TextFromDrive,NEAR
1191 ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
1193 Entry TextFromDrive1
1194 ADD AL,'A'-1 ; *d++ = drive-1+'A';
1195 MOV AH,":" ; strcat (d, ":");
1198 EndProc TextFromDrive
1200 Break <PathPref - see if one path is a prefix of another>
1203 ; PathPref - compare DS:SI with ES:DI to see if one is the prefix of the
1204 ; other. Remember that only at a pathchar break are we allowed to have a
1205 ; prefix: A:\ and A:\FOO
1207 ; Inputs: DS:SI potential prefix
1209 ; Outputs: Zero set => prefix found
1210 ; DI/SI advanced past matching part
1211 ; Zero reset => no prefix, DS/SI garbage
1212 ; Registers modified: CX
1214 Procedure PathPref,NEAR
1215 Invoke DStrLen ; get length
1216 DEC CX ; do not include nul byte
1218 ;----------------------- Start of DBCS 2/13/KK
1219 SaveReg <AX> ;AN000;; save char register
1222 invoke Testkanj ;AN000;
1228 JMP SHORT NotSep ;AN000;
1233 ;----------------------- End of DBCS 2/13/KK
1235 REPZ CMPSB ; compare
1236 retnz ; if NZ then return NZ
1237 SaveReg <AX> ; save char register
1239 MOV AL,[SI-1] ; get last byte to match
1240 Invoke PathChrCmp ; is it a path char (Root!)
1241 JZ Prefix ; yes, match root (I hope)
1243 MOV AL,ES:[DI] ; get next char to match
1244 CALL PathSepGotCh ; was it a pathchar?
1246 RestoreReg <AX> ; get back original
1250 Break <ScanPathChar - see if there is a path character in a string>
1253 ; ScanPathChar - search through the string (pointed to by DS:SI) for
1256 ; Input: DS:SI target string (null terminated)
1257 ; Output: Zero set => path separator encountered in string
1258 ; Zero clear => null encountered
1259 ; Registers modified: SI
1261 Procedure ScanPathChar,NEAR
1262 LODSB ; fetch a character
1264 invoke TestKanj ;AN000;; 2/13/KK
1265 jz NotKanjr ;AN000;; 2/13/KK
1266 LODSB ;AN000;; 2/13/KK
1267 OR AL,AL ;AN000;; 2/13/KK 3/31/removed
1268 JNZ ScanPathChar ;AN000;; 2/13/KK 3/31/removed
1269 INC AL ;AN000;; 2/13/KK
1270 return ;AN000;; 2/13/KK
1272 NotKanjr: ;AN000;; 2/13/KK
1275 JNZ ScanPathChar ; not \, / or NUL => go back for more
1276 invoke PathChrCmp ; path separator?
1278 EndProc ScanPathChar