1 /* check.c - Check and repair a PC/MS-DOS file system */
3 /* Written 1993 by Werner Almesberger */
5 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
6 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
25 static DOS_FILE
*root
;
27 /* get start field of a dir entry */
28 #define FSTART(p,fs) \
29 ((unsigned long)CF_LE_W(p->dir_ent.start) | \
30 (fs->fat_bits == 32 ? CF_LE_W(p->dir_ent.starthi) << 16 : 0))
32 #define MODIFY(p,i,v) \
36 fs_write(p->offset+offsetof(DIR_ENT,i), \
37 sizeof(p->dir_ent.i),&p->dir_ent.i); \
41 #define MODIFY_START(p,v,fs) \
43 unsigned long __v = (v); \
45 /* writing to fake entry for FAT32 root dir */ \
46 if (!__v) die("Oops, deleting FAT32 root dir!"); \
47 fs->root_cluster = __v; \
48 p->dir_ent.start = CT_LE_W(__v&0xffff); \
49 p->dir_ent.starthi = CT_LE_W(__v>>16); \
51 fs_write((loff_t)offsetof(struct boot_sector,root_cluster), \
52 sizeof(((struct boot_sector *)0)->root_cluster), \
56 MODIFY(p,start,CT_LE_W((__v)&0xffff)); \
57 if (fs->fat_bits == 32) \
58 MODIFY(p,starthi,CT_LE_W((__v)>>16)); \
63 loff_t
alloc_rootdir_entry(DOS_FS
*fs
, DIR_ENT
*de
, const char *pattern
)
65 static int curr_num
= 0;
68 if (fs
->root_cluster
) {
71 unsigned long clu_num
, prev
= 0;
74 clu_num
= fs
->root_cluster
;
75 offset
= cluster_start(fs
,clu_num
);
76 while (clu_num
> 0 && clu_num
!= -1) {
77 fs_read(offset
,sizeof(DIR_ENT
),&d2
);
78 if (IS_FREE(d2
.name
) && d2
.attr
!= VFAT_LN_ATTR
) {
83 offset
+= sizeof(DIR_ENT
);
84 if ((i
% fs
->cluster_size
) == 0) {
86 if ((clu_num
= next_cluster(fs
,clu_num
)) == 0 || clu_num
== -1)
88 offset
= cluster_start(fs
,clu_num
);
92 /* no free slot, need to extend root dir: alloc next free cluster
93 * after previous one */
95 die("Root directory has no cluster allocated!");
96 for (clu_num
= prev
+1; clu_num
!= prev
; clu_num
++) {
97 if (clu_num
>= fs
->clusters
+2) clu_num
= 2;
98 if (!fs
->fat
[clu_num
].value
)
102 die("Root directory full and no free cluster");
103 set_fat(fs
,prev
,clu_num
);
104 set_fat(fs
,clu_num
,-1);
105 set_owner(fs
, clu_num
, get_owner(fs
, fs
->root_cluster
));
106 /* clear new cluster */
107 memset( &d2
, 0, sizeof(d2
) );
108 offset
= cluster_start(fs
,clu_num
);
109 for( i
= 0; i
< (int)fs
->cluster_size
; i
+= sizeof(DIR_ENT
) )
110 fs_write( offset
+i
, sizeof(d2
), &d2
);
112 memset(de
,0,sizeof(DIR_ENT
));
114 sprintf(de
->name
,pattern
,curr_num
);
115 clu_num
= fs
->root_cluster
;
117 offset2
= cluster_start(fs
,clu_num
);
118 while (clu_num
> 0 && clu_num
!= -1) {
119 fs_read(offset2
,sizeof(DIR_ENT
),&d2
);
120 if (offset2
!= offset
&&
121 !strncmp(d2
.name
,de
->name
,MSDOS_NAME
))
123 i
+= sizeof(DIR_ENT
);
124 offset2
+= sizeof(DIR_ENT
);
125 if ((i
% fs
->cluster_size
) == 0) {
126 if ((clu_num
= next_cluster(fs
,clu_num
)) == 0 ||
129 offset2
= cluster_start(fs
,clu_num
);
132 if (clu_num
== 0 || clu_num
== -1)
134 if (++curr_num
>= 10000) die("Unable to create unique name");
139 int next_free
= 0, scan
;
141 root
= alloc(fs
->root_entries
*sizeof(DIR_ENT
));
142 fs_read(fs
->root_start
,fs
->root_entries
*sizeof(DIR_ENT
),root
);
144 while (next_free
< (int)fs
->root_entries
)
145 if (IS_FREE(root
[next_free
].name
) &&
146 root
[next_free
].attr
!= VFAT_LN_ATTR
)
149 if (next_free
== (int)fs
->root_entries
)
150 die("Root directory is full.");
151 offset
= fs
->root_start
+next_free
*sizeof(DIR_ENT
);
152 memset(de
,0,sizeof(DIR_ENT
));
154 sprintf(de
->name
,pattern
,curr_num
);
155 for (scan
= 0; scan
< (int)fs
->root_entries
; scan
++)
156 if (scan
!= next_free
&&
157 !strncmp(root
[scan
].name
,de
->name
,MSDOS_NAME
))
159 if (scan
== (int)fs
->root_entries
) break;
160 if (++curr_num
>= 10000) die("Unable to create unique name");
169 static char *path_name(DOS_FILE
*file
)
171 // static char path[PATH_MAX*2];
172 static char path
[MAX_PATH
*2];
174 if (!file
) *path
= 0;
176 if (strlen(path_name(file
->parent
)) > MAX_PATH
)
177 die("Path name too long.");
178 if (strcmp(path
,"/") != 0) strcat(path
,"/");
179 strcpy(strrchr(path
,0),file
->lfn
?file
->lfn
:file_name(file
->dir_ent
.name
));
185 static int day_n
[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
186 /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
189 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
191 time_t date_dos2unix(unsigned short time
,unsigned short date
)
196 month
= ((date
>> 5) & 15)-1;
198 secs
= (time
& 31)*2+60*((time
>> 5) & 63)+(time
>> 11)*3600+86400*
199 ((date
& 31)-1+day_n
[month
]+(year
/4)+year
*365-((year
& 3) == 0 &&
200 month
< 2 ? 1 : 0)+3653);
201 /* days since 1.1.70 plus 80's leap day */
206 static char *file_stat(DOS_FILE
*file
)
208 static char temp
[100];
213 date
= date_dos2unix(CF_LE_W(file
->dir_ent
.time
),CF_LE_W(file
->
215 tm
= localtime(&date
);
216 strftime(tmp
,99,"%H:%M:%S %b %d %Y",tm
);
217 sprintf(temp
," Size %u bytes, date %s",CF_LE_L(file
->dir_ent
.size
),tmp
);
222 static int bad_name(unsigned char *name
)
224 int i
, spc
, suspicious
= 0;
225 char *bad_chars
= atari_format
? "*?\\/:" : "*?<>|\"\\/:";
227 /* Do not complain about (and auto-correct) the extended attribute files
229 if (strncmp(name
,"EA DATA SF",11) == 0 ||
230 strncmp(name
,"WP ROOT SF",11) == 0) return 0;
232 for (i
= 0; i
< 8; i
++) {
233 if (name
[i
] < ' ' || name
[i
] == 0x7f) return 1;
234 if (name
[i
] > 0x7f) ++suspicious
;
235 if (strchr(bad_chars
,name
[i
])) return 1;
238 for (i
= 8; i
< 11; i
++) {
239 if (name
[i
] < ' ' || name
[i
] == 0x7f) return 1;
240 if (name
[i
] > 0x7f) ++suspicious
;
241 if (strchr(bad_chars
,name
[i
])) return 1;
245 for (i
= 0; i
< 8; i
++) {
249 /* non-space after a space not allowed, space terminates the name
255 for (i
= 8; i
< 11; i
++) {
259 /* non-space after a space not allowed, space terminates the name
264 /* Under GEMDOS, chars >= 128 are never allowed. */
265 if (atari_format
&& suspicious
)
268 /* Only complain about too much suspicious chars in interactive mode,
269 * never correct them automatically. The chars are all basically ok, so we
270 * shouldn't auto-correct such names. */
271 if (interactive
&& suspicious
> 6)
277 static void drop_file(DOS_FS
*fs
,DOS_FILE
*file
)
279 unsigned long cluster
;
281 MODIFY(file
,name
[0],DELETED_FLAG
);
282 for (cluster
= FSTART(file
,fs
); cluster
> 0 && cluster
<
283 fs
->clusters
+2; cluster
= next_cluster(fs
,cluster
))
284 set_owner(fs
,cluster
,NULL
);
289 static void truncate_file(DOS_FS
*fs
,DOS_FILE
*file
,unsigned long clusters
)
292 unsigned long walk
,next
,prev
;
294 walk
= FSTART(file
,fs
);
296 if ((deleting
= !clusters
)) MODIFY_START(file
,0,fs
);
297 while (walk
> 0 && walk
!= -1) {
298 next
= next_cluster(fs
,walk
);
299 if (deleting
) set_fat(fs
,walk
,0);
300 else if ((deleting
= !--clusters
)) set_fat(fs
,walk
,-1);
307 static void auto_rename(DOS_FILE
*file
)
309 DOS_FILE
*first
,*walk
;
312 if (!file
->offset
) return; /* cannot rename FAT32 root dir */
313 first
= file
->parent
? file
->parent
->first
: root
;
316 sprintf(file
->dir_ent
.name
,"FSCK%04d",number
);
317 strncpy(file
->dir_ent
.ext
,"REN",3);
318 for (walk
= first
; walk
; walk
= walk
->next
)
319 if (walk
!= file
&& !strncmp(walk
->dir_ent
.name
,file
->dir_ent
.
320 name
,MSDOS_NAME
)) break;
322 fs_write(file
->offset
,MSDOS_NAME
,file
->dir_ent
.name
);
327 die("Can't generate a unique name.");
331 static void rename_file(DOS_FILE
*file
)
333 unsigned char name
[46];
334 unsigned char *walk
,*here
;
337 printf( "Cannot rename FAT32 root dir\n" );
338 return; /* cannot rename FAT32 root dir */
341 printf("New name: ");
343 if (fgets(name
,45,stdin
)) {
344 if ((here
= strchr(name
,'\n'))) *here
= 0;
345 for (walk
= strrchr(name
,0); walk
>= name
&& (*walk
== ' ' ||
346 *walk
== '\t'); walk
--);
348 for (walk
= name
; *walk
== ' ' || *walk
== '\t'; walk
++);
349 if (file_cvt(walk
,file
->dir_ent
.name
)) {
350 fs_write(file
->offset
,MSDOS_NAME
,file
->dir_ent
.name
);
358 static int handle_dot(DOS_FS
*fs
,DOS_FILE
*file
,int dots
)
362 name
= strncmp(file
->dir_ent
.name
,MSDOS_DOT
,MSDOS_NAME
) ? ".." : ".";
363 if (!(file
->dir_ent
.attr
& ATTR_DIR
)) {
364 printf("%s\n Is a non-directory.\n",path_name(file
));
366 printf("1) Drop it\n2) Auto-rename\n3) Rename\n"
367 "4) Convert to directory\n");
368 else printf(" Auto-renaming it.\n");
369 switch (interactive
? get_key("1234","?") : '2') {
375 printf(" Renamed to %s\n",file_name(file
->dir_ent
.name
));
381 MODIFY(file
,size
,CT_LE_L(0));
382 MODIFY(file
,attr
,file
->dir_ent
.attr
| ATTR_DIR
);
387 printf("Root contains directory \"%s\". Dropping it.\n",name
);
395 static int check_file(DOS_FS
*fs
,DOS_FILE
*file
)
399 unsigned long expect
,curr
,this,clusters
,prev
,walk
,clusters2
;
401 if (file
->dir_ent
.attr
& ATTR_DIR
) {
402 if (CF_LE_L(file
->dir_ent
.size
)) {
403 printf("%s\n Directory has non-zero size. Fixing it.\n",
405 MODIFY(file
,size
,CT_LE_L(0));
407 if (file
->parent
&& !strncmp(file
->dir_ent
.name
,MSDOS_DOT
,MSDOS_NAME
)) {
408 expect
= FSTART(file
->parent
,fs
);
409 if (FSTART(file
,fs
) != expect
) {
410 printf("%s\n Start (%ld) does not point to parent (%ld)\n",
411 path_name(file
),FSTART(file
,fs
),expect
);
412 MODIFY_START(file
,expect
,fs
);
416 if (file
->parent
&& !strncmp(file
->dir_ent
.name
,MSDOS_DOTDOT
,
418 expect
= file
->parent
->parent
? FSTART(file
->parent
->parent
,fs
):0;
419 if (fs
->root_cluster
&& expect
== fs
->root_cluster
)
421 if (FSTART(file
,fs
) != expect
) {
422 printf("%s\n Start (%lu) does not point to .. (%lu)\n",
423 path_name(file
),FSTART(file
,fs
),expect
);
424 MODIFY_START(file
,expect
,fs
);
428 if (FSTART(file
,fs
)==0){
429 printf ("%s\n Start does point to root directory. Deleting dir. \n",
431 MODIFY(file
,name
[0],DELETED_FLAG
);
435 if (FSTART(file
,fs
) >= fs
->clusters
+2) {
436 printf("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n",
437 path_name(file
),FSTART(file
,fs
),fs
->clusters
+1);
439 die( "Bad FAT32 root directory! (bad start cluster)\n" );
440 MODIFY_START(file
,0,fs
);
443 for (curr
= FSTART(file
,fs
) ? FSTART(file
,fs
) :
444 -1; curr
!= -1; curr
= next_cluster(fs
,curr
)) {
445 if (!fs
->fat
[curr
].value
|| bad_cluster(fs
,curr
)) {
446 printf("%s\n Contains a %s cluster (%lu). Assuming EOF.\n",
447 path_name(file
),fs
->fat
[curr
].value
? "bad" : "free",curr
);
448 if (prev
) set_fat(fs
,prev
,-1);
449 else if (!file
->offset
)
450 die( "FAT32 root dir starts with a bad cluster!" );
451 else MODIFY_START(file
,0,fs
);
454 if (!(file
->dir_ent
.attr
& ATTR_DIR
) && CF_LE_L(file
->dir_ent
.size
) <=
455 clusters
*fs
->cluster_size
) {
456 printf("%s\n File size is %u bytes, cluster chain length is > %lu "
457 "bytes.\n Truncating file to %u bytes.\n",path_name(file
),
458 CF_LE_L(file
->dir_ent
.size
),clusters
*fs
->cluster_size
,
459 CF_LE_L(file
->dir_ent
.size
));
460 truncate_file(fs
,file
,clusters
);
463 if ((owner
= get_owner(fs
,curr
))) {
465 printf("%s and\n",path_name(owner
));
466 printf("%s\n share clusters.\n",path_name(file
));
468 for (walk
= FSTART(owner
,fs
); walk
> 0 && walk
!= -1; walk
=
469 next_cluster(fs
,walk
))
470 if (walk
== curr
) break;
472 restart
= file
->dir_ent
.attr
& ATTR_DIR
;
473 if (!owner
->offset
) {
474 printf( " Truncating second to %lu bytes because first "
475 "is FAT32 root dir.\n", clusters2
*fs
->cluster_size
);
478 else if (!file
->offset
) {
479 printf( " Truncating first to %lu bytes because second "
480 "is FAT32 root dir.\n", clusters
*fs
->cluster_size
);
483 else if (interactive
)
484 printf("1) Truncate first to %lu bytes%s\n"
485 "2) Truncate second to %lu bytes\n",clusters
*fs
->cluster_size
,
486 restart
? " and restart" : "",clusters2
*fs
->cluster_size
);
487 else printf(" Truncating second to %lu bytes.\n",clusters2
*
491 (interactive
&& get_key("12","?") == '1'))) {
494 for (this = FSTART(owner
,fs
); this > 0 && this != -1; this =
495 next_cluster(fs
,this)) {
497 if (prev
) set_fat(fs
,prev
,-1);
498 else MODIFY_START(owner
,0,fs
);
499 MODIFY(owner
,size
,CT_LE_L(clusters
*fs
->cluster_size
));
500 if (restart
) return 1;
501 while (this > 0 && this != -1) {
502 set_owner(fs
,this,NULL
);
503 this = next_cluster(fs
,this);
511 die("Internal error: didn't find cluster %d in chain"
512 " starting at %d",curr
,FSTART(owner
,fs
));
515 if (prev
) set_fat(fs
,prev
,-1);
516 else MODIFY_START(file
,0,fs
);
520 set_owner(fs
,curr
,file
);
524 if (!(file
->dir_ent
.attr
& ATTR_DIR
) && CF_LE_L(file
->dir_ent
.size
) >
525 clusters
*fs
->cluster_size
) {
526 printf("%s\n File size is %u bytes, cluster chain length is %lu bytes."
527 "\n Truncating file to %lu bytes.\n",path_name(file
),CF_LE_L(file
->
528 dir_ent
.size
),clusters
*fs
->cluster_size
,clusters
*fs
->cluster_size
);
529 MODIFY(file
,size
,CT_LE_L(clusters
*fs
->cluster_size
));
535 static int check_files(DOS_FS
*fs
,DOS_FILE
*start
)
538 if (check_file(fs
,start
)) return 1;
545 static int check_dir(DOS_FS
*fs
,DOS_FILE
**root
,int dots
)
547 DOS_FILE
*parent
,**walk
,**scan
;
548 int dot
,dotdot
,skip
,redo
;
551 if (!*root
) return 0;
552 parent
= (*root
)->parent
;
554 for (walk
= root
; *walk
; walk
= &(*walk
)->next
)
555 if (bad_name((*walk
)->dir_ent
.name
)) bad
++;
557 if (*root
&& parent
&& good
+bad
> 4 && bad
> good
/2) {
558 printf("%s\n Has a large number of bad entries. (%d/%d)\n",
559 path_name(parent
),bad
,good
+bad
);
560 if (!dots
) printf( " Not dropping root directory.\n" );
561 else if (!interactive
) printf(" Not dropping it in auto-mode.\n");
562 else if (get_key("yn","Drop directory ? (y/n)") == 'y') {
563 truncate_file(fs
,parent
,0);
564 MODIFY(parent
,name
[0],DELETED_FLAG
);
565 /* buglet: deleted directory stays in the list. */
569 dot
= dotdot
= redo
= 0;
572 if (!strncmp((*walk
)->dir_ent
.name
,MSDOS_DOT
,MSDOS_NAME
) ||
573 !strncmp((*walk
)->dir_ent
.name
,MSDOS_DOTDOT
,MSDOS_NAME
)) {
574 if (handle_dot(fs
,*walk
,dots
)) {
575 *walk
= (*walk
)->next
;
578 if (!strncmp((*walk
)->dir_ent
.name
,MSDOS_DOT
,MSDOS_NAME
)) dot
++;
581 if (!((*walk
)->dir_ent
.attr
& ATTR_VOLUME
) &&
582 bad_name((*walk
)->dir_ent
.name
)) {
583 printf("%s\n Bad file name.\n",path_name(*walk
));
585 printf("1) Drop file\n2) Rename file\n3) Auto-rename\n"
587 else printf(" Auto-renaming it.\n");
588 switch (interactive
? get_key("1234","?") : '3') {
591 walk
= &(*walk
)->next
;
599 printf(" Renamed to %s\n",file_name((*walk
)->dir_ent
.
606 /* don't check for duplicates of the volume label */
607 if (!((*walk
)->dir_ent
.attr
& ATTR_VOLUME
)) {
608 scan
= &(*walk
)->next
;
610 while (*scan
&& !skip
) {
611 if (!((*scan
)->dir_ent
.attr
& ATTR_VOLUME
) &&
612 !strncmp((*walk
)->dir_ent
.name
,(*scan
)->dir_ent
.name
,MSDOS_NAME
)) {
613 printf("%s\n Duplicate directory entry.\n First %s\n",
614 path_name(*walk
),file_stat(*walk
));
615 printf(" Second %s\n",file_stat(*scan
));
617 printf("1) Drop first\n2) Drop second\n3) Rename first\n"
618 "4) Rename second\n5) Auto-rename first\n"
619 "6) Auto-rename second\n");
620 else printf(" Auto-renaming second.\n");
621 switch (interactive
? get_key("123456","?") : '6') {
624 *walk
= (*walk
)->next
;
629 *scan
= (*scan
)->next
;
633 printf(" Renamed to %s\n",path_name(*walk
));
638 printf(" Renamed to %s\n",path_name(*walk
));
643 printf(" Renamed to %s\n",file_name((*walk
)->dir_ent
.
648 printf(" Renamed to %s\n",file_name((*scan
)->dir_ent
.
653 scan
= &(*scan
)->next
;
657 if (!redo
) walk
= &(*walk
)->next
;
660 dot
= dotdot
= redo
= 0;
664 printf("%s\n \".\" is missing. Can't fix this yet.\n",
667 printf("%s\n \"..\" is missing. Can't fix this yet.\n",
673 static void test_file(DOS_FS
*fs
,DOS_FILE
*file
,int read_test
)
676 unsigned long walk
,prev
,clusters
,next_clu
;
679 for (walk
= FSTART(file
,fs
); walk
> 0 && walk
< fs
->clusters
+2;
681 next_clu
= next_cluster(fs
,walk
);
682 if ((owner
= get_owner(fs
,walk
))) {
684 printf("%s\n Circular cluster chain. Truncating to %lu "
685 "cluster%s.\n",path_name(file
),clusters
,clusters
== 1 ? "" :
687 if (prev
) set_fat(fs
,prev
,-1);
688 else if (!file
->offset
)
689 die( "Bad FAT32 root directory! (bad start cluster)\n" );
690 else MODIFY_START(file
,0,fs
);
694 if (bad_cluster(fs
,walk
)) break;
696 if (fs_test(cluster_start(fs
,walk
),fs
->cluster_size
)) {
701 printf("%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n",
702 path_name(file
),clusters
,walk
);
703 if (prev
) set_fat(fs
,prev
,next_cluster(fs
,walk
));
704 else MODIFY_START(file
,next_cluster(fs
,walk
),fs
);
708 set_owner(fs
,walk
,file
);
710 for (walk
= FSTART(file
,fs
); walk
> 0 && walk
< fs
->clusters
+2;
711 walk
= next_cluster(fs
,walk
))
712 if (bad_cluster(fs
,walk
)) break;
713 else if (get_owner(fs
,walk
) == file
) set_owner(fs
,walk
,NULL
);
718 static void undelete(DOS_FS
*fs
,DOS_FILE
*file
)
720 unsigned long clusters
,left
,prev
,walk
;
722 clusters
= left
= (CF_LE_L(file
->dir_ent
.size
)+fs
->cluster_size
-1)/
725 for (walk
= FSTART(file
,fs
); left
&& walk
>= 2 && walk
<
726 fs
->clusters
+2 && !fs
->fat
[walk
].value
; walk
++) {
728 if (prev
) set_fat(fs
,prev
,walk
);
731 if (prev
) set_fat(fs
,prev
,-1);
732 else MODIFY_START(file
,0,fs
);
734 printf("Warning: Did only undelete %lu of %lu cluster%s.\n",clusters
-left
,
735 clusters
,clusters
== 1 ? "" : "s");
740 static void new_dir( void )
746 static void add_file(DOS_FS
*fs
,DOS_FILE
***chain
,DOS_FILE
*parent
,
747 loff_t offset
,FDSC
**cp
)
753 char tmpBuffer
[512]; // TMN:
756 // fs_read(offset,sizeof(DIR_ENT),&de);
757 fs_read(offset
,sizeof(tmpBuffer
),&tmpBuffer
); // TMN:
758 memcpy(&de
, tmpBuffer
, sizeof(DIR_ENT
)); // TMN:
760 memcpy(de
.name
," ",MSDOS_NAME
);
762 de
.size
= de
.time
= de
.date
= 0;
763 de
.start
= CT_LE_W(fs
->root_cluster
& 0xffff);
764 de
.starthi
= CT_LE_W((fs
->root_cluster
>> 16) & 0xffff);
766 if ((type
= file_type(cp
,de
.name
)) != fdt_none
) {
767 if (type
== fdt_undelete
&& (de
.attr
& ATTR_DIR
))
768 die("Can't undelete directories.");
769 file_modify(cp
,de
.name
);
770 fs_write(offset
,1,&de
);
772 if (IS_FREE(de
.name
)) {
773 lfn_check_orphaned();
776 if (de
.attr
== VFAT_LN_ATTR
) {
777 lfn_add_slot(&de
,offset
);
780 new = qalloc(&mem_queue
,sizeof(DOS_FILE
));
781 new->lfn
= lfn_get(&de
);
782 new->offset
= offset
;
783 memcpy(&new->dir_ent
,&de
,sizeof(de
));
784 new->next
= new->first
= NULL
;
785 new->parent
= parent
;
786 if (type
== fdt_undelete
) undelete(fs
,new);
790 printf("Checking file %s",path_name(new));
792 printf(" (%s)", file_name(new->dir_ent
.name
) );
796 strncmp(de
.name
,MSDOS_DOT
,MSDOS_NAME
) != 0 &&
797 strncmp(de
.name
,MSDOS_DOTDOT
,MSDOS_NAME
) != 0)
799 test_file(fs
,new,test
);
803 static int subdirs(DOS_FS
*fs
,DOS_FILE
*parent
,FDSC
**cp
);
806 static int scan_dir(DOS_FS
*fs
,DOS_FILE
*this,FDSC
**cp
)
810 unsigned long clu_num
;
812 chain
= &this->first
;
814 clu_num
= FSTART(this,fs
);
816 while (clu_num
> 0 && clu_num
!= -1) {
817 add_file(fs
,&chain
,this,cluster_start(fs
,clu_num
)+(i
% fs
->
819 i
+= sizeof(DIR_ENT
);
820 if (!(i
% fs
->cluster_size
))
821 if ((clu_num
= next_cluster(fs
,clu_num
)) == 0 || clu_num
== -1)
824 lfn_check_orphaned();
825 if (check_dir(fs
,&this->first
,this->offset
)) return 0;
826 if (check_files(fs
,this->first
)) return 1;
827 return subdirs(fs
,this,cp
);
831 static int subdirs(DOS_FS
*fs
,DOS_FILE
*parent
,FDSC
**cp
)
835 for (walk
= parent
? parent
->first
: root
; walk
; walk
= walk
->next
)
836 if (walk
->dir_ent
.attr
& ATTR_DIR
)
837 if (strncmp(walk
->dir_ent
.name
,MSDOS_DOT
,MSDOS_NAME
) &&
838 strncmp(walk
->dir_ent
.name
,MSDOS_DOTDOT
,MSDOS_NAME
))
839 if (scan_dir(fs
,walk
,file_cd(cp
,walk
->dir_ent
.name
))) return 1;
844 int scan_root(DOS_FS
*fs
)
852 if (fs
->root_cluster
) {
853 add_file(fs
,&chain
,NULL
,0,&fp_root
);
856 for (i
= 0; i
< fs
->root_entries
; i
++)
857 add_file(fs
,&chain
,NULL
,fs
->root_start
+i
*sizeof(DIR_ENT
),&fp_root
);
859 lfn_check_orphaned();
860 (void) check_dir(fs
,&root
,0);
861 if (check_files(fs
,root
)) return 1;
862 return subdirs(fs
,NULL
,&fp_root
);
865 /* Local Variables: */