From 80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 Mon Sep 17 00:00:00 2001 From: Rich Turner Date: Fri, 12 Aug 1983 17:53:34 -0700 Subject: MS-DOS v2.0 Release --- v2.0/source/CHKPROC.ASM | 1408 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1408 insertions(+) create mode 100644 v2.0/source/CHKPROC.ASM (limited to 'v2.0/source/CHKPROC.ASM') diff --git a/v2.0/source/CHKPROC.ASM b/v2.0/source/CHKPROC.ASM new file mode 100644 index 0000000..b003f83 --- /dev/null +++ b/v2.0/source/CHKPROC.ASM @@ -0,0 +1,1408 @@ +TITLE CHKPROC - Procedures called from chkdsk + +FALSE EQU 0 +TRUE EQU NOT FALSE + +DRVCHAR EQU ":" + + INCLUDE DOSSYM.ASM + +SUBTTL Segments used in load order + +CODE SEGMENT PUBLIC +CODE ENDS + +CONST SEGMENT PUBLIC BYTE + + EXTRN CLUSBAD:BYTE,BADATT:BYTE,BADSIZM:BYTE + EXTRN DIRECMES:BYTE,CDDDMES:BYTE,NDOTMES:BYTE + EXTRN BADTARG1:BYTE,BADTARG2:BYTE,FATALMES:BYTE + EXTRN STACKMES:BYTE,BADDPBDIR:BYTE,CREATMES:BYTE + EXTRN FREEBYMES_PRE:BYTE,FREEBYMESF_PRE:BYTE + EXTRN FREEBYMES_POST:BYTE,FREEBYMESF_POST:BYTE + EXTRN NULNZ:BYTE,NULDMES:BYTE,BADCLUS:BYTE + EXTRN NORECDDOT:BYTE,NORECDOT:BYTE,DOTMES:BYTE + EXTRN BADWRITE_PRE:BYTE,BADCHAIN:BYTE,CROSSMES_PRE:BYTE + EXTRN BADWRITE_POST:BYTE,CROSSMES_POST:BYTE,INDENT:BYTE + EXTRN PTRANDIR:BYTE,PTRANDIR2:BYTE,FREEMES:BYTE,FIXMES:BYTE + + EXTRN NOISY:BYTE,DOFIX:BYTE,DIRBUF:WORD,DOTENT:BYTE,FIXMFLG:BYTE + EXTRN HAVFIX:BYTE,SECONDPASS:BYTE,LCLUS:WORD,DIRTYFAT:BYTE + EXTRN NUL:BYTE,ALLFILE:BYTE,PARSTR:BYTE,ERRSUB:WORD,USERDIR:BYTE + EXTRN HIDCNT:WORD,HIDSIZ:WORD,FILCNT:WORD,FILSIZ:WORD,DIRCHAR:BYTE + EXTRN DIRCNT:WORD,DIRSIZ:WORD,FRAGMENT:BYTE,HECODE:BYTE + EXTRN BADSIZ:WORD,ORPHSIZ:WORD,DDOTENT:BYTE,CROSSCNT:WORD + EXTRN ORPHCNT:WORD,ORPHFCB:BYTE,ORPHEXT:BYTE,ALLDRV:BYTE,DIRCHAR:BYTE + +CONST ENDS + +DATA SEGMENT PUBLIC WORD + + EXTRN THISDPB:DWORD,HARDCH:DWORD,CONTCH:DWORD,USERDEV:BYTE + EXTRN CSIZE:BYTE,SSIZE:WORD,DSIZE:WORD,MCLUS:WORD,NAMBUF:BYTE + EXTRN DOTSNOGOOD:BYTE,ZEROTRUNC:BYTE,ISCROSS:BYTE,SRFCBPT:WORD + EXTRN FATMAP:WORD,SECBUF:WORD,ERRCNT:BYTE,STACKLIM:WORD,FAT:WORD + +DATA ENDS + +DG GROUP CODE,CONST,DATA + +SUBTTL Initialized Data +PAGE + + +CODE SEGMENT PUBLIC +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + + PUBLIC INT_23,INT_24,FINDCHAIN,DONE,AMDONE,RDONE + PUBLIC FATAL,DIRPROC,CHKMAP,CHKCROSS,UNPACK + PUBLIC PRINTTHISEL2,CHECKERR,PRINTCURRDIRERR + + EXTRN EPRINT:NEAR,DOCRLF:NEAR,PRINT:NEAR + EXTRN PROMPTYN:NEAR,DOINT26:NEAR,SUBERRP:NEAR + EXTRN DOTCOMBMES:NEAR,DISP16BITS:NEAR + EXTRN CHAINREPORT:NEAR,DISPCLUS:NEAR + EXTRN PRTCHR:NEAR,WDSKERR:NEAR,CHECKFILES:NEAR + EXTRN FCB_TO_ASCZ:NEAR,FIGREC:NEAR,RDSKERR:NEAR + +CHKPROC: + +SUBTTL DIRPROC -- Recursive directory processing + +; YOU ARE ADVISED NOT TO COPY THE FOLLOWING METHOD!!! + +DOTDOTHARDWAY: + LDS DI,[THISDPB] +ASSUME DS:NOTHING + MOV [DI.dpb_current_dir],-1 ;Invalidate path + MOV SI,DI + ADD SI,dpb_dir_text + MOV CX,SI +FINDEND: + LODSB ;Scan to end of current path + OR AL,AL + JNZ FINDEND + DEC SI ;Point at the NUL +DELLOOP: ;Delete last element + CMP SI,CX + JZ SETROOT + CMP BYTE PTR [SI],"/" + JZ SETTERM + CMP BYTE PTR [SI],"\" + JZ SETTERM + DEC SI + JMP SHORT DELLOOP + +SETTERM: + MOV BYTE PTR [SI],0 +SETCURR: + PUSH CS + POP DS +ASSUME DS:DG + MOV DX,OFFSET DG:DOTMES + MOV AH,CHDIR ;Chdir to altered path + INT 21H + RET + +SETROOT: +ASSUME DS:NOTHING + MOV [DI.dpb_current_dir],0 ;Set Path to Root + JMP SHORT SETCURR ;The CHDIR will fail, but who cares + + +;Structures used by DIRPROC + +SRCHFCB STRUC + DB 44 DUP (?) +SRCHFCB ENDS +SFCBSIZ EQU SIZE SRCHFCB +THISENT EQU 17H ;Relative entry number of current entry + +DIRENT STRUC + DB 7 DUP (?) ;Ext FCB junk + DB ? ;Drive +DIRNAM DB 11 DUP (?) +DIRATT DB ? + DB 10 DUP (?) +DIRTIM DW ? +DIRDAT DW ? +DIRCLUS DW ? +DIRESIZ DD ? +DIRENT ENDS +ENTSIZ EQU SIZE DIRENT + +;Attribute bits + +RDONLY EQU 1 +HIDDN EQU 2 +SYSTM EQU 4 +VOLIDA EQU 8 +ISDIR EQU 10H + +ASSUME DS:DG + +NODOT: ;No . + PUSH AX ;Return from SRCH + CMP [NOISY],0 + JNZ DOEXTMES1 + CALL SUBERRP + JMP SHORT MESD1 +DOEXTMES1: + MOV SI,OFFSET DG:DOTMES + CALL PRINTCURRDIRERR + MOV DX,OFFSET DG:NDOTMES + CALL EPRINT +MESD1: + XOR AX,AX + PUSH BX + PUSH BP + CALL GETENT + POP BP + PUSH BP + CMP BYTE PTR [DI],0E5H ;Have place to put .? + JNZ CANTREC ;Nope + MOV SI,OFFSET DG:DOTENT + MOV CX,11 + REP MOVSB ;Name + PUSH AX + MOV AL,ISDIR + STOSB ;Attribute + ADD DI,10 + XOR AX,AX + STOSW ;Date = 0 + STOSW ;Time = 0 + MOV AX,[BP+6] + STOSW ;Alloc # + XOR AX,AX + STOSW + STOSW ;Size + POP AX + MOV [HAVFIX],1 ;Have a fix + CMP [DOFIX],0 + JZ DOTGOON ;No fix if not F + MOV CX,1 + CALL DOINT26 + JMP SHORT DOTGOON + +CANTREC: + INC [DOTSNOGOOD] + CMP [NOISY],0 + JZ DOTGOON + MOV DX,OFFSET DG:NORECDOT + CALL EPRINT +DOTGOON: + POP BP + POP BX + POP AX + MOV SI,OFFSET DG:DIRBUF + JMP CHKDOTDOT ;Go look for .. + +NODDOT: ;No .. + PUSH AX ;Return from SRCH + CMP [NOISY],0 + JNZ DOEXTMES2 + CALL SUBERRP + JMP SHORT MESD2 +DOEXTMES2: + MOV SI,OFFSET DG:PARSTR + CALL PRINTCURRDIRERR + MOV DX,OFFSET DG:NDOTMES + CALL EPRINT +MESD2: + MOV AX,1 + PUSH BX + PUSH BP + CALL GETENT + POP BP + PUSH BP + CMP BYTE PTR [DI],0E5H ;Place to put it? + JNZ CANTREC2 ;Nope + MOV SI,OFFSET DG:DDOTENT + MOV CX,11 + REP MOVSB ;Name + PUSH AX + MOV AL,ISDIR + STOSB ;Attribute + ADD DI,10 + XOR AX,AX + STOSW ;Date + STOSW ;Time + MOV AX,[BP+4] + STOSW ;Alloc # + XOR AX,AX + STOSW + STOSW ;Size + POP AX + MOV [HAVFIX],1 ;Got a fix + CMP [DOFIX],0 + JZ NFIX ;No fix if no F, carry clear + MOV CX,1 + CALL DOINT26 +NFIX: + POP BP + POP BX + POP AX + MOV SI,OFFSET DG:DIRBUF + JMP ROOTDIR ;Process files + +CANTREC2: + POP BP + POP BX + POP AX + CMP [NOISY],0 + JZ DOTSBAD + MOV DX,OFFSET DG:NORECDDOT + CALL EPRINT + JMP DOTSBAD + +NULLDIRERR: + CMP [NOISY],0 + JNZ DOEXTMES3 + CALL SUBERRP + JMP SHORT DOTSBAD +DOEXTMES3: + MOV SI,OFFSET DG:NUL + CALL PRINTCURRDIRERR + MOV DX,OFFSET DG:NULDMES + CALL EPRINT +DOTSBAD: ;Can't recover + MOV DX,OFFSET DG:BADTARG2 + CALL EPRINT + CALL DOTDOTHARDWAY + INC [DOTSNOGOOD] + JMP DIRDONE ;Terminate tree walk at this level + +ROOTDIRJ: JMP ROOTDIR + +PAGE +DIRPROC: +;Recursive tree walker +;dirproc(self,parent) + MOV [DOTSNOGOOD],0 ;Init to dots OK + MOV [ERRSUB],0 ;No subdir errors yet + PUSH BP ;Save frame pointer + MOV BP,SP + SUB SP,SFCBSIZ ;Only local var + CMP SP,[STACKLIM] + JA STACKISOK + MOV BX,OFFSET DG:STACKMES ;Out of stack + JMP FATAL +STACKISOK: + CMP [NOISY],0 + JZ NOPRINT + CMP [SECONDPASS],0 + JNZ NOPRINT ;Don't do it again on second pass + MOV DX,OFFSET DG:DIRECMES ;Tell user where we are + CALL PRINT + MOV SI,OFFSET DG:NUL + CALL PRINTCURRDIR + CALL DOCRLF +NOPRINT: + MOV SI,OFFSET DG:ALLFILE + MOV DI,SP + PUSH DI + MOV CX,SFCBSIZ + REP MOVSB ;Initialize search FCB + POP DX + MOV BX,DX ;BX points to SRCH FCB + MOV AH,DIR_SEARCH_FIRST + INT 21H + CMP WORD PTR [BP+6],0 ;Am I the root + JZ ROOTDIRJ ;Yes, no . or .. + OR AL,AL + JZ NONULLDERR + JMP NULLDIRERR ;Dir is empty! +NONULLDERR: + MOV SI,OFFSET DG:DIRBUF + DIRNAM + MOV DI,OFFSET DG:DOTENT + MOV CX,11 + REP CMPSB + JZ DOTOK ;Got a . as first entry + JMP NODOT ;No . +DOTOK: + MOV SI,OFFSET DG:DIRBUF + MOV AL,[SI.DIRATT] + TEST AL,ISDIR + JNZ DATTOK + PUSH SI ;. not a dir? + MOV SI,OFFSET DG:DOTMES + MOV DX,OFFSET DG:BADATT + CALL DOTCOMBMES + POP SI + OR [SI.DIRATT],ISDIR + CALL FIXENT ;Fix it +DATTOK: + MOV AX,[SI.DIRCLUS] + CMP AX,[BP+6] ;. link = MYSELF? + JZ DLINKOK + PUSH SI ;Link messed up + MOV SI,OFFSET DG:DOTMES + MOV DX,OFFSET DG:CLUSBAD + CALL DOTCOMBMES + POP SI + MOV AX,[BP+6] + MOV [SI.DIRCLUS],AX + CALL FIXENT ;Fix it +DLINKOK: + MOV AX,WORD PTR [SI.DIRESIZ] + OR AX,AX + JNZ BADDSIZ + MOV AX,WORD PTR [SI.DIRESIZ+2] + OR AX,AX + JZ DSIZOK +BADDSIZ: ;Size should be zero + PUSH SI + MOV SI,OFFSET DG:DOTMES + MOV DX,OFFSET DG:BADSIZM + CALL DOTCOMBMES + POP SI + XOR AX,AX + MOV WORD PTR [SI.DIRESIZ],AX + MOV WORD PTR [SI.DIRESIZ+2],AX + CALL FIXENT ;Fix it +DSIZOK: ;Get next (should be ..) + MOV DX,BX + MOV AH,DIR_SEARCH_NEXT + INT 21H +CHKDOTDOT: ;Come here after . failure + OR AL,AL + JZ DOTDOTOK +NODDOTJ: JMP NODDOT ;No .. +DOTDOTOK: + MOV SI,OFFSET DG:DIRBUF + DIRNAM + MOV DI,OFFSET DG:DDOTENT + MOV CX,11 + REP CMPSB + JNZ NODDOTJ ;No .. + MOV SI,OFFSET DG:DIRBUF + MOV AL,[SI.DIRATT] + TEST AL,ISDIR + JNZ DDATTOK ;.. must be a dir + PUSH SI + MOV SI,OFFSET DG:PARSTR + MOV DX,OFFSET DG:BADATT + CALL DOTCOMBMES + POP SI + OR [SI.DIRATT],ISDIR + CALL FIXENT ;Fix it +DDATTOK: + PUSH SI + MOV AX,[SI.DIRCLUS] + CMP AX,[BP+4] ;.. link must be PARENT + JZ DDLINKOK + MOV SI,OFFSET DG:PARSTR + MOV DX,OFFSET DG:CLUSBAD + CALL DOTCOMBMES + POP SI + MOV AX,[BP+4] + MOV [SI.DIRCLUS],AX + CALL FIXENT ;Fix it +DDLINKOK: + MOV AX,WORD PTR [SI.DIRESIZ] + OR AX,AX + JNZ BADDDSIZ + MOV AX,WORD PTR [SI.DIRESIZ+2] + OR AX,AX + JZ DDSIZOK +BADDDSIZ: ;.. size should be 0 + PUSH SI + MOV SI,OFFSET DG:PARSTR + MOV DX,OFFSET DG:BADSIZM + CALL DOTCOMBMES + POP SI + XOR AX,AX + MOV WORD PTR [SI.DIRESIZ],AX + MOV WORD PTR [SI.DIRESIZ+2],AX + CALL FIXENT ;Fix it +DDSIZOK: + MOV DX,BX ;Next entry + MOV AH,DIR_SEARCH_NEXT + INT 21H + +ROOTDIR: ;Come here after .. failure also + OR AL,AL + JZ MOREDIR ;More to go + CMP WORD PTR [BP+6],0 ;Am I the root? + JZ DIRDONE ;Yes, no chdir + MOV DX,OFFSET DG:PARSTR + MOV AH,CHDIR ;Chdir to parent (..) + INT 21H + JNC DIRDONE ;Worked + CMP [NOISY],0 + JZ DODDH + MOV SI,OFFSET DG:NUL + CALL PRINTCURRDIRERR + MOV DX,OFFSET DG:CDDDMES + CALL EPRINT +DODDH: + CALL DOTDOTHARDWAY ;Try again +DIRDONE: + MOV SP,BP ;Pop local vars + POP BP ;Restore frame + RET 4 ;Pop args + +MOREDIR: + MOV SI,OFFSET DG:DIRBUF + TEST [SI.DIRATT],ISDIR + JNZ NEWDIR ;Is a new directory + CMP [SECONDPASS],0 + JZ FPROC1 ;First pass + CALL CROSSLOOK ;Check for cross links + JMP DDSIZOK ;Next +FPROC1: + CMP [NOISY],0 + JZ NOPRINT2 + MOV DX,OFFSET DG:INDENT ;Tell user where we are + CALL PRINT + PUSH BX + MOV BX,SI + CALL PRINTTHISEL + CALL DOCRLF + MOV SI,BX + POP BX +NOPRINT2: + MOV AL,81H ;Head of file + CALL MARKFAT + TEST [SI.DIRATT],VOLIDA + JNZ HIDENFILE ;VOL ID counts as hidden + TEST [SI.DIRATT],HIDDN + JZ NORMFILE +HIDENFILE: + INC [HIDCNT] + ADD [HIDSIZ],CX + JMP DDSIZOK ;Next +NORMFILE: + INC [FILCNT] + ADD [FILSIZ],CX + JMP DDSIZOK ;Next + +NEWDIR: + CMP [SECONDPASS],0 + JZ DPROC1 + CALL CROSSLOOK ;Check for cross links + JMP SHORT DPROC2 +DPROC1: + MOV AL,82H ;Head of dir + CALL MARKFAT + INC [DIRCNT] + ADD [DIRSIZ],CX + CMP [ZEROTRUNC],0 + JZ DPROC2 ;Dir not truncated +CONVDIR: + AND [SI.DIRATT],NOT ISDIR ;Turn into file + CALL FIXENT + JMP DDSIZOK ;Next +DPROC2: + PUSH [ERRSUB] + PUSH BX ;Save my srch FCB pointer + PUSH [SI.DIRCLUS] ;MYSELF for next directory + PUSH [BP+6] ;His PARENT is me + ADD SI,DIRNAM + MOV DI,OFFSET DG:NAMBUF + PUSH DI + CALL FCB_TO_ASCZ + POP DX + MOV AH,CHDIR ;CHDIR to new dir + INT 21H + JC CANTTARG ;Barfed + CALL DIRPROC + POP BX ;Get my SRCH FCB pointer back + POP [ERRSUB] + CMP [DOTSNOGOOD],0 + JNZ ASKCONV + JMP DDSIZOK ;Next + +CANTTARG: + POP AX ;Clean stack + POP AX + POP AX + POP AX + PUSH DX ;Save pointer to bad DIR + MOV DX,OFFSET DG:BADTARG1 + CALL EPRINT + POP SI ;Pointer to bad DIR + CALL PRINTCURRDIRERR + MOV DX,OFFSET DG:BADTARG2 + CALL EPRINT +DDSIZOKJ: JMP DDSIZOK ;Next + +ASKCONV: + CMP [SECONDPASS],0 + JNZ DDSIZOKJ ;Leave on second pass + MOV DX,OFFSET DG:PTRANDIR + CMP [NOISY],0 + JNZ PRINTTRMES + MOV DX,OFFSET DG:PTRANDIR2 +PRINTTRMES: + CALL PROMPTYN ;Ask user what to do + JNZ DDSIZOKJ ;User say leave alone + PUSH BP + PUSH BX + MOV AX,[BX+THISENT] ;Entry number + CALL GETENT ;Get the entry + MOV SI,DI + MOV DI,OFFSET DG:DIRBUF + PUSH DI + ADD DI,DIRNAM + MOV CX,32 + REP MOVSB ;Transfer entry to DIRBUF + POP SI + PUSH SI + MOV SI,[SI.DIRCLUS] ;First cluster + CALL GETFILSIZ + POP SI + POP BX + POP BP + MOV WORD PTR [SI.DIRESIZ],AX ;Fix entry + MOV WORD PTR [SI.DIRESIZ+2],DX + JMP CONVDIR + +SUBTTL FAT Look routines +PAGE +CROSSLOOK: +;Same as MRKFAT only simpler for pass 2 + MOV [SRFCBPT],BX + MOV BX,SI + MOV SI,[BX.DIRCLUS] + CALL CROSSCHK + JNZ CROSSLINKJ +CHLP: + PUSH BX + CALL UNPACK + POP BX + XCHG SI,DI + CMP SI,0FF8H + JAE CHAINDONEJ + CALL CROSSCHK + JZ CHLP +CROSSLINKJ: JMP SHORT CROSSLINK + +CROSSCHK: + MOV DI,[FATMAP] + ADD DI,SI + MOV AH,[DI] + TEST AH,10H + RET + +NOCLUSTERSJ: JMP NOCLUSTERS + +MARKFAT: +; Map the file and perform checks +; SI points to dir entry +; AL is head mark with app type +; On return CX is number of clusters +; BX,SI preserved +; ZEROTRUNC is non zero if the file was trimmed to zero length +; ISCROSS is non zero if the file is cross linked + + MOV [ZEROTRUNC],0 ;Initialize + MOV [ISCROSS],0 + MOV [SRFCBPT],BX + MOV BX,SI + XOR CX,CX + MOV SI,[BX.DIRCLUS] + CMP SI,2 + JB NOCLUSTERSJ ;Bad cluster # or nul file (SI = 0) + CMP SI,[MCLUS] + JA NOCLUSTERSJ ;Bad cluster # + PUSH BX + CALL UNPACK + POP BX + JZ NOCLUSTERSJ ;Bad cluster (it is marked free) + CALL MARKMAP + JNZ CROSSLINK + AND AL,7FH ;Turn off head bit +CHASELOOP: + PUSH BX + CALL UNPACK + POP BX + INC CX + XCHG SI,DI + CMP SI,0FF8H + JAE CHAINDONE + CMP SI,2 + JB MRKBAD + CMP SI,[MCLUS] + JBE MRKOK +MRKBAD: ;Bad cluster # in chain + PUSH CX + PUSH DI + CALL PRINTTHISELERR + MOV DX,OFFSET DG:BADCHAIN + CALL EPRINT + POP SI + MOV DX,0FFFH ;Insert EOF + PUSH BX + CALL PACK + POP BX + POP CX +CHAINDONEJ: JMP SHORT CHAINDONE + +MRKOK: + CALL MARKMAP + JZ CHASELOOP +CROSSLINK: ;File is cross linked + INC [ISCROSS] + CMP [SECONDPASS],0 + JZ CHAINDONE ;Crosslinks only on second pass + PUSH SI ;Cluster number + CALL PRINTTHISEL + CALL DOCRLF + MOV DX,OFFSET DG:CROSSMES_PRE + CALL PRINT + POP SI + PUSH BX + PUSH CX + MOV BX,OFFSET DG:CROSSMES_POST + XOR DI,DI + CALL DISP16BITS + POP CX + POP BX +CHAINDONE: + TEST [BX.DIRATT],ISDIR + JNZ NOSIZE ;Don't size dirs + CMP [ISCROSS],0 + JNZ NOSIZE ;Don't size cross linked files + CMP [SECONDPASS],0 + JNZ NOSIZE ;Don't size on pass 2 (CX garbage) + MOV AL,[CSIZE] + XOR AH,AH + MUL [SSIZE] + PUSH AX ;Size in bytes of one alloc unit + MUL CX + MOV DI,DX ;Save allocation size + MOV SI,AX + SUB AX,WORD PTR [BX.DIRESIZ] + SBB DX,WORD PTR [BX.DIRESIZ+2] + JC BADFSIZ ;Size to big + OR DX,DX + JNZ BADFSIZ ;Size to small + POP DX + CMP AX,DX + JB NOSIZE ;Size within one Alloc unit + PUSH DX ;Size to small +BADFSIZ: + POP DX + PUSH CX ;Save size of file + MOV WORD PTR [BX.DIRESIZ],SI + MOV WORD PTR [BX.DIRESIZ+2],DI + CALL FIXENT2 ;Fix it + CALL PRINTTHISELERR + MOV DX,OFFSET DG:BADCLUS + CALL EPRINT + POP CX ;Restore size of file +NOSIZE: + MOV SI,BX + MOV BX,[SRFCBPT] + RET + +NOCLUSTERS: +;File is zero length + OR SI,SI + JZ CHKSIZ ;Firclus is OK, Check size + MOV DX,OFFSET DG:NULNZ +ADJUST: + PUSH DX + CALL PRINTTHISELERR + POP DX + CALL EPRINT + XOR SI,SI + MOV [BX.DIRCLUS],SI ;Set it to 0 + MOV WORD PTR [BX.DIRESIZ],SI ;Set size too + MOV WORD PTR [BX.DIRESIZ+2],SI + CALL FIXENT2 ;Fix it + INC [ZEROTRUNC] ;Indicate truncation + JMP CHAINDONE + +CHKSIZ: + MOV DX,OFFSET DG:BADCLUS + CMP WORD PTR [BX.DIRESIZ],0 + JNZ ADJUST ;Size wrong + CMP WORD PTR [BX.DIRESIZ+2],0 + JNZ ADJUST ;Size wrong + JMP CHAINDONE ;Size OK + +UNPACK: +;Cluster number in SI, Return contents in DI, BX destroyed +;ZERO SET IF CLUSTER IS FREE + MOV BX,OFFSET DG:FAT + MOV DI,SI + SHR DI,1 + ADD DI,SI + MOV DI,WORD PTR [DI+BX] + TEST SI,1 + JZ HAVCLUS + SHR DI,1 + SHR DI,1 + SHR DI,1 + SHR DI,1 +HAVCLUS: + AND DI,0FFFH + RET + +PACK: +; SI CLUSTER NUMBER TO BE PACKED +; DX DATA TO BE PLACED IN CLUSTER (SI) +; BX,DX DESTROYED + MOV [DIRTYFAT],1 ;Set FAT dirty byte + MOV [HAVFIX],1 ;Indicate a fix + MOV BX,OFFSET DG:FAT + PUSH SI + MOV DI,SI + SHR SI,1 + ADD SI,BX + ADD SI,DI + SHR DI,1 + MOV DI,[SI] + JNC ALIGNED + SHL DX,1 + SHL DX,1 + SHL DX,1 + SHL DX,1 + AND DI,0FH + JMP SHORT PACKIN +ALIGNED: + AND DI,0F000H +PACKIN: + OR DI,DX + MOV [SI],DI + POP SI + RET + + + +MARKMAP: +; Mark in AL +; Cluster in SI +; AL,SI,CX preserved +; ZERO RESET IF CROSSLINK, AH IS THE MARK THAT WAS THERE + MOV DI,[FATMAP] + ADD DI,SI + MOV AH,[DI] + OR AH,AH + PUSH AX + JZ SETMARK + MOV AL,AH + INC [CROSSCNT] ;Count the crosslink + OR AL,10H ;Resets zero +SETMARK: + MOV [DI],AL + POP AX + RET + + +CHKMAP: +;Compare FAT and FATMAP looking for badsectors orphans + MOV SI,[FATMAP] + INC SI + INC SI + MOV DX,2 + MOV CX,[DSIZE] +CHKMAPLP: + LODSB + OR AL,AL + JNZ CONTLP ;Already seen this one + XCHG SI,DX + CALL UNPACK + XCHG SI,DX + JZ CONTLP ;Free cluster + CMP DI,0FF7H ;Bad sector? + JNZ ORPHAN ;No, found an orphan + INC [BADSIZ] + MOV BYTE PTR [SI-1],4 ;Flag it + JMP CONTLP +ORPHAN: + INC [ORPHSIZ] + MOV BYTE PTR [SI-1],8 ;Flag it +CONTLP: + INC DX ;Next cluster + LOOP CHKMAPLP + MOV SI,[ORPHSIZ] + OR SI,SI + JZ RET18 ;No orphans + CALL RECOVER +RET18: RET + +RECOVER: +;free orphans or do chain recovery + CALL CHECKNOFMES + CALL DOCRLF + CALL CHAINREPORT + MOV DX,OFFSET DG:FREEMES + CALL PROMPTYN ;Ask user + JNZ NOCHAINREC + JMP CHAINREC +NOCHAINREC: + MOV SI,[FATMAP] ;Free all orphans + INC SI + INC SI + MOV DX,2 + MOV CX,[DSIZE] +CHKMAPLP2: + LODSB + TEST AL,8 + JZ NEXTCLUS + XCHG SI,DX + PUSH DX + XOR DX,DX + CALL PACK ;Mark as free + POP DX + XCHG SI,DX +NEXTCLUS: + INC DX + LOOP CHKMAPLP2 + XOR AX,AX + XCHG AX,[ORPHSIZ] + PUSH AX + MOV DX,OFFSET DG:FREEBYMESF_PRE + CMP [DOFIX],0 + JNZ PRINTFMES + MOV DX,OFFSET DG:FREEBYMES_PRE +PRINTFMES: + CALL PRINT + POP AX + MOV BX,OFFSET DG:FREEBYMESF_POST + CMP [DOFIX],0 + JNZ DISPFRB + MOV BX,OFFSET DG:FREEBYMES_POST + MOV [LCLUS],AX +DISPFRB: + CALL DISPCLUS ;Tell how much freed + RET + +FINDCHAIN: +;Do chain recovery on orphans + MOV SI,[FATMAP] + INC SI + INC SI + MOV DX,2 + MOV CX,[DSIZE] +CHKMAPLP3: + LODSB + TEST AL,8 ;Orphan? + JZ NEXTCLUS2 ;Nope + TEST AL,1 ;Seen before ? + JNZ NEXTCLUS2 ;Yup + PUSH SI ;Save search environment + PUSH CX + PUSH DX + DEC SI + OR BYTE PTR [SI],81H ;Mark as seen and head + INC [ORPHCNT] ;Found a chain + MOV SI,DX +CHAINLP: + CALL UNPACK + XCHG SI,DI + CMP SI,0FF8H + JAE CHGOON ;EOF + PUSH DI + CMP SI,2 + JB INSERTEOF ;Bad cluster number + CMP SI,[MCLUS] + JA INSERTEOF ;Bad cluster number + CMP SI,DI + JZ INSERTEOF ;Tight loop + CALL CROSSCHK + TEST AH,8 ;Points to a non-orphan? + JNZ CHKCHHEAD ;Nope +INSERTEOF: + POP SI ;Need to stick EOF here + MOV DX,0FFFH + CALL PACK + JMP SHORT CHGOON +CHKCHHEAD: + TEST AH,80H ;Previosly marked head? + JZ ADDCHAIN ;Nope + AND BYTE PTR [DI],NOT 80H ;Turn off head bit + DEC [ORPHCNT] ;Wasn't really a head + POP DI ;Clean stack + JMP SHORT CHGOON +ADDCHAIN: + TEST AH,1 ;Previosly seen? + JNZ INSERTEOF ;Yup, don't make a cross link + OR BYTE PTR [DI],1 ;Mark as seen + POP DI ;Clean stack + JMP CHAINLP ;Follow chain + +CHGOON: + POP DX ;Restore search + POP CX + POP SI +NEXTCLUS2: + INC DX + LOOP CHKMAPLP3 + RET + +CHAINREC: + LDS DI,[THISDPB] +ASSUME DS:NOTHING + MOV CX,[DI.dpb_root_entries] + PUSH CS + POP DS +ASSUME DS:DG + MOV SI,[FATMAP] + INC SI + INC SI + MOV DI,1 + CALL NEXTORPH + PUSH SI + PUSH DI + MOV SI,DI + XOR AX,AX + MOV DX,[ORPHCNT] +MAKFILLP: + PUSH AX + PUSH CX + PUSH DX + PUSH SI + CALL GETENT + POP SI + CMP BYTE PTR [DI],0E5H + JZ GOTENT + CMP BYTE PTR [DI],0 + JNZ NEXTENT +GOTENT: + MOV [HAVFIX],1 ;Making a fix + CMP [DOFIX],0 + JZ ENTMADE ;Not supposed to, carry clear + MOV [DI+26],SI ;FIRCLUS Pointer + PUSH AX ;Save INT 26 data + PUSH DX + PUSH BX + MOV AH,DISK_RESET ;Force current state + INT 21H + MOV DX,OFFSET DG:ORPHFCB + MOV AH,FCB_OPEN +OPAGAIN: + INT 21H + OR AL,AL + JNZ GOTORPHNAM + CALL MAKORPHNAM ;Try next name + JMP SHORT OPAGAIN + +GOTORPHNAM: + MOV SI,OFFSET DG:ORPHFCB + 1 ;ORPHFCB Now has good name + MOV CX,11 + REP MOVSB + CALL MAKORPHNAM ;Make next name + XOR AX,AX + MOV CX,15 + REP STOSB + MOV SI,[DI] + INC DI ;Skip FIRCLUS + INC DI + PUSH DI + CALL GETFILSIZ + POP DI + STOSW + MOV AX,DX + STOSW + POP BX + POP DX + POP AX + MOV CX,1 + CALL DOINT26 +ENTMADE: + POP DX + POP CX + POP AX + POP DI + POP SI + DEC DX + OR DX,DX + JZ RET100 + CALL NEXTORPH + PUSH SI + PUSH DI + MOV SI,DI + JMP SHORT NXTORP + +NEXTENT: + POP DX + POP CX + POP AX +NXTORP: + INC AX + LOOP MAKFILLPJ + POP AX ;Clean Stack + POP AX + SUB [ORPHCNT],DX ;Couldn't make them all + MOV DX,OFFSET DG:CREATMES + CALL EPRINT +RET100: RET + +MAKFILLPJ: JMP MAKFILLP + +NEXTORPH: + PUSH AX + LODSB + INC DI + CMP AL,89H + POP AX + JZ RET100 + JMP SHORT NEXTORPH + +MAKORPHNAM: + PUSH SI + MOV SI,OFFSET DG:ORPHEXT - 1 +NAM0: + INC BYTE PTR [SI] + CMP BYTE PTR [SI],'9' + JLE NAMMADE + MOV BYTE PTR [SI],'0' + DEC SI + JMP NAM0 + +NAMMADE: + POP SI + RET + +GETFILSIZ: +;SI is start cluster, returns filesize as DX:AX + XOR AX,AX +NCLUS: + CALL UNPACK + XCHG SI,DI + INC AX + CMP SI,0FF8H + JAE GOTEOF + CMP SI,2 + JAE NCLUS +GOTEOF: + MOV BL,[CSIZE] + XOR BH,BH + MUL BX + MUL [SSIZE] + RET + + + +CHKCROSS: +;Check for Crosslinks, do second pass if any to find pairs + MOV SI,[CROSSCNT] + OR SI,SI + JZ RET8 ;None + CALL DOCRLF + INC [SECONDPASS] + XOR AX,AX + PUSH AX + PUSH AX + CALL DIRPROC ;Do it again +RET8: RET + +SUBTTL AMDONE - Finish up routine +PAGE +AMDONE: +ASSUME DS:NOTHING + CMP [DIRTYFAT],0 + JZ NOWRITE ;FAT not dirty + CMP [DOFIX],0 + JZ NOWRITE ;Not supposed to fix +REWRITE: + LDS BX,[THISDPB] +ASSUME DS:NOTHING + MOV CL,[BX.dpb_FAT_size] ;Sectors for one fat + XOR CH,CH + MOV DI,CX + MOV CL,[BX.dpb_FAT_count] ;Number of FATs + MOV DX,[BX.dpb_first_FAT] ;First sector of FAT + PUSH CS + POP DS +ASSUME DS:DG + MOV [ERRCNT],CH + MOV BX,OFFSET DG:FAT + MOV AL,[ALLDRV] + DEC AL + MOV AH,'1' + PUSH CX +WRTLOOP: + XCHG CX,DI + PUSH DX + PUSH CX + PUSH DI + PUSH AX + INT 26H ;Write out the FAT + MOV [HECODE],AL + POP AX ;Flags + JNC WRTOK + INC [ERRCNT] + MOV DX,OFFSET DG:BADWRITE_PRE + CALL PRINT + POP AX + PUSH AX + MOV DL,AH + CALL PRTCHR + MOV DX,OFFSET DG:BADWRITE_POST + CALL PRINT +WRTOK: + POP AX + POP CX + POP DI + POP DX + INC AH + ADD DX,DI + LOOP WRTLOOP ;Next FAT + POP CX ;Number of FATs + CMP CL,[ERRCNT] ;Error on all? + JNZ NOWRITE ;no + CALL WDSKERR + JZ REWRITE +NOWRITE: + MOV AH,DISK_RESET ;Invalidate any buffers in system + INT 21H + MOV DX,OFFSET DG:USERDIR ;Recover users directory + MOV AH,CHDIR + INT 21H + CMP BYTE PTR [FRAGMENT],1 ;Check for any fragmented files? + JNZ DONE ;No -- we're finished + CALL CHECKFILES ;Yes -- report any fragments +DONE: +ASSUME DS:NOTHING + MOV DL,[USERDEV] ;Recover users drive + MOV AH,SET_DEFAULT_DRIVE + INT 21H + RET + +SUBTTL Routines for manipulating dir entries +PAGE +FIXENT2: +;Same as FIXENT only [SRFCBPT] points to the search FCB, BX points to the entry + PUSH SI + PUSH BX + PUSH CX + MOV SI,BX + MOV BX,[SRFCBPT] + CALL FIXENT + POP CX + POP BX + POP SI +RET20: RET + +FIXENT: +;BX Points to search FCB +;SI Points to Entry to fix + MOV [HAVFIX],1 ;Indicate a fix + CMP [DOFIX],0 + JZ RET20 ;But don't do it! + PUSH BP + PUSH BX + PUSH SI + PUSH SI ;Entry pointer + MOV AX,[BX+THISENT] ;Entry number + CALL GETENT + POP SI ;Entry pointer + ADD SI,DIRNAM ;Point to start of entry + MOV CX,32 + REP MOVSB + INC CL + CALL DOINT26 + POP SI + POP BX + POP BP + RET + +GETENT: +;AX is desired entry number (in current directory) +; +;DI points to entry in SECBUF +;AX DX BX set to do an INT 26 to write it back out (CX must be reset to 1) +;ALL registers destroyed (via int 25) + LDS DI,[THISDPB] +ASSUME DS:NOTHING + MOV BX,[DI.dpb_current_dir] + PUSH CS + POP DS +ASSUME DS:DG + CMP BX,0FF8H + JB CLUSISOK + MOV BX,OFFSET DG:BADDPBDIR ;This should never happen + JMP FATAL +CLUSISOK: + MOV CL,4 + SHL AX,CL + XOR DX,DX + SHL AX,1 + RCL DX,1 ;Account for overflow + MOV CX,[SSIZE] + AND CL,255-31 ;Must be a multiple of 32 + DIV CX ;DX is position in sector, AX is dir sector # + OR BX,BX + JZ WANTROOT + DIV [CSIZE] ;AL # clusters to skip, AH position in cluster + MOV CL,AL + XOR CH,CH + JCXZ GOTCLUS + MOV SI,BX +SKIPLP: + CALL UNPACK + XCHG SI,DI + LOOP SKIPLP + MOV BX,SI +GOTCLUS: + PUSH DX ;Position in sector + CALL FIGREC ;Convert to sector # +DOROOTDIR: + MOV BX,[SECBUF] + MOV AL,[ALLDRV] + DEC AL +RDRETRY: + PUSH AX + PUSH DX + PUSH BX + MOV CX,1 + INT 25H ;Read it + MOV [HECODE],AL + POP AX ;FLAGS + POP BX + POP DX + POP AX + JNC RDOK2 + CALL RDSKERR + JZ RDRETRY +RDOK2: + POP DI ;Offset into sector + ADD DI,BX ;Add sector base offset + RET + +WANTROOT: + PUSH DX + LDS DI,[THISDPB] +ASSUME DS:NOTHING + MOV DX,AX + ADD DX,[DI.dpb_dir_sector] + PUSH CS + POP DS +ASSUME DS:DG + JMP DOROOTDIR + +CHECKNOFMES: + MOV AL,1 + XCHG AL,[FIXMFLG] + OR AL,AL + JNZ RET14 ;Don't print it more than once + CMP [DOFIX],0 + JNZ RET14 ;Don't print it if F switch specified + PUSH DX + MOV DX,OFFSET DG:FIXMES + CALL PRINT + POP DX + RET + +CHECKERR: + CALL CHECKNOFMES + CMP [SECONDPASS],0 +RET14: RET + +PRINTCURRDIRERR: + CALL CHECKERR + JNZ RET14 + CALL PRINTCURRDIR + JMP SHORT ERREX + +PRINTTHISELERR: + CALL CHECKERR + JNZ RET14 + CALL PRINTTHISEL +ERREX: + CALL DOCRLF + RET + +PRINTTHISEL: + MOV SI,BX + ADD SI,DIRNAM +PRINTTHISEL2: + MOV DI,OFFSET DG:NAMBUF + PUSH DI + CALL FCB_TO_ASCZ + POP SI +PRINTCURRDIR: + PUSH SI + MOV DL,[ALLDRV] + ADD DL,'@' + CALL PRTCHR + MOV DL,DRVCHAR + CALL PRTCHR + LDS SI,[THISDPB] +ASSUME DS:NOTHING + CMP [SI.dpb_current_dir],0 + JZ CURISROOT + MOV DL,[DIRCHAR] + CALL PRTCHR + ADD SI,dpb_dir_text +PCURRLP: + LODSB + OR AL,AL + JZ CURISROOT + MOV DL,AL + CALL PRTCHR + JMP PCURRLP + +CURISROOT: + PUSH CS + POP DS +ASSUME DS:DG + POP SI + CMP BYTE PTR [SI],0 + JZ LPDONE ;If tail string NUL, no '/' + MOV DL,[DIRCHAR] + CALL PRTCHR +ERRLOOP: + LODSB + OR AL,AL + JZ LPDONE + MOV DL,AL + CALL PRTCHR + JMP ERRLOOP +LPDONE: + RET + +FATAL: +;Unrecoverable error + MOV DX,OFFSET DG:FATALMES + CALL PRINT + MOV DX,BX + CALL PRINT + MOV DL,[USERDEV] ;At least leave on same drive + MOV AH,SET_DEFAULT_DRIVE + INT 21H + INT 20H + + +INT_24_RETADDR DW OFFSET DG:INT_24_BACK + +INT_24 PROC FAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSHF + PUSH CS + PUSH [INT_24_RETADDR] + PUSH WORD PTR [HARDCH+2] + PUSH WORD PTR [HARDCH] + RET +INT_24 ENDP + +INT_24_BACK: + CMP AL,2 ;Abort? + JNZ IRETI + CALL DONE ;Forget about directory, restore users drive + INT 20H +IRETI: + IRET + +INT_23: + LDS DX,[HARDCH] + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 24H + INT 21H + LDS DX,[CONTCH] + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H + INT 21H + PUSH CS + POP DS +ASSUME DS:DG + MOV [FRAGMENT],0 +RDONE: + CALL NOWRITE ;Restore users drive and directory + INT 20H + +CODE ENDS + END CHKPROC + \ No newline at end of file -- cgit v1.2.3