]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/CHKDSK/CHKFAT.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / CMD / CHKDSK / CHKFAT.ASM
1 TITLE CHKFAT - procedures that acces the fat and/or fatmap
2 page ,132 ;\ f
3
4 .xlist
5 include chkseg.inc ;an005;bgb
6 INCLUDE CHKCHNG.inc
7 INCLUDE DOSSYM.inc
8 INCLUDE CHKEQU.inc
9 INCLUDE CHKMACRO.inc
10 include pathmac.inc
11
12
13 CONST SEGMENT PUBLIC PARA 'DATA'
14 EXTRN CREATMES:byte,FIXMES_ARG:word
15 EXTRN FREEMES:byte
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
27 CONST ENDS
28
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
42 DATA ENDS
43
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
52
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
61 .list
62 PHONEY_STACK DW 5 DUP(0) ;ac048;bgb
63
64 pathlabl chkfat
65 ;***************************************************************************** ;an005;bgb
66 ; CALC-FAT-ADDR - calculate the seg/off of the fat cell from the cell number ;an005;bgb
67 ; ;an005;bgb
68 ; Inputs: es - fat table segment
69 ; si - cluster number
70 ;
71 ; Outputs: es - fat table segment + cluster seg
72 ; di - cluster offset
73 ; ;an005;bgb
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
101 return ;an005;bgb
102 EndProc calc_fat_addr ;an005;bgb
103
104 ;=========================================================================
105 ; UNPACK : This routine calculates the position in the FAT
106 ; where the cluster number resides and obtains
107 ; its contents.
108 ;
109 ; Inputs : SI - Cluster number
110 ; Outputs : DI - Cluster contents
111 ; zero flag is set if fat cell = zero
112 ;
113 ; LOGIC
114 ; - get addr of fat table
115 ; - if 16-bit fat,
116 ; then get the address of the cell (calc_fat_addr)
117 ; mov it into di
118 ; set the zero flag
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
123 ; set the zero flag
124 ; else (its already shifted right)
125 ; set the zero flag
126 ;=========================================================================
127 UNPACK proc near ;ac005; dms;unpack FAT
128 push es ;an005;bgb
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?
132 ; $IF nz ;yes
133 JZ $$IF1
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
136 or DI,DI ; Set zero
137 ; $ELSE ;small fat
138 JMP SHORT $$EN1
139 $$IF1:
140 SHR DI,1
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
145 JZ $$IF3
146 SHR DI,1 ;shift by 1 nibble
147 SHR DI,1
148 SHR DI,1
149 SHR DI,1
150 and di,0fffh ;ac005; dms;
151 ; $ELSE ;ac005; dms;even cluster bound.
152 JMP SHORT $$EN3
153 $$IF3:
154 AND DI,0FFFH
155 ; $ENDIF
156 $$EN3:
157 ; $ENDIF
158 $$EN1:
159 pop es
160 return
161 UNPACK endp ;ac005; dms;
162
163 ;=========================================================================
164 ; PACK : This routine puts data into the FAT.
165 ;
166 ; Inputs : SI - Cluster number to be packed
167 ; dx - Data to be packed
168 ;
169 ; Outputs : Altered FAT
170 ; LOGIC
171 ; - set the fat-changed-flags
172 ; - get the seg of the fat-table
173 ; - if 16-bit fat,
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
180 ; set the zero flag
181 ; else (its already shifted right)
182 ; set the zero flag
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
189 mov DI,SI
190 cmp [BIGFAT],0
191 ; $IF nz ;ac005; dms;big fat?
192 JZ $$IF7
193 call calc_fat_addr ;calc addr of cluster ;an005;bgb
194 mov es:[di],dx ;move dx into cluster ;an005;bgb
195 ; $ELSE
196 JMP SHORT $$EN7
197 $$IF7:
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
204 JZ $$IF9
205 SHL dx,1 ;shift by 1 nibble
206 SHL dx,1
207 SHL dx,1
208 SHL dx,1
209 AND DI,0FH ;zero out 1st 3 nibbles '000f'
210 ; $ELSE ;even cluster number
211 JMP SHORT $$EN9
212 $$IF9:
213 AND DI,0F000H ;zero out last 3 nibbles 'f000'
214 ; $ENDIF
215 $$EN9:
216 or DI,dx ;put new value in with old
217 pop si ;get cluster offset
218 mov es:[SI],DI
219 ; $ENDIF
220 $$EN7:
221 restorereg <es,di,si> ;ac048;bgb
222 ret
223 PACK endp ;ac005; dms;
224
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
228 ; ;an005;bgb
229 ; Inputs : si - cluster number of the orphan ;an005;bgb
230 ; ;an005;bgb
231 ; Outputs : ah - contents of the fatmap pointed to by di ;an005;bgb
232 ; LOGIC ;an005;bgb
233 ; ***** ;an005;bgb
234 ;========================================================================= ;an005;bgb
235 procedure CROSSCHK ;an005;bgb
236 push es
237 mov es,fatmap ;an005;bgb
238 xor di,di ;an005;bgb
239 ADD DI,SI
240 mov ah,es:[di] ;an005;bgb
241 TEST AH,10H
242 pop es
243 ret
244 EndProc CROSSCHK ;an005;bgb
245
246 ;***************************************************************************** ;an005;bgb
247 ; INIT_FATMAP ;an005;bgb
248 ; description: initialize the fatmap area to all zeros ;an005;bgb
249 ; ;an005;bgb
250 ; called from: main-routine ;an005;bgb
251 ; ;an005;bgb
252 ;Change History: Created 8/31/87 bgb ;an005;bgb
253 ; ;an005;bgb
254 ;Input: segment addr of the fatmap ;an005;bgb
255 ; number of clusters in the fat (1-65535) ;an005;bgb
256 ; ;an005;bgb
257 ;Output: fatmap ;an005;bgb
258 ; ;an005;bgb
259 ; LOGIC ;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>
271 return
272 endproc init_fatmap ; ;AN000;
273 ;
274 ;***************************************************************************** ;an005;bgb
275 ; CALC_FATMAP_SEG ;an005;bgb
276 ; description: calculate the segment of the fatmap for addressing purposes ;an005;bgb
277 ; ;an005;bgb
278 ; called from: main-routine ;an005;bgb
279 ; ;an005;bgb
280 ;Change History: Created 8/31/87 bgb ;an005;bgb
281 ; ;an005;bgb
282 ;Input: bytes-per-sector ;an005;bgb
283 ; fatsiz ;an005;bgb
284 ; ;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
289 ; ;an005;bgb
290 ; LOGIC ;an005;bgb
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
301 push es
302 mov ax,bytes_per_sector ; bytes per sector ;an005;bgb
303 xor dx,dx ;an005;bgb
304 mov bx,16 ;an005;bgb
305 div bx ; paras per sector ;an022;bgb;bgb
306 mov cx,fatsiz ;2 ; get sectors per fat ;an005;bgb
307 xor dx,dx ;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.
322 shr bx, 1 ;P5000
323 shr bx, 1 ;P5000
324 shr bx, 1 ;P5000
325 add ax,bx ;add in fatmap seg = ;an030;bgb
326 inc ax ;P5000
327 mov end_of_fatmap,ax ;last seg value ;an030;bgb
328 pop es
329 ret ; ;AN000;
330 endproc calc_fatmap_seg ; ;AN000;
331 ;
332 ;ac048;bgb
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
336 ; ;ac048;bgb
337 ; WARNING!! NOTE!! --> ;ac048;bgb
338 ; ;ac048;bgb
339 ; called by - CHAINREC ;ac048;bgb
340 ; ;ac048;bgb
341 ; inputs: AX - drive number ;ac048;bgb
342 ; BX - ram offset of beginning of sector ;ac048;bgb
343 ; CX - ;ac048;bgb
344 ; DX - sector number low ;ac048;bgb
345 ; SP - ;ac048;bgb
346 ; BP - ;ac048;bgb
347 ; SI - cluster number of first cluster in this lost chain ;ac048;bgb
348 ; DI - points to entry in ram ;ac048;bgb
349 ; ;ac048;bgb
350 ; output: AX - ;ac048;bgb
351 ; BX - ;ac048;bgb
352 ; CX - ;ac048;bgb
353 ; DX - ;ac048;bgb
354 ; SP - ;ac048;bgb
355 ; BP - ;ac048;bgb
356 ; SI - ;ac048;bgb
357 ; DI- ;ac048;bgb
358 ; ;ac048;bgb
359 ; Regs abused - di,si,cx ;ac048;bgb
360 ; ;ac048;bgb
361 ;logic: 1. save the starting cluster number ;ac048;bgb
362 ; ;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
365 ; ;ac048;bgb
366 ; 3. move all the pertinant info into the dir entry. ;ac048;bgb
367 ; ;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
377 OPAGAIN: ;ac048;bgb
378 ; $do ;ac048;bgb
379 $$DO13:
380 INT 21H ;ac048;bgb
381 or AL,AL ;did the open fail? ;ac048;bgb
382 ; $leave nz ;ac048;bgb
383 JNZ $$EN13
384 call MAKORPHNAM ;Try next name ;ac048;bgb
385 ; $enddo ;ac048;bgb
386 JMP SHORT $$DO13
387 $$EN13:
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
391 REP MOVSB ;ac048;bgb
392 call MAKORPHNAM ;Make next name ;ac048;bgb
393 xor ax,ax ;fill dir entry with zeros ;ac048;bgb
394 mov cx,11 ;ac048;bgb
395 REP STOSB ;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
400 mov ax,dx ;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
405 inc DI ;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
411 STOSW ; ;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
415 ret ;ac048;bgb
416 endproc fix_entry ;ac048;bgb
417 ;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
463 ; $do ;ac048;bgb
464 $$DO16:
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
470 JZ $$EN16
471 ; $enddo ;ac048;bgb
472 JMP SHORT $$DO16
473 $$EN16:
474 restorereg <es,ax> ;restore regs ;ac048;bgb
475 return ;ac048;bgb
476 endproc nextorph ;ac048;bgb
477 ;ac048;bgb
478 ;ac048;bgb
479
480 ;****************************************************************************
481 ; MARKMAP - make a mark in the fat map for every cluster encountered
482 ;
483 ; called by - markfat,
484 ;
485 ; inputs - AL - the mark
486 ; DI - cluster number
487 ;
488 ; outputs - CY if crosslink found
489 ; - AH - previous mark
490 ; - crosscnt (count of number of crosslinks found)
491 ; - fatmap marked
492 ;
493 ; LOGIC
494 ;******
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;
506 JZ $$IF19
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 ; ;
512 JMP SHORT $$EN19
513 $$IF19:
514 mov es:[di],al ;Set mark in map ;Ac005;bgb
515 clc ;Indicate things okay ; ;
516 ; $ENDIF ; ;AN000;
517 $$EN19:
518 restorereg <es,si> ; ;AN005;bgb
519 ret ; ; ;
520
521
522 ;****************************************************************************
523 ; CHKMAP - Compare FAT and FATMAP looking for badsectors and orphans
524 ;
525 ; called by -
526 ;
527 ; inputs - fatmap
528 ; - dsize - number of clusters on the disk
529 ;
530 ; outputs - badsiz -
531 ; -
532 ; -
533 ; LOGIC
534 ;******
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
547 ; end-of-loop
548 ; - if there are any orphans,
549 ; then recover them
550 ;****************************************************************************
551 CHKMAP:
552 push es ;an014;bgb
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
558 CHKMAPLP:
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
562 JNZ $$IF22
563 call unpack ;get the contents of it
564 ; $IF NZ ;is there something in the cell?
565 JZ $$IF23
566 cmp di,[badval] ;is the fat cell pointing to a bad sector? fff7
567 ; $IF Z ; yes
568 JNZ $$IF24
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
572 JMP SHORT $$EN24
573 $$IF24:
574 orphan: inc [orphsiz] ; then its an orphan
575 mov byte ptr es:[si],8 ;Flag it ;an005;bgb
576 ; $ENDIF
577 $$EN24:
578 ; $ENDIF
579 $$IF23:
580 ; $ENDIF
581 $$IF22:
582 CONTLP:
583 inc si ;point si to next cluster
584 loop chkmaplp
585 cmp [orphsiz],0 ;an005;bgb
586 ; $IF A ;if there are any orphans, go recover them ;an005;bgb
587 JNA $$IF29
588 call recover
589 ; $ENDIF
590 $$IF29:
591 pop es ;an014;bgb
592 RET18: ret
593
594 ;*****************************************************************************
595 ; PROMPTRECOVER - do the actual recovering of files
596 ;
597 ; inputs: es - points to fatmap
598 ; ax -
599 ; bx -
600 ; cx -
601 ; dx -
602 ;
603 ; outputs:
604 ; LOGIC
605 ; - ask the user if he wants to convert the orphans to files
606 ; -
607 ; -
608 ;***************************************************************************
609 PromptRecover:
610 mov dx,OFFSET DG:FREEMES
611 call PROMPTYN ;Ask user
612 ; $IF Z
613 JNZ $$IF31
614 jmp CHAINREC
615 ; $ENDIF
616 $$IF31:
617 NOCHAINREC:
618 mov es,[fatmap] ;Free all orphans ;an005;bgb
619 mov si,2 ;an005;bgb
620 mov cx,[dsize]
621 xor dx,dx ;dx is the new value (free)
622 CHKMAPLP2:
623 mov al,es:[si] ;get next byte from fatmap into al
624 TEST AL,8 ; is it an orphan?
625 ; $IF NZ ;yes
626 JZ $$IF33
627 call PACK ;si=cluster number dx=new value
628 ; $ENDIF
629 $$IF33:
630 NEXTCLUS:
631 inc si
632 loop CHKMAPLP2
633 xor ax,ax
634 XCHG ax,[ORPHSIZ] ;number of orphans = zero
635 mov cx,OFFSET DG:FREEBYMES1 ;print msg
636 cmp [DOFIX],0
637 ; $IF Z
638 JNZ $$IF35
639 mov cx,OFFSET DG:FREEBYMES2
640 mov [LCLUS],ax ;move number of lost clust would be ;an049;bgb
641 ; $ENDIF
642 $$IF35:
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
655 mov [free_arg1],ax
656 mov [free_arg2],bx ;an049;bgb
657 mov [free_arg3],cx
658 pop cx
659 pop bx
660 mov dx,cx ;Point to right message;an049;bgb
661 call printf_crlf
662 ret
663
664
665
666
667 ;*****************************************************************************
668 ; FINDCHAIN -
669 ;
670 ; called by - recover
671 ;
672 ; inputs:
673 ;
674 ; outputs:
675 ; LOGIC - search thru entire fatmap
676 ; -
677 ; -
678 ;***************************************************************************
679 lostdeb equ 0 ;set private build version on ;an047;bgb
680 lost_str db '00000' ;max size of cluster number
681 FINDCHAIN:
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
687 CHKMAPLP3:
688 mov al,es:[si] ;get next fatmap entry
689 inc si ;point to next fatmap entry
690 ;has to be an orphan(08)
691 TEST AL,8 ;Orphan?
692 jz NEXTCLUS2 ;Nope
693 ;make sure its not a regular file entry
694 TEST AL,1 ;Seen before ?
695 jnz NEXTCLUS2 ;Yup
696 ;recover this chain
697 savereg <si,cx,dx> ;Save search environment
698 dec SI
699 or byte ptr es:[si],81H ;Mark as seen and head
700
701
702 IF LOSTDEB ;is this private build version?
703 call lostdisp ;display lost cluster numbers
704 ENDIF
705
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
709 CHAINLP:
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
714 PUSH DI ;no, not eof
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
720 cmp SI,[dsize]
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
725 call CROSSCHK
726 TEST AH,8 ;Points to a non-orphan?
727 jnz CHKCHHEAD ;Nope
728 ;orphan points to nothing
729 INSERTEOF:
730 ; you come here if:
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)
736 cmp [BIGFAT],0
737 jz FAT12_4
738 mov dx,0FFFFH ;get eof value (16-bit)
739 FAT12_4:
740 call PACK ;stick it in!
741 jmp SHORT CHGOON ;and we are done
742 ; orphan point to a head entry
743 CHKCHHEAD:
744 TEST AH,80H ;Previosly marked head?
745 jz ADDCHAIN ;Nope
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
749 POP DI ;Clean stack
750 jmp SHORT CHGOON
751 ADDCHAIN:
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
755 POP DI ;Clean stack
756 jmp CHAINLP ;Follow chain
757 CHGOON:
758 POP dx ;Restore search
759 POP cx
760 POP SI
761 NEXTCLUS2:
762 inc dx
763 loop CHKMAPLP3
764 ret
765
766
767
768 ;***************************************************************************** ;ac048;bgb
769 ; CHAINREC - the user has requested us to recover the lost clusters ;ac048;bgb
770 ; ;ac048;bgb
771 ; inputs: ;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
775 ;ac048;bgb
776 ;***************************************************************************** ;ac048;bgb
777 ; CHAINREC - The user has requested us to recover the lost clusters ;ac048;bgb
778 ; ;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.
782 ; ;ac048;bgb
783 ; called by - PROCEDURE NAME ;ac048;bgb
784 ; ;ac048;bgb
785 ; inputs: AX - N/A ;ac048;bgb
786 ; bx - ;ac048;bgb
787 ; cx - N/A ;ac048;bgb
788 ; dx - N/A ;ac048;bgb
789 ; SP - ;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
794 ; orphcnt ;ac048;bgb
795 ; ;ac048;bgb
796 ; output: AX - ;ac048;bgb
797 ; bx - ;ac048;bgb
798 ; cx - ;ac048;bgb
799 ; dx - ;ac048;bgb
800 ; SP - ;ac048;bgb
801 ; BP - ;ac048;bgb
802 ; SI - ;ac048;bgb
803 ; DI- ;ac048;bgb
804 ; ;ac048;bgb
805 ; Regs abused - ;ac048;bgb
806 ; ;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
812 pop es ;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
827 MAKFILLP: ;ac048;bgb
828 ; $DO ;do for all root entries ;ac048;bgb
829 $$DO37:
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
834 JZ $$LL38
835 cmp BYTE PTR ds:[DI],0 ;is this dir entry empty? ;an;ac048;bgb005;bgb
836 ; $if z ;ac048;bgb
837 JNZ $$IF38
838 $$LL38:
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
842 JZ $$IF39
843 call fix_entry ;ac048;bgb
844 ; $endif ;ac048;bgb
845 $$IF39:
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
851 JNZ $$IF41
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
854 JNZ $$IF41
855 jmp RET100 ; yes,we are done ;ac048;bgb;an049;bgb
856 ; $endif ;an049;bgb
857 $$IF41:
858 call NEXTORPH ;get the cluster of the next one ;ac048;bgb
859 savereg <si,di> ;ac048;bgb
860 mov SI,DI ;ac048;bgb
861 ; $else ;dir entry was not erased or zero ;ac048;bgb
862 JMP SHORT $$EN38
863 $$IF38:
864 NEXTENT: restorereg <ax> ;ac048;bgb;an049;bgb
865 ; $endif ;ac048;bgb
866 $$EN38:
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
870 JZ $$EN37
871 ; $ENDDO ;ac048;bgb
872 JMP SHORT $$DO37
873 $$EN37:
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
881 ret ;ac048;bgb
882 ;ac048;bgb
883 ;ac048;bgb
884 ;ac048;bgb
885
886 ;*****************************************************************************
887 ;*****************************************************************************
888 SUBTTL AMDONE - Finish up routine
889 PAGE
890 Public AmDone
891 AMDONE:
892 ASSUME DS:NOTHING
893 cmp [DIRTYFAT],0
894 jz NOWRITE ;FAT not dirty
895 cmp [DOFIX],0
896 jz NOWRITE ;Not supposed to fix
897 REWRITE:
898 LDS bx,[THISDPB]
899 ASSUME DS:NOTHING
900 mov cx,[bx.dpb_FAT_size] ;Sectors for one fat (DCR) ;AC000;
901 mov DI,cx
902 mov CL,[bx.dpb_FAT_count] ;Number of FATs
903 mov dx,[bx.dpb_first_FAT] ;First sector of FAT
904 PUSH CS
905 POP DS
906 ASSUME DS:DG
907 mov [ERRCNT],0
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
911 mov AL,[ALLDRV]
912 dec AL
913 mov AH,1
914 PUSH cx
915 WRTLOOP:
916 XCHG cx,DI
917 PUSH dx
918 PUSH cx
919 PUSH DI
920 PUSH ax
921
922 call Write_Disk ;Do relative sector write ;AC000;
923
924 JNC WRTOK
925 inc [ERRCNT]
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
931 mov [badrw_num],ax
932 mov dx,offset dg:badw_arg
933 call PRINTf_crlf
934 WRTOK:
935 POP ax
936 POP cx
937 POP DI
938 POP dx
939 inc AH
940 ADD dx,DI
941 loop WRTLOOP ;Next FAT
942 POP cx ;Number of FATs
943 cmp CL,[ERRCNT] ;Error on all?
944 ; $if e
945 JNE $$IF47
946 jmp fatal
947 ; $endif
948 $$IF47:
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:
951 NOWRITE:
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
958 Public Done
959 DONE:
960 ASSUME DS:NOTHING
961 mov DL,cs:[USERDEV] ;Recover users drive ;an029;bgb
962 DOS_Call Set_Default_Drive ; ;AC000;
963 ret
964
965
966
967
968
969
970
971
972
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
977
978 mov cl,12 ;shift 3 nibbles
979 shr dx,cl ;remove al but last nibble
980 and dx,000fh
981 cmp dx,0ah
982 ; $IF B
983 JNB $$IF49
984 add dx,30h ;make it char
985 ; $ELSE
986 JMP SHORT $$EN49
987 $$IF49:
988 add dx,37h
989 ; $ENDIF
990 $$EN49:
991 push ax
992 mov ah,2
993 int 21h
994 pop ax
995
996 mov dx,ax ;get orig value
997 mov cl,8
998 shr dx,cl
999 and dx,000fh
1000 cmp dx,0ah
1001 ; $IF B
1002 JNB $$IF52
1003 add dx,30h ;make it char
1004 ; $ELSE
1005 JMP SHORT $$EN52
1006 $$IF52:
1007 add dx,37h
1008 ; $ENDIF
1009 $$EN52:
1010 push ax
1011 mov ah,2
1012 int 21h
1013 pop ax
1014
1015 mov dx,ax ;get orig value
1016 mov cl,4
1017 shr dx,cl
1018 and dx,000fh
1019 cmp dx,0ah
1020 ; $IF B
1021 JNB $$IF55
1022 add dx,30h ;make it char
1023 ; $ELSE
1024 JMP SHORT $$EN55
1025 $$IF55:
1026 add dx,37h
1027 ; $ENDIF
1028 $$EN55:
1029 push ax
1030 mov ah,2
1031 int 21h
1032 pop ax
1033
1034 mov dx,ax ;get orig value
1035 and dx,000fh
1036 cmp dx,0ah
1037 ; $IF B
1038 JNB $$IF58
1039 add dx,30h ;make it char
1040 ; $ELSE
1041 JMP SHORT $$EN58
1042 $$IF58:
1043 add dx,37h
1044 ; $ENDIF
1045 $$EN58:
1046 mov ah,2
1047 int 21h
1048
1049 mov dl,' ' ;space after last number
1050 mov ah,2
1051 int 21h
1052
1053 restorereg <di,si,dx,bx,cx,ax> ;an005;bgb
1054 return ;an005;bgb
1055 EndProc lostdisp ;an005;bgb
1056 ENDIF
1057
1058
1059 pathlabl chkfat
1060
1061
1062 CODE ENDS
1063 END
1064 \1a