summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/CHKDSK/CHKFAT.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/CHKDSK/CHKFAT.ASM')
-rw-r--r--v4.0/src/CMD/CHKDSK/CHKFAT.ASM1064
1 files changed, 1064 insertions, 0 deletions
diff --git a/v4.0/src/CMD/CHKDSK/CHKFAT.ASM b/v4.0/src/CMD/CHKDSK/CHKFAT.ASM
new file mode 100644
index 0000000..badd48c
--- /dev/null
+++ b/v4.0/src/CMD/CHKDSK/CHKFAT.ASM
@@ -0,0 +1,1064 @@
1TITLE CHKFAT - procedures that acces the fat and/or fatmap
2page ,132 ;
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
13CONST 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
27CONST ENDS
28
29DATA 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
42DATA ENDS
43
44CODE SEGMENT PUBLIC PARA 'CODE'
45ASSUME 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
53public calc_fatmap_seg, MARKMAP, CHKMAP, CHKMAPLP, ORPHAN, CONTLP, RET18
54public PromptRecover, NOCHAINREC, CHKMAPLP2, NEXTCLUS
55public DISPFRB, FINDCHAIN, CHKMAPLP3, CHAINLP, INSERTEOF, FAT12_4, CHKCHHEAD
56public ADDCHAIN, CHGOON, NEXTCLUS2,
57public CHAINREC, MAKFILLP, GOTENT, OPAGAIN, GOTORPHNAM, ENTMADE, NEXTENT
58public NXTORP, RET100, nextorph
59public AMDONE, REWRITE, WRTLOOP
60public WRTOK, NOWRITE, DONE, CROSSCHK, calc_fat_addr, pack, unpack
61 .list
62PHONEY_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
89Procedure 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
102EndProc 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;=========================================================================
127UNPACK 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
161UNPACK 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;=========================================================================
184PACK 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
223PACK 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
235procedure 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
244EndProc 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
262Procedure 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
272endproc 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
299Procedure 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;
330endproc 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
370procedure 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
377OPAGAIN: ;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:
388GOTORPHNAM: ;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
416endproc 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
460procedure 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:
465loopno: 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
475return ;ac048;bgb
476endproc 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;****************************************************************************
500markmap: 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;****************************************************************************
551CHKMAP:
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
558CHKMAPLP:
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:
574orphan: 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:
582CONTLP:
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
592RET18: 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;***************************************************************************
609PromptRecover:
610 mov dx,OFFSET DG:FREEMES
611 call PROMPTYN ;Ask user
612; $IF Z
613 JNZ $$IF31
614 jmp CHAINREC
615; $ENDIF
616$$IF31:
617NOCHAINREC:
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)
622CHKMAPLP2:
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:
630NEXTCLUS:
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:
643DISPFRB: ;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;***************************************************************************
679lostdeb equ 0 ;set private build version on ;an047;bgb
680lost_str db '00000' ;max size of cluster number
681FINDCHAIN:
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
687CHKMAPLP3:
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
709CHAINLP:
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
729INSERTEOF:
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)
739FAT12_4:
740 call PACK ;stick it in!
741 jmp SHORT CHGOON ;and we are done
742; orphan point to a head entry
743CHKCHHEAD:
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
751ADDCHAIN:
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
757CHGOON:
758 POP dx ;Restore search
759 POP cx
760 POP SI
761NEXTCLUS2:
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 CHAINREC: ;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
827MAKFILLP: ;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:
839GOTENT: 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:
846ENTMADE: 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:
864NEXTENT: restorereg <ax> ;ac048;bgb;an049;bgb
865; $endif ;ac048;bgb
866$$EN38:
867NXTORP: 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
880RET100: pop es ;restore es ;ac048;bgb
881 ret ;ac048;bgb
882 ;ac048;bgb
883 ;ac048;bgb
884 ;ac048;bgb
885
886;*****************************************************************************
887;*****************************************************************************
888SUBTTL AMDONE - Finish up routine
889PAGE
890Public AmDone
891AMDONE:
892ASSUME DS:NOTHING
893 cmp [DIRTYFAT],0
894 jz NOWRITE ;FAT not dirty
895 cmp [DOFIX],0
896 jz NOWRITE ;Not supposed to fix
897REWRITE:
898 LDS bx,[THISDPB]
899ASSUME 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
906ASSUME 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
915WRTLOOP:
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
934WRTOK:
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:
951NOWRITE:
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
958Public Done
959DONE:
960ASSUME 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?
974Procedure 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
1055EndProc lostdisp ;an005;bgb
1056ENDIF
1057
1058
1059 pathlabl chkfat
1060
1061
1062CODE ENDS
1063 END
1064 \ No newline at end of file