1 TITLE CHKPROC
- PART1 Procedures called
from chkdsk
14 DATA SEGMENT PUBLIC PARA
'DATA'
15 EXTRN FIXMES_ARG
:word,DIREC_ARG
:word
16 EXTRN NULDMES
:byte,NULNZ
:byte,BADCLUS
:byte,NORECDOT
:byte
18 EXTRN BADCHAIN
:byte,NDOTMES
:byte,CDDDMES
:byte
19 EXTRN NORECDDOT1
:byte,NORECDDOT2
:byte,NORECDDOT3
:byte
21 EXTRN BADDPBDIR
:byte, BadSubDir
:byte
22 EXTRN BADTARG_PTR
:byte,BADTARG2
:byte,JOINMES
:byte
23 EXTRN PTRANDIR
:byte,PTRANDIR2
:byte
24 EXTRN CROSS_ARG
:word,NOISY_ARG
:word
25 EXTRN FILE_ARG1
:WORD,FILE_ARG2
:WORD,FILE_ARG
:word
26 EXTRN DOTMES
:byte,NOISY
:byte,DOTENT
:byte,HAVFIX
:byte
27 EXTRN DOFIX
:byte,DIRBUF
:byte,PARSTR
:byte,DDOTENT
:byte
28 EXTRN NUL
:byte,ERRSUB
:word,SECONDPASS
:byte,ALLFILE
:byte
29 EXTRN HIDCNT
:dword,HIDSIZ
:word,FILCNT
:dword,FILSIZ
:word ;an049;bgb
30 EXTRN DIRCNT
:dword ;an049;bgb
31 EXTRN DIRSIZ
:word ;an049;bgb
34 EXTRN ALLDRV
:byte,FIXMFLG
:byte,DIRCHAR
:byte
35 EXTRN BIGFAT
:byte,EOFVAL
:word,BADVAL
:word
36 Extrn fTrunc
:BYTE ;ac048;bgb
37 Extrn dirsec
:word ;ac048;bgb
39 EXTRN THISDPB
:dword,DOTSNOGOOD
:byte,NUL_ARG
:byte,STACKLIM
:word
40 EXTRN ZEROTRUNC
:byte,NAMBUF
:byte,SRFCBPT
:word,FATMAP
:word
41 EXTRN ISCROSS
:byte,MCLUS
:word,CSIZE
:byte,SSIZE
:word,fattbl
:byte
42 EXTRN DSIZE
:word,ARG1
:word,ARG_BUF
:byte,TMP_SPC
:BYTE
44 EXTRN Inv_XA_Msg
:Byte,Alloc_XA_Msg
:Byte
45 Extrn Data_Start_Low
:Word,Data_Start_High
:Word
46 EXTRN Read_Write_Relative
:Byte
47 EXTRN MClus
:Word,Chain_End
:Word
49 XA_Buffer XAL
<> ;XA buffer space to read in 1st sector ;AN000;
50 Head_Mark db 0 ;Flag for MarkMap ;AN000;
51 BClus dw 0 ;Bytes/Cluster
53 Cross_Clus dw 0 ;Cluster crosslink occurred on
54 Cluster_Count dw 0 ; ;AN000;
55 First_Cluster dw 0 ; ;AN000;
56 Previous_Cluster dw 0 ; ;AN000;
57 XA_Pass db 0 ; ;AN000;
58 File_Size_High dw 0 ; ;AN000;
59 File_Size_Low dw 0 ; ;AN000;
60 Chain_Size_Low dw 0 ; ;AN000;
61 Chain_Size_High dw 0 ; ;AN000;
68 public Previous_Cluster
73 public Chain_Size_High
77 CODE SEGMENT PUBLIC PARA
'CODE'
78 ASSUME
CS:DG
,DS:DG
,ES:DG
,SS:DG
79 ;Structures used by DIRPROC
83 SFCBSIZ EQU SIZE SRCHFCB
84 EXTRN PRINTF_CRLF
:NEAR,SUBERRP
:NEAR,FCB_TO_ASCZ
:NEAR
85 EXTRN FIGREC
:NEAR,EPRINT
:NEAR
86 EXTRN DOINT26
:NEAR,PROMPTYN
:NEAR
87 EXTRN DOTCOMBMES
:NEAR,FATAL
:NEAR,MARKMAP
:NEAR,GETFILSIZ
:NEAR
88 EXTRN SYSTIME
:NEAR, Read_Disk
:Near,DoCRLF
:Near
90 extrn UNPACK
:near, PACK
:near
91 public DOTDOTHARDWAY
, NODOT
, DOEXTMES1
, MESD1
, CANTREC
, DOTGOON
, NODDOT
92 public DOEXTMES2
, MESD2
, NFIX
, CANTREC2
, NULLDIRERR
, DOEXTMES3
, DOTSBAD
93 public dotsbad2
, DIRPROC
, STACKISOK
, NOPRINT
, JOINERR
94 public NONULLDERr
, DOTOK
, DATTOK
, DLINKOK
, BADDSIZ
, DSIZOK
, CHKDOTDOT
95 public DOTDOTOK
, DDATTOK
, DDLINKOK
, BADDDSIZ
, DDSIZOK
, ROOTDIR
96 public DODDH
, DIRDONE
, MOREDIR
, FPROC1
, NOPRINT2
, HIDENFILE
, NORMFILE
, NEWDIR
97 public DPROC1
, CONVDIR
, DPROC2
, CANTTARG
, BogusDir
, ASKCONV
98 public PRINTTRMES
, CROSSLOOK
, CHLP
, CROSSLINK
, CHAINDONE
99 public FIXENT2
, RET20
, FIXENT
, GETENT
, CLUSISOK
100 public SKIPLP
, GOTCLUS
, DOROOTDIR
, RDRETRY
, RDOK2
, WANTROOT
, CHECKNOFMES
, ret14
101 public CHECKERR
, get_currdirERR
, ok_pri_dir
, get_thiselERR
, ok_pri_el
102 public get_THISEL
, get_THISEL2
, get_currdir
, GET_END
, ERRLOOP
, LPDONE
103 public CHECK_SPLICE
, NT_SPLC
, MarkFAT
, Bad_Cluster
, Check_Chain_Sizes
104 public print_filename
;ac048;bgb
105 public NOTROOT
;ac048;bgb
106 public FIXDOT
;ac048;bgb
110 SUBTTL DIRPROC
-- Recursive directory processing
112 ;**************************************************************************
113 ; DOTDOTHARDWAY - change dir to the previous directory using '..'
117 ; inputs - parse string '..'
119 ; outputs - new default directory
122 ; On versions of DOS < 2.50 "cd .." would fail if there was no ".."
123 ; entry in the current directory. On versions >= 2.50 "cd .."
124 ; is handled as a string manipulation and therefore should always
125 ; work. On < 2.50 this routine didddled the current directory string
126 ; INSIDE THE DOS DATA STRUCTURES. This is no longer desirable, or
128 ;**************************************************************************
129 procedure dotdothardway
,near
130 MOV DX,OFFSET DG
:PARSTR
131 DOS_Call ChDir
; ;AC000;
133 endproc dotdothardway
136 ;************************************************************************** ;ac048;bgb
137 ; NODOT - come here if there is no . entry in the first entry of the sub- ;ac048;bgb
138 ; directory. The . entry is a pointer to the subdirectory itself. ;ac048;bgb
139 ; The entry from the search first did not find it, and the subdir is ;ac048;bgb
140 ; not joined. So, try to put a new . entry into the first slot. ;ac048;bgb
142 ; called by - nonullderr ;ac048;bgb
144 ; inputs - SI - points to arg_buf, which is a filespec ;ac048;bgb
145 ; DI - points to tmp_spc, which is a filespec ;ac048;bgb
146 ; AX - return value from search first ;ac048;bgb
148 ; outputs - if the /f parm was entered, tries to replace the . entry ;ac048;bgb
149 ; AX - saves the return value from search first ;ac048;bgb
151 ; logic: 1. go display error messages. Different messages are displayed, ;ac048;bgb
152 ; depending on /f and /v parms. ;ac048;bgb
154 ; 2. go get the sector number and read it into ram ;ac048;bgb
156 ; 3. if the first entry is erased (begins with hex e5), then we can ;ac048;bgb
157 ; fill it with the corrected . entry. Otherwise, go to #6. ;ac048;bgb
159 ; 4. So, fill entry with all the dir fields - name, ext, attr, date, ;ac048;bgb
160 ; time, size, cluster #. ;ac048;bgb
162 ; 5. write it back to disk. ;ac048;bgb
164 ; 6. go check out the .. entry ;ac048;bgb
165 ;************************************************************************** ;ac048;bgb
166 NODOT: ;No . ;ac048;bgb
167 PUSH AX ;save the return value from search 1st ;ac048;bgb
168 ;display msgs ;;;;;;;;jnz doextmes1 ;ac048;bgb
169 CMP [NOISY
],OFF
;was /v parm entered? ;ac048;bgb;AC000;
170 ; $IF Z ;display no /v msgs ;ac048;bgb
172 call suberrp
;ac048;bgb
173 ;;;;;;;;jmp short mesd1 ;ac048;bgb
174 ; $ELSE ;display /v msgs ;ac048;bgb
177 DOEXTMES1: mov si,offset dg
:dotmes
;first find out where we are ;ac048;bgb
178 call get_currdirerr
;ac048;bgb
179 mov dx,offset dg
:ndotmes
;print dir, dot, and 'not found' msg ;ac048;bgb
180 call eprint
;ac048;bgb
184 ;go find the sector ;ac048;bgb
185 MESD1: XOR AX,AX ;set entry number to zero ;ac048;bgb
186 PUSH BX ;save ;ac048;bgb
187 PUSH BP ;save ;ac048;bgb
188 CALL GETENT
;get the sector number ;ac048;bgb
189 POP BP ;restore bp ;ac048;bgb
190 PUSH BP ;put it back ;ac048;bgb
191 CMP BYTE PTR [DI],0E5H ;is this 1st entry erased/open? ;ac048;bgb
194 ;cant fill . entry ;JNZ CANTREC ;ac048;bgb ;Nope
195 CANTREC: INC [DOTSNOGOOD
] ;ac048;bgb
196 CMP [NOISY
],OFF
; ;ac048;bgb ;AC000;
199 ;JZ DOTGOON ;ac048;bgb
200 MOV DX,OFFSET DG
:NORECDOT
;ac048;bgb
201 CALL EPRINT
;ac048;bgb
204 jmp dotgoon
;ac048;bgb
209 fixdot: MOV SI,OFFSET DG
:DOTENT
;point to valid . entry
210 MOV CX,11 ;move filename and ext
212 PUSH AX ;save disk number
216 ; Add in time for directory - BAS July 17/85
218 push dx ;save starting sector number ;ac048;bgb
228 pop dx ;restore starting sector number ;ac048;bgbb
231 MOV [HAVFIX
],1 ;Have a fix
232 CMP [DOFIX
],0 ; /f parm entered?
235 ;JZ DOTGOON ;ac048;bgbif not F
237 CALL DOINT26
;ac048;bgb
238 ;JMP SHORT DOTGOON ;ac048;bgb
241 ;go check out .. entry
245 MOV SI,OFFSET DG
:DIRBUF
246 JMP CHKDOTDOT
;Go look for ..
247 ;*****************************************************************************
252 NODDOT
label far ;No ..
253 PUSH AX ;Return from SRCH
254 CMP [NOISY
],OFF
; ;AC000;
259 MOV SI,OFFSET DG
:PARSTR
261 MOV DX,OFFSET DG
:NDOTMES
271 CMP BYTE PTR [DI],0E5H ;Place to put it?
273 MOV SI,OFFSET DG
:DDOTENT
281 ; Add in time for directory - BAS July 17/85
282 push dx ;save starting sector number ;ac048;bgb
292 pop dx ;restore starting sector number ;ac048;bgbb
294 MOV [HAVFIX
],1 ;Got a fix
296 JZ NFIX
;No fix if no F, carry clear
300 restorereg
<bp,bx,ax> ;ac048;bgb
301 MOV SI,OFFSET DG
:DIRBUF
302 JMP far ptr ROOTDIR
;Process files
305 restorereg
<bp,bx,ax> ;ac048;bgb
306 CMP [NOISY
],OFF
; ;AC000;
308 MOV DX,OFFSET DG
:NORECDDOT
311 NULLDIRERR
label far ;dir is empty
312 CMP [NOISY
],OFF
; ;AC000;
319 MOV DX,OFFSET DG
:NULDMES
320 DOTSBAD: ;Can't recover
321 mov [file_arg2
],offset dg
:badtarg2
322 inc byte ptr [nul_arg
]
328 MOV SP,BP ;Pop local vars
329 POP BP ;Restore frame
336 ;***************************************************************************
337 ; DIRPROC - recursive tree walker
339 ; called by - main-routine in chkdsk1.sal
342 ; - two words of 0 on the stack
344 ;Recursive tree walker
345 ;dirproc(self,parent)
346 ;****************************************************************************
348 MOV [DOTSNOGOOD
],0 ;Init to dots OK - set . or .. error flag to false
349 MOV [ERRSUB
],0 ;No subdir errors yet
350 PUSH BP ;Save frame pointer - 0
351 MOV BP,SP ;ffe2 - 2c = ffb6
352 SUB SP,SFCBSIZ
;Only local var
354 ; are we at stack overflow ?
355 CMP SP,[STACKLIM
] ; ffb6 vs. 5943 ;an005;bgb
359 MOV BX,OFFSET DG
:STACKMES
;Out of stack
365 ;print the files as they are found
366 CMP [NOISY
],off
; off= 0 ;AC000;
367 ; $IF NZ ;if not noisy, dont print filenames
370 CMP [SECONDPASS
],False
; ;AC000;
371 ; $IF Z ;only print on the first pass
373 ;;;;;;;;;;;;JNZ NOPRINT ;Don't do it again on second pass
376 mov dx,offset dg
:DIREC_arg
;Tell user where we are
383 ; initialize search fcb
385 MOV SI,OFFSET DG
:ALLFILE
;extended fcb
388 MOV CX,SFCBSIZ
;move 44dec bytes
389 REP MOVSB ;from allfile (ds:si) to es:di
391 POP DX ; from push bp
392 MOV BX,DX ;BX points to SRCH FCB
393 DOS_Call Dir_Search_First
;search for any file ;AC000;
395 CMP WORD PTR [BP+6],0 ;attribute byte- root will = zero
398 jmp far ptr rootdir
;yes, we are at the root
401 OR AL,AL ;check return code from search first
403 CALL CHECK_SPLICE
; See if dir is spliced
406 ;;;;;;;;;;;;JC nulldirerr ; Not spliced, error
414 mov dx,offset dg
:joinmes
; ;AC000;
415 call Printf_Crlf
; ;AC000;
416 mov dx,offset dg
:badtarg2
; ;AC000;
417 call Printf_CRLF
; ;AC000;
419 MOV SP,BP ;Pop local vars
420 POP BP ;Restore frame
426 MOV SI,OFFSET DG
:DIRBUF
+ DIRNAM
427 MOV DI,OFFSET DG
:DOTENT
430 JZ DOTOK
;Got a . as first entry
431 push ax ;save return code from search first ;an045;bgb
432 CALL CHECK_SPLICE
; See if dir is spliced
433 ; $IF C ;carry means no join on this dir ;an045;bgb
435 pop ax ;restore return code ;an045;bgb
436 jmp nodot
;goto no . entry code ;an045;bgb
437 ; $ELSE ;no carry means dir is joined ;an045;bgb
440 pop ax ;restore return code ;an045;bgb
441 jmp joinerr
;goto join error code ;an045;bgb
442 ; $ENDIF ;no carry means dir is joined ;an045;bgb
444 ;;;;;;;;JNC JOINERR ; spliced, stop ;an045;bgb
445 ;;;;;;;;JMP NODOT ;No . ;an045;bgb
448 MOV SI,OFFSET DG
:DIRBUF
452 PUSH SI ;. not a dir?
453 MOV SI,OFFSET DG
:DOTMES
454 ;MOV DX,OFFSET DG:BADATT
455 mov dx,offset dg
:norecddot2
; ;AN000;
462 CMP AX,[BP+6] ;. link = MYSELF?
464 PUSH SI ;Link messed up
465 MOV SI,OFFSET DG
:DOTMES
466 ;MOV DX,OFFSET DG:CLUSBAD
467 mov dx,offset dg
:norecddot1
; ;AN000;
474 MOV AX,WORD PTR [SI.DIRESIZ
]
477 MOV AX,WORD PTR [SI.DIRESIZ
+2]
480 BADDSIZ: ;Size should be zero
482 MOV SI,OFFSET DG
:DOTMES
483 ;MOV DX,OFFSET DG:BADSIZM
484 mov dx,offset dg
:norecddot3
; ;AN000;
488 MOV WORD PTR [SI.DIRESIZ
],AX
489 MOV WORD PTR [SI.DIRESIZ
+2],AX
491 DSIZOK: ;Get next (should be ..)
493 DOS_Call Dir_Search_Next
; ;AC000;
494 CHKDOTDOT: ;Come here after . failure
499 MOV SI,OFFSET DG
:DIRBUF
+ DIRNAM
500 MOV DI,OFFSET DG
:DDOTENT
506 ;;; ;;;;;;;;JNZ NODDOT ;No ..
509 MOV SI,OFFSET DG
:DIRBUF
512 JNZ DDATTOK
;.. must be a dir
514 MOV SI,OFFSET DG
:PARSTR
515 ;MOV DX,OFFSET DG:BADATT
516 mov dx,offset dg
:norecddot2
; ;AN000;
524 CMP AX,[BP+4] ;.. link must be PARENT
526 MOV SI,OFFSET DG
:PARSTR
527 ;MOV DX,OFFSET DG:CLUSBAD
528 mov dx,offset dg
:norecddot1
; ;AN000;
535 MOV AX,WORD PTR [SI.DIRESIZ
]
538 MOV AX,WORD PTR [SI.DIRESIZ
+2]
545 BADDDSIZ: ;.. size should be 0
547 MOV SI,OFFSET DG
:PARSTR
548 ;MOV DX,OFFSET DG:BADSIZM
549 mov dx,offset dg
:norecddot3
; ;AN000;
553 MOV WORD PTR [SI.DIRESIZ
],AX
554 MOV WORD PTR [SI.DIRESIZ
+2],AX
558 ;***************************************************************************
559 ; DDSIZOK - search for the next file in this directory
560 ;***************************************************************************
562 MOV DX,BX ;search for Next entry
563 DOS_Call Dir_Search_Next
;func=12 ;AC000;
565 ROOTDIR
label far ;come here after search first .. failure also
566 OR AL,AL ; was a matching filename found?
567 JZ MOREDIR
;zero = yes ;More to go
568 CMP WORD PTR [BP+6],0 ;nz=no ;Am I the root?
569 JZ DIRDONE
;Yes, no chdir
570 MOV DX,OFFSET DG
:PARSTR
571 DOS_Call ChDir
; ;AC000;
574 ; NOTE************************************************
575 ; On DOS >= 2.50 "cd .." should ALWAYS work since it is
576 ; a string manipulation. Should NEVER get to here.
578 CMP [NOISY
],OFF
; ;AC000;
582 MOV DX,OFFSET DG
:CDDDMES
585 CALL DOTDOTHARDWAY
;Try again
587 MOV SP,BP ;Pop local vars
588 POP BP ;Restore frame
593 ;*****************************************************************
594 ; found at least one file in this subdir!
595 ;*****************************************************************
597 MOV SI,OFFSET DG
:DIRBUF
;point to where ext fcb of found file is
598 TEST [SI.DIRATT
],ISDIR
;attr 010h = sub-directory
599 JNZ NEWDIR
;Is a new directory?
600 CMP [SECONDPASS
],False
;no, same dir ;AC000;
601 JZ FPROC1
;2nd pass here
602 CALL CROSSLOOK
;Check for cross links
606 CMP [NOISY
],OFF
; ;AC000;
607 ; $IF NZ ;print filenames?
613 mov Cluster_Count
,0 ;No clusters for vol label ;AN000;
614 mov cx,0 ;setup cx for 0 size vol labels ;an016;bgb
615 TEST [SI.DIRATT
],VOLIDA
;attr=08 ;Don't chase chains on labels ;AC000;
616 ; $IF Z ;no, regular file
618 MOV AL,81H
;Head of file
619 mov di,word ptr [si].DIRESIZ
+0 ;Get file size
620 mov File_Size_Low
,di ;
621 mov di,word ptr [si].DIRESIZ
+2 ;
622 mov File_Size_High
,di ;
623 mov di,[si].DirClus
;First cluster of file ;AN000;
625 MOV CX,Cluster_Count
;Get number of clusters
626 ;;;;;;;;;;;;PUSH CX ;Save them
627 ;;;;;;;;;;;;CALL Check_Extended_Attributes ;See if XA exist, and handle ;AN000;
628 ;;;;;;;;;;;;POP CX ;Get File length clusters
629 ;;;;;;;;;;;;ADD CX,Cluster_Count ;Add in XA clusters
630 TEST [SI.DIRATT
],HIDDN
;
635 add word ptr hidcnt
,1 ;found another hidden file ;an049;bgb
636 adc word ptr hidcnt
+2,0 ;add high word if > 64k files ;an049;bgb
637 add hidsiz
,cx ;it was this many bytes ;an049;bgb
640 add word ptr filcnt
,1 ;inc file counter ;an049;bgb
641 adc word ptr filcnt
+2,0 ;add high word if >64k files ;an049;bgb
642 add filsiz
,cx ;add in size of file ;an049;bgb
646 ;***************************************************************************
647 ; NEWDIR - come here whenever you find another directory entry
648 ; inputs: SI - points to directory entry
649 ;***************************************************************************
651 CMP [SECONDPASS
],False
;are we on 2nd pass? ;AC000;
652 JZ DPROC1
;zero means no - skip next part
653 CALL CROSSLOOK
;2nd pass - Check for cross links
654 JMP SHORT DPROC2
;goto dproc2
656 MOV AL,82H
;Head of dir
657 mov di,[si].DirClus
;get 1st clus num from dir entry ;AN000;
658 mov File_Size_Low
,0 ; ;Set to zero, shouldn't ;AN000;
659 mov File_Size_High
,0 ; be looked at for dir ;AN000;
661 add word ptr dircnt
,1 ;add 1 to the dir counter ;an047;bgb
662 adc word ptr dircnt
+2,0 ;add 1 to the high word if carry ;an047;bgb
663 MOV CX,Cluster_Count
;Add count of clusters in files ;AN000;
664 CMP [ZEROTRUNC
],0 ;did we modify the file size? ;an026;bgb
665 JZ DPROC2
;Dir not truncated
666 CONVDIR: ;yes, dir size truncated
667 AND [SI.DIRATT
],NOT ISDIR
;Turn into file
669 POP BX ;Get my SRCH FCB pointer back
670 POP [ERRSUB
] ;restore from prev dir
673 add dirsiz
,cx ;add in siz of clusters ;an049;bgb
674 ; put 4 words on the stack - for next call to dirproc?
675 PUSH [ERRSUB
] ;save the fcb ptr from prev dir
676 PUSH BX ;Save my srch FCB pointer
677 MOV AX,[SI].DirCLus
;get 1st cluster number
678 PUSH AX ; Give him his own first clus pointer
679 PUSH [BP+6] ; His PARENT is me
680 ;copy fcb name to msg string name
681 ADD SI,DIRNAM
;point to name, +08
682 MOV DI,OFFSET DG
:NAMBUF
683 savereg
<di,ax> ;copy to msg string
686 ;check out validity of dir
687 OR AX,AX ;does the 1st clus in dir point to zero?
688 JZ BogusDir
; no, it is bogus
690 DOS_Call ChDir
; chdir to it ;AC000;
691 JC CANTTARG
; carry means bad dir
692 ; go check out new dir
694 POP BX ;Get my SRCH FCB pointer back
695 POP [ERRSUB
] ;restore from prev dir
699 ;newdir error routines
702 ADD SP,8 ; Clean stack
703 mov SI,dx ; Pointer to bad DIR
705 MOV DX,OFFSET DG
:BADTarg_PTR
711 ADD SP,8 ; clean off stack
712 MOV SI,DX ; pointer to bad dir
713 CALL get_currdirERR
; output message with dir
714 MOV DX,OFFSET DG
:BadSubDir
; real error message
715 CALL EPRINT
; to stderr...
717 CMP [SECONDPASS
],False
; ;AC000;
721 ;;;;;;;;;;;;JNZ DDSIZOK ;Leave on second pass
724 cmp [NOISY
],on ; /v entered ? ;An027;bgb
725 ; $IF E ; no, skip next msg ;An027;bgb
727 MOV DX,OFFSET DG
:PTRANDIR
;unrecoverable error in directory ;An027;bgb
728 call printf_crlf
;display msg ;An027;bgb
732 MOV DX,OFFSET DG
:PTRANDIR2
;either case - "convert dir to file?" ;An027;bgb
733 CALL PROMPTYN
;Ask user what to do
737 ;;;;;;;;;;; JNZ DDSIZOK ;Leave on second pass
742 MOV AX,[BX+THISENT
] ;Entry number
743 CALL GETENT
;Get the entry
745 MOV DI,OFFSET DG
:DIRBUF
749 REP MOVSB ;Transfer entry to DIRBUF
752 MOV SI,[SI.DIRCLUS
] ;First cluster
757 MOV WORD PTR [SI.DIRESIZ
],AX ;Fix entry
758 MOV WORD PTR [SI.DIRESIZ
+2],DX
759 JMP CONVDIR
;convert directory
760 ;*****************************************************************************
762 ;*****************************************************************************
766 SUBTTL fat
-Look routines
768 ;*****************************************************************************
769 ; CROSSLOOK - look at the fat, check for cross linked files
771 ;****************************************************************************
773 ;Same as MRKFAT only simpler for pass 2
774 MOV [SRFCBPT
],BX ;an014;bgb
776 MOV SI,[BX.DIRCLUS
] ;an014;bgb
777 CALL CROSSCHK
;an014;bgb
778 JNZ CROSSLINK
;an014;bgb
779 ;;;;;;;;mov XA_Pass,False ;an014;bgb ;an014;bgb
783 CALL UNPACK
;an014;bgb
785 XCHG SI,DI ;an014;bgb
786 CMP SI,[EOFVAL
] ;an014;bgb
787 jae chaindone
;an014;bgb ;an014;bgb
788 ;;;;;;;;JAE Check_XA_Cross ;an014;bgb ;an014;bgb
789 CALL CROSSCHK
;an014;bgb
791 JMP SHORT CROSSLINK
;an014;bgb
793 Check_XA_Cross: ; ;AN000;
795 ;;;;;;;;mov SI,[BX.DIR_XA] ;See if extended attribute ;an014;bgb ;AN000;
796 ;;;;;;;;cmp si,0 ;Is there? ;an014;bgb ;AN000;
797 ;;;;;;;;je ChainDoneJ ;No if zero ;an014;bgb ;AN000;
798 ; CALL CROSSCHK ;Yes, see if crosslinked ;an014;bgb ;AN000;
799 ; JNZ CROSSLINKJ ;NZ means yes ;an014;bgb ;AN000;
800 ;A_Cross_Loop: ; ;an014;bgb ;AN000;
801 ; PUSH BX ; ;an014;bgb ;AN000;
802 ; CALL UNPACK ;Get next cluster ;an014;bgb ;AN000;
803 ; POP BX ; ;an014;bgb ;AN000;
804 ; XCHG SI,DI ; ;an014;bgb ;AN000;
805 ; CMP SI,[EOFVAL] ;Reach the end? ;an014;bgb ;AN000;
806 ; JAE ChainDoneJ ;Leave if so ;an014;bgb ;AN000;
807 ; CALL CROSSCHK ;See if crosslink ;an014;bgb ;AN000;
808 ; JZ XA_Cross_Loop ;Go check next cluster if not ;AN000;
809 ; jmp CrossLink ;Go handle crosslink ;an014;bgb ;AN000;
812 ;NOCLUSTERSJ: JMP NOCLUSTERS
815 CHASELOOP: ;an014;bgb
817 CALL UNPACK
;an014;bgb
820 XCHG SI,DI ;an014;bgb
821 CMP SI,[EOFVAL
] ;an014;bgb
822 JAE CHAINDONE
;an014;bgb
825 CMP SI,[MCLUS
] ;an014;bgb
827 MRKBAD: ;Bad cluster # in chain
830 CALL get_THISELERR
;an014;bgb
831 MOV DX,OFFSET dg
:BADCHAIN
;an014;bgb
832 CALL EPRINT
;an014;bgb
834 MOV DX,0FFFH ;Insert EOF ;an014;bgb
835 CMP [BIGFAT
],0 ;an014;bgb
836 JZ FAT12_1
;an014;bgb
837 MOV DX,0FFFFH ;an014;bgb
838 FAT12_1: ;an014;bgb ;an014;bgb ;an014;bgb
843 JMP SHORT CHAINDONE
;an014;bgb
846 CALL MARKMAP
;an014;bgb
847 JZ CHASELOOP
;an014;bgb
849 CROSSLINK: ;File is cross linked
850 INC [ISCROSS
] ;an014;bgb
851 CMP [SECONDPASS
],False
; ;an014;bgb ;AC000;
852 JZ CHAINDONE
;Crosslinks only on second pass ;an014;bgb
853 mov [cross_clus
],si ;Cluster number ;an014;bgb
854 CALL get_THISEL
;an014;bgb
855 Message File_Arg
;Print file out ;an014;bgb ;AN000;
856 MOV DX,OFFSET DG
:CROSS_arg
;Print message out ;an014;bgb ;AC000;
857 CALL PRINTf_crlf
;an014;bgb
860 TEST [BX.DIRATT
],ISDIR
861 JNZ NOSIZE
;Don't size dirs
863 JNZ NOSIZE
;Don't size cross linked files;an014;bgb
864 CMP [SECONDPASS
],False
;
865 JNZ NOSIZE
;Don't size on pass 2 (CX garbage)
869 PUSH AX ;Size in bytes of one alloc unit
871 MOV DI,DX ;Save allocation size
873 SUB AX,WORD PTR [BX.DIRESIZ
]
874 SBB DX,WORD PTR [BX.DIRESIZ
+2]
875 JC BADFSIZ
;Size to big
877 JNZ BADFSIZ
;Size to small
880 JB NOSIZE
;Size within one Alloc unit
881 PUSH DX ;Size too small
885 PUSH CX ;Save size of file
886 MOV WORD PTR [BX.DIRESIZ
],SI
887 MOV WORD PTR [BX.DIRESIZ
+2],DI
890 MOV DX,OFFSET DG
:BADCLUS
892 POP CX ;Restore size of file
901 JZ CHKSIZ
;Firclus is OK, Check size
902 MOV DX,OFFSET DG
:NULNZ
909 MOV [BX.DIRCLUS
],SI ;Set it to 0
910 MOV WORD PTR [BX.DIRESIZ
],SI ;Set size too
911 MOV WORD PTR [BX.DIRESIZ
+2],SI
913 INC [ZEROTRUNC
] ;Indicate truncation
918 MOV DX,OFFSET DG
:BADCLUS
919 CMP WORD PTR [BX.DIRESIZ
],0
920 JNZ ADJUST
;Size wrong
921 CMP WORD PTR [BX.DIRESIZ
+2],0
922 JNZ ADJUST
;Size wrong
923 JMP CHAINDONE
;Size OK
926 SUBTTL Routines for manipulating dir entries
930 ;Same as FIXENT only [SRFCBPT] points to the search FCB, BX points to the entry
935 restorereg
<cx,bx,si>
939 ;BX Points to search FCB
940 ;SI Points to Entry to fix
941 MOV [HAVFIX
],1 ;Indicate a fix
942 CMP [DOFIX
],0 ;did the user enter /f flag?
943 JZ fixret
;zero means no - dont fix it
944 savereg
<bp,bx,si,si>
945 MOV AX,[BX+THISENT
] ;Entry number
947 POP SI ;Entry pointer
948 ADD SI,DIRNAM
;Point to start of entry
953 restorereg
<si,bx,bp>
958 ;***************************************************************************** ;ac048;bgb
959 ; GETENT - calculate, and read into ram, the sector of the directory entry ;ac048;bgb
960 ; that is invalid. This entry can be in either the root directory, ;ac048;bgb
961 ; or in a sub-directory. If it is in the root, it can be in the first ;ac048;bgb
962 ; sector of the root dir, or in a subsequent sector. If it is in a ;ac048;bgb
963 ; subdirectory, it can be in the first cluster of the subdir, or in ;ac048;bgb
964 ; any subsequent cluster. It can also be in the first sector of the ;ac048;bgb
965 ; cluster, or in any of the following sectors within that cluster. ;ac048;bgb
967 ; WARNING!! NOTE!! --> this procedure has a limit on the input value of 64k ;ac048;bgb
968 ; entries. If the disk fails on an entry in a subdir ;ac048;bgb
969 ; which has an invalid entry past this value, then the ;ac048;bgb
970 ; calling procedure will probably wrap on this word value, ;ac048;bgb
971 ; causing getent to calc the wrong sector, and then ;ac048;bgb
972 ; corrupting the disk. Not likely, but poss. ;ac048;bgb
974 ; called by - nodot/mesd1 - no . entry found (always subdir) ;ac048;bgb
975 ; - noddot/mesd2 - no .. entry found (always subdir) ;ac048;bgb
976 ; - askconv/printtrmes - convert dir to file (can be in root) ;ac048;bgb
977 ; - makfillp - find root entry in which to place lost clus ;ac048;bgb
979 ; inputs - AX - desired entry num (in curr dir, reffed off BP) ;ac048;bgb
980 ; 0=. 1=.. 2=first entry ;ac048;bgb
981 ; DX - number of lost clusters
982 ; BP - ptr to extended fcb for this dir ;ac048;bgb
983 ; BP+6 - 1st cluster number of this dir ;ac048;bgb
985 ; output - AX - contains number of the disk to use for int26 ;ac048;bgb
986 ; DI - points to entry in subdir in ram ;ac048;bgb
987 ; DX - low sector number of the dir ;ac048;bgb
988 ; BX - ram offset of the sector ;ac048;bgb
989 ; Read_Write_Relative.Start_Sector_Hi - hi sector number of the dir ;ac048;bgb
991 ; Regs abused - all of 'em !! (ok, well, maybe not bp...) ;ac048;bgb
993 ;logic: 1. make sure there will not be a problem with the cluster number. This ;ac048;bgb
994 ; should not be a problem, since if the cluster number is invalid, it ;ac048;bgb
995 ; should have been flagged by previous routines. ;ac048;bgb
997 ; 2. calc clus-num & offset ;ac048;bgb
998 ; Entries * bytes/entry / BPS --> number of sectors from the beg of ;ac048;bgb
999 ; the dir. There are 16 entries per sector (starting at zero). The ;ac048;bgb
1000 ; bytes/entry and bytes/sector are condensed, giving a div by 16, ;ac048;bgb
1001 ; instead of "* 32 / 512". Now we have the first cluster (0-fff7), ;ac048;bgb
1002 ; the sector-offset (0-fff), and the entry-offset (0-f). ;ac048;bgb
1004 ; forumla: entry (0-ffff) / 16 = sector-offset (0-fff) ax ;ac048;bgb
1005 ; = entry-offset (0-f) dx ;ac048;bgb
1007 ; 3. if we are in the root directory, then we have the correct sector ;ac048;bgb
1008 ; number, so just add it to the starting sector number of the ;ac048;bgb
1009 ; directory. ;ac048;bgb
1011 ; 4. otherwise, we are in a subdirectory. Here, we need to get the ;ac048;bgb
1012 ; cluster-offset, since the sector-offset can be more than 1 cluster ;ac048;bgb
1013 ; in length. So, divide the sectors by (secs/clus) to get cluster- ;ac048;bgb
1014 ; offset. This value is now a power of 2, from 2 up to 16. ;ac048;bgb
1016 ; / sectors/cluster (2-16) = cluster offset AL ;ac048;bgb
1017 ; = sector offset AH ;ac048;bgb
1019 ; 5. If AL > 0, then we have to walk the fat chain to find the cluster ;ac048;bgb
1020 ; where this sector is. Fortunately, we have the starting cluster ;ac048;bgb
1021 ; number (BX), UNPACK will find the next cluster number, and we have ;ac048;bgb
1022 ; the number of clusters to jump (AL). So, move the appropriate ;ac048;bgb
1023 ; into the regs, and loop until completed. Now BX has the correct ;ac048;bgb
1024 ; cluster number. ;ac048;bgb
1026 ; 6. Now we need to translate the cluster and sector numbers into an ;ac048;bgb
1027 ; absolute, double word, sector number. FIGREC will do this. ;ac048;bgb
1029 ; 7. Now, from either root dir, or from subdir, we have the absolute ;ac048;bgb
1030 ; sector, so set up the regs, and call READ_DISK to read it into ram. ;ac048;bgb
1031 ; Now DX contains the sector number (low), and BX points to the ;ac048;bgb
1032 ; sector in ram. ;ac048;bgb
1034 ; 8. Finally, get the entry-offset that we had stored on the stack, and ;ac048;bgb
1035 ; translate it into a byte-offset by multpying it times the number of ;ac048;bgb
1036 ; bytes per entry (32). Now DI points to the entry in ram. ;ac048;bgb
1037 ;***************************************************************************** ;ac048;bgb
1039 mov bx,[bp+6] ;Get 1st cluster of subdir ;ac048;bgb
1040 ;double check for invalid cluster ;ac048;bgb
1041 cmp bx,[eofval
] ;Last entry in cluster? ;ac048;bgb
1044 mov bx,offset dg
:baddpbdir
;This should never happen ;ac048;bgb
1045 jmp fatal
;Danger, warning Phil Robins;ac048;bgbon
1049 CLUSISOK: ;ac048;bgb
1050 ;calc cluster number and offset ;ac048;bgb
1051 mov cx,16 ;32 bytes/entry / 512 bytes/sec ;ac048;bgb
1052 xor dx,dx ;zero out hi word for divide ;ac048;bgb
1053 div cx ;NOW- bx=first clus, ax=sec-offset, dx=entry-offset ;ac048;bgb
1054 ;NOTE: ax can be > 1 cluster ;ac048;bgb
1055 ;are we at the root? ;ac048;bgb
1056 or bx,bx ;cluster zero? ;ac048;bgb
1057 ; $IF Z ;yes, then we are in root dir ;ac048;bgb
1059 ;;;;;;;;jz wantroot ;Cluster 0 means root dir ;ac048;bgb
1060 WANTROOT: push dx ;restored as di- ptr to invalid entry ;ac048;bgb
1061 mov dx,ax ;get sector offset ;ac048;bgb
1062 add dx,[dirsec
] ;add in first sector of dir ;ac048;bgb
1063 mov Read_Write_Relative
.Start_Sector_High
,0 ;save hi value ;ac048;bgb
1064 ;;;;;;;;;;;JMP DOROOTDIR ;now ready for int25 ;ac048;bgb
1066 ; $ELSE ;not in root dir ;ac048;bgb
1069 NOTROOT: div csize
;divide by sectors/cluster (2-16) ;ac048;bgb
1070 ;AL=# cluster-offset (QUO), AH= sector-offset (REM);ac048;bgb
1071 mov cl,al ;get cluster offset from al ;ac048;bgb
1072 xor ch,ch ;zero out hi byte to make word value ;ac048;bgb
1073 or cx,cx ;do we have more than one cluster worth to go yet? ;ac048;bgb
1074 ; $IF NZ ;yes - we have to walk the chain to find it ;ac048;bgb
1076 ;;;;;;;;JCXZ GOTCLUS ;jump if cx reg = zero ;ac048;bgb
1077 mov si,bx ;move the cluster num for input ;ac048;bgb
1078 SKIPLP: call unpack
;find the next cluster number ;ac048;bgb
1079 xchg si,di ;move it into input position ;ac048;bgb
1080 loop skiplp
;do for number of cluster-offset ;ac048;bgb
1081 mov bx,si ;now we have the cluster number ;ac048;bgb
1085 ;calculate the sector from the cluster & sec-offset ;ac048;bgb
1086 GOTCLUS: push dx ;restored as di -> entry offset ;ac048;bgb
1087 call figrec
;Convert to sector # - ax=low, dx=hi ;ac048;bgb
1088 ; $ENDIF ;are we in root dir? ;ac048;bgb
1091 DOROOTDIR: ;ac048;bgb
1092 mov bx,[secbuf
] ;get offset of ram area ;ac048;bgb
1093 mov al,[alldrv
] ;get drive number ;ac048;bgb
1094 dec al ;adjust for int25 ;ac048;bgb
1095 RDRETRY: mov cx,1 ;read 1 sector ;ac048;bgb
1096 call Read_Disk
;do it ;ac048;bgb
1097 jnc rdok2
;was it good? ;ac048;bgb
1098 ;Need to handle 'Fail' option of critical error here ;ac048;bgb
1099 JZ RDRETRY
;ac048;bgb
1101 RDOK2: pop ax ;get byte-offset into sector ;ac048;bgb
1102 mov cl,5 ;value of 32= bytes per entry ;ac048;bgb
1103 shl ax,cl ;mul entry offset to get byte offset ;ac048;bgb
1104 add ax,bx ;add in offset of dir in ram ;ac048;bgb
1105 mov di,ax ;ac048;bgb
1106 mov al,[alldrv
] ;get drive number ;ac048;bgb
1107 dec al ;adjust for int26 ;ac048;bgb
1108 RET ;di now points to offending entry ;ac048;bgb
1109 ;***************************************************************************** ;ac048;bgb
1118 JNZ RET14
;Don't print it more than once
1120 JNZ RET14
;Don't print it if F switch specified
1121 mov dx,offset dg
:FIXMES_arg
1123 call DoCRLF
; ;AN000;
1128 CMP [SECONDPASS
],False
; ;AC000;
1134 mov byte ptr [arg_buf
],0
1143 mov byte ptr [arg_buf
],0
1151 ;*****************************************************************************
1152 ; called by: checkfiles
1153 ; inputs: AX - number of fragments
1155 ;*****************************************************************************
1157 MOV DI,OFFSET DG
:NAMBUF
1163 ; get drive letter prefix (c:\)
1164 mov di,offset dg
:arg_buf
1173 ; get the name of the current directory, and put it into es:di
1175 DOS_Call Current_Dir
; ;AC000;
1177 ;find the end of the string - it will be hex zero
1182 DEC SI ; Point at NUL
1184 POP SI ;point to begin of string
1186 JZ LPDONE
;If tail string NUL, no '/'
1187 ; move '\' for between path and filename
1189 CMP BYTE PTR [DI - 1],AL
1190 JZ ERRLOOP
; Don't double '/' if root
1193 ; move filename from ds:si to es:di until find hex zero
1200 ; finish off string with hex zero for asciiz
1206 ; Carry set if current directory is NOT spliced (joined) onto.
1207 ; Carry clear if current directory is spliced (joined) onto.
1209 MOV SI,OFFSET DG
:NUL
1210 CALL get_currdir
; Build ASCIZ text of current dir
1212 mov si,offset dg
:arg_buf
1213 mov di,offset dg
:TMP_SPC
1214 DOS_Call xNameTrans
; ;AC000;
1215 JC NT_SPLC
; Say NOT spliced if error
1216 CMP WORD PTR [TMP_SPC
+1],"\" SHL 8 OR ":"
1218 CMP BYTE PTR [TMP_SPC+3],0
1220 MOV AL,BYTE PTR [arg_buf] ; Source drive letter
1221 CMP AL,BYTE PTR [TMP_SPC] ; Different from dest if spliced
1222 JZ NT_SPLC ; Drive letter didn't change
1231 ;*****************************************************************************
1232 ;Routine name: MarkFAT
1233 ;*****************************************************************************
1235 ;Description: Trace the fat chain for a single file, marking entries in FATMap,
1236 ; and handling errors -
1237 ; (crosslink, truncation, allocation error, invalid cluster entry)
1239 ; called by : moredir
1242 ;Called Procedures: Unpack
1249 ;Change History: Created 5/10/87 MT
1251 ;Input: BX = pointer to search FCB
1252 ; AL is head mark with app type =81h
1253 ; SI = points to dir entry
1254 ; DI = cluster entry of file or XA in directory
1255 ; File_Size_Low/High = bytes length directory or XA structure says
1257 ; SecondPass = TRUE/FALSE
1258 ; XA_Pass = TRUE/FALSE
1259 ; EOFVal = 0FF8h/0FFF8h
1262 ; ZEROTRUNC is non zero if the file was trimmed to zero length
1263 ; ISCROSS is non zero if the file is cross linked
1265 ; Cluster_Count = number of clusters in chain
1266 ; carry flag is set if the clusters are ok
1267 ; fatmap entries - 81h = head of file,
1268 ; 01h = used cluster
1273 ; ZeroTrunc,IsCross = FALSE, SRFCBPT = BX, Cluster_Count = 0
1274 ; Get file cluster entry (CALL Unpack)
1275 ; IF cluster < 2 or > maximum cluster (MClus)
1276 ; Go handle invalid cluster (CALL Bad_Cluster)
1279 ; Go mark cluster in FATMap (CALL MarkMAP)
1280 ; Turn off head bit on FATMap marker
1283 ; IF SecondPass = FALSE
1284 ; Setup filename for message (CALL ThisEl)
1285 ; Display crosslink message (Call Eprint)
1287 ; ORELSE (no crosslink)
1288 ; Get next cluster (CALL Unpack)
1289 ; IF Cluster >= EOFVAL [(0/F)FF8h]
1290 ; Verify file sizes (CALL Check_Chain_Sizes)
1291 ; clc (Force loop to end)
1293 ; IF cluster < 2 or > maximum cluster (MClus)
1294 ; Go handle invalid cluster (CALL Bad_Cluster)
1295 ; clc (Force loop to end)
1297 ; stc (Force loop to keep goining
1304 ;*****************************************************************************
1305 Procedure MarkFAT ; ;AN000;
1308 mov Head_Mark,al ;Save flag to put in map ;AN000;
1309 mov ZeroTrunc,False ;Init values ; ;
1310 mov IsCross,False ; ; ;
1311 mov Cluster_Count,0 ;Init count of clusters ; ;
1312 mov SrFCBPt,bx ;Pointer to search FCB ; ;
1313 mov First_Cluster,di ; ;AN000;
1314 mov Previous_Cluster,di ;Init pointer
1315 cmp di,2 ;Cluster < 2? ;AC000;
1316 ; $IF B,OR ; or ;AC000;
1318 cmp di,MClus ;Cluster > total clusters? ;AC000;
1322 cmp word ptr [si].dirclus,0 ;if both cluster and size = 0, ;an025;bgb
1323 ; $IF NE,OR ;then its not an error, ;an025;bgb
1325 cmp word ptr [si].diresiz,0 ;and dont print msg ;an025;bgb
1329 call Bad_Cluster ;Yes, go indicate bad stuff ;AN000;
1332 ; $ELSE ;Cluster in valid range ;AN000;
1335 ; $SEARCH ;Chase the cluster chain ;AN000;
1337 mov al,Head_Mark ;Get flag for map 01 ;AC000;
1338 call MarkMap ;Mark the cluster (SI) ;AC000;
1339 push ax ;Save head mark ;AN000;
1340 lahf ;Save CY status
1341 and Head_Mark,Head_Mask ;Turn off head bit of map flag ;AC000;
1342 sahf ;Get CY flags back
1343 pop ax ;Get haed mark back ;AN000;
1344 ; $EXITIF C ;Quit if crosslink ;AC000;
1346 mov IsCross,True ;Set crosslink flag ;AC000;
1347 cmp SecondPass,True ;Handle crosslink 2nd pass only ;AC000;
1348 ; $IF E ;This is first pass ;AC000;
1350 mov Cross_Clus,di ;Put cluster in message ;AN000;
1351 push bx ;Get dir pointer into bx ;AN000;
1353 mov bx,si ; for the call ;AN000;
1354 call Get_ThisELErr ; ;AC000;
1355 mov dx,offset DG:Cross_arg ;Specify error message ;AC000;
1356 call EPrint ;Go print file and error ;AC000;
1359 Message Cross_Arg ; ;AC000;
1362 ; $ORELSE ;No crosslink found ;AN000;
1365 push si ;Save dir pointer
1366 mov si,di ;Provide current cluster
1367 mov Previous_Cluster,di ;Save current cluster
1368 call UnPack ;Get next cluster entry (di) ;AC000;
1369 inc Cluster_Count ;Got a cluster ;AN000;
1370 pop si ;Get dir pointer back
1371 cmp di,EOFVal ;Is it the last clus in file? ;AC000;
1372 ; $IF AE ;Yes - good chain so far ;AN000;
1374 call Check_Chain_Sizes ;Go verify file sizes ;AN000;
1375 clc ;Clear CY to force exit ;AN000;
1376 ; $ELSE ;Not end of chain
1379 cmp di,2 ;Cluster < 2? ;AC000;
1380 ; $IF B,OR ; or ;AC000;
1382 cmp di,MClus ;Cluster > total clusters? ;AC000;
1383 ; $IF A ;Yep ;AN000;
1386 call Bad_Cluster ;Yes, go indicate bad stuff ;AN000;
1387 clc ;Clear CY to force loop exit ;AN000;
1388 ; $ELSE ;No, more clusters to go ;AN000;
1391 stc ;Set CY to keep going ;AN000;
1396 ; $ENDLOOP NC ;Exit if done with chain ;AN000;
1398 ; $ENDSRCH ;End of chain chase loop ;AN000;
1402 pop bx ;Restore registers ;AN000;
1405 MarkFAT endp ; ;AN000;
1407 ;*****************************************************************************
1408 ;Routine name: Bad_Cluster
1409 ;*****************************************************************************
1411 ;description: IF first cluster =0, truncate file or XA to zero length.
1412 ; If bad cluster elsewhere, put in EOFVal.
1414 ;Called Procedures: Get_ThisElErr
1418 ;Change History: Created 5/10/87 MT
1420 ;Input: First_Cluster
1422 ; XA_PASS = TRUE/FALSE
1423 ; DI = Cluster entry
1424 ; SI = dir block pointer
1425 ; First_Cluster = first cluster or extended XA
1426 ; Previous_Cluster = last good cluster number
1428 ;Output: ZeroTrunc = TRUE/FALSE
1433 ; Setup filename for any messages (Call Get_ThisELErr)
1434 ; IF cluster = First_Cluster
1435 ; IF XA_PASS = FALSE
1436 ; Zero out file length in DIR
1437 ; Setup message (CALL Get_ThisElErr)
1438 ; Display message (Call Eprint)
1440 ; Zero out XA pointer
1441 ; Setup message (CALL Get_ThisElErr)
1442 ; Display message (Call Eprint)
1444 ; Write out corrected directory (CALL FixENT2)
1445 ; ELSE (cluster other than first in chain)
1447 ; Display Bad XA cluster message
1449 ; Display bad file chain message
1451 ; Move EOF into bad cluster (CALL PACK - Chain_End)
1454 ;*****************************************************************************
1455 Procedure Bad_Cluster ; ;AN000;
1456 savereg <si,di,dx,si,di,bx> ;Preserve registers ;AN000;
1457 mov bx,si ; for the call ;AN000;
1458 call Get_ThisElErr ;Setup message ;AC000;
1459 restorereg <bx,di,si>
1460 cmp di,First_Cluster ;does 1st clus point to itself? ;Need to change the directory ;AC000;
1461 ; $IF E,OR ;yes ; pointer if the dir cluster or ;AC000;
1463 push di ;if not, try this next test ; XA is bad, or the last good ;AN000;
1464 mov di,Previous_Cluster ;get prev cluster ; entry was the dir cluster or ;AN000;
1465 cmp di,First_Cluster ;does prev clus = 1st clus? ; XA cluster. ;AN000;
1466 pop di ;means the 1st cluster is bad
1467 ; $IF E ;yes ; ;AN000;
1470 cmp word ptr [si].dirclus,0 ;is cluster num already 0? ;an025;bgb
1471 ; $IF NE ;no, its bad ;an025;bgb
1473 mov dx,offset DG:NulNZ ;1st cluster number is invalid;an025;bgb
1474 call EPrint ;Go print file and error ;an025;bgb
1475 mov word ptr [si].dirclus,0 ;set cluster number to 0 ;an025;bgb
1476 mov zerotrunc,true ;modified the file size ;an026;bgb
1477 ; $ENDIF ;already set to 0, dont print err msg ;an025;bgb
1479 mov word ptr [si].DIRESIZ,0 ;set file size to 0 ;Kill the file size ;AC000;
1480 mov word ptr [si].DIRESIZ+2,0 ;Kill the file size ;AC000;0;
1481 mov bx,si ;Get pointer to directory ;AN000;
1482 call FixEnt2 ;Write out updated directory ;AC000;
1483 ; $ELSE ;Not first cluster in chain ;AN000;
1486 mov dx,offset dg:Badchain ;Tell user file and error ;AN000;
1488 mov dx,Chain_End ;Terminate chain at bad spot ;AC000;
1489 mov si,Previous_Cluster ;Change the last good cluster ;AC000;
1490 call Pack ;Go fix it ;AC000;
1493 restorereg <dx,di,si>
1495 Bad_Cluster endp ; ;AN000;
1497 ;*****************************************************************************
1498 ;Routine name: Check_Chain_Sizes
1499 ;*****************************************************************************
1501 ;description: See if length of chain as listed in dir or XA matches up
1502 ; with the number of clusters allocated. Don't check if crosslink
1503 ; error, or chasing directory chain.
1505 ;Called Procedures: FixEnt
1509 ;Change History: Created 5/10/87 MT
1511 ;Input: CSIZE = sectors per cluster
1512 ; SSIZE = bytes per sector
1513 ; Cluster_Count = number of clusters in chain
1514 ; File_Size_Low/High = bytes dir or XA says is in chain
1515 ; SI = Pointer to Dir entry
1517 ;Output: Cluster_Count = Size of chain in clusters
1518 ; SI = Pointer to dir entry
1524 ; IF !Directory attribute,AND
1525 ; IF !Crosslinked (ISCROSS = FALSE),AND
1526 ; IF !Second pass (SecondPass = FALSE)
1527 ; Compute bytes/cluster
1528 ; Compute bytes/chain
1529 ; IF size > File_Size_High/Low
1530 ; Fix the size (CALL Bad_Chain_Size)
1532 ; Subtract file size from chain length
1533 ; IF Difference in Chain_Length and Size >= bytes/cluster
1534 ; Fix the size (CALL Bad_Chain_Size)
1539 ; CX = Cluster_Count (kept for compatibility with old code)
1540 ; BX = SRFCPT (kept for compatibility with old code)
1542 ;*****************************************************************************
1543 Procedure Check_Chain_Sizes ;AN000;
1546 test [si].DirAtt,Dir_Attribute ;Is this a directory? ;AC000;
1547 ; $IF Z,AND ;No ;AC000;
1549 cmp IsCross,False ; and,is it crosslinked? ;AC000;
1550 ; $IF E,AND ;No ;AC000;
1552 cmp SecondPass,False ;and, is this the first pass? ;AC000;
1553 ; $IF E ;Yes, ;AC000;
1555 xor ax,ax ;AX =0 ;AC000;
1556 mov ax,SSize ;Get (bytes/sector) * ;AC000;
1557 mov cl,CSize ; (Sectors/cluster) ;AC000;
1558 mul cx ;AX=Bytes/cluster (< 64k) ;AC000;
1559 mov BClus,ax ;Save Bytes/cluster ;AN000;
1560 mov cx,Cluster_Count ;Number of clusters in chain ;AC000;
1561 mul cx ;DX:AX = bytes/chain ;AC000;
1562 mov Chain_Size_Low,ax ;Save allocation size in bytes ;AN000;
1563 mov Chain_Size_High,dx ; ;AN000;
1564 cmp dx,File_Size_High ;See if file size if greater ;AN000;
1565 ; $IF E,AND ; than chain length - if ;AN000;
1567 cmp ax,File_Size_Low ; so, than there is an ;AC000;
1568 ; $IF B ; allocation error. ;AC000;
1570 call Bad_Chain_Size ;Fix it! ;AC013;bgb
1571 ; $ELSE ;Chain larger than file ;AC000;
1574 cmp dx,File_Size_High ;See if high part lower ;AN000;
1575 ; $IF B ;Chain < filsize if so ;AN000;
1577 call Bad_Chain_Size ;Fix it! ;AC013;bgb
1578 ; $ELSE ;Chain > filesize ;AN000;
1581 mov cx,File_Size_Low ;See if within 1 cluster ;AN000;
1582 mov bx,File_Size_High ; ;AN000;
1583 sub ax,cx ;Subtract file size from ;AC000;
1584 sbb dx,bx ; the chain size ;AN000;
1585 cmp dx,0 ;See if within 1 cluster ;AN000;
1586 ; $IF NE,OR ;Not if high size set,or ;AN000;
1588 cmp ax,BClus ;Within (bytes/cluster -1)? ;AC000;
1589 ; $IF AE ;Nope, allocation error ;AC000;
1592 call Bad_Chain_Size ;Go fix the chain ;AN013;bgb
1601 mov bx,SrFCBPt ; Needed for compat ;AC000;
1602 pop ax ;Restore used regs ;AN000;
1603 pop si ;SI = Dir pointer ;AN000;
1605 check_chain_sizes endp ; ;AN000;
1609 Procedure print_filename ;AN000;
1613 mov dx,offset dg:noisy_arg
1618 print_filename endp ; ;AN000;
1620 ;these procedures were for the extended attribute support, which was removed ;an006;bgb
1622 ;*****************************************************************************
1623 ;Routine name: Bad_Chain_Size
1624 ;*****************************************************************************
1626 ;Description: adjust
1627 ; filesize to allocation length.
1629 ;Called Procedures: Truncate_XA
1634 ;Change History: Created 5/11/87 MT
1636 ;Input: XA_Pass = TRUE/FALSE
1637 ; Chain_Size_High/Low
1639 ; Chain_Size_Low/High = length in bytes of allocation chain
1647 ; Delete XA chain (CALL Truncate_XA)
1649 ; Set directory entry to length = Total allocation size
1650 ; Go write out (CALL FixEnt2)
1651 ; Setup message (CALL Get_Thiselerr)
1652 ; Display it (Call Eprint)
1655 ;*****************************************************************************
1656 Procedure Bad_Chain_Size ; ;AN000;
1658 push ax ;Save register ;AN000;
1660 push ds ;make es point to dg
1662 ;;;;;; cmp XA_Pass,True ;Are we handling XA's? ;AN013;bgb
1663 ;;;;;;;;$IF E ;Yes ;AN013;bgb
1664 ;;;;;;;;;;;call Truncate_XA ;Go truncate the chain ;AN013;bgb
1665 ;;;;;;;;$ELSE ;Normal file chain ;AN013;bgb
1666 mov ax,Chain_Size_Low ;Get length of allocation ;AN000;
1667 mov dx,Chain_Size_High ; chain for filesize ;AN000;
1668 mov word ptr [si].DirESiz,ax ;Put it in the directory ;AC000;
1669 mov word ptr [si+2].DirESiz,dx ; " " " " ;AC000;
1672 mov bx,si ;Get pointer to directory ;AN000;
1673 call FixENT2 ;Write dir to disk ;AC000;
1674 call Get_ThisElErr ;Setup message ;AC000;
1675 mov dx,offset DG:BadClus ;Specify error message ;AC000;
1676 call EPrint ;Go print file and error ;AC000;
1679 ;;;;;;;;$ENDIF ; ;AN013;bgb
1680 pop ax ;Restore registers ;AN000;
1684 Bad_Chain_Size endp ; ;AN000;
1686 ;*****************************************************************************
1687 ;Routine name: Truncate_XA
1688 ;*****************************************************************************
1690 ;Description: If /F entered, than truncate XA chain and remove pointer.
1691 ; If XA allocation error, than deallocate all of XA chain.
1693 ;Called Procedures: Get_ThisElErr
1699 ;Change History: Created 5/11/87 MT
1701 ;Input: First_Cluster
1703 ; SI = directory entry pointer
1706 ;Output: FATMap entries for XA chain zero'd out
1711 ; Set XA pointer in dir to 0
1712 ; Write it out (CALL FixEnt2)
1713 ; Setup message (Call get_ThisElErr
1714 ; Display message (Call Eprint)
1715 ; Get first cluster number (First_Cluster)
1717 ; Get first cluster entry (Call Unpack)
1718 ; Go mark cluster in FATMap with "Open
" (CALL MarkMAP)
1719 ; Set cluster entry with 0000 (Call Pack)
1720 ; ENDDO cluster value >= EOFVal
1722 ;*****************************************************************************
1724 ;rocedure Truncate_XA ; ;AN000;
1726 ; push si ;Save dir pointer ;AN000;
1729 ; mov bx,si ;Get directory pointer ;AN000;
1730 ; call Get_ThisEl ;Setup message ;AN000;
1731 ; mov dx,offset DG:Alloc_XA_Msg ;Specify error message ;AC000;
1732 ; call EPrint ;Go print file and error ;AC000;
1734 ; mov word ptr [si].DIR_XA,No_Ext_Attrib ;Erase XA pointer ;AN000;
1735 ; call FixENT2 ;Write dir entry out ;AN000;
1737 ; mov si,First_Cluster ;Get first cluster ;AN000;
1738 ; $DO ;Chase and erase XA chain ;AN000;
1739 ; call Unpack ;Get next cluster ;AN000;
1740 ; push di ;Save it- DI next, SI current ;AN000;
1741 ; mov al,No_Entry ;Free entry in map ;AN000;
1742 ; call MarkMap ; " " " " ;AN000;
1743 ; mov dx,No_Entry ;Free up cluster in Fat ;AN000;
1744 ; call Pack ; " " " " ;AN000;
1745 ; pop si ;Get back next cluster ;AN000;
1746 ; cmp si,[EOFVal] ;Reached end of chain? ;AN000;
1747 ; $ENDDO AE ;Keep looping if not ;AN000;
1748 ; pop si ;Restore Dir pointer ;AN000;
1751 ;runcate_XA endp ; ;AN000;
1753 ;*****************************************************************************
1754 ;Routine name: Check_Extended_Attributes
1755 ;*****************************************************************************
1757 ;Description: Get the first cluster of XA chain, if it is zero, than erase
1758 ; extended attribute pointer (/F only). Otherwise, map the
1759 ; cluster in the FATMAP. If crosslink found on first cluster,
1760 ; no more processing is done. If value other than EOF mark
1761 ; found in first cluster
1763 ;Called Procedures: Load_XA
1765 ; Check_XA_Structure
1768 ;Change History: Created 5/10/87 MT
1770 ;Input: SI = pointer to directory entry
1772 ;Output: FATMap marked with XA_Cluster for each XA cluster found
1778 ; IF (XA exists for file)
1780 ; DI = XA entry cluster in dir
1781 ; Load in first sector of XA (CALL Load_XA)
1783 ; File_Size_Low/High = length of XA's in bytes
1784 ; AL = chain head mark (XA_Chain)
1785 ; Trace chain and map it (CALL MarkFAT)
1791 ;*****************************************************************************
1793 ;rocedure Check_Extended_Attributes ; ;AN000;
1795 ; push ax ;Save register ;AN000;
1799 ; mov ax,[si].DIR_XA ;Get first cluster of XA's ;AN000;
1800 ; cmp ax,No_Ext_Attrib ;Are there extended attrib's ;AN000;
1801 ; $IF NE ;Quit if no ;AN000;
1802 ; mov di,ax ;Pointer to current cluster ;AN000;
1803 ; mov First_Cluster,di ;Remember first cluster ;AN000;
1804 ; mov XA_Pass,Yes ;Indicate processing XA's ;AN000;
1805 ; call Load_XA ;Go load sector ;AN000;
1806 ; $IF NC ;CY means load error ;AN000;
1807 ; mov ax,XA_Buffer.XAL_TSIZE ;Get bytes in XA chain ;AN000;
1808 ; mov File_Size_High,0 ;Save it ;AN000;
1809 ; mov File_Size_Low,ax ; ;AN000;
1810 ; mov al,XA_Chain ;Set up mark for map ;AN000;
1811 ; call MarkFAT ;Go map out chain ;AN000;
1812 ; $ELSE ;Error on read of XA ;AN000;
1813 ; call Bad_Cluster ;Delete extended attribs ;AN000;
1816 ; pop di ;Restore registers
1822 ;heck_Extended_Attributes endp ; ;AN000;
1825 ;*****************************************************************************
1826 ;Routine name: Load_XA
1827 ;*****************************************************************************
1829 ;description: Read in the first XA cluster
1831 ;Called Procedures: Read_Disk
1834 ;Change History: Created 5/13/87 MT
1836 ;Input: AX has start cluster of XA chain
1838 ;Output: CY if read failed
1843 ; Get start of data area
1845 ; Compute XA location from starting cluster
1846 ; Read it in (CALL Read_Disk)
1849 ; ENDIF (NC if didn't take IF)
1851 ;*****************************************************************************
1853 ;rocedure Load_XA ; ;AN000;
1855 ; push si ;Save used registers ;AN000;
1859 ; sub ax,2 ;Make cluster 0 based ;AN000;
1860 ; mov cl,CSize ;Get sectors/cluster ;AN000;
1861 ; mul cl ;Offset sec in data area ;AN000;
1862 ; add ax,Data_Start_Low ;Get actual sector in partition ;AN000;
1863 ; adc dx,Data_Start_High ; " " " " ;AN000;
1864 ; mov Read_Write_Relative.Start_Sector_High,dx ;Setup high sector addr;AN000;
1865 ; mov bx,offset dg:XA_Buffer ;Read into buffer ;AN000;
1866 ; mov cx,1 ;Get just first sector ;AN000;
1867 ; mov dx,ax ;Get logical sector low ;AN000;
1868 ; mov al,AllDrv ;Get drive number 1=A,2=B ;AN000;
1869 ; dec al ;Make 0 based drive 0=A ;AN000;
1870 ; call Read_Disk ;Read in sector ;AN000;
1871 ; $IF C ;Problem? ;AN000;
1874 ; pop bx ;Restore registers ;AN000;
1880 ;oad_XA endp ; ;AN000;
1882 ;****************************************************************************
1883 ;WARNING!!! this must be the last label in the code section
1884 ; any changes to chkdsk.arf must take into account this area.
1885 ; it is used for reading things from disk into memory, such as dir
1887 Chkprmt_End label byte
1888 ;****************************************************************************