TITLE CHKFAT - procedures that acces the fat and/or fatmap page ,132 ; .xlist include chkseg.inc ;an005;bgb INCLUDE CHKCHNG.inc INCLUDE DOSSYM.inc INCLUDE CHKEQU.inc INCLUDE CHKMACRO.inc include pathmac.inc CONST SEGMENT PUBLIC PARA 'DATA' EXTRN CREATMES:byte,FIXMES_ARG:word EXTRN FREEMES:byte EXTRN BADW_ARG:word,FATAL_END:word EXTRN badrw_num:word,BADRW_STR:WORD,HAVFIX:byte EXTRN FREEBYMES1:byte,FREEBYMES2:byte EXTRN FREE_ARG1:WORD,FREE_ARG2:WORD,FREE_ARG3:WORD,ORPHCNT:dword EXTRN DIRTYFAT:byte,CROSSCNT:dword,DOFIX:byte,SECONDPASS:byte EXTRN BADSIZ:word,ORPHSIZ:word,LCLUS:word,ORPHFCB:byte EXTRN HECODE:byte,USERDIR:byte,FRAGMENT:byte EXTRN ORPHEXT:byte,ALLDRV:byte,FIXMFLG:byte,DIRCHAR:byte EXTRN BIGFAT:byte,EOFVAL:word,BADVAL:word extrn fTrunc:BYTE, rarg1:word ;an018;bgb extrn temp_dd:dword ;an049;bgb CONST ENDS DATA SEGMENT PUBLIC PARA 'DATA' extrn fatcnt:byte ;an005;bgb EXTRN THISDPB:dword,NUL_ARG:byte EXTRN NAMBUF:byte,SRFCBPT:word,FATMAP:word EXTRN MCLUS:word,CSIZE:byte,SSIZE:word EXTRN DSIZE:word,ARG1:word,ARG_BUF:byte,ERRCNT:byte EXTRN USERDEV:byte,HARDCH:dword,CONTCH:dword EXTRN ExitStatus:Byte,Read_Write_Relative:Byte extrn bytes_per_sector:word, fattbl:word ;an005;bgb extrn sec_count:word, secs_per_64k:word, paras_per_64k:word ;an005;bgb extrn fattbl_seg:word, fatsiz:word, paras_per_fat:word ;an005;bgb extrn end_of_fatmap:word ;an030;bgb extrn root_entries:word ;ac048;bgb;an047;bgb DATA ENDS CODE SEGMENT PUBLIC PARA 'CODE' ASSUME CS:DG,DS:DG,ES:DG,SS:DG EXTRN PRINTF_CRLF:NEAR,FCB_TO_ASCZ:NEAR, recover:near EXTRN EPRINT:NEAR, makorphnam:near EXTRN DOINT26:NEAR,PROMPTYN:NEAR,CHECKFILES:NEAR,DIRPROC:NEAR EXTRN DOCRLF:NEAR, getfilsiz:near, fatal:near, write_disk:near EXTRN GETENT:NEAR,CHECKNOFMES:NEAR, systime:near EXTRN multiply_32_bits:near ;an049;bgb public calc_fatmap_seg, MARKMAP, CHKMAP, CHKMAPLP, ORPHAN, CONTLP, RET18 public PromptRecover, NOCHAINREC, CHKMAPLP2, NEXTCLUS public DISPFRB, FINDCHAIN, CHKMAPLP3, CHAINLP, INSERTEOF, FAT12_4, CHKCHHEAD public ADDCHAIN, CHGOON, NEXTCLUS2, public CHAINREC, MAKFILLP, GOTENT, OPAGAIN, GOTORPHNAM, ENTMADE, NEXTENT public NXTORP, RET100, nextorph public AMDONE, REWRITE, WRTLOOP public WRTOK, NOWRITE, DONE, CROSSCHK, calc_fat_addr, pack, unpack .list PHONEY_STACK DW 5 DUP(0) ;ac048;bgb pathlabl chkfat ;***************************************************************************** ;an005;bgb ; CALC-FAT-ADDR - calculate the seg/off of the fat cell from the cell number ;an005;bgb ; ;an005;bgb ; Inputs: es - fat table segment ; si - cluster number ; ; Outputs: es - fat table segment + cluster seg ; di - cluster offset ; ;an005;bgb ; LARGE FAT SUPPORT ;an005;bgb ;******************* ;an005;bgb ; the offset into the fat table is cluster number times 2 (2 bytes per fat entry) ;an005;bgb ; This will result not only in the segment boundary being passed, but also in ;an005;bgb ; a single-word math overflow. So, we calculate the the address as follows: ;an005;bgb ; 0. start with cluster number (1-65535) ;an005;bgb ; 1. divide by 8 to get the number of paragraphs per fat-cell (0-8191) ;an005;bgb ; remainder = (0-7) ;an005;bgb ; 2. multiply the remainder by 2 to get offset in bytes (0-15) ;an005;bgb ; You now have a paragraph-offset number that you can use to calc the addr into ;an005;bgb ; the fat table. To get the physical addr you must add it to the offset of the ;an005;bgb ; table in memory. ;an005;bgb ; 3. add the paras to the segment register ;an005;bgb ; 4. add the offset to the offset register ;an005;bgb ;****************************************************************************** ;an005;bgb Procedure calc_fat_addr,near ;an005;bgb savereg ; ;an005;bgb mov ax,si ;get cluster number from si mov bx,0008h ; div by para (* 2 bytes per clus) ;an005;bgb xor dx,dx ; zero dx for word divide ;an005;bgb div bx ; do it ;an022;bgb;bgb mov bx,es ; get fat table segment ;an005;bgb add bx,ax ; add number of paras to the cluster ;an005;bgb mov es,bx ; move it back ;an005;bgb shl dx,1 ; remainder times 2 ;an005;bgb mov di,dx ; offset = 00 + remainder ;an005;bgb restorereg ;an005;bgb return ;an005;bgb EndProc calc_fat_addr ;an005;bgb ;========================================================================= ; UNPACK : This routine calculates the position in the FAT ; where the cluster number resides and obtains ; its contents. ; ; Inputs : SI - Cluster number ; Outputs : DI - Cluster contents ; zero flag is set if fat cell = zero ; ; LOGIC ; - get addr of fat table ; - if 16-bit fat, ; then get the address of the cell (calc_fat_addr) ; mov it into di ; set the zero flag ; else multiply the cluster-number by 1.5 to get the byte-offset ; move the contents of the cluster into di ; if the cluster-number is odd, ; then shift it right by 1 nibble ; set the zero flag ; else (its already shifted right) ; set the zero flag ;========================================================================= UNPACK proc near ;ac005; dms;unpack FAT push es ;an005;bgb mov es,fattbl_seg ;point to FAT in memory ;an005;bgb mov DI,SI ;put cluster number in DI cmp [BIGFAT],0 ;big fat? ; $IF nz ;yes JZ $$IF1 call calc_fat_addr ;calc addr of cluster ;an005;bgb mov di,word ptr es:[di] ;es:bx points to fat cluster ;an005;bgb or DI,DI ; Set zero ; $ELSE ;small fat JMP SHORT $$EN1 $$IF1: SHR DI,1 ADD DI,SI ; Mult by 1.5 mov DI,word ptr es:[di] TEST SI,1 ;is the cluster number odd? ; $IF nz ;last bit is non-zero; means it is odd JZ $$IF3 SHR DI,1 ;shift by 1 nibble SHR DI,1 SHR DI,1 SHR DI,1 and di,0fffh ;ac005; dms; ; $ELSE ;ac005; dms;even cluster bound. JMP SHORT $$EN3 $$IF3: AND DI,0FFFH ; $ENDIF $$EN3: ; $ENDIF $$EN1: pop es return UNPACK endp ;ac005; dms; ;========================================================================= ; PACK : This routine puts data into the FAT. ; ; Inputs : SI - Cluster number to be packed ; dx - Data to be packed ; ; Outputs : Altered FAT ; LOGIC ; - set the fat-changed-flags ; - get the seg of the fat-table ; - if 16-bit fat, ; then get the address of the cell (calc_fat_addr) ; mov the new value into it ; else multiply the cluster-number by 1.5 to get the byte-offset ; move the contents of the cluster into di ; if the cluster-number is odd, ; then shift it right by 1 nibble ; set the zero flag ; else (its already shifted right) ; set the zero flag ;========================================================================= PACK proc near ;ac005; dms; savereg ;ac048;bgb mov [DIRTYFAT],1 ;Set FAT dirty byte mov [HAVFIX],1 ;Indicate a fix mov es,fattbl_seg ; ;an005;bgb mov DI,SI cmp [BIGFAT],0 ; $IF nz ;ac005; dms;big fat? JZ $$IF7 call calc_fat_addr ;calc addr of cluster ;an005;bgb mov es:[di],dx ;move dx into cluster ;an005;bgb ; $ELSE JMP SHORT $$EN7 $$IF7: shr di,1 ;offset = clus-num * 1.5 add di,si ;offset = clus-num * 1.5 push di ;save cluster offset mov DI,es:[di] ;get previous value, 4 nibbles test si,1 ;is the cluster number odd? ; $IF nz ;last bit is non-zero; means it is odd JZ $$IF9 SHL dx,1 ;shift by 1 nibble SHL dx,1 SHL dx,1 SHL dx,1 AND DI,0FH ;zero out 1st 3 nibbles '000f' ; $ELSE ;even cluster number JMP SHORT $$EN9 $$IF9: AND DI,0F000H ;zero out last 3 nibbles 'f000' ; $ENDIF $$EN9: or DI,dx ;put new value in with old pop si ;get cluster offset mov es:[SI],DI ; $ENDIF $$EN7: restorereg ;ac048;bgb ret PACK endp ;ac005; dms; ;========================================================================= ;an005;bgb ; CROSSCHK : this proc gets the value of the fatmap entry that is pointed ;an005;bgb ; to by an orphan ;an005;bgb ; ;an005;bgb ; Inputs : si - cluster number of the orphan ;an005;bgb ; ;an005;bgb ; Outputs : ah - contents of the fatmap pointed to by di ;an005;bgb ; LOGIC ;an005;bgb ; ***** ;an005;bgb ;========================================================================= ;an005;bgb procedure CROSSCHK ;an005;bgb push es mov es,fatmap ;an005;bgb xor di,di ;an005;bgb ADD DI,SI mov ah,es:[di] ;an005;bgb TEST AH,10H pop es ret EndProc CROSSCHK ;an005;bgb ;***************************************************************************** ;an005;bgb ; INIT_FATMAP ;an005;bgb ; description: initialize the fatmap area to all zeros ;an005;bgb ; ;an005;bgb ; called from: main-routine ;an005;bgb ; ;an005;bgb ;Change History: Created 8/31/87 bgb ;an005;bgb ; ;an005;bgb ;Input: segment addr of the fatmap ;an005;bgb ; number of clusters in the fat (1-65535) ;an005;bgb ; ;an005;bgb ;Output: fatmap ;an005;bgb ; ;an005;bgb ; LOGIC ;an005;bgb ;---------- ;an005;bgb ;***************************************************************************** ;an005;bgb Procedure init_fatmap,Near ;AN000;bgb ;an005;bgb savereg mov es,fatmap ;get seg of the fatmap ;an005;bgb xor di,di ;get off of the fatmap ;an005;bgb mov cx,[MCLUS] ;do once for each cluster xor AL,AL ;zero means free REP STOSB ;Initialize fatmap to all free mov byte ptr es:[di],al ; ;an010;bgb restorereg return endproc init_fatmap ; ;AN000; ; ;***************************************************************************** ;an005;bgb ; CALC_FATMAP_SEG ;an005;bgb ; description: calculate the segment of the fatmap for addressing purposes ;an005;bgb ; ;an005;bgb ; called from: main-routine ;an005;bgb ; ;an005;bgb ;Change History: Created 8/31/87 bgb ;an005;bgb ; ;an005;bgb ;Input: bytes-per-sector ;an005;bgb ; fatsiz ;an005;bgb ; ;an005;bgb ;Output: ram-based fat table ;an005;bgb ; paras-per-fat - number of paragraphs of mem in the fat ; fattbl-seg - segment number of fat table ; fatmap - segment number of the fat map table ; ;an005;bgb ; LOGIC ;an005;bgb ;---------- ;an005;bgb ; - calc length fat-table (in paras) ;an005;bgb ; = bytes-per-sector / 16 * sectors-per-fat ;an005;bgb ; - calc segment of fat table in memory ;an005;bgb ; = es + 64k ;an005;bgb ; - calc segment of fatmap area in memory ;an005;bgb ; = es + 64k + length of fat-table ;an005;bgb ;***************************************************************************** ;an005;bgb Procedure calc_fatmap_seg,Near ;AN000;bgb ;an005;bgb ; calc fat table length ;an005;bgb push es mov ax,bytes_per_sector ; bytes per sector ;an005;bgb xor dx,dx ;an005;bgb mov bx,16 ;an005;bgb div bx ; paras per sector ;an022;bgb;bgb mov cx,fatsiz ;2 ; get sectors per fat ;an005;bgb xor dx,dx ;an005;bgb mul cx ; paras per fat ;an005;bgb mov paras_per_fat,ax ;an005;bgb ; calc fat table segment ;an005;bgb mov bx,es ;get seg of fat-table ;an005;bgb add bx,01000h ;add 64k for end of pgm seg ;an005;bgb mov fattbl_seg,bx ;starting segment of fattbl ;an005;bgb ; calc fatmap segment :an005;bgb add ax,bx ;seg of fatmap= seg of fattbl + size of fattbl ;an005;bgb mov fatmap,ax ;this is the seg of the fatmap ;an005;bgb ; find segment number of end of fatmap ;an030;bgb ;ptm p5000 mov bx,paras_per_fat ;each fat cell is 2 bytes ;an030;bgb ;ptm p5000 shr bx,1 ;each fatmap cell is 1 byte = ;an030;bgb mov bx, [MCLUS] ;P5000 INIT_FATMAP use [MCLUS] shr bx, 1 ;P5000 convert it to para. shr bx, 1 ;P5000 shr bx, 1 ;P5000 shr bx, 1 ;P5000 add ax,bx ;add in fatmap seg = ;an030;bgb inc ax ;P5000 mov end_of_fatmap,ax ;last seg value ;an030;bgb pop es ret ; ;AN000; endproc calc_fatmap_seg ; ;AN000; ; ;ac048;bgb ;***************************************************************************** ;ac048;bgb ; FIX_ENTRY - fill in the dir entry with the lost cluster information, give it ;ac048;bgb ; unique filename, and write it back to disk. ;ac048;bgb ; ;ac048;bgb ; WARNING!! NOTE!! --> ;ac048;bgb ; ;ac048;bgb ; called by - CHAINREC ;ac048;bgb ; ;ac048;bgb ; inputs: AX - drive number ;ac048;bgb ; BX - ram offset of beginning of sector ;ac048;bgb ; CX - ;ac048;bgb ; DX - sector number low ;ac048;bgb ; SP - ;ac048;bgb ; BP - ;ac048;bgb ; SI - cluster number of first cluster in this lost chain ;ac048;bgb ; DI - points to entry in ram ;ac048;bgb ; ;ac048;bgb ; output: AX - ;ac048;bgb ; BX - ;ac048;bgb ; CX - ;ac048;bgb ; DX - ;ac048;bgb ; SP - ;ac048;bgb ; BP - ;ac048;bgb ; SI - ;ac048;bgb ; DI- ;ac048;bgb ; ;ac048;bgb ; Regs abused - di,si,cx ;ac048;bgb ; ;ac048;bgb ;logic: 1. save the starting cluster number ;ac048;bgb ; ;ac048;bgb ; 2. if the recovered file name already exists, then use the next one. ;ac048;bgb ; do this until the name is unique. ;ac048;bgb ; ;ac048;bgb ; 3. move all the pertinant info into the dir entry. ;ac048;bgb ; ;ac048;bgb ; 4. write the dir entry out to disk. ;ac048;bgb ;***************************************************************************** ;ac048;bgb procedure fix_entry,near ;ac048;bgb mov ds:[DI+26],SI ;move 1st clus num into dir entry ;ac048;bgb ;an005;bgb savereg ;Save INT 26 data ;ac048;bgb ;make sure this name is unique ;ac048;bgb DOS_Call Disk_Reset ;func 0d - flush buffers ;AC000;ac048;bgb; mov dx,OFFSET DG:ORPHFCB ;point to filename file0000.chk ;ac048;bgb mov AH,FCB_OPEN ;open the file just put into the dir ;ac048;bgb OPAGAIN: ;ac048;bgb ; $do ;ac048;bgb $$DO13: INT 21H ;ac048;bgb or AL,AL ;did the open fail? ;ac048;bgb ; $leave nz ;ac048;bgb JNZ $$EN13 call MAKORPHNAM ;Try next name ;ac048;bgb ; $enddo ;ac048;bgb JMP SHORT $$DO13 $$EN13: GOTORPHNAM: ;di still points to entry ;ac048;bgb mov SI,OFFSET DG:ORPHFCB + 1 ;ORPHFCB Now has good name ;ac048;bgb mov cx,11 ;move filename, ext ;ac048;bgb REP MOVSB ;ac048;bgb call MAKORPHNAM ;Make next name ;ac048;bgb xor ax,ax ;fill dir entry with zeros ;ac048;bgb mov cx,11 ;ac048;bgb REP STOSB ;ac048;bgb ; Add in time for orphan file - BAS July 17/85 ;ac048;bgb push dx ;save starting sector number ;ac048;bgb;an045;bgb call SYSTIME ;ac048;bgb STOSW ; Time ;ac048;bgb mov ax,dx ;ac048;bgb STOSW ; Date ;ac048;bgb pop dx ;restore starting sector number ;ac048;bgb ;an045;bgb mov SI,ds:[DI] ;get starting cluster number ;ac048;bgb ;an005;bgb inc DI ;skip firstclus in entry ;ac048;bgb inc DI ;ac048;bgb PUSH DI ;save it from getfilsiz ;ac048;bgb call GETFILSIZ ;calc file size from number of clus ;ac048;bgb POP DI ;restore di ;ac048;bgb STOSW ;ax=file size low ;ac048;bgb mov ax,dx ;dx=filesize high ;ac048;bgb STOSW ; ;ac048;bgb restorereg ;offset, sector num, drive num ;ac048;bgb mov cx,1 ;number of sectors = 1 ;ac048;bgb call DOINT26 ;write it out to disk ;ac048;bgb ret ;ac048;bgb endproc fix_entry ;ac048;bgb ;ac048;bgb ;***************************************************************************** ;ac048;bgb;an047;bgb ; NEXTORPH - find the cluster number of the next orphan. This assumes that ;ac048;bgb;an047;bgb ; there is at least one lost cluster available. ;ac048;bgb;an047;bgb ; ;ac048;bgb;an047;bgb ; WARNING!! NOTE!! --> ;ac048;bgb;an047;bgb ; ;ac048;bgb;an047;bgb ; called by - PROCEDURE NAME ;ac048;bgb;an047;bgb ; ;ac048;bgb;an047;bgb ; inputs: AX - ;ac048;bgb;an047;bgb ; BX - ;ac048;bgb;an047;bgb ; CX - ;ac048;bgb;an047;bgb ; DX - ;a;ac048;bgbn047;bgb ; SP - ;;ac048;bgban047;bgb ; BP - ;a;ac048;bgbn047;bgb ; SI - cluster number of the previous orphan ;a;ac048;bgbn047;bgb ; DI - ;a;ac048;bgbn047;bgb ; DS - ;a;ac048;bgbn047;bgb ; ES - points to one byte map of the fat ;a;ac048;bgbn047;bgb ; ;a;ac048;bgbn047;bgb ; output: AX - ;;ac048;bgban047;bgb ; BX - ;a;ac048;bgbn047;bgb ; CX - ;;ac048;bgban047;bgb ; DX - ;a;ac048;bgbn047;bgb ; SP - ;a;ac048;bgbn047;bgb ; BP - ;a;ac048;bgbn047;bgb ; SI - cluster number of one past the orphan ;ac048;bgb;an047;bgb ; DI - cluster number of the orphan ;a;ac048;bgbn047;bgb ; DS - ;a;ac048;bgbn047;bgb ; ES - ;a;ac048;bgbn047;bgb ; ;a;ac048;bgbn047;bgb ; Regs abused - none ;ac048;bgb;an047;bgb ; ;;ac048;bgban047;bgb ;logic: 1. save ax & es, and point to fat map ;ac048;bgb;an047;bgb ; ;a;ac048;bgbn047;bgb ; 2. do until the head of a chain is found: ;ac048;bgb ;an047;bgb ; ;;ac048;bgban047;bgb ; 3. get the next cell ;ac048;bgb ;an047;bgb ; ;;ac048;bgban047;bgb ; 4. bump pointers into fat map ;ac048;bgb ;an047;bgb ; ;;ac048;bgban047;bgb ; 5. restore ax & es ;;ac048;bgban047;bgb ;*****************************************************************************;a;ac048;bgbn047;bgb procedure NEXTORPH,near ;a;ac048;bgbn047;bgb savereg ;save regs abused ;ac048;bgb mov es,[FATMAP] ;point to fat map ;ac048;bgb ; $do ;ac048;bgb $$DO16: loopno: mov al,byte ptr es:[si] ;get the indicated fatmap entry ;ac048;bgb ;an005;bgb inc si ;point to the next one ;ac048;bgb ;an005;bgb inc di ;point to the next one ;ac048;bgb ;an005;bgb cmp AL,89H ;stop when you find an 89 ;ac048;bgb ; $leave z ;this means head(80), found(1), and orphan(8) ;ac048;bgb JZ $$EN16 ; $enddo ;ac048;bgb JMP SHORT $$DO16 $$EN16: restorereg ;restore regs ;ac048;bgb return ;ac048;bgb endproc nextorph ;ac048;bgb ;ac048;bgb ;ac048;bgb ;**************************************************************************** ; MARKMAP - make a mark in the fat map for every cluster encountered ; ; called by - markfat, ; ; inputs - AL - the mark ; DI - cluster number ; ; outputs - CY if crosslink found ; - AH - previous mark ; - crosscnt (count of number of crosslinks found) ; - fatmap marked ; ; LOGIC ;****** ; - point to fatmap with es ; - if that cell has been found before, ; then mark it crossed x'10' ; else mark it found al ;**************************************************************************** markmap: savereg ;Save registers ;AN000; xor si,si ;Get addr of map ;an005;bgb mov es,[FATMAP] ;Get addr of map ;an005;bgb mov ah,es:[di] ;Get entry at that spot ;an005;bgb or ah,ah ;Is it zero? ; ; ; $IF NZ ;already found - mark crossed;If not, we got crosslink ;AC000; JZ $$IF19 add word ptr crosscnt,1 ;Count the crosslink ; ; adc word ptr crosscnt+2,0 ;Count the crosslink ; ; or byte ptr es:[di],10H ;Resets zero in map ;An005;bgb stc ;Indicate crosslink on ret ; ; ; $ELSE ;not found - mark found ;No crosslink ; ; JMP SHORT $$EN19 $$IF19: mov es:[di],al ;Set mark in map ;Ac005;bgb clc ;Indicate things okay ; ; ; $ENDIF ; ;AN000; $$EN19: restorereg ; ;AN005;bgb ret ; ; ; ;**************************************************************************** ; CHKMAP - Compare FAT and FATMAP looking for badsectors and orphans ; ; called by - ; ; inputs - fatmap ; - dsize - number of clusters on the disk ; ; outputs - badsiz - ; - ; - ; LOGIC ;****** ; - get addr of fatmap ; - get offset of 1st cluster in fatmap ; - do for all the clusters on the disk: ; - if the cluster has been found ; then get the next cluster in its chain ; if the cell was never pointed to by anyone (0) ; then get the contents of that cell from the fat ; (the contents of the fat cell should be zero, too) ; if the fat-cell is not zero ; then (it should only be a bad sector) ; if it is a bad sector, inc the bad-sector-counter ; otherwise, we have found an orphan sector ; end-of-loop ; - if there are any orphans, ; then recover them ;**************************************************************************** CHKMAP: push es ;an014;bgb mov es,fatmap ;get segment of the fatmap ;an005;bgb xor si,si ;get the offset of the fatmap ;an005;bgb mov si,2 ;go past the first two (invalid) entries;an005;bgb ;do for all the clusters on the disk mov cx,[DSIZE] ;loop for the number of clusters on the disk CHKMAPLP: mov al,es:[si] ;move a byte from the fatmap to al ;an005;bgb or al,al ;is the cluster found already? ; $IF Z ;fatmap cell is zero JNZ $$IF22 call unpack ;get the contents of it ; $IF NZ ;is there something in the cell? JZ $$IF23 cmp di,[badval] ;is the fat cell pointing to a bad sector? fff7 ; $IF Z ; yes JNZ $$IF24 inc [badsiz] ;inc the bad sector counter mov byte ptr es:[si],4 ;Flag the map ;an005;bgb ; $ELSE ; no, not a bad sector JMP SHORT $$EN24 $$IF24: orphan: inc [orphsiz] ; then its an orphan mov byte ptr es:[si],8 ;Flag it ;an005;bgb ; $ENDIF $$EN24: ; $ENDIF $$IF23: ; $ENDIF $$IF22: CONTLP: inc si ;point si to next cluster loop chkmaplp cmp [orphsiz],0 ;an005;bgb ; $IF A ;if there are any orphans, go recover them ;an005;bgb JNA $$IF29 call recover ; $ENDIF $$IF29: pop es ;an014;bgb RET18: ret ;***************************************************************************** ; PROMPTRECOVER - do the actual recovering of files ; ; inputs: es - points to fatmap ; ax - ; bx - ; cx - ; dx - ; ; outputs: ; LOGIC ; - ask the user if he wants to convert the orphans to files ; - ; - ;*************************************************************************** PromptRecover: mov dx,OFFSET DG:FREEMES call PROMPTYN ;Ask user ; $IF Z JNZ $$IF31 jmp CHAINREC ; $ENDIF $$IF31: NOCHAINREC: mov es,[fatmap] ;Free all orphans ;an005;bgb mov si,2 ;an005;bgb mov cx,[dsize] xor dx,dx ;dx is the new value (free) CHKMAPLP2: mov al,es:[si] ;get next byte from fatmap into al TEST AL,8 ; is it an orphan? ; $IF NZ ;yes JZ $$IF33 call PACK ;si=cluster number dx=new value ; $ENDIF $$IF33: NEXTCLUS: inc si loop CHKMAPLP2 xor ax,ax XCHG ax,[ORPHSIZ] ;number of orphans = zero mov cx,OFFSET DG:FREEBYMES1 ;print msg cmp [DOFIX],0 ; $IF Z JNZ $$IF35 mov cx,OFFSET DG:FREEBYMES2 mov [LCLUS],ax ;move number of lost clust would be ;an049;bgb ; $ENDIF $$IF35: DISPFRB: ;ax=lost clusters (1-fff6) push bx ;save it ;an049;bgb push cx ;save it ;an049;bgb mov cl,[csize] ;get sectors per cluster (1-32) ;an049;bgb xor ch,ch ;zero out high byte ;an049;bgb xor dx,dx ;zero out hi word for word mult ;an049;bgb mul cx ;cx*ax=dx:ax lost sectors (1-1ffec0);an049;bgb mov bx,dx ;move high word for call ;an049;bgb mov cx,ssize ;word to mult with ;an049;bgb call multiply_32_bits ;bx:ax is result ;an049;bgb mov word ptr rarg1,ax ;low word into low word ;an049;bgb mov word ptr rarg1+2,bx ;hi word into hi word ;an049;bgb mov [free_arg1],ax mov [free_arg2],bx ;an049;bgb mov [free_arg3],cx pop cx pop bx mov dx,cx ;Point to right message;an049;bgb call printf_crlf ret ;***************************************************************************** ; FINDCHAIN - ; ; called by - recover ; ; inputs: ; ; outputs: ; LOGIC - search thru entire fatmap ; - ; - ;*************************************************************************** lostdeb equ 0 ;set private build version on ;an047;bgb lost_str db '00000' ;max size of cluster number FINDCHAIN: ;Do chain recovery on orphans mov es,[FATMAP] ; point to fatmap mov SI,2 ; point to fatmap mov dx,si ; point to fatmap mov cx,[DSIZE] ;get total number of clusters on disk CHKMAPLP3: mov al,es:[si] ;get next fatmap entry inc si ;point to next fatmap entry ;has to be an orphan(08) TEST AL,8 ;Orphan? jz NEXTCLUS2 ;Nope ;make sure its not a regular file entry TEST AL,1 ;Seen before ? jnz NEXTCLUS2 ;Yup ;recover this chain savereg ;Save search environment dec SI or byte ptr es:[si],81H ;Mark as seen and head IF LOSTDEB ;is this private build version? call lostdisp ;display lost cluster numbers ENDIF add word ptr orphcnt,1 ;Found a chain adc word ptr orphcnt+2,0 ;Found a chain mov SI,dx ;point to the next fatmap entry CHAINLP: call UNPACK ;si = fat cell XCHG SI,DI ;si=contents, di=cell number cmp SI,[EOFVAL] ;is this the end of the file? JAE CHGOON ;yes, then we are done PUSH DI ;no, not eof ;dont do this next part if any of two conditions: ; 1. invalid cluster number ; 2. points to itself cmp SI,2 ;well, is it a valid cluster number? JB INSERTEOF ;Bad cluster number cmp SI,[dsize] JA INSERTEOF ;Bad cluster number cmp SI,DI ;how bout if it points to itself? jz INSERTEOF ;Tight loop ; find out what it points TO call CROSSCHK TEST AH,8 ;Points to a non-orphan? jnz CHKCHHEAD ;Nope ;orphan points to nothing INSERTEOF: ; you come here if: ; 1. invalid cluster number ; 2. points to itself ; 3. points to nothing POP SI ;the previous cluster number mov dx,0FFFH ;get eof value (12-bit) cmp [BIGFAT],0 jz FAT12_4 mov dx,0FFFFH ;get eof value (16-bit) FAT12_4: call PACK ;stick it in! jmp SHORT CHGOON ;and we are done ; orphan point to a head entry CHKCHHEAD: TEST AH,80H ;Previosly marked head? jz ADDCHAIN ;Nope AND BYTE PTR es:[DI],NOT 80H ;Turn off head bit sub word ptr orphcnt,1 ;Wasn't really a head sbb word ptr orphcnt+2,0 ;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 es:[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 ;***************************************************************************** ;ac048;bgb ; CHAINREC - the user has requested us to recover the lost clusters ;ac048;bgb ; ;ac048;bgb ; inputs: ;ac048;bgb ; note: although called from PROMPTRECOVER, this routine returns control to ;ac048;bgb ; recover via the ret instruction. ;ac048;bgb ;***************************************************************************** ;ac048;bgb ;ac048;bgb ;***************************************************************************** ;ac048;bgb ; CHAINREC - The user has requested us to recover the lost clusters ;ac048;bgb ; ;ac048;bgb ; WARNING!! NOTE!! --> the count of the number of lost cluster chains remains, ; for this proc, a single word. More than 64k chains ; will cause this proc to fail. ; ;ac048;bgb ; called by - PROCEDURE NAME ;ac048;bgb ; ;ac048;bgb ; inputs: AX - N/A ;ac048;bgb ; bx - ;ac048;bgb ; cx - N/A ;ac048;bgb ; dx - N/A ;ac048;bgb ; SP - ;ac048;bgb ; BP - N/A ;ac048;bgb ; SI - N/A ;ac048;bgb ; DI - N/A ;ac048;bgb ; data: root_entries ;ac048;bgb ; orphcnt ;ac048;bgb ; ;ac048;bgb ; output: AX - ;ac048;bgb ; bx - ;ac048;bgb ; cx - ;ac048;bgb ; dx - ;ac048;bgb ; SP - ;ac048;bgb ; BP - ;ac048;bgb ; SI - ;ac048;bgb ; DI- ;ac048;bgb ; ;ac048;bgb ; Regs abused - ;ac048;bgb ; ;ac048;bgb ;logic: 1. ;ac048;bgb ;***************************************************************************** ;ac048;bgb CHAINREC: ;ac048;bgb push es ;save es if it is used for anything ;ac048;bgb push ds ;make es point to data ;ac048;bgb pop es ;ac048;bgb ;find the cluster number of the orphan ;ac048;bgb mov SI,2 ;start at first cluster ;an005;bgb ;ac048;bgb mov DI,1 ;point to previous cluster? ;ac048;bgb call NEXTORPH ;di points to orphan ;ac048;bgb ;init for loop ;ac048;bgb savereg ;save orphan, orphan+1 ;ac048;bgb mov SI,DI ;si point to orphan ;ac048;bgb xor ax,ax ;set count of dir entries processed to zero;ac048;bgb mov dx,word ptr orphcnt ;get low word of lost clusters ;ac048;bgb;an049;bgb mov word ptr temp_dd,dx ;get low word of lost clusters ;an049;bgb mov dx,word ptr orphcnt+2 ;get hi word of lost clusters ;an049;bgb mov word ptr temp_dd+2,dx ;get hi word of lost clusters ;an049;bgb mov BP,OFFSET DG:PHONEY_STACK ;Set BP to point to "root" ;ac048;bgb ;do for all dir entries: ;ac048;bgb MAKFILLP: ;ac048;bgb ; $DO ;do for all root entries ;ac048;bgb $$DO37: savereg ;cnt of entries processed, num orphans ;ac048;bgb;an049;bgb call GETENT ;DI points to entry ;ac048;bgb cmp BYTE PTR ds:[DI],0E5H ;is this dir entry erased? ;an;ac048;bgb005;bgb ; $if z,or ;ac048;bgb JZ $$LL38 cmp BYTE PTR ds:[DI],0 ;is this dir entry empty? ;an;ac048;bgb005;bgb ; $if z ;ac048;bgb JNZ $$IF38 $$LL38: GOTENT: mov [HAVFIX],1 ;Making a fix ;ac048;bgb cmp [DOFIX],0 ;/f parameter specified? ;ac048;bgb ; $if NZ ;yes- do the fix ;ac048;bgb JZ $$IF39 call fix_entry ;ac048;bgb ; $endif ;ac048;bgb $$IF39: ENTMADE: restorereg ;ac048;bgb;an049;bgb sub word ptr temp_dd,1 ;finished with one orphan ;ac048;bgb;an049;bgb sbb word ptr temp_dd+2,0 ;finished with one orphan ;ac048;bgb;an049;bgb cmp word ptr temp_dd,0 ;is that the last one? ;ac048;bgb;an049;bgb ; $IF Z,AND ;no, check the hi word ;an049;bgb JNZ $$IF41 cmp word ptr temp_dd+2,0;is that the last one? ;ac048;bgb;an049;bgb ; $IF Z ;neither are zero ;an049;bgb JNZ $$IF41 jmp RET100 ; yes,we are done ;ac048;bgb;an049;bgb ; $endif ;an049;bgb $$IF41: call NEXTORPH ;get the cluster of the next one ;ac048;bgb savereg ;ac048;bgb mov SI,DI ;ac048;bgb ; $else ;dir entry was not erased or zero ;ac048;bgb JMP SHORT $$EN38 $$IF38: NEXTENT: restorereg ;ac048;bgb;an049;bgb ; $endif ;ac048;bgb $$EN38: NXTORP: inc ax ;ac048;bgb cmp ax,root_entries ;do for 0 to (root_entries - 1) ;ac048;bgb ; $leave z ;ac048;bgb JZ $$EN37 ; $ENDDO ;ac048;bgb JMP SHORT $$DO37 $$EN37: restorereg ;Clean Stack from si,di ;ac048;bgb sub word ptr orphcnt,dx ;Couldn't make them all ;ac048;bgb sbb word ptr orphcnt+2,0 ;Couldn't make them all ;ac048;bgb mov dx,OFFSET DG:CREATMES ;ac048;bgb mov byte ptr [arg_buf],0 ;ac048;bgb call EPRINT ;ac048;bgb RET100: pop es ;restore es ;ac048;bgb ret ;ac048;bgb ;ac048;bgb ;ac048;bgb ;ac048;bgb ;***************************************************************************** ;***************************************************************************** SUBTTL AMDONE - Finish up routine PAGE Public AmDone 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 cx,[bx.dpb_FAT_size] ;Sectors for one fat (DCR) ;AC000; 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],0 ; set up to write to the disk xor bx,bx ;offset of the fat-table ;an005;bgb mov es,fattbl_seg ;segment of the fat-table ;an005;bgb mov AL,[ALLDRV] dec AL mov AH,1 PUSH cx WRTLOOP: XCHG cx,DI PUSH dx PUSH cx PUSH DI PUSH ax call Write_Disk ;Do relative sector write ;AC000; JNC WRTOK inc [ERRCNT] ;mov [badrw_str],offset dg:writing POP ax ; Get fat # in AH PUSH ax ; Back on stack xchg al,ah ; Fat # to AL xor ah,ah ; Make it a word mov [badrw_num],ax mov dx,offset dg:badw_arg call PRINTf_crlf 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? ; $if e JNE $$IF47 jmp fatal ; $endif $$IF47: ; make sure that the data fields are always adressable, because ;we can come here after a ctl - break has happened. so point to them w/ cs: NOWRITE: DOS_Call Disk_Reset ; ;AC000; mov dx,OFFSET DG:USERDIR ;Recover users directory DOS_Call ChDir ; ;AC000; cmp BYTE PTR cs:[FRAGMENT],1 ;Check for any fragmented files? ;an029;bgb jnz DONE ;No -- we're finished call CHECKFILES ;Yes -- report any fragments Public Done DONE: ASSUME DS:NOTHING mov DL,cs:[USERDEV] ;Recover users drive ;an029;bgb DOS_Call Set_Default_Drive ; ;AC000; ret IF LOSTDEB ;is this private build version? Procedure lostdisp,near ;an005;bgb savereg ; ;an005;bgb mov ax,dx ;save orig value mov cl,12 ;shift 3 nibbles shr dx,cl ;remove al but last nibble and dx,000fh cmp dx,0ah ; $IF B JNB $$IF49 add dx,30h ;make it char ; $ELSE JMP SHORT $$EN49 $$IF49: add dx,37h ; $ENDIF $$EN49: push ax mov ah,2 int 21h pop ax mov dx,ax ;get orig value mov cl,8 shr dx,cl and dx,000fh cmp dx,0ah ; $IF B JNB $$IF52 add dx,30h ;make it char ; $ELSE JMP SHORT $$EN52 $$IF52: add dx,37h ; $ENDIF $$EN52: push ax mov ah,2 int 21h pop ax mov dx,ax ;get orig value mov cl,4 shr dx,cl and dx,000fh cmp dx,0ah ; $IF B JNB $$IF55 add dx,30h ;make it char ; $ELSE JMP SHORT $$EN55 $$IF55: add dx,37h ; $ENDIF $$EN55: push ax mov ah,2 int 21h pop ax mov dx,ax ;get orig value and dx,000fh cmp dx,0ah ; $IF B JNB $$IF58 add dx,30h ;make it char ; $ELSE JMP SHORT $$EN58 $$IF58: add dx,37h ; $ENDIF $$EN58: mov ah,2 int 21h mov dl,' ' ;space after last number mov ah,2 int 21h restorereg ;an005;bgb return ;an005;bgb EndProc lostdisp ;an005;bgb ENDIF pathlabl chkfat CODE ENDS END