1 TITLE CHKFAT
- procedures that acces the fat
and/or fatmap
5 include chkseg
.inc ;an005;bgb
13 CONST
SEGMENT PUBLIC PARA
'DATA'
14 EXTRN CREATMES
:byte,FIXMES_ARG
:word
16 EXTRN BADW_ARG
:word,FATAL_END
:word
17 EXTRN badrw_num
:word,BADRW_STR
:WORD,HAVFIX
:byte
18 EXTRN FREEBYMES1
:byte,FREEBYMES2
:byte
19 EXTRN FREE_ARG1
:WORD,FREE_ARG2
:WORD,FREE_ARG3
:WORD,ORPHCNT
:dword
20 EXTRN DIRTYFAT
:byte,CROSSCNT
:dword,DOFIX
:byte,SECONDPASS
:byte
21 EXTRN BADSIZ
:word,ORPHSIZ
:word,LCLUS
:word,ORPHFCB
:byte
22 EXTRN HECODE
:byte,USERDIR
:byte,FRAGMENT
:byte
23 EXTRN ORPHEXT
:byte,ALLDRV
:byte,FIXMFLG
:byte,DIRCHAR
:byte
24 EXTRN BIGFAT
:byte,EOFVAL
:word,BADVAL
:word
25 extrn fTrunc
:BYTE, rarg1
:word ;an018;bgb
26 extrn temp_dd
:dword ;an049;bgb
29 DATA SEGMENT PUBLIC PARA
'DATA'
30 extrn fatcnt
:byte ;an005;bgb
31 EXTRN THISDPB
:dword,NUL_ARG
:byte
32 EXTRN NAMBUF
:byte,SRFCBPT
:word,FATMAP
:word
33 EXTRN MCLUS
:word,CSIZE
:byte,SSIZE
:word
34 EXTRN DSIZE
:word,ARG1
:word,ARG_BUF
:byte,ERRCNT
:byte
35 EXTRN USERDEV
:byte,HARDCH
:dword,CONTCH
:dword
36 EXTRN ExitStatus
:Byte,Read_Write_Relative
:Byte
37 extrn bytes_per_sector
:word, fattbl
:word ;an005;bgb
38 extrn sec_count
:word, secs_per_64k
:word, paras_per_64k
:word ;an005;bgb
39 extrn fattbl_seg
:word, fatsiz
:word, paras_per_fat
:word ;an005;bgb
40 extrn end_of_fatmap
:word ;an030;bgb
41 extrn root_entries
:word ;ac048;bgb;an047;bgb
44 CODE SEGMENT PUBLIC PARA
'CODE'
45 ASSUME
CS:DG
,DS:DG
,ES:DG
,SS:DG
46 EXTRN PRINTF_CRLF
:NEAR,FCB_TO_ASCZ
:NEAR, recover
:near
47 EXTRN EPRINT
:NEAR, makorphnam
:near
48 EXTRN DOINT26
:NEAR,PROMPTYN
:NEAR,CHECKFILES
:NEAR,DIRPROC
:NEAR
49 EXTRN DOCRLF
:NEAR, getfilsiz
:near, fatal
:near, write_disk
:near
50 EXTRN GETENT
:NEAR,CHECKNOFMES
:NEAR, systime
:near
51 EXTRN multiply_32_bits
:near ;an049;bgb
53 public calc_fatmap_seg
, MARKMAP
, CHKMAP
, CHKMAPLP
, ORPHAN
, CONTLP
, RET18
54 public PromptRecover
, NOCHAINREC
, CHKMAPLP2
, NEXTCLUS
55 public DISPFRB
, FINDCHAIN
, CHKMAPLP3
, CHAINLP
, INSERTEOF
, FAT12_4
, CHKCHHEAD
56 public ADDCHAIN
, CHGOON
, NEXTCLUS2
,
57 public CHAINREC
, MAKFILLP
, GOTENT
, OPAGAIN
, GOTORPHNAM
, ENTMADE
, NEXTENT
58 public NXTORP
, RET100
, nextorph
59 public AMDONE
, REWRITE
, WRTLOOP
60 public WRTOK
, NOWRITE
, DONE
, CROSSCHK
, calc_fat_addr
, pack
, unpack
62 PHONEY_STACK
DW 5 DUP(0) ;ac048;bgb
65 ;***************************************************************************** ;an005;bgb
66 ; CALC-FAT-ADDR - calculate the seg/off of the fat cell from the cell number ;an005;bgb
68 ; Inputs: es - fat table segment
71 ; Outputs: es - fat table segment + cluster seg
74 ; LARGE FAT SUPPORT ;an005;bgb
75 ;******************* ;an005;bgb
76 ; the offset into the fat table is cluster number times 2 (2 bytes per fat entry) ;an005;bgb
77 ; This will result not only in the segment boundary being passed, but also in ;an005;bgb
78 ; a single-word math overflow. So, we calculate the the address as follows: ;an005;bgb
79 ; 0. start with cluster number (1-65535) ;an005;bgb
80 ; 1. divide by 8 to get the number of paragraphs per fat-cell (0-8191) ;an005;bgb
81 ; remainder = (0-7) ;an005;bgb
82 ; 2. multiply the remainder by 2 to get offset in bytes (0-15) ;an005;bgb
83 ; You now have a paragraph-offset number that you can use to calc the addr into ;an005;bgb
84 ; the fat table. To get the physical addr you must add it to the offset of the ;an005;bgb
85 ; table in memory. ;an005;bgb
86 ; 3. add the paras to the segment register ;an005;bgb
87 ; 4. add the offset to the offset register ;an005;bgb
88 ;****************************************************************************** ;an005;bgb
89 Procedure calc_fat_addr
,near ;an005;bgb
90 savereg
<ax,bx,dx> ; ;an005;bgb
91 mov ax,si ;get cluster number from si
92 mov bx,0008h ; div by para (* 2 bytes per clus) ;an005;bgb
93 xor dx,dx ; zero dx for word divide ;an005;bgb
94 div bx ; do it ;an022;bgb;bgb
95 mov bx,es ; get fat table segment ;an005;bgb
96 add bx,ax ; add number of paras to the cluster ;an005;bgb
97 mov es,bx ; move it back ;an005;bgb
98 shl dx,1 ; remainder times 2 ;an005;bgb
99 mov di,dx ; offset = 00 + remainder ;an005;bgb
100 restorereg
<dx,bx,ax> ;an005;bgb
102 EndProc calc_fat_addr
;an005;bgb
104 ;=========================================================================
105 ; UNPACK : This routine calculates the position in the FAT
106 ; where the cluster number resides and obtains
109 ; Inputs : SI - Cluster number
110 ; Outputs : DI - Cluster contents
111 ; zero flag is set if fat cell = zero
114 ; - get addr of fat table
116 ; then get the address of the cell (calc_fat_addr)
119 ; else multiply the cluster-number by 1.5 to get the byte-offset
120 ; move the contents of the cluster into di
121 ; if the cluster-number is odd,
122 ; then shift it right by 1 nibble
124 ; else (its already shifted right)
126 ;=========================================================================
127 UNPACK proc
near ;ac005; dms;unpack FAT
129 mov es,fattbl_seg
;point to FAT in memory ;an005;bgb
130 mov DI,SI ;put cluster number in DI
131 cmp [BIGFAT
],0 ;big fat?
134 call calc_fat_addr
;calc addr of cluster ;an005;bgb
135 mov di,word ptr es:[di] ;es:bx points to fat cluster ;an005;bgb
141 ADD DI,SI ; Mult by 1.5
142 mov DI,word ptr es:[di]
143 TEST SI,1 ;is the cluster number odd?
144 ; $IF nz ;last bit is non-zero; means it is odd
146 SHR DI,1 ;shift by 1 nibble
150 and di,0fffh ;ac005; dms;
151 ; $ELSE ;ac005; dms;even cluster bound.
161 UNPACK endp
;ac005; dms;
163 ;=========================================================================
164 ; PACK : This routine puts data into the FAT.
166 ; Inputs : SI - Cluster number to be packed
167 ; dx - Data to be packed
169 ; Outputs : Altered FAT
171 ; - set the fat-changed-flags
172 ; - get the seg of the fat-table
174 ; then get the address of the cell (calc_fat_addr)
175 ; mov the new value into it
176 ; else multiply the cluster-number by 1.5 to get the byte-offset
177 ; move the contents of the cluster into di
178 ; if the cluster-number is odd,
179 ; then shift it right by 1 nibble
181 ; else (its already shifted right)
183 ;=========================================================================
184 PACK proc
near ;ac005; dms;
185 savereg
<si,di,es> ;ac048;bgb
186 mov [DIRTYFAT
],1 ;Set FAT dirty byte
187 mov [HAVFIX
],1 ;Indicate a fix
188 mov es,fattbl_seg
; ;an005;bgb
191 ; $IF nz ;ac005; dms;big fat?
193 call calc_fat_addr
;calc addr of cluster ;an005;bgb
194 mov es:[di],dx ;move dx into cluster ;an005;bgb
198 shr di,1 ;offset = clus-num * 1.5
199 add di,si ;offset = clus-num * 1.5
200 push di ;save cluster offset
201 mov DI,es:[di] ;get previous value, 4 nibbles
202 test si,1 ;is the cluster number odd?
203 ; $IF nz ;last bit is non-zero; means it is odd
205 SHL dx,1 ;shift by 1 nibble
209 AND DI,0FH ;zero out 1st 3 nibbles '000f'
210 ; $ELSE ;even cluster number
213 AND DI,0F000H ;zero out last 3 nibbles 'f000'
216 or DI,dx ;put new value in with old
217 pop si ;get cluster offset
221 restorereg
<es,di,si> ;ac048;bgb
223 PACK endp
;ac005; dms;
225 ;========================================================================= ;an005;bgb
226 ; CROSSCHK : this proc gets the value of the fatmap entry that is pointed ;an005;bgb
227 ; to by an orphan ;an005;bgb
229 ; Inputs : si - cluster number of the orphan ;an005;bgb
231 ; Outputs : ah - contents of the fatmap pointed to by di ;an005;bgb
234 ;========================================================================= ;an005;bgb
235 procedure CROSSCHK
;an005;bgb
237 mov es,fatmap
;an005;bgb
240 mov ah,es:[di] ;an005;bgb
244 EndProc CROSSCHK
;an005;bgb
246 ;***************************************************************************** ;an005;bgb
247 ; INIT_FATMAP ;an005;bgb
248 ; description: initialize the fatmap area to all zeros ;an005;bgb
250 ; called from: main-routine ;an005;bgb
252 ;Change History: Created 8/31/87 bgb ;an005;bgb
254 ;Input: segment addr of the fatmap ;an005;bgb
255 ; number of clusters in the fat (1-65535) ;an005;bgb
257 ;Output: fatmap ;an005;bgb
260 ;---------- ;an005;bgb
261 ;***************************************************************************** ;an005;bgb
262 Procedure init_fatmap
,Near ;AN000;bgb ;an005;bgb
263 savereg
<es,di,ax,cx>
264 mov es,fatmap
;get seg of the fatmap ;an005;bgb
265 xor di,di ;get off of the fatmap ;an005;bgb
266 mov cx,[MCLUS
] ;do once for each cluster
267 xor AL,AL ;zero means free
268 REP STOSB ;Initialize fatmap to all free
269 mov byte ptr es:[di],al ; ;an010;bgb
270 restorereg
<cx,ax,di,es>
272 endproc init_fatmap
; ;AN000;
274 ;***************************************************************************** ;an005;bgb
275 ; CALC_FATMAP_SEG ;an005;bgb
276 ; description: calculate the segment of the fatmap for addressing purposes ;an005;bgb
278 ; called from: main-routine ;an005;bgb
280 ;Change History: Created 8/31/87 bgb ;an005;bgb
282 ;Input: bytes-per-sector ;an005;bgb
285 ;Output: ram-based fat table ;an005;bgb
286 ; paras-per-fat - number of paragraphs of mem in the fat
287 ; fattbl-seg - segment number of fat table
288 ; fatmap - segment number of the fat map table
291 ;---------- ;an005;bgb
292 ; - calc length fat-table (in paras) ;an005;bgb
293 ; = bytes-per-sector / 16 * sectors-per-fat ;an005;bgb
294 ; - calc segment of fat table in memory ;an005;bgb
295 ; = es + 64k ;an005;bgb
296 ; - calc segment of fatmap area in memory ;an005;bgb
297 ; = es + 64k + length of fat-table ;an005;bgb
298 ;***************************************************************************** ;an005;bgb
299 Procedure calc_fatmap_seg
,Near ;AN000;bgb ;an005;bgb
300 ; calc fat table length ;an005;bgb
302 mov ax,bytes_per_sector
; bytes per sector ;an005;bgb
305 div bx ; paras per sector ;an022;bgb;bgb
306 mov cx,fatsiz
;2 ; get sectors per fat ;an005;bgb
308 mul cx ; paras per fat ;an005;bgb
309 mov paras_per_fat
,ax ;an005;bgb
310 ; calc fat table segment ;an005;bgb
311 mov bx,es ;get seg of fat-table ;an005;bgb
312 add bx,01000h ;add 64k for end of pgm seg ;an005;bgb
313 mov fattbl_seg
,bx ;starting segment of fattbl ;an005;bgb
314 ; calc fatmap segment :an005;bgb
315 add ax,bx ;seg of fatmap= seg of fattbl + size of fattbl ;an005;bgb
316 mov fatmap
,ax ;this is the seg of the fatmap ;an005;bgb
317 ; find segment number of end of fatmap ;an030;bgb
318 ;ptm p5000 mov bx,paras_per_fat ;each fat cell is 2 bytes ;an030;bgb
319 ;ptm p5000 shr bx,1 ;each fatmap cell is 1 byte = ;an030;bgb
320 mov bx, [MCLUS
] ;P5000 INIT_FATMAP use [MCLUS]
321 shr bx, 1 ;P5000 convert it to para.
325 add ax,bx ;add in fatmap seg = ;an030;bgb
327 mov end_of_fatmap
,ax ;last seg value ;an030;bgb
330 endproc calc_fatmap_seg
; ;AN000;
333 ;***************************************************************************** ;ac048;bgb
334 ; FIX_ENTRY - fill in the dir entry with the lost cluster information, give it ;ac048;bgb
335 ; unique filename, and write it back to disk. ;ac048;bgb
337 ; WARNING!! NOTE!! --> ;ac048;bgb
339 ; called by - CHAINREC ;ac048;bgb
341 ; inputs: AX - drive number ;ac048;bgb
342 ; BX - ram offset of beginning of sector ;ac048;bgb
344 ; DX - sector number low ;ac048;bgb
347 ; SI - cluster number of first cluster in this lost chain ;ac048;bgb
348 ; DI - points to entry in ram ;ac048;bgb
350 ; output: AX - ;ac048;bgb
359 ; Regs abused - di,si,cx ;ac048;bgb
361 ;logic: 1. save the starting cluster number ;ac048;bgb
363 ; 2. if the recovered file name already exists, then use the next one. ;ac048;bgb
364 ; do this until the name is unique. ;ac048;bgb
366 ; 3. move all the pertinant info into the dir entry. ;ac048;bgb
368 ; 4. write the dir entry out to disk. ;ac048;bgb
369 ;***************************************************************************** ;ac048;bgb
370 procedure fix_entry
,near ;ac048;bgb
371 mov ds:[DI+26],SI ;move 1st clus num into dir entry ;ac048;bgb ;an005;bgb
372 savereg
<ax,dx,bx> ;Save INT 26 data ;ac048;bgb
373 ;make sure this name is unique ;ac048;bgb
374 DOS_Call Disk_Reset
;func 0d - flush buffers ;AC000;ac048;bgb;
375 mov dx,OFFSET DG
:ORPHFCB
;point to filename file0000.chk ;ac048;bgb
376 mov AH,FCB_OPEN
;open the file just put into the dir ;ac048;bgb
381 or AL,AL ;did the open fail? ;ac048;bgb
382 ; $leave nz ;ac048;bgb
384 call MAKORPHNAM
;Try next name ;ac048;bgb
388 GOTORPHNAM: ;di still points to entry ;ac048;bgb
389 mov SI,OFFSET DG
:ORPHFCB
+ 1 ;ORPHFCB Now has good name ;ac048;bgb
390 mov cx,11 ;move filename, ext ;ac048;bgb
392 call MAKORPHNAM
;Make next name ;ac048;bgb
393 xor ax,ax ;fill dir entry with zeros ;ac048;bgb
396 ; Add in time for orphan file - BAS July 17/85 ;ac048;bgb
397 push dx ;save starting sector number ;ac048;bgb;an045;bgb
398 call SYSTIME
;ac048;bgb
399 STOSW ; Time ;ac048;bgb
401 STOSW ; Date ;ac048;bgb
402 pop dx ;restore starting sector number ;ac048;bgb ;an045;bgb
403 mov SI,ds:[DI] ;get starting cluster number ;ac048;bgb ;an005;bgb
404 inc DI ;skip firstclus in entry ;ac048;bgb
406 PUSH DI ;save it from getfilsiz ;ac048;bgb
407 call GETFILSIZ
;calc file size from number of clus ;ac048;bgb
408 POP DI ;restore di ;ac048;bgb
409 STOSW ;ax=file size low ;ac048;bgb
410 mov ax,dx ;dx=filesize high ;ac048;bgb
412 restorereg
<bx,dx,ax> ;offset, sector num, drive num ;ac048;bgb
413 mov cx,1 ;number of sectors = 1 ;ac048;bgb
414 call DOINT26
;write it out to disk ;ac048;bgb
416 endproc fix_entry
;ac048;bgb
418 ;***************************************************************************** ;ac048;bgb;an047;bgb
419 ; NEXTORPH - find the cluster number of the next orphan. This assumes that ;ac048;bgb;an047;bgb
420 ; there is at least one lost cluster available. ;ac048;bgb;an047;bgb
421 ; ;ac048;bgb;an047;bgb
422 ; WARNING!! NOTE!! --> ;ac048;bgb;an047;bgb
423 ; ;ac048;bgb;an047;bgb
424 ; called by - PROCEDURE NAME ;ac048;bgb;an047;bgb
425 ; ;ac048;bgb;an047;bgb
426 ; inputs: AX - ;ac048;bgb;an047;bgb
427 ; BX - ;ac048;bgb;an047;bgb
428 ; CX - ;ac048;bgb;an047;bgb
429 ; DX - ;a;ac048;bgbn047;bgb
430 ; SP - ;;ac048;bgban047;bgb
431 ; BP - ;a;ac048;bgbn047;bgb
432 ; SI - cluster number of the previous orphan ;a;ac048;bgbn047;bgb
433 ; DI - ;a;ac048;bgbn047;bgb
434 ; DS - ;a;ac048;bgbn047;bgb
435 ; ES - points to one byte map of the fat ;a;ac048;bgbn047;bgb
436 ; ;a;ac048;bgbn047;bgb
437 ; output: AX - ;;ac048;bgban047;bgb
438 ; BX - ;a;ac048;bgbn047;bgb
439 ; CX - ;;ac048;bgban047;bgb
440 ; DX - ;a;ac048;bgbn047;bgb
441 ; SP - ;a;ac048;bgbn047;bgb
442 ; BP - ;a;ac048;bgbn047;bgb
443 ; SI - cluster number of one past the orphan ;ac048;bgb;an047;bgb
444 ; DI - cluster number of the orphan ;a;ac048;bgbn047;bgb
445 ; DS - ;a;ac048;bgbn047;bgb
446 ; ES - ;a;ac048;bgbn047;bgb
447 ; ;a;ac048;bgbn047;bgb
448 ; Regs abused - none ;ac048;bgb;an047;bgb
449 ; ;;ac048;bgban047;bgb
450 ;logic: 1. save ax & es, and point to fat map ;ac048;bgb;an047;bgb
451 ; ;a;ac048;bgbn047;bgb
452 ; 2. do until the head of a chain is found: ;ac048;bgb ;an047;bgb
453 ; ;;ac048;bgban047;bgb
454 ; 3. get the next cell ;ac048;bgb ;an047;bgb
455 ; ;;ac048;bgban047;bgb
456 ; 4. bump pointers into fat map ;ac048;bgb ;an047;bgb
457 ; ;;ac048;bgban047;bgb
458 ; 5. restore ax & es ;;ac048;bgban047;bgb
459 ;*****************************************************************************;a;ac048;bgbn047;bgb
460 procedure NEXTORPH
,near ;a;ac048;bgbn047;bgb
461 savereg
<ax,es> ;save regs abused ;ac048;bgb
462 mov es,[FATMAP
] ;point to fat map ;ac048;bgb
465 loopno: mov al,byte ptr es:[si] ;get the indicated fatmap entry ;ac048;bgb ;an005;bgb
466 inc si ;point to the next one ;ac048;bgb ;an005;bgb
467 inc di ;point to the next one ;ac048;bgb ;an005;bgb
468 cmp AL,89H
;stop when you find an 89 ;ac048;bgb
469 ; $leave z ;this means head(80), found(1), and orphan(8) ;ac048;bgb
474 restorereg
<es,ax> ;restore regs ;ac048;bgb
476 endproc nextorph
;ac048;bgb
480 ;****************************************************************************
481 ; MARKMAP - make a mark in the fat map for every cluster encountered
483 ; called by - markfat,
485 ; inputs - AL - the mark
486 ; DI - cluster number
488 ; outputs - CY if crosslink found
489 ; - AH - previous mark
490 ; - crosscnt (count of number of crosslinks found)
495 ; - point to fatmap with es
496 ; - if that cell has been found before,
497 ; then mark it crossed x'10'
498 ; else mark it found al
499 ;****************************************************************************
500 markmap: savereg
<si,es> ;Save registers ;AN000;
501 xor si,si ;Get addr of map ;an005;bgb
502 mov es,[FATMAP
] ;Get addr of map ;an005;bgb
503 mov ah,es:[di] ;Get entry at that spot ;an005;bgb
504 or ah,ah ;Is it zero? ; ;
505 ; $IF NZ ;already found - mark crossed;If not, we got crosslink ;AC000;
507 add word ptr crosscnt
,1 ;Count the crosslink ; ;
508 adc word ptr crosscnt
+2,0 ;Count the crosslink ; ;
509 or byte ptr es:[di],10H
;Resets zero in map ;An005;bgb
510 stc ;Indicate crosslink on ret ; ;
511 ; $ELSE ;not found - mark found ;No crosslink ; ;
514 mov es:[di],al ;Set mark in map ;Ac005;bgb
515 clc ;Indicate things okay ; ;
518 restorereg
<es,si> ; ;AN005;bgb
522 ;****************************************************************************
523 ; CHKMAP - Compare FAT and FATMAP looking for badsectors and orphans
528 ; - dsize - number of clusters on the disk
535 ; - get addr of fatmap
536 ; - get offset of 1st cluster in fatmap
537 ; - do for all the clusters on the disk:
538 ; - if the cluster has been found
539 ; then get the next cluster in its chain
540 ; if the cell was never pointed to by anyone (0)
541 ; then get the contents of that cell from the fat
542 ; (the contents of the fat cell should be zero, too)
543 ; if the fat-cell is not zero
544 ; then (it should only be a bad sector)
545 ; if it is a bad sector, inc the bad-sector-counter
546 ; otherwise, we have found an orphan sector
548 ; - if there are any orphans,
550 ;****************************************************************************
553 mov es,fatmap
;get segment of the fatmap ;an005;bgb
554 xor si,si ;get the offset of the fatmap ;an005;bgb
555 mov si,2 ;go past the first two (invalid) entries;an005;bgb
556 ;do for all the clusters on the disk
557 mov cx,[DSIZE
] ;loop for the number of clusters on the disk
559 mov al,es:[si] ;move a byte from the fatmap to al ;an005;bgb
560 or al,al ;is the cluster found already?
561 ; $IF Z ;fatmap cell is zero
563 call unpack
;get the contents of it
564 ; $IF NZ ;is there something in the cell?
566 cmp di,[badval
] ;is the fat cell pointing to a bad sector? fff7
569 inc [badsiz
] ;inc the bad sector counter
570 mov byte ptr es:[si],4 ;Flag the map ;an005;bgb
571 ; $ELSE ; no, not a bad sector
574 orphan: inc [orphsiz
] ; then its an orphan
575 mov byte ptr es:[si],8 ;Flag it ;an005;bgb
583 inc si ;point si to next cluster
585 cmp [orphsiz
],0 ;an005;bgb
586 ; $IF A ;if there are any orphans, go recover them ;an005;bgb
594 ;*****************************************************************************
595 ; PROMPTRECOVER - do the actual recovering of files
597 ; inputs: es - points to fatmap
605 ; - ask the user if he wants to convert the orphans to files
608 ;***************************************************************************
610 mov dx,OFFSET DG
:FREEMES
611 call PROMPTYN
;Ask user
618 mov es,[fatmap
] ;Free all orphans ;an005;bgb
621 xor dx,dx ;dx is the new value (free)
623 mov al,es:[si] ;get next byte from fatmap into al
624 TEST AL,8 ; is it an orphan?
627 call PACK
;si=cluster number dx=new value
634 XCHG ax,[ORPHSIZ
] ;number of orphans = zero
635 mov cx,OFFSET DG
:FREEBYMES1
;print msg
639 mov cx,OFFSET DG
:FREEBYMES2
640 mov [LCLUS
],ax ;move number of lost clust would be ;an049;bgb
643 DISPFRB: ;ax=lost clusters (1-fff6)
644 push bx ;save it ;an049;bgb
645 push cx ;save it ;an049;bgb
646 mov cl,[csize
] ;get sectors per cluster (1-32) ;an049;bgb
647 xor ch,ch ;zero out high byte ;an049;bgb
648 xor dx,dx ;zero out hi word for word mult ;an049;bgb
649 mul cx ;cx*ax=dx:ax lost sectors (1-1ffec0);an049;bgb
650 mov bx,dx ;move high word for call ;an049;bgb
651 mov cx,ssize
;word to mult with ;an049;bgb
652 call multiply_32_bits
;bx:ax is result ;an049;bgb
653 mov word ptr rarg1
,ax ;low word into low word ;an049;bgb
654 mov word ptr rarg1
+2,bx ;hi word into hi word ;an049;bgb
656 mov [free_arg2
],bx ;an049;bgb
660 mov dx,cx ;Point to right message;an049;bgb
667 ;*****************************************************************************
670 ; called by - recover
675 ; LOGIC - search thru entire fatmap
678 ;***************************************************************************
679 lostdeb equ
0 ;set private build version on ;an047;bgb
680 lost_str db '00000' ;max size of cluster number
682 ;Do chain recovery on orphans
683 mov es,[FATMAP
] ; point to fatmap
684 mov SI,2 ; point to fatmap
685 mov dx,si ; point to fatmap
686 mov cx,[DSIZE
] ;get total number of clusters on disk
688 mov al,es:[si] ;get next fatmap entry
689 inc si ;point to next fatmap entry
690 ;has to be an orphan(08)
693 ;make sure its not a regular file entry
694 TEST AL,1 ;Seen before ?
697 savereg
<si,cx,dx> ;Save search environment
699 or byte ptr es:[si],81H
;Mark as seen and head
702 IF LOSTDEB
;is this private build version?
703 call lostdisp
;display lost cluster numbers
706 add word ptr orphcnt
,1 ;Found a chain
707 adc word ptr orphcnt
+2,0 ;Found a chain
708 mov SI,dx ;point to the next fatmap entry
710 call UNPACK
;si = fat cell
711 XCHG SI,DI ;si=contents, di=cell number
712 cmp SI,[EOFVAL
] ;is this the end of the file?
713 JAE CHGOON
;yes, then we are done
715 ;dont do this next part if any of two conditions:
716 ; 1. invalid cluster number
717 ; 2. points to itself
718 cmp SI,2 ;well, is it a valid cluster number?
719 JB INSERTEOF
;Bad cluster number
721 JA INSERTEOF
;Bad cluster number
722 cmp SI,DI ;how bout if it points to itself?
723 jz INSERTEOF
;Tight loop
724 ; find out what it points TO
726 TEST AH,8 ;Points to a non-orphan?
728 ;orphan points to nothing
731 ; 1. invalid cluster number
732 ; 2. points to itself
733 ; 3. points to nothing
734 POP SI ;the previous cluster number
735 mov dx,0FFFH ;get eof value (12-bit)
738 mov dx,0FFFFH ;get eof value (16-bit)
740 call PACK
;stick it in!
741 jmp SHORT CHGOON
;and we are done
742 ; orphan point to a head entry
744 TEST AH,80H
;Previosly marked head?
746 AND BYTE PTR es:[DI],NOT 80H
;Turn off head bit
747 sub word ptr orphcnt
,1 ;Wasn't really a head
748 sbb word ptr orphcnt
+2,0 ;Wasn't really a head
752 TEST AH,1 ;Previosly seen?
753 jnz INSERTEOF
;Yup, don't make a cross link
754 or BYTE PTR es:[DI],1 ;Mark as seen
756 jmp CHAINLP
;Follow chain
758 POP dx ;Restore search
768 ;***************************************************************************** ;ac048;bgb
769 ; CHAINREC - the user has requested us to recover the lost clusters ;ac048;bgb
772 ; note: although called from PROMPTRECOVER, this routine returns control to ;ac048;bgb
773 ; recover via the ret instruction. ;ac048;bgb
774 ;***************************************************************************** ;ac048;bgb
776 ;***************************************************************************** ;ac048;bgb
777 ; CHAINREC - The user has requested us to recover the lost clusters ;ac048;bgb
779 ; WARNING!! NOTE!! --> the count of the number of lost cluster chains remains,
780 ; for this proc, a single word. More than 64k chains
781 ; will cause this proc to fail.
783 ; called by - PROCEDURE NAME ;ac048;bgb
785 ; inputs: AX - N/A ;ac048;bgb
787 ; cx - N/A ;ac048;bgb
788 ; dx - N/A ;ac048;bgb
790 ; BP - N/A ;ac048;bgb
791 ; SI - N/A ;ac048;bgb
792 ; DI - N/A ;ac048;bgb
793 ; data: root_entries ;ac048;bgb
796 ; output: AX - ;ac048;bgb
805 ; Regs abused - ;ac048;bgb
807 ;logic: 1. ;ac048;bgb
808 ;***************************************************************************** ;ac048;bgb
809 \fCHAINREC: ;ac048;bgb
810 push es ;save es if it is used for anything ;ac048;bgb
811 push ds ;make es point to data ;ac048;bgb
813 ;find the cluster number of the orphan ;ac048;bgb
814 mov SI,2 ;start at first cluster ;an005;bgb ;ac048;bgb
815 mov DI,1 ;point to previous cluster? ;ac048;bgb
816 call NEXTORPH
;di points to orphan ;ac048;bgb
817 ;init for loop ;ac048;bgb
818 savereg
<si,di> ;save orphan, orphan+1 ;ac048;bgb
819 mov SI,DI ;si point to orphan ;ac048;bgb
820 xor ax,ax ;set count of dir entries processed to zero;ac048;bgb
821 mov dx,word ptr orphcnt
;get low word of lost clusters ;ac048;bgb;an049;bgb
822 mov word ptr temp_dd
,dx ;get low word of lost clusters ;an049;bgb
823 mov dx,word ptr orphcnt
+2 ;get hi word of lost clusters ;an049;bgb
824 mov word ptr temp_dd
+2,dx ;get hi word of lost clusters ;an049;bgb
825 mov BP,OFFSET DG
:PHONEY_STACK
;Set BP to point to "root" ;ac048;bgb
826 ;do for all dir entries: ;ac048;bgb
828 ; $DO ;do for all root entries ;ac048;bgb
830 savereg
<ax> ;cnt of entries processed, num orphans ;ac048;bgb;an049;bgb
831 call GETENT
;DI points to entry ;ac048;bgb
832 cmp BYTE PTR ds:[DI],0E5H ;is this dir entry erased? ;an;ac048;bgb005;bgb
833 ; $if z,or ;ac048;bgb
835 cmp BYTE PTR ds:[DI],0 ;is this dir entry empty? ;an;ac048;bgb005;bgb
839 GOTENT: mov [HAVFIX
],1 ;Making a fix ;ac048;bgb
840 cmp [DOFIX
],0 ;/f parameter specified? ;ac048;bgb
841 ; $if NZ ;yes- do the fix ;ac048;bgb
843 call fix_entry
;ac048;bgb
846 ENTMADE: restorereg
<ax,di,si> ;ac048;bgb;an049;bgb
847 sub word ptr temp_dd
,1 ;finished with one orphan ;ac048;bgb;an049;bgb
848 sbb word ptr temp_dd
+2,0 ;finished with one orphan ;ac048;bgb;an049;bgb
849 cmp word ptr temp_dd
,0 ;is that the last one? ;ac048;bgb;an049;bgb
850 ; $IF Z,AND ;no, check the hi word ;an049;bgb
852 cmp word ptr temp_dd
+2,0;is that the last one? ;ac048;bgb;an049;bgb
853 ; $IF Z ;neither are zero ;an049;bgb
855 jmp RET100
; yes,we are done ;ac048;bgb;an049;bgb
858 call NEXTORPH
;get the cluster of the next one ;ac048;bgb
859 savereg
<si,di> ;ac048;bgb
861 ; $else ;dir entry was not erased or zero ;ac048;bgb
864 NEXTENT: restorereg
<ax> ;ac048;bgb;an049;bgb
867 NXTORP: inc ax ;ac048;bgb
868 cmp ax,root_entries
;do for 0 to (root_entries - 1) ;ac048;bgb
869 ; $leave z ;ac048;bgb
874 restorereg
<ax,ax> ;Clean Stack from si,di ;ac048;bgb
875 sub word ptr orphcnt
,dx ;Couldn't make them all ;ac048;bgb
876 sbb word ptr orphcnt
+2,0 ;Couldn't make them all ;ac048;bgb
877 mov dx,OFFSET DG
:CREATMES
;ac048;bgb
878 mov byte ptr [arg_buf
],0 ;ac048;bgb
879 call EPRINT
;ac048;bgb
880 RET100: pop es ;restore es ;ac048;bgb
886 ;*****************************************************************************
887 ;*****************************************************************************
888 SUBTTL AMDONE
- Finish up routine
894 jz NOWRITE
;FAT not dirty
896 jz NOWRITE
;Not supposed to fix
900 mov cx,[bx.dpb_FAT_size
] ;Sectors for one fat (DCR) ;AC000;
902 mov CL,[bx.dpb_FAT_count
] ;Number of FATs
903 mov dx,[bx.dpb_first_FAT
] ;First sector of FAT
908 ; set up to write to the disk
909 xor bx,bx ;offset of the fat-table ;an005;bgb
910 mov es,fattbl_seg
;segment of the fat-table ;an005;bgb
922 call Write_Disk
;Do relative sector write ;AC000;
926 ;mov [badrw_str],offset dg:writing
927 POP ax ; Get fat # in AH
928 PUSH ax ; Back on stack
929 xchg al,ah ; Fat # to AL
930 xor ah,ah ; Make it a word
932 mov dx,offset dg
:badw_arg
941 loop WRTLOOP
;Next FAT
942 POP cx ;Number of FATs
943 cmp CL,[ERRCNT
] ;Error on all?
949 ; make sure that the data fields are always adressable, because
950 ;we can come here after a ctl - break has happened. so point to them w/ cs:
952 DOS_Call Disk_Reset
; ;AC000;
953 mov dx,OFFSET DG
:USERDIR
;Recover users directory
954 DOS_Call ChDir
; ;AC000;
955 cmp BYTE PTR cs:[FRAGMENT
],1 ;Check for any fragmented files? ;an029;bgb
956 jnz DONE
;No -- we're finished
957 call CHECKFILES
;Yes -- report any fragments
961 mov DL,cs:[USERDEV
] ;Recover users drive ;an029;bgb
962 DOS_Call Set_Default_Drive
; ;AC000;
973 IF LOSTDEB
;is this private build version?
974 Procedure lostdisp
,near ;an005;bgb
975 savereg
<ax,bx,cx,dx,si,di> ; ;an005;bgb
976 mov ax,dx ;save orig value
978 mov cl,12 ;shift 3 nibbles
979 shr dx,cl ;remove al but last nibble
984 add dx,30h
;make it char
996 mov dx,ax ;get orig value
1003 add dx,30h
;make it char
1015 mov dx,ax ;get orig value
1022 add dx,30h
;make it char
1034 mov dx,ax ;get orig value
1039 add dx,30h
;make it char
1049 mov dl,' ' ;space after last number
1053 restorereg
<di,si,dx,bx,cx,ax> ;an005;bgb
1055 EndProc lostdisp
;an005;bgb