1 TITLE CHKPROC
- Procedures called
from chkdsk
10 SUBTTL Segments
used in load order
15 CONST
SEGMENT PUBLIC BYTE
17 EXTRN CLUSBAD
:BYTE,BADATT
:BYTE,BADSIZM
:BYTE
18 EXTRN DIRECMES
:BYTE,CDDDMES
:BYTE,NDOTMES
:BYTE
19 EXTRN BADTARG1
:BYTE,BADTARG2
:BYTE,FATALMES
:BYTE
20 EXTRN STACKMES
:BYTE,BADDPBDIR
:BYTE,CREATMES
:BYTE
21 EXTRN FREEBYMES_PRE
:BYTE,FREEBYMESF_PRE
:BYTE
22 EXTRN FREEBYMES_POST
:BYTE,FREEBYMESF_POST
:BYTE
23 EXTRN NULNZ
:BYTE,NULDMES
:BYTE,BADCLUS
:BYTE
24 EXTRN NORECDDOT
:BYTE,NORECDOT
:BYTE,DOTMES
:BYTE
25 EXTRN BADWRITE_PRE
:BYTE,BADCHAIN
:BYTE,CROSSMES_PRE
:BYTE
26 EXTRN BADWRITE_POST
:BYTE,CROSSMES_POST
:BYTE,INDENT
:BYTE
27 EXTRN PTRANDIR
:BYTE,PTRANDIR2
:BYTE,FREEMES
:BYTE,FIXMES
:BYTE
29 EXTRN NOISY
:BYTE,DOFIX
:BYTE,DIRBUF
:WORD,DOTENT
:BYTE,FIXMFLG
:BYTE
30 EXTRN HAVFIX
:BYTE,SECONDPASS
:BYTE,LCLUS
:WORD,DIRTYFAT
:BYTE
31 EXTRN NUL
:BYTE,ALLFILE
:BYTE,PARSTR
:BYTE,ERRSUB
:WORD,USERDIR
:BYTE
32 EXTRN HIDCNT
:WORD,HIDSIZ
:WORD,FILCNT
:WORD,FILSIZ
:WORD,DIRCHAR
:BYTE
33 EXTRN DIRCNT
:WORD,DIRSIZ
:WORD,FRAGMENT
:BYTE,HECODE
:BYTE
34 EXTRN BADSIZ
:WORD,ORPHSIZ
:WORD,DDOTENT
:BYTE,CROSSCNT
:WORD
35 EXTRN ORPHCNT
:WORD,ORPHFCB
:BYTE,ORPHEXT
:BYTE,ALLDRV
:BYTE,DIRCHAR
:BYTE
39 DATA SEGMENT PUBLIC WORD
41 EXTRN THISDPB
:DWORD,HARDCH
:DWORD,CONTCH
:DWORD,USERDEV
:BYTE
42 EXTRN CSIZE
:BYTE,SSIZE
:WORD,DSIZE
:WORD,MCLUS
:WORD,NAMBUF
:BYTE
43 EXTRN DOTSNOGOOD
:BYTE,ZEROTRUNC
:BYTE,ISCROSS
:BYTE,SRFCBPT
:WORD
44 EXTRN FATMAP
:WORD,SECBUF
:WORD,ERRCNT
:BYTE,STACKLIM
:WORD,FAT
:WORD
48 DG GROUP
CODE,CONST
,DATA
50 SUBTTL Initialized
Data
55 ASSUME
CS:DG
,DS:DG
,ES:DG
,SS:DG
57 PUBLIC INT_23
,INT_24
,FINDCHAIN
,DONE
,AMDONE
,RDONE
58 PUBLIC FATAL
,DIRPROC
,CHKMAP
,CHKCROSS
,UNPACK
59 PUBLIC PRINTTHISEL2
,CHECKERR
,PRINTCURRDIRERR
61 EXTRN EPRINT
:NEAR,DOCRLF
:NEAR,PRINT
:NEAR
62 EXTRN PROMPTYN
:NEAR,DOINT26
:NEAR,SUBERRP
:NEAR
63 EXTRN DOTCOMBMES
:NEAR,DISP16BITS
:NEAR
64 EXTRN CHAINREPORT
:NEAR,DISPCLUS
:NEAR
65 EXTRN PRTCHR
:NEAR,WDSKERR
:NEAR,CHECKFILES
:NEAR
66 EXTRN FCB_TO_ASCZ
:NEAR,FIGREC
:NEAR,RDSKERR
:NEAR
70 SUBTTL DIRPROC
-- Recursive directory processing
72 ; YOU ARE ADVISED NOT TO COPY THE FOLLOWING METHOD!!!
77 MOV [DI.dpb_current_dir
],-1 ;Invalidate path
82 LODSB ;Scan to end of current path
85 DEC SI ;Point at the NUL
86 DELLOOP: ;Delete last element
102 MOV DX,OFFSET DG:DOTMES
103 MOV AH,CHDIR ;Chdir to altered path
109 MOV [DI.dpb_current_dir],0 ;Set Path to Root
110 JMP SHORT SETCURR ;The CHDIR will fail, but who cares
113 ;Structures used by DIRPROC
118 SFCBSIZ EQU SIZE SRCHFCB
119 THISENT EQU 17H ;Relative entry number of current entry
122 DB 7 DUP (?) ;Ext FCB junk
132 ENTSIZ EQU SIZE DIRENT
145 PUSH AX ;Return from SRCH
151 MOV SI,OFFSET DG:DOTMES
153 MOV DX,OFFSET DG:NDOTMES
162 CMP BYTE PTR [DI],0E5H ;Have place to put .?
164 MOV SI,OFFSET DG:DOTENT
180 MOV [HAVFIX],1 ;Have a fix
182 JZ DOTGOON ;No fix if not F
191 MOV DX,OFFSET DG:NORECDOT
197 MOV SI,OFFSET DG:DIRBUF
198 JMP CHKDOTDOT ;Go look for ..
201 PUSH AX ;Return from SRCH
207 MOV SI,OFFSET DG:PARSTR
209 MOV DX,OFFSET DG:NDOTMES
218 CMP BYTE PTR [DI],0E5H ;Place to put it?
220 MOV SI,OFFSET DG:DDOTENT
236 MOV [HAVFIX],1 ;Got a fix
238 JZ NFIX ;No fix if no F, carry clear
245 MOV SI,OFFSET DG:DIRBUF
246 JMP ROOTDIR ;Process files
254 MOV DX,OFFSET DG:NORECDDOT
266 MOV DX,OFFSET DG:NULDMES
268 DOTSBAD: ;Can't recover
269 MOV DX,OFFSET DG:BADTARG2
273 JMP DIRDONE ;Terminate tree walk at this level
275 ROOTDIRJ: JMP ROOTDIR
279 ;Recursive tree walker
280 ;dirproc(self,parent)
281 MOV [DOTSNOGOOD],0 ;Init to dots OK
282 MOV [ERRSUB],0 ;No subdir errors yet
283 PUSH BP ;Save frame pointer
285 SUB SP,SFCBSIZ ;Only local var
288 MOV BX,OFFSET DG:STACKMES ;Out of stack
294 JNZ NOPRINT ;Don't do it again on second pass
295 MOV DX,OFFSET DG:DIRECMES ;Tell user where we are
301 MOV SI,OFFSET DG:ALLFILE
305 REP MOVSB ;Initialize search FCB
307 MOV BX,DX ;BX points to SRCH FCB
308 MOV AH,DIR_SEARCH_FIRST
310 CMP WORD PTR [BP+6],0 ;Am I the root
311 JZ ROOTDIRJ ;Yes, no . or ..
314 JMP NULLDIRERR ;Dir is empty!
316 MOV SI,OFFSET DG:DIRBUF + DIRNAM
317 MOV DI,OFFSET DG:DOTENT
320 JZ DOTOK ;Got a . as first entry
323 MOV SI,OFFSET DG:DIRBUF
327 PUSH SI ;. not a dir?
328 MOV SI,OFFSET DG:DOTMES
329 MOV DX,OFFSET DG:BADATT
336 CMP AX,[BP+6] ;. link = MYSELF?
338 PUSH SI ;Link messed up
339 MOV SI,OFFSET DG:DOTMES
340 MOV DX,OFFSET DG:CLUSBAD
347 MOV AX,WORD PTR [SI.DIRESIZ]
350 MOV AX,WORD PTR [SI.DIRESIZ+2]
353 BADDSIZ: ;Size should be zero
355 MOV SI,OFFSET DG:DOTMES
356 MOV DX,OFFSET DG:BADSIZM
360 MOV WORD PTR [SI.DIRESIZ],AX
361 MOV WORD PTR [SI.DIRESIZ+2],AX
363 DSIZOK: ;Get next (should be ..)
365 MOV AH,DIR_SEARCH_NEXT
367 CHKDOTDOT: ;Come here after . failure
370 NODDOTJ: JMP NODDOT ;No ..
372 MOV SI,OFFSET DG:DIRBUF + DIRNAM
373 MOV DI,OFFSET DG:DDOTENT
377 MOV SI,OFFSET DG:DIRBUF
380 JNZ DDATTOK ;.. must be a dir
382 MOV SI,OFFSET DG:PARSTR
383 MOV DX,OFFSET DG:BADATT
391 CMP AX,[BP+4] ;.. link must be PARENT
393 MOV SI,OFFSET DG:PARSTR
394 MOV DX,OFFSET DG:CLUSBAD
401 MOV AX,WORD PTR [SI.DIRESIZ]
404 MOV AX,WORD PTR [SI.DIRESIZ+2]
407 BADDDSIZ: ;.. size should be 0
409 MOV SI,OFFSET DG:PARSTR
410 MOV DX,OFFSET DG:BADSIZM
414 MOV WORD PTR [SI.DIRESIZ],AX
415 MOV WORD PTR [SI.DIRESIZ+2],AX
418 MOV DX,BX ;Next entry
419 MOV AH,DIR_SEARCH_NEXT
422 ROOTDIR: ;Come here after .. failure also
424 JZ MOREDIR ;More to go
425 CMP WORD PTR [BP+6],0 ;Am I the root?
426 JZ DIRDONE ;Yes, no chdir
427 MOV DX,OFFSET DG:PARSTR
428 MOV AH,CHDIR ;Chdir to parent (..)
435 MOV DX,OFFSET DG:CDDDMES
438 CALL DOTDOTHARDWAY ;Try again
440 MOV SP,BP ;Pop local vars
441 POP BP ;Restore frame
445 MOV SI,OFFSET DG:DIRBUF
446 TEST [SI.DIRATT],ISDIR
447 JNZ NEWDIR ;Is a new directory
449 JZ FPROC1 ;First pass
450 CALL CROSSLOOK ;Check for cross links
455 MOV DX,OFFSET DG:INDENT ;Tell user where we are
464 MOV AL,81H ;Head of file
466 TEST [SI.DIRATT],VOLIDA
467 JNZ HIDENFILE ;VOL ID counts as hidden
468 TEST [SI.DIRATT],HIDDN
482 CALL CROSSLOOK ;Check for cross links
485 MOV AL,82H ;Head of dir
490 JZ DPROC2 ;Dir not truncated
492 AND [SI.DIRATT],NOT ISDIR ;Turn into file
497 PUSH BX ;Save my srch FCB pointer
498 PUSH [SI.DIRCLUS] ;MYSELF for next directory
499 PUSH [BP+6] ;His PARENT is me
501 MOV DI,OFFSET DG:NAMBUF
505 MOV AH,CHDIR ;CHDIR to new dir
509 POP BX ;Get my SRCH FCB pointer back
520 PUSH DX ;Save pointer to bad DIR
521 MOV DX,OFFSET DG:BADTARG1
523 POP SI ;Pointer to bad DIR
525 MOV DX,OFFSET DG:BADTARG2
527 DDSIZOKJ: JMP DDSIZOK ;Next
531 JNZ DDSIZOKJ ;Leave on second pass
532 MOV DX,OFFSET DG:PTRANDIR
535 MOV DX,OFFSET DG:PTRANDIR2
537 CALL PROMPTYN ;Ask user what to do
538 JNZ DDSIZOKJ ;User say leave alone
541 MOV AX,[BX+THISENT] ;Entry number
542 CALL GETENT ;Get the entry
544 MOV DI,OFFSET DG:DIRBUF
548 REP MOVSB ;Transfer entry to DIRBUF
551 MOV SI,[SI.DIRCLUS] ;First cluster
556 MOV WORD PTR [SI.DIRESIZ],AX ;Fix entry
557 MOV WORD PTR [SI.DIRESIZ+2],DX
560 SUBTTL FAT Look routines
563 ;Same as MRKFAT only simpler for pass 2
578 CROSSLINKJ: JMP SHORT CROSSLINK
587 NOCLUSTERSJ: JMP NOCLUSTERS
590 ; Map the file and perform checks
591 ; SI points to dir entry
592 ; AL is head mark with app type
593 ; On return CX is number of clusters
595 ; ZEROTRUNC is non zero if the file was trimmed to zero length
596 ; ISCROSS is non zero if the file is cross linked
598 MOV [ZEROTRUNC],0 ;Initialize
605 JB NOCLUSTERSJ ;Bad cluster # or nul file (SI = 0)
607 JA NOCLUSTERSJ ;Bad cluster #
611 JZ NOCLUSTERSJ ;Bad cluster (it is marked free)
614 AND AL,7FH ;Turn off head bit
627 MRKBAD: ;Bad cluster # in chain
631 MOV DX,OFFSET DG:BADCHAIN
634 MOV DX,0FFFH ;Insert EOF
639 CHAINDONEJ: JMP SHORT CHAINDONE
644 CROSSLINK: ;File is cross linked
647 JZ CHAINDONE ;Crosslinks only on second pass
648 PUSH SI ;Cluster number
651 MOV DX,OFFSET DG:CROSSMES_PRE
656 MOV BX,OFFSET DG:CROSSMES_POST
662 TEST [BX.DIRATT],ISDIR
663 JNZ NOSIZE ;Don't size dirs
665 JNZ NOSIZE ;Don't size cross linked files
667 JNZ NOSIZE ;Don't size on pass 2 (CX garbage)
671 PUSH AX ;Size in bytes of one alloc unit
673 MOV DI,DX ;Save allocation size
675 SUB AX,WORD PTR [BX.DIRESIZ]
676 SBB DX,WORD PTR [BX.DIRESIZ+2]
677 JC BADFSIZ ;Size to big
679 JNZ BADFSIZ ;Size to small
682 JB NOSIZE ;Size within one Alloc unit
683 PUSH DX ;Size to small
686 PUSH CX ;Save size of file
687 MOV WORD PTR [BX.DIRESIZ],SI
688 MOV WORD PTR [BX.DIRESIZ+2],DI
691 MOV DX,OFFSET DG:BADCLUS
693 POP CX ;Restore size of file
702 JZ CHKSIZ ;Firclus is OK, Check size
703 MOV DX,OFFSET DG:NULNZ
710 MOV [BX.DIRCLUS],SI ;Set it to 0
711 MOV WORD PTR [BX.DIRESIZ],SI ;Set size too
712 MOV WORD PTR [BX.DIRESIZ+2],SI
714 INC [ZEROTRUNC] ;Indicate truncation
718 MOV DX,OFFSET DG:BADCLUS
719 CMP WORD PTR [BX.DIRESIZ],0
720 JNZ ADJUST ;Size wrong
721 CMP WORD PTR [BX.DIRESIZ+2],0
722 JNZ ADJUST ;Size wrong
723 JMP CHAINDONE ;Size OK
726 ;Cluster number in SI, Return contents in DI, BX destroyed
727 ;ZERO SET IF CLUSTER IS FREE
732 MOV DI,WORD PTR [DI+BX]
744 ; SI CLUSTER NUMBER TO BE PACKED
745 ; DX DATA TO BE PLACED IN CLUSTER (SI)
747 MOV [DIRTYFAT],1 ;Set FAT dirty byte
748 MOV [HAVFIX],1 ;Indicate a fix
778 ; ZERO RESET IF CROSSLINK, AH IS THE MARK THAT WAS THERE
786 INC [CROSSCNT] ;Count the crosslink
787 OR AL,10H ;Resets zero
795 ;Compare FAT and FATMAP looking for badsectors orphans
804 JNZ CONTLP ;Already seen this one
808 JZ CONTLP ;Free cluster
809 CMP DI,0FF7H ;Bad sector?
810 JNZ ORPHAN ;No, found an orphan
812 MOV BYTE PTR [SI-1],4 ;Flag it
816 MOV BYTE PTR [SI-1],8 ;Flag it
827 ;free orphans or do chain recovery
831 MOV DX,OFFSET DG:FREEMES
832 CALL PROMPTYN ;Ask user
836 MOV SI,[FATMAP] ;Free all orphans
848 CALL PACK ;Mark as free
857 MOV DX,OFFSET DG:FREEBYMESF_PRE
860 MOV DX,OFFSET DG:FREEBYMES_PRE
864 MOV BX,OFFSET DG:FREEBYMESF_POST
867 MOV BX,OFFSET DG:FREEBYMES_POST
870 CALL DISPCLUS ;Tell how much freed
874 ;Do chain recovery on orphans
884 TEST AL,1 ;Seen before ?
886 PUSH SI ;Save search environment
890 OR BYTE PTR [SI],81H ;Mark as seen and head
891 INC [ORPHCNT] ;Found a chain
900 JB INSERTEOF ;Bad cluster number
902 JA INSERTEOF ;Bad cluster number
904 JZ INSERTEOF ;Tight loop
906 TEST AH,8 ;Points to a non-orphan?
909 POP SI ;Need to stick EOF here
914 TEST AH,80H ;Previosly marked head?
916 AND BYTE PTR [DI],NOT 80H ;Turn off head bit
917 DEC [ORPHCNT] ;Wasn't really a head
921 TEST AH,1 ;Previosly seen?
922 JNZ INSERTEOF ;Yup, don't make a cross link
923 OR BYTE PTR [DI],1 ;Mark as seen
925 JMP CHAINLP ;Follow chain
928 POP DX ;Restore search
939 MOV CX,[DI.dpb_root_entries]
960 CMP BYTE PTR [DI],0E5H
965 MOV [HAVFIX],1 ;Making a fix
967 JZ ENTMADE ;Not supposed to, carry clear
968 MOV [DI+26],SI ;FIRCLUS Pointer
969 PUSH AX ;Save INT 26 data
972 MOV AH,DISK_RESET ;Force current state
974 MOV DX,OFFSET DG:ORPHFCB
980 CALL MAKORPHNAM ;Try next name
984 MOV SI,OFFSET DG:ORPHFCB + 1 ;ORPHFCB Now has good name
987 CALL MAKORPHNAM ;Make next name
1029 SUB [ORPHCNT],DX ;Couldn't make them all
1030 MOV DX,OFFSET DG:CREATMES
1034 MAKFILLPJ: JMP MAKFILLP
1047 MOV SI,OFFSET DG:ORPHEXT - 1
1050 CMP BYTE PTR [SI],'9'
1052 MOV BYTE PTR [SI],'0'
1061 ;SI is start cluster, returns filesize as DX:AX
1081 ;Check for Crosslinks, do second pass if any to find pairs
1090 CALL DIRPROC ;Do it again
1093 SUBTTL AMDONE - Finish up routine
1098 JZ NOWRITE ;FAT not dirty
1100 JZ NOWRITE ;Not supposed to fix
1104 MOV CL,[BX.dpb_FAT_size] ;Sectors for one fat
1107 MOV CL,[BX.dpb_FAT_count] ;Number of FATs
1108 MOV DX,[BX.dpb_first_FAT] ;First sector of FAT
1113 MOV BX,OFFSET DG:FAT
1124 INT 26H ;Write out the FAT
1129 MOV DX,OFFSET DG:BADWRITE_PRE
1135 MOV DX,OFFSET DG:BADWRITE_POST
1144 LOOP WRTLOOP ;Next FAT
1145 POP CX ;Number of FATs
1146 CMP CL,[ERRCNT] ;Error on all?
1151 MOV AH,DISK_RESET ;Invalidate any buffers in system
1153 MOV DX,OFFSET DG:USERDIR ;Recover users directory
1156 CMP BYTE PTR [FRAGMENT],1 ;Check for any fragmented files?
1157 JNZ DONE ;No -- we're finished
1158 CALL CHECKFILES ;Yes -- report any fragments
1161 MOV DL,[USERDEV] ;Recover users drive
1162 MOV AH,SET_DEFAULT_DRIVE
1166 SUBTTL Routines for manipulating dir entries
1169 ;Same as FIXENT only [SRFCBPT] points to the search FCB, BX points to the entry
1182 ;BX Points to search FCB
1183 ;SI Points to Entry to fix
1184 MOV [HAVFIX],1 ;Indicate a fix
1186 JZ RET20 ;But don't do it!
1190 PUSH SI ;Entry pointer
1191 MOV AX,[BX+THISENT] ;Entry number
1193 POP SI ;Entry pointer
1194 ADD SI,DIRNAM ;Point to start of entry
1205 ;AX is desired entry number (in current directory)
1207 ;DI points to entry in SECBUF
1208 ;AX DX BX set to do an INT 26 to write it back out (CX must be reset to 1)
1209 ;ALL registers destroyed (via int 25)
1212 MOV BX,[DI.dpb_current_dir]
1218 MOV BX,OFFSET DG:BADDPBDIR ;This should never happen
1225 RCL DX,1 ;Account for overflow
1227 AND CL,255-31 ;Must be a multiple of 32
1228 DIV CX ;DX is position in sector, AX is dir sector #
1231 DIV [CSIZE] ;AL # clusters to skip, AH position in cluster
1242 PUSH DX ;Position in sector
1243 CALL FIGREC ;Convert to sector #
1263 POP DI ;Offset into sector
1264 ADD DI,BX ;Add sector base offset
1272 ADD DX,[DI.dpb_dir_sector]
1282 JNZ RET14 ;Don't print it more than once
1284 JNZ RET14 ;Don't print it if F switch specified
1286 MOV DX,OFFSET DG:FIXMES
1314 MOV DI,OFFSET DG:NAMBUF
1327 CMP [SI.dpb_current_dir],0
1346 JZ LPDONE ;If tail string NUL, no '/'
1360 ;Unrecoverable error
1361 MOV DX,OFFSET DG:FATALMES
1365 MOV DL,[USERDEV] ;At least leave on same drive
1366 MOV AH,SET_DEFAULT_DRIVE
1371 INT_24_RETADDR DW OFFSET DG:INT_24_BACK
1374 ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
1377 PUSH [INT_24_RETADDR]
1378 PUSH WORD PTR [HARDCH+2]
1379 PUSH WORD PTR [HARDCH]
1386 CALL DONE ;Forget about directory, restore users drive
1393 MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 24H
1396 MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H
1403 CALL NOWRITE ;Restore users drive and directory