summaryrefslogtreecommitdiff
path: root/v2.0/source/DIR.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v2.0/source/DIR.ASM')
-rw-r--r--v2.0/source/DIR.ASM1084
1 files changed, 1084 insertions, 0 deletions
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 @@
1;
2; Directory routines for MSDOS
3;
4
5INCLUDE DOSSEG.ASM
6
7CODE SEGMENT BYTE PUBLIC 'CODE'
8 ASSUME SS:DOSGROUP,CS:DOSGROUP
9
10.xlist
11.xcref
12INCLUDE DOSSYM.ASM
13INCLUDE DEVSYM.ASM
14.cref
15.list
16
17TITLE DIR - Directory and path cracking
18NAME Dir
19
20 i_need NoSetDir,BYTE
21 i_need EntFree,WORD
22 i_need DirStart,WORD
23 i_need LastEnt,WORD
24 i_need ClusNum,WORD
25 i_need CurBuf,DWORD
26 i_need ThisFCB,DWORD
27 i_need Attrib,BYTE
28 i_need DelAll,BYTE
29 i_need VolID,BYTE
30 i_need Name1,BYTE
31 i_need ThisDPB,DWORD
32 i_need EntLast,WORD
33 i_need Creating,BYTE
34 i_need SecClusPos,BYTE
35 i_need ClusFac,BYTE
36 i_need NxtClusNum,WORD
37 i_need DirSec,WORD
38 i_need DriveSpec,BYTE
39 i_need Device_availability,BYTE
40 i_need RootStart,BYTE
41 i_need DevString,BYTE
42 i_need DevStrLen,BYTE
43
44SUBTTL BUILDDIR,NEWDIR -- ALLOCATE DIRECTORIES
45PAGE
46 procedure BUILDDIR,NEAR
47ASSUME DS:DOSGROUP,ES:NOTHING
48
49; Inputs:
50; ES:BP Points to DPB
51; [THISFCB] Set if using NEWDIR entry point
52; [LASTENT] current last valid entry number in directory if no free
53; entries
54; Function:
55; Grow directory if no free entries and not root
56; Outputs:
57; CARRY SET IF FAILURE
58; ELSE
59; AX entry number of new entry
60; If a new dir [DIRSTART],[CLUSFAC],[CLUSNUM],[DIRSEC] set
61; AX = first entry of new dir
62; GETENT should be called to set [LASTENT]
63
64 MOV AX,[ENTFREE]
65 CMP AX,-1
66 JNZ GOTRET
67 CMP [DIRSTART],0
68 JNZ NEWDIR
69 STC
70 return ; Can't grow root
71
72 entry NEWDIR
73 MOV BX,[DIRSTART]
74 OR BX,BX
75 JZ NULLDIR
76 invoke GETEOF
77NULLDIR:
78 MOV CX,1
79 invoke ALLOCATE
80 retc
81 MOV DX,[DIRSTART]
82 OR DX,DX
83 JNZ ADDINGDIR
84 call SETDIRSRCH
85 MOV [LASTENT],-1
86 JMP SHORT GOTDIRREC
87ADDINGDIR:
88 CMP [CLUSNUM],0FF8H
89 JB NOTFIRSTGROW
90 MOV [CLUSNUM],BX
91NOTFIRSTGROW:
92 MOV DX,BX
93 XOR BL,BL
94 invoke FIGREC
95GOTDIRREC:
96 MOV CL,ES:[BP.dpb_cluster_mask]
97 INC CL
98 XOR CH,CH
99ZERODIR:
100 PUSH CX
101 MOV AL,0FFH
102 invoke GETBUFFR
103 MOV CX,ES:[BP.dpb_sector_size]
104 PUSH ES
105 LES DI,[CURBUF]
106 PUSH DI
107 ADD DI,BUFINSIZ
108 XOR AX,AX
109 SHR CX,1
110 REP STOSW
111 JNC EVENZ
112 STOSB
113EVENZ:
114 POP DI
115 INC AL
116 MOV ES:[DI.BUFDIRTY],AL
117 POP ES
118 POP CX
119 INC DX
120 LOOP ZERODIR
121 MOV AX,[LASTENT]
122 INC AX
123GOTRET:
124 CLC
125 return
126
127BUILDDIR ENDP
128
129;
130; set up a . and .. directory entry for a directory
131;
132 procedure SETDOTENT,NEAR
133ASSUME DS:DOSGROUP
134 MOV CX,4
135 MOV AX,2020H
136 REP STOSW
137 STOSB
138 MOV SI,WORD PTR [THISFCB]
139 MOV AL,attr_directory
140 STOSB
141 ADD DI,10
142 MOV AX,[SI.fcb_FTIME]
143 STOSW
144 MOV AX,[SI.fcb_FDATE]
145 STOSW
146 MOV AX,DX
147 STOSW
148 XOR AX,AX
149 STOSW
150 STOSW
151 return
152SETDOTENT ENDP
153
154SUBTTL GETFILE, GETNAME, FINDNAME -- LOOK FOR A FILE
155PAGE
156 procedure SEARCH,near
157
158 entry GETFILE
159ASSUME DS:NOTHING,ES:NOTHING
160; Same as GETNAME except ES:DI points to FCB on successful return
161 invoke MOVNAME
162 retc
163 PUSH DX
164 PUSH DS
165 CALL FINDNAME
166 POP ES
167 POP DI
168 return
169
170 entry GETNAME
171ASSUME DS:NOTHING,ES:NOTHING
172
173; Inputs:
174; DS,DX point to FCB
175; Function:
176; Find file name in disk directory. First byte is
177; drive number (0=current disk). "?" matches any
178; character.
179; Outputs:
180; Carry set if file not found
181; ELSE
182; Zero set if attributes match (always except when creating)
183; AH = Device ID (bit 7 set if not disk)
184; [THISDPB] = Base of drive parameters
185; DS = DOSGROUP
186; ES = DOSGROUP
187; [CURBUF+2]:BX = Pointer into directory buffer
188; [CURBUF+2]:SI = Pointer to First Cluster field in directory entry
189; [CURBUF] has directory record with match
190; [NAME1] has file name
191; All other registers destroyed.
192
193 invoke MOVNAME
194ASSUME ES:DOSGROUP
195 retc ; Bad file name?
196
197 entry FINDNAME
198 PUSH SS
199 POP DS
200ASSUME DS:DOSGROUP
201 invoke DEVNAME
202 JC FindEntry
203 invoke BUILDFCB
204 return
205ASSUME ES:NOTHING
206
207; NOTE THE FALL THROUGH
208
209SUBTTL FINDENTRY -- LOOK FOR AN ENTRY
210PAGE
211 entry FindEntry
212ASSUME DS:DOSGROUP,ES:NOTHING
213
214; Inputs:
215; [THISDPB] set
216; [SECCLUSPOS] = 0
217; [DIRSEC] = Starting directory sector number
218; [CLUSNUM] = Next cluster of directory
219; [CLUSFAC] = Sectors/Cluster
220; [NAME1] = Name to look for
221; Function:
222; Find file name in disk directory.
223; "?" matches any character.
224; Outputs:
225; Carry set if name not found
226; ELSE
227; Zero set if attributes match (always except when creating)
228; AH = Device ID (bit 7 set if not disk)
229; [THISDPB] = Base of drive parameters
230; DS = DOSGROUP
231; ES = DOSGROUP
232; [CURBUF+2]:BX = Pointer into directory buffer
233; [CURBUF+2]:SI = Pointer to First Cluster field in directory entry
234; [CURBUF] has directory record with match
235; [NAME1] has file name
236; [LASTENT] is entry number of the entry
237; All other registers destroyed.
238
239 CALL STARTSRCH
240 CMP BYTE PTR [ATTRIB],attr_volume_id
241 ; Looking for vol ID only ?
242 JNZ NOTVOLSRCH ; No
243 CALL SETROOTSRCH ; Yes force search of root
244NOTVOLSRCH:
245 CALL GETENTRY
246 entry Srch
247 PUSH DS
248 MOV DS,WORD PTR [CURBUF+2]
249ASSUME DS:NOTHING
250 MOV AH,BYTE PTR [BX]
251 OR AH,AH ; End of directory?
252 JZ FREE
253 CMP AH,BYTE PTR [DELALL] ; Free entry?
254 JZ FREE
255 TEST BYTE PTR [BX+11],attr_volume_id
256 ; Volume ID file?
257 JZ CHKFNAM ; NO
258 INC BYTE PTR [VOLID]
259CHKFNAM:
260 MOV SI,BX
261 PUSH SS
262 POP ES
263ASSUME ES:DOSGROUP
264 MOV DI,OFFSET DOSGROUP:NAME1
265 MOV CX,11
266WILDCRD:
267 REPE CMPSB
268 JZ FOUND
269 CMP BYTE PTR ES:[DI-1],"?"
270 JZ WILDCRD
271 POP DS
272ASSUME DS:DOSGROUP
273 entry NEXTENT
274 LES BP,[THISDPB]
275ASSUME ES:NOTHING
276 CALL NEXTENTRY
277 JNC SRCH
278 JMP SHORT SETESRET
279
280FREE:
281 POP DS
282ASSUME DS:DOSGROUP
283 MOV CX,[LASTENT]
284 CMP CX,[ENTFREE]
285 JAE TSTALL
286 MOV [ENTFREE],CX
287TSTALL:
288 CMP AH,BYTE PTR [DELALL] ; At end of directory?
289 JZ NEXTENT ; No - continue search
290 MOV [ENTLAST],CX
291 STC
292 JMP SHORT SETESRET
293
294FOUND:
295;
296; We have a file with a matching name. We must now consider
297; the attributes:
298; ATTRIB Action
299; ------ ------
300; Volume_ID Is Volume_ID in test?
301; Otherwise If no create then Is ATTRIB+extra superset of test?
302; If create then Is ATTRIB equal to test?
303;
304 MOV CH,[SI] ; Attributes of file
305 POP DS
306ASSUME DS:DOSGROUP
307 MOV AH,BYTE PTR [ATTRIB] ; Attributes of search
308 TEST CH,attr_volume_id ; Volume ID file?
309 JZ check_one_volume_id ; Nope check other attributes
310 TEST AH,attr_volume_id ; Can we find Volume ID?
311 JZ NEXTENT ; Nope, (not even $FCB_CREATE)
312 XOR AH,AH ; Set zero flag for $FCB_CREATE
313 JMP SHORT RETF ; Found Volume ID
314check_one_volume_id:
315 CMP AH,attr_volume_id ; Looking only for Volume ID?
316 JZ NEXTENT ; Yes, continue search
317 ADD SI,15
318 CALL MatchAttributes
319 JZ RETF
320 TEST BYTE PTR [CREATING],-1 ; Pass back mismatch if creating
321 JZ NEXTENT ; Otherwise continue searching
322RETF:
323 LES BP,[THISDPB]
324 MOV AH,ES:[BP.dpb_drive]
325SETESRET:
326 PUSH SS
327 POP ES
328 return
329
330SUBTTL GETENTRY, NEXTENTRY, GETENT -- STEP THROUGH DIRECTORY
331PAGE
332 entry GETENTRY
333ASSUME DS:DOSGROUP,ES:NOTHING
334
335; Inputs:
336; [LASTENT] has directory entry
337; ES:BP points to drive parameters
338; Function:
339; Locates directory entry in preparation for search
340; GETENT provides entry for passing desired entry in AX
341; A valid search environment MUST exist
342; ENDENT,ENTLAST,ENTFREE
343; Outputs:
344; [CURBUF+2]:BX = Pointer to next directory entry in CURBUF
345; [CURBUF+2]:DX = Pointer to first byte after end of CURBUF
346; [LASTENT] = New directory entry number
347
348 MOV AX,[LASTENT]
349 entry GETENT
350 MOV [LASTENT],AX
351 MOV CL,4
352 SHL AX,CL
353 XOR DX,DX
354 SHL AX,1
355 RCL DX,1 ; Account for overflow in last shift
356 MOV BX,ES:[BP.dpb_sector_size]
357 AND BL,255-31 ; Must be multiple of 32
358 DIV BX
359 MOV BX,DX ; Position within sector
360 PUSH BX
361 invoke DIRREAD
362 POP BX
363SETENTRY:
364 MOV DX,WORD PTR [CURBUF]
365 ADD DX,BUFINSIZ
366 ADD BX,DX
367 ADD DX,ES:[BP.dpb_sector_size] ; Always clears carry
368 return
369
370 entry NEXTENTRY
371ASSUME DS:DOSGROUP,ES:NOTHING
372
373; Inputs:
374; Same as outputs of GETENTRY, above
375; Function:
376; Update BX, and [LASTENT] for next directory entry.
377; Carry set if no more.
378
379 MOV AX,[LASTENT]
380 CMP AX,[ENTLAST]
381 JZ NONE
382 INC AX
383 ADD BX,32
384 CMP BX,DX
385 JB HAVIT
386 MOV BL,BYTE PTR [SECCLUSPOS]
387 INC BL
388 CMP BL,BYTE PTR [CLUSFAC]
389 JB SAMECLUS
390 MOV BX,[NXTCLUSNUM]
391 CMP BX,0FF8H
392 JAE NONE
393 CMP BX,2
394 JB NONE
395 JMP GETENT
396
397NONE:
398 STC
399 return
400
401HAVIT:
402 MOV [LASTENT],AX
403 CLC
404 return
405
406SAMECLUS:
407 MOV BYTE PTR [SECCLUSPOS],BL
408 MOV [LASTENT],AX
409 PUSH DS
410 LDS DI,[CURBUF]
411ASSUME DS:NOTHING
412 MOV DX,[DI.BUFSECNO]
413 INC DX
414 POP DS
415ASSUME DS:DOSGROUP
416 invoke FIRSTCLUSTER
417 XOR BX,BX
418 JMP SETENTRY
419Search ENDP
420
421SUBTTL GETCURRDIR -- GET CURRENT DIRECTORY
422PAGE
423 procedure Dir_search,NEAR
424 entry GETCURRDIR
425ASSUME DS:NOTHING,ES:NOTHING
426
427; Inputs:
428; ES:BP Points to DPB
429; FATREAD should be called before this routine
430; Function:
431; Find current directory for drive
432; If path is bad set current directory to the root
433; Outputs:
434; DS = DOSGROUP
435; [SECCLUSPOS] = 0
436; [DIRSTART] = Cluster # of first cluster of directory ( 0 if root)
437; [DIRSEC] Set to phys sec # of first sector first cluster of directory
438; [CLUSNUM] Set to next cluster
439; [CLUSFAC] Sectors/cluster
440; Destroys all registers
441
442 MOV BX,ES:[BP.dpb_current_dir]
443 OR BX,BX
444 JZ SETROOTSRCH
445 CMP BX,0FF8H
446 JB SETDIRSRCH
447 PUSH ES
448 POP DS
449 LEA SI,[BP.dpb_dir_text]
450 CALL ROOTPATH
451ASSUME DS:DOSGROUP
452 JNC SETCURR
453 MOV ES:[BP.dpb_current_dir],0
454
455SETROOTSRCH:
456ASSUME DS:NOTHING,ES:NOTHING
457 PUSH SS
458 POP DS
459ASSUME DS:DOSGROUP
460 XOR AX,AX
461 MOV [DIRSTART],AX
462 MOV BYTE PTR [SECCLUSPOS],AL
463 DEC AX
464 MOV [CLUSNUM],AX
465 MOV AX,ES:[BP.dpb_first_sector]
466 MOV DX,ES:[BP.dpb_dir_sector]
467 SUB AX,DX
468 MOV BYTE PTR [CLUSFAC],AL
469 MOV [DIRSEC],DX
470 return
471
472SETCURR:
473ASSUME DS:DOSGROUP
474 MOV AX,[DIRSTART]
475 MOV ES:[BP.dpb_current_dir],AX
476 return
477
478 entry SETDIRSRCH
479ASSUME DS:NOTHING,ES:NOTHING
480
481; Inputs:
482; BX cluster number of start of directory
483; ES:BP Points to DPB
484; Function:
485; Set up a directory search
486; Outputs:
487; DS = DOSGROUP
488; [DIRSTART] = BX
489; [CLUSFAC],[CLUSNUM],[SECCLUSPOS],[DIRSEC] set
490; destroys AX,DX
491
492 OR BX,BX
493 JZ SETROOTSRCH
494 PUSH SS
495 POP DS
496ASSUME DS:DOSGROUP
497 MOV [DIRSTART],BX
498 MOV AL,ES:[BP.dpb_cluster_mask]
499 INC AL
500 MOV BYTE PTR [CLUSFAC],AL
501 invoke UNPACK
502 MOV [CLUSNUM],DI
503 MOV DX,BX
504 XOR BL,BL
505 MOV BYTE PTR [SECCLUSPOS],BL
506 invoke FIGREC
507 MOV [DIRSEC],DX
508 return
509Dir_search ENDP
510
511SUBTTL MAKENODE -- CREATE A NEW NODE
512PAGE
513 procedure MakeNode,NEAR
514ASSUME DS:NOTHING,ES:NOTHING
515
516; Inputs:
517; AL - attribute to create
518; DS:SI Points to asciz path
519; [THISFCB] Points to an empty FCB
520; Function:
521; Make a new node
522; Outputs:
523; DS=DOSGROUP
524; ES:BP Points to DPB
525; AX = 0 Success
526; AX = 1 A node by this name exists and is a directory
527; AX = 2 A new node could not be created error
528; AX = 3 A node by this name exists and is a file error
529; AX = 4 Bad Path error
530; AX = 5 Attribute mismatch error
531; CARRY SET IF ERROR
532; ELSE
533; [DIRSTART],[DIRSEC],[CLUSFAC],[CLUSNUM] set to directory
534; containing new node.
535; [CURBUF+2]:BX Points to entry
536; [CURBUF+2]:SI Points to entry.fcb_firclus
537; [ThisFCB] is filled in
538; If this is a new entry zero is set and
539; Attribute byte in entry is directory
540; else a file existed by this name and:
541; [NAME1] has name
542; entry is not changed in any way
543; Destroys all registers
544
545 PUSH AX
546 CALL GetPath
547 MOV DL,CL ; Save CL info
548 POP CX
549 MOV BYTE PTR [ATTRIB],CL
550 MOV CX,AX
551 JNC make_exists ; File existed
552 JNZ make_err_4 ; Path bad
553 OR DL,DL ; Check "CL" return from GETPATH
554 JNZ make_type ; Name simply not found
555make_err_4:
556 MOV AL,4 ; case 1 bad path
557make_err_ret:
558 STC
559 return
560
561make_type:
562 XOR AL,AL ; nothing exists... assume 0
563 STC
564 JMP SHORT make_save
565make_exists:
566 JZ make_exists_dir
567 MOV AL,3 ; file exists type 3
568 TEST BYTE PTR [ATTRIB],(attr_volume_id+attr_directory)
569 JNZ make_err_ret_5 ; but we wanted a volid or dir
570 OR CH,CH
571 JS make_dev ; No furthur checks if device
572 PUSH CX
573 MOV DS,WORD PTR [CURBUF+2]
574 MOV CH,[BX+dir_attr] ; Get file attributes
575 TEST CH,attr_read_only
576 JNZ make_err_ret_5P ; Cannot create on read only files
577 CALL MatchAttributes
578make_err_ret_5P:
579 POP CX
580 JZ make_dev ; Attributes ok
581make_err_ret_5:
582 MOV AL,5 ; Attribute mismatch
583 JMP SHORT make_err_ret
584
585make_dev:
586 XOR AL,AL ; Make sure zero set(atts match), carry clear(exists)
587 MOV AL,3 ; Restore correct value
588 JMP SHORT make_save
589make_exists_dir:
590 MOV AL,1 ; directory exists
591 TEST BYTE PTR [ATTRIB],attr_directory
592 JZ make_err_ret ; we didn't want a directory
593 CLC
594 return ; just return
595make_save:
596 PUSH AX
597;
598; set up for call to NewEntry - it is in the middle of FCB_CREATE
599; so we must also pre-push two registers. They will be popped off
600; by FCB_CREATE
601;
602 PUSH SS
603 POP DS
604 ASSUME DS:DOSGROUP
605 PUSHF ;Save state of flags
606 CMP BYTE PTR [NAME1],'.' ;Detect attempt to make '.' or '..'
607 JNZ NOTLDOT ; Needed because no '.' or '..' in root
608 POPF
609 MOV AL,1 ;Force type 2 error
610 JMP SHORT SET2ERR
611
612NOTLDOT:
613 POPF
614 PUSH ES
615 LES DI,[ThisFCB]
616 PUSH DS
617 PUSH DI
618 PUSH ES
619 MOV AX,CX
620 invoke NewEntry
621 POP DS
622 POP ES
623SET2ERR:
624 OR AL,AL
625 POP AX
626 JZ make_set_fcb
627 MOV AL,2 ; create failed case 2
628 STC
629 return
630make_set_fcb:
631ASSUME DS:DOSGROUP
632 PUSH ES
633 LES DI,[THISFCB]
634 INC DI
635 PUSH DS
636 PUSH SI
637 MOV DS,WORD PTR [CURBUF+2]
638ASSUME DS:NOTHING
639 MOV SI,BX
640 MOV CX,11
641 REP MOVSB
642 POP SI
643 POP DS
644ASSUME DS:DOSGROUP
645 POP ES
646 CMP AL,1
647 JA make_errors
648 OR AL,AL
649 CLC
650 return
651make_errors:
652 STC
653 return
654
655MakeNode ENDP
656
657SUBTTL GETPATH -- PARSE AN asciz PATH
658PAGE
659
660 procedure GETPATH,near
661ASSUME DS:NOTHING,ES:NOTHING
662
663; Inputs:
664; DS:SI Points to asciz path
665; Function:
666; Crack the path
667; Outputs:
668; [DRIVESPEC] is non zero if a drive was specified
669; [ROOTSTART] is non zero if a / started the path
670; [ATTRIB] set to attr_directory+attr_hidden+attr_system
671; Same as FINDPATH except if path specifies a device in which case
672; bit 7 of AH will be set and SI and BX will point DOSGROUP relative
673; Destroys all registers
674
675 XOR AX,AX
676 MOV WORD PTR [DRIVESPEC],AX
677 MOV BYTE PTR [ATTRIB],attr_directory+attr_system+attr_hidden
678 LODSB
679 invoke PATHCHRCMP
680 JZ DEFAULTROOT
681 MOV AH,AL
682 LODSB
683 CMP AL,':'
684 JZ DRVSPEC
685 DEC SI
686 DEC SI
687 PUSH DS
688 PUSH SI
689 PUSH SS
690 POP ES
691 CMP BYTE PTR [device_availability],0
692 JZ NOWDEV
693 CALL GOTPRESTRING2
694 JNC BUILDFCBJ ; If no carry then we have a device
695NOWDEV:
696 CALL DEFPATH
697GOFIND:
698 MOV AL,[NoSetDir]
699 PUSH AX
700 MOV [NoSetDir],0
701 CALL GETCURRDIR
702 POP AX
703 MOV [NoSetDir],AL
704 POP SI
705 POP DS
706 JMP FINDPATH
707
708DEFPATH:
709 XOR AL,AL
710DRVPATH:
711 invoke GETTHISDRV
712 retc ; Bad drive
713 PUSH SS
714 POP DS
715 invoke FATREAD
716 CLC
717 return
718
719DEFAULTROOT:
720 PUSH DS
721 PUSH SI
722 CALL DEFPATH
723 POP SI
724 POP DS
725ROOTSRCH:
726 INC BYTE PTR [ROOTSTART]
727 CMP BYTE PTR [SI],0
728 JZ PATHISNULL
729 PUSH DS
730 PUSH SI
731 PUSH ES ; Save pointer to DPB
732 CALL CHKDEV
733 POP ES
734 JNC BUILDFCBJ
735 POP SI
736 POP DS
737 JMP ROOTPATH
738
739BUILDFCBJ:
740 POP AX
741 POP AX
742 context es
743 invoke BUILDFCB ; Clears carry sets zero
744 INC AL ; reset zero
745 return
746
747DRVSPEC:
748 INC [DRIVESPEC]
749 MOV AL,AH
750 OR AL,20H ; Convert to lower case
751 SUB AL,60H ; Make A=1
752 PUSH DS
753 PUSH SI
754 PUSH AX
755 context es
756 CALL GotPreString2
757 ASSUME ES:NOTHING
758 POP AX
759 JNC BuildFCBJ
760 CALL DRVPATH
761 POP SI
762 POP DS
763 retc ; Bad drive
764 LODSB
765 invoke PATHCHRCMP
766 JZ ROOTSRCH
767 DEC SI
768 PUSH DS
769 PUSH SI
770 JMP GOFIND
771
772PATHISNULL:
773 CALL SETROOTSRCH
774ASSUME DS:DOSGROUP
775 XOR AL,AL ; Set zero (directory) clear carry
776 return
777
778CHKDEV:
779ASSUME DS:NOTHING
780 PUSH SS
781 POP ES
782 MOV DI,OFFSET DOSGROUP:DEVSTRING
783 XOR CX,CX
784 MOV CL,DEVSTRLEN
785CHKPRESTRING:
786 REPE CMPSB
787 JZ GOTPRESTRING
788 DEC SI
789 invoke GETLET ; Try convert to upper case
790 CMP AL,ES:[DI-1]
791 JZ CHKPRESTRING
792NOPRESTRING:
793 STC
794 return
795
796GOTPRESTRING:
797 LODSB
798 invoke PATHCHRCMP
799 JNZ NOPRESTRING
800GOTPRESTRING2:
801 MOV DI,OFFSET DOSGROUP:NAME1
802 MOV CX,9
803TESTLOOP:
804 invoke GETLET
805 CMP AL,'.'
806 JZ TESTDEVICE
807 invoke PATHCHRCMP
808 JZ NOTDEV
809 OR AL,AL
810 JZ TESTDEVICE
811 STOSB
812 LOOP TESTLOOP
813NOTDEV:
814 STC
815 return
816
817TESTDEVICE:
818 ADD CX,2
819 MOV AL,' '
820 REP STOSB
821 PUSH SS
822 POP DS
823 invoke DEVNAME
824 return
825GETPATH ENDP
826
827SUBTTL ROOTPATH, FINDPATH -- PARSE A PATH
828PAGE
829 procedure ROOTPATH,near
830
831ASSUME DS:NOTHING,ES:NOTHING
832
833; Inputs:
834; ES:BP Points to DPB
835; FATREAD should be called before this routine
836; DS:SI Points to asciz string of path which is assumed to start at
837; the root (no leading '/').
838; Function:
839; Search from root for path
840; Outputs:
841; Same as FINDPATH
842; Destroys all registers
843
844 PUSH DS
845 CALL SETROOTSRCH
846 POP DS
847
848; NOTE FALL THROUGH
849
850 entry FINDPATH
851ASSUME DS:NOTHING,ES:NOTHING
852
853; Inputs:
854; ES:BP Points to DPB
855; DS:SI Points to asciz string of path (no leading '/').
856; [SECCLUSPOS] = 0
857; [DIRSEC] = Phys sec # of first sector of directory
858; [CLUSNUM] = Cluster # of next cluster
859; [CLUSFAC] = Sectors per cluster
860; Validate_path should be called before this routine is used,
861; unless it is KNOWN the path is good.
862; Function:
863; Parse path name
864; Outputs:
865; ES:BP Points to DPB
866; Carry set if bad path
867; DS:SI Points to path element causing failure
868; Zero set
869; [DIRSTART],[DIRSEC],[CLUSNUM], and [CLUSFAC] are set up to
870; start a search on the last directory
871; CL is zero if there is a bad name in the path
872; CL is non-zero if the name was simply not found
873; [ENTFREE] may have free spot in directory
874; [NAME1] is the name.
875; CL = 81H if '*'s or '?' in name 1, 80H otherwise
876; Zero reset
877; File in middle of path or bad name in path
878; or path too long or malformed path
879; ELSE
880; DS = DOSGROUP
881; AH = device ID
882; [CURBUF] contains directory record with match
883; [CURBUF+2]:BX Points into [CURBUF] to start of entry
884; [CURBUF+2]:SI Points to fcb_FIRCLUS field for entry
885; [NAME1] Has entry name
886; If last element is a directory zero is set and:
887; [DIRSTART],[SECCLUSPOS],[DIRSEC],[CLUSNUM], and [CLUSFAC]
888; are set up to start a search on it.
889; If last element is a file zero is reset
890; Destroys all registers
891
892 PUSH ES
893 PUSH SI
894 invoke NAMETRANS
895 MOV CL,AL
896 OR CL,80H
897 POP DI
898 POP ES
899 CMP SI,DI
900 JNZ check_device
901 JMP BADPATH
902check_device:
903 PUSH DS
904 PUSH SI
905 MOV AL,BYTE PTR [SI]
906
907;
908; can we see all devices
909;
910 context DS
911 CMP BYTE PTR [device_availability],0
912 JZ FindFile
913
914;
915; check name1 to see if we have a device...
916;
917 PUSH ES
918 context ES
919 invoke DevName ; blast BX
920 POP ES
921 ASSUME ES:NOTHING
922 JC FindFile
923 OR AL,AL
924 JNZ FileInPath
925 POP SI
926 POP SI
927 context ES
928 invoke BuildFCB
929 INC AL
930 return
931
932FindFile:
933 ASSUME ES:NOTHING
934 PUSH DI ; Start of this element
935 PUSH ES
936 PUSH CX
937 CALL FINDENTRY
938 POP CX
939 POP ES
940 POP DI
941 JC BADPATHPOP
942 LDS DI,[CURBUF]
943ASSUME DS:NOTHING
944 TEST BYTE PTR [BX+dir_attr],attr_directory
945 JZ FileInPath
946
947;
948; if we are not setting the directory, then
949; check for end of string
950;
951 CMP BYTE PTR [NoSetDir],0
952 JZ SetDir
953 MOV DX,DI
954 MOV AX,DS
955 POP DI
956 POP DS
957 CMP BYTE PTR [DI],0
958 JZ SetRet
959 PUSH DS
960 PUSH DI
961 MOV DI,DX
962 MOV DS,AX
963
964SetDir:
965 MOV DX,[SI]
966 SUB BX,DI
967 SUB SI,DI
968 PUSH BX
969 PUSH AX
970 PUSH SI
971 PUSH CX
972 PUSH [DI.BUFSECNO]
973 MOV BX,DX
974 CALL SETDIRSRCH
975ASSUME DS:DOSGROUP
976 POP DX
977 XOR AL,AL
978 invoke GETBUFFR
979 POP CX
980 POP SI
981 POP AX
982 POP BX
983 MOV DI,WORD PTR [CURBUF]
984 ADD SI,DI
985 ADD BX,DI
986 POP DI
987 POP DS
988ASSUME DS:NOTHING
989 MOV AL,[DI]
990 OR AL,AL
991 JZ SETRET
992 INC DI
993 MOV SI,DI
994 invoke PATHCHRCMP
995 JNZ find_bad_name
996 JMP FINDPATH
997
998find_bad_name:
999 DEC SI
1000BADPATH:
1001 XOR CL,CL ; Set zero
1002 STC
1003 return
1004
1005FILEINPATH:
1006 POP DI
1007 POP DS
1008 MOV AL,[DI]
1009 OR AL,AL
1010 JZ INCRET
1011 MOV SI,DI ; Path too long
1012 STC
1013 return
1014
1015INCRET:
1016 INC AL ; Reset zero
1017SETRET:
1018 PUSH SS
1019 POP DS
1020 return
1021
1022BADPATHPOP:
1023 POP SI
1024 POP DS
1025 MOV AL,[SI]
1026 MOV SI,DI ; Start of bad element
1027 OR AL,AL ; zero if bad element is last, non-zero if path too long
1028 STC
1029 return
1030ROOTPATH ENDP
1031
1032SUBTTL STARTSRCH -- INITIATE DIRECTORY SEARCH
1033PAGE
1034 procedure StartSrch,NEAR
1035ASSUME DS:DOSGROUP,ES:NOTHING
1036
1037; Inputs:
1038; [THISDPB] Set
1039; Function:
1040; Set up a search for GETENTRY and NEXTENTRY
1041; Outputs:
1042; ES:BP = Drive parameters
1043; Sets up LASTENT, ENDENT, ENTFREE=ENTLAST=-1, VOLID=0
1044; Destroys all registers (via FATREAD)
1045
1046 LES BP,[THISDPB]
1047 XOR AX,AX
1048 MOV [LASTENT],AX
1049 MOV BYTE PTR [VOLID],AL ; No volume ID found
1050 DEC AX
1051 MOV [ENTFREE],AX
1052 MOV [ENTLAST],AX
1053 return
1054StartSrch ENDP
1055
1056BREAK <MatchAttributes - the final check for attribute matching>
1057
1058;
1059; Input: [Attrib] = attribute to search for
1060; CH = found attribute
1061; Output: JZ <match>
1062; JNZ <nomatch>
1063;
1064 procedure MatchAttributes,near
1065 ASSUME DS:NOTHING,ES:NOTHING
1066 PUSH AX
1067 MOV AL,[Attrib] ; AL <- SearchSet
1068 NOT AL ; AL <- SearchSet'
1069 AND AL,CH ; AL <- SearchSet' and FoundSet
1070 AND AL,attr_all ; AL <- SearchSet' and FoundSet and Important
1071;
1072; the result is non-zero if an attribute is not in the search set
1073; and in the found set and in the important set. This means that we do not
1074; have a match. Do a JNZ <nomatch> or JZ <match>
1075;
1076 POP AX
1077 return
1078MatchAttributes ENDP
1079
1080do_ext
1081
1082CODE ENDS
1083 END
1084