ReactOS 0.4.15-dev-7788-g1ad9096
check.c
Go to the documentation of this file.
1/* check.c - Check and repair a PC/MS-DOS filesystem
2
3 Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
4 Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5 Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
6 Copyright (C) 2015 Andreas Bombe <aeb@debian.org>
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21 The complete text of the GNU General Public License
22 can be found in /usr/share/common-licenses/GPL-3 file.
23*/
24
25/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
26 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
27
28#include "vfatlib.h"
29
30#define NDEBUG
31#include <debug.h>
32
33
34/* the longest path on the filesystem that can be handled by path_name() */
35#define PATH_NAME_MAX 1023
36
37static DOS_FILE *root;
38
39/* get start field of a dir entry */
40#define FSTART(p,fs) \
41 ((uint32_t)le16toh(p->dir_ent.start) | \
42 (fs->fat_bits == 32 ? le16toh(p->dir_ent.starthi) << 16 : 0))
43
44#define MODIFY(p,i,v) \
45 do { \
46 if (p->offset) { \
47 p->dir_ent.i = v; \
48 fs_write(p->offset+offsetof(DIR_ENT,i), \
49 sizeof(p->dir_ent.i),&p->dir_ent.i); \
50 } \
51 } while(0)
52
53#define MODIFY_START(p,v,fs) \
54 do { \
55 uint32_t __v = (v); \
56 if (!p->offset) { \
57 /* writing to fake entry for FAT32 root dir */ \
58 if (!__v) die("Oops, deleting FAT32 root dir!"); \
59 fs->root_cluster = __v; \
60 p->dir_ent.start = htole16(__v&0xffff); \
61 p->dir_ent.starthi = htole16(__v>>16); \
62 __v = htole32(__v); \
63 fs_write(offsetof(struct boot_sector,root_cluster), \
64 sizeof(((struct boot_sector *)0)->root_cluster), \
65 &__v); \
66 } \
67 else { \
68 MODIFY(p,start,htole16((__v)&0xffff)); \
69 if (fs->fat_bits == 32) \
70 MODIFY(p,starthi,htole16((__v)>>16)); \
71 } \
72 } while(0)
73
74off_t alloc_rootdir_entry(DOS_FS * fs, DIR_ENT * de, const char *pattern, int gen_name)
75{
76 static int curr_num = 0;
78
79 if (fs->root_cluster) {
80 DIR_ENT d2;
81 int i = 0, got = 0;
82 uint32_t clu_num, prev = 0;
83 off_t offset2;
84
85 clu_num = fs->root_cluster;
86 offset = cluster_start(fs, clu_num);
87 while (clu_num > 0 && clu_num != -1) {
88 fs_read(offset, sizeof(DIR_ENT), &d2);
89 if (IS_FREE(d2.name) && d2.attr != VFAT_LN_ATTR) {
90 got = 1;
91 break;
92 }
93 i += sizeof(DIR_ENT);
94 offset += sizeof(DIR_ENT);
95 if ((i % fs->cluster_size) == 0) {
96 prev = clu_num;
97 if ((clu_num = next_cluster(fs, clu_num)) == 0 || clu_num == -1)
98 break;
99 offset = cluster_start(fs, clu_num);
100 }
101 }
102 if (!got) {
103 /* no free slot, need to extend root dir: alloc next free cluster
104 * after previous one */
105 if (!prev)
106 die("Root directory has no cluster allocated!");
107 for (clu_num = prev + 1; clu_num != prev; clu_num++) {
109
110 if (clu_num >= fs->data_clusters + 2)
111 clu_num = 2;
112 get_fat(&entry, fs->fat, clu_num, fs);
113 if (!entry.value)
114 break;
115 }
116 if (clu_num == prev)
117 die("Root directory full and no free cluster");
118 set_fat(fs, prev, clu_num);
119 set_fat(fs, clu_num, -1);
120 set_owner(fs, clu_num, get_owner(fs, fs->root_cluster));
121 /* clear new cluster */
122 memset(&d2, 0, sizeof(d2));
123 offset = cluster_start(fs, clu_num);
124 for (i = 0; i < fs->cluster_size; i += sizeof(DIR_ENT))
125 fs_write(offset + i, sizeof(d2), &d2);
126 }
127 memset(de, 0, sizeof(DIR_ENT));
128 if (gen_name) {
129 while (1) {
130 char expanded[12];
131 sprintf(expanded, pattern, curr_num);
132 memcpy(de->name, expanded, MSDOS_NAME);
133 clu_num = fs->root_cluster;
134 i = 0;
135 offset2 = cluster_start(fs, clu_num);
136 while (clu_num > 0 && clu_num != -1) {
137 fs_read(offset2, sizeof(DIR_ENT), &d2);
138 if (offset2 != offset &&
139 !strncmp((const char *)d2.name, (const char *)de->name,
140 MSDOS_NAME))
141 break;
142 i += sizeof(DIR_ENT);
143 offset2 += sizeof(DIR_ENT);
144 if ((i % fs->cluster_size) == 0) {
145 if ((clu_num = next_cluster(fs, clu_num)) == 0 ||
146 clu_num == -1)
147 break;
148 offset2 = cluster_start(fs, clu_num);
149 }
150 }
151 if (clu_num == 0 || clu_num == -1)
152 break;
153 if (++curr_num >= 10000)
154 die("Unable to create unique name");
155 }
156 } else {
157 memcpy(de->name, pattern, MSDOS_NAME);
158 }
159 } else {
160 DIR_ENT *root;
161 int next_free = 0, scan;
162
163 root = alloc(fs->root_entries * sizeof(DIR_ENT));
164 fs_read(fs->root_start, fs->root_entries * sizeof(DIR_ENT), root);
165
166 while (next_free < fs->root_entries)
167 if (IS_FREE(root[next_free].name) &&
168 root[next_free].attr != VFAT_LN_ATTR)
169 break;
170 else
171 next_free++;
172 if (next_free == fs->root_entries)
173 die("Root directory is full.");
174 offset = fs->root_start + next_free * sizeof(DIR_ENT);
175 memset(de, 0, sizeof(DIR_ENT));
176 if (gen_name) {
177 while (1) {
178 char expanded[12];
179 sprintf(expanded, pattern, curr_num);
180 memcpy(de->name, expanded, MSDOS_NAME);
181 for (scan = 0; scan < fs->root_entries; scan++)
182 if (scan != next_free &&
183 !strncmp((const char *)root[scan].name,
184 (const char *)de->name, MSDOS_NAME))
185 break;
186 if (scan == fs->root_entries)
187 break;
188 if (++curr_num >= 10000)
189 die("Unable to create unique name");
190 }
191 } else {
192 memcpy(de->name, pattern, MSDOS_NAME);
193 }
194 free(root);
195 }
196 ++n_files;
197 return offset;
198}
199
208static char *path_name(DOS_FILE * file)
209{
210 static char path[PATH_NAME_MAX * 2];
211
212 if (!file)
213 *path = 0; /* Reached the root directory */
214 else {
215 if (strlen(path_name(file->parent)) > PATH_NAME_MAX)
216 die("Path name too long.");
217 if (strcmp(path, "/") != 0)
218 strcat(path, "/");
219
220 /* Append the long name to the path,
221 * or the short name if there isn't a long one
222 */
223 strcpy(strrchr(path, 0),
224 file->lfn ? file->lfn : file_name(file->dir_ent.name));
225 }
226 return path;
227}
228
229static const int day_n[] =
230 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0 };
231/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
232
233/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
234
235static time_t date_dos2unix(unsigned short time, unsigned short date)
236{
237 int month, year;
238 time_t secs;
239
240 month = ((date >> 5) & 15) - 1;
241 if (month < 0) {
242 /* make sure that nothing bad happens if the month bits were zero */
243 month = 0;
244 }
245 year = date >> 9;
246 secs =
247 (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
248 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 -
249 ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
250 /* days since 1.1.70 plus 80's leap day */
251 return secs;
252}
253
254#ifdef __REACTOS__ // Old version!
255
256static char *file_stat(DOS_FILE * file)
257{
258 static char temp[100];
259 char tmp[100];
260 time_t date;
262 TIME_FIELDS time_fields;
263
264 date = date_dos2unix(le16toh(file->dir_ent.time), le16toh(file->dir_ent.date));
265
267 RtlTimeToTimeFields(&time, &time_fields);
268
269 _snprintf(tmp, sizeof(tmp), "%d:%d:%d %d.%d.%d",
270 time_fields.Hour, time_fields.Minute, time_fields.Second,
271 time_fields.Day, time_fields.Month, time_fields.Year);
272
273 _snprintf(temp, sizeof(temp), " Size %u bytes, date %s", le32toh(file->dir_ent.size), tmp);
274 return temp;
275}
276
277#else
278
279static char *file_stat(DOS_FILE * file)
280{
281 static char temp[100];
282 struct tm *tm;
283 char tmp[100];
284 time_t date;
285
286 date =
287 date_dos2unix(le16toh(file->dir_ent.time), le16toh(file->dir_ent.date));
288 tm = localtime(&date);
289 strftime(tmp, 99, "%H:%M:%S %b %d %Y", tm);
290 sprintf(temp, " Size %u bytes, date %s", le32toh(file->dir_ent.size), tmp);
291 return temp;
292}
293
294#endif
295
296static int bad_name(DOS_FILE * file)
297{
298 int i, spc, suspicious = 0;
299 const char *bad_chars = atari_format ? "*?\\/:" : "*?<>|\"\\/:";
300 const unsigned char *name = file->dir_ent.name;
301 const unsigned char *ext = name + 8;
302
303 /* Do not complain about (and auto-correct) the extended attribute files
304 * of OS/2. */
305 if (strncmp((const char *)name, "EA DATA SF", 11) == 0 ||
306 strncmp((const char *)name, "WP ROOT SF", 11) == 0)
307 return 0;
308
309 /* check if we have neither a long filename nor a short name */
310 if ((file->lfn == NULL) && (file->dir_ent.lcase & FAT_NO_83NAME)) {
311 return 1;
312 }
313
314 /* don't complain about the dummy 11 bytes used by patched Linux
315 kernels */
316 if (file->dir_ent.lcase & FAT_NO_83NAME)
317 return 0;
318
319 for (i = 0; i < MSDOS_NAME; i++) {
320 if (name[i] < ' ' || name[i] == 0x7f)
321 return 1;
322 if (name[i] > 0x7f)
323 ++suspicious;
324 if (strchr(bad_chars, name[i]))
325 return 1;
326 }
327
328 spc = 0;
329 for (i = 0; i < 8; i++) {
330 if (name[i] == ' ')
331 spc = 1;
332 else if (spc)
333 /* non-space after a space not allowed, space terminates the name
334 * part */
335 return 1;
336 }
337
338 spc = 0;
339 for (i = 0; i < 3; i++) {
340 if (ext[i] == ' ')
341 spc = 1;
342 else if (spc)
343 /* non-space after a space not allowed, space terminates the ext
344 * part */
345 return 1;
346 }
347
348 /* Under GEMDOS, chars >= 128 are never allowed. */
349 if (atari_format && suspicious)
350 return 1;
351
352#ifdef __REACTOS__ // Old !!!!!!!!!!!!!!!
353
354 /* Only complain about too much suspicious chars in interactive mode,
355 * never correct them automatically. The chars are all basically ok, so we
356 * shouldn't auto-correct such names. */
357 if (interactive && suspicious > 6)
358 return 1;
359 return 0;
360
361#else
362
363 /* Under MS-DOS and Windows, chars >= 128 in short names are valid
364 * (but these characters can be visualised differently depending on
365 * local codepage: CP437, CP866, etc). The chars are all basically ok,
366 * so we shouldn't auto-correct such names. */
367 return 0;
368
369#endif
370}
371
372static void lfn_remove(off_t from, off_t to)
373{
374 DIR_ENT empty;
375
376 /* New dir entry is zeroed except first byte, which is set to 0xe5.
377 * This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading
378 * a directory at the first zero entry...
379 */
380 memset(&empty, 0, sizeof(empty));
381 empty.name[0] = DELETED_FLAG;
382
383 for (; from < to; from += sizeof(empty)) {
384 fs_write(from, sizeof(DIR_ENT), &empty);
385 }
386}
387
388static void drop_file(DOS_FS * fs, DOS_FILE * file)
389{
390 uint32_t cluster;
391
393 if (file->lfn)
394 lfn_remove(file->lfn_offset, file->offset);
395 for (cluster = FSTART(file, fs); cluster > 0 && cluster <
396 fs->data_clusters + 2; cluster = next_cluster(fs, cluster))
397 set_owner(fs, cluster, NULL);
398 --n_files;
399}
400
401static void truncate_file(DOS_FS * fs, DOS_FILE * file, uint32_t clusters)
402{
403 int deleting;
404 uint32_t walk, next;
405
406 walk = FSTART(file, fs);
407 if ((deleting = !clusters))
408 MODIFY_START(file, 0, fs);
409 while (walk > 0 && walk != -1) {
410 next = next_cluster(fs, walk);
411 if (deleting)
412 set_fat(fs, walk, 0);
413 else if ((deleting = !--clusters))
414 set_fat(fs, walk, -1);
415 walk = next;
416 }
417}
418
420{
421 DOS_FILE *first, *walk;
423
424 if (!file->offset)
425 return; /* cannot rename FAT32 root dir */
426 first = file->parent ? file->parent->first : root;
427 number = 0;
428 while (1) {
429 char num[8];
430 sprintf(num, "%07lu", (unsigned long)number);
431 memcpy(file->dir_ent.name, "FSCK", 4);
432 memcpy(file->dir_ent.name + 4, num, 7);
433 for (walk = first; walk; walk = walk->next)
434 if (walk != file
435 && !strncmp((const char *)walk->dir_ent.name,
436 (const char *)file->dir_ent.name, MSDOS_NAME))
437 break;
438 if (!walk) {
439 if (file->dir_ent.lcase & FAT_NO_83NAME) {
440 /* as we only assign a new 8.3 filename, reset flag that 8.3 name is not
441 present */
442 file->dir_ent.lcase &= ~FAT_NO_83NAME;
443 /* reset the attributes, only keep DIR and VOLUME */
444 file->dir_ent.attr &= ~(ATTR_DIR | ATTR_VOLUME);
445 fs_write(file->offset, MSDOS_NAME + 2, &file->dir_ent);
446 } else {
447 fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
448 }
449 if (file->lfn)
450 lfn_fix_checksum(file->lfn_offset, file->offset,
451 (const char *)file->dir_ent.name);
452 return;
453 }
454 number++;
455 if (number > 9999999) {
456 die("Too many files need repair.");
457 }
458 }
459 die("Can't generate a unique name.");
460}
461
463{
464#ifndef __REACTOS__
465 unsigned char name[46];
466 unsigned char *walk, *here;
467#endif
468
469 if (!file->offset) {
470#ifndef __REACTOS__
471 printf("Cannot rename FAT32 root dir\n");
472#else
473 VfatPrint( "Cannot rename FAT32 root dir\n" );
474#endif
475 return; /* cannot rename FAT32 root dir */
476 }
477 while (1) {
478#ifndef __REACTOS__
479 printf("New name: ");
480 fflush(stdout);
481 if (fgets((char *)name, 45, stdin)) {
482 if ((here = (unsigned char *)strchr((const char *)name, '\n')))
483 *here = 0;
484 for (walk = (unsigned char *)strrchr((const char *)name, 0);
485 walk >= name && (*walk == ' ' || *walk == '\t'); walk--) ;
486 walk[1] = 0;
487 for (walk = name; *walk == ' ' || *walk == '\t'; walk++) ;
488 if (file_cvt(walk, file->dir_ent.name)) {
489 if (file->dir_ent.lcase & FAT_NO_83NAME) {
490 /* as we only assign a new 8.3 filename, reset flag that 8.3 name is not
491 present */
492 file->dir_ent.lcase &= ~FAT_NO_83NAME;
493 /* reset the attributes, only keep DIR and VOLUME */
494 file->dir_ent.attr &= ~(ATTR_DIR | ATTR_VOLUME);
495 fs_write(file->offset, MSDOS_NAME + 2, &file->dir_ent);
496 } else {
497 fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
498 }
499 if (file->lfn)
500 lfn_fix_checksum(file->lfn_offset, file->offset,
501 (const char *)file->dir_ent.name);
502 return;
503 }
504 }
505#else
506 return;
507#endif
508 }
509}
510
511static int handle_dot(DOS_FS * fs, DOS_FILE * file, int dots)
512{
513 const char *name;
514
515 name =
516 strncmp((const char *)file->dir_ent.name, MSDOS_DOT,
517 MSDOS_NAME) ? ".." : ".";
518 if (!(file->dir_ent.attr & ATTR_DIR)) {
519 printf("%s\n Is a non-directory.\n", path_name(file));
520 if (interactive)
521 printf("1) Drop it\n2) Auto-rename\n3) Rename\n"
522 "4) Convert to directory\n");
523#ifndef __REACTOS__
524 else
525#else
526 else if (rw)
527#endif
528 printf(" Auto-renaming it.\n");
529#ifdef __REACTOS__
530 if (rw || interactive) {
531#endif
532 switch (interactive ? get_key("1234", "?") : '2') {
533 case '1':
534 drop_file(fs, file);
535 return 1;
536 case '2':
538 printf(" Renamed to %s\n", file_name(file->dir_ent.name));
539 return 0;
540 case '3':
542 return 0;
543 case '4':
544 MODIFY(file, size, htole32(0));
545 MODIFY(file, attr, file->dir_ent.attr | ATTR_DIR);
546 break;
547#ifdef __REACTOS__
548 }
549#endif
550 }
551 }
552 if (!dots) {
553 printf("Root contains directory \"%s\". Dropping it.\n", name);
554 drop_file(fs, file);
555 return 1;
556 }
557 return 0;
558}
559
561{
562 DOS_FILE *owner;
563 int restart;
564 uint32_t expect, curr, this, clusters, prev, walk, clusters2;
565
566 if (file->dir_ent.attr & ATTR_DIR) {
567 if (le32toh(file->dir_ent.size)) {
568#ifndef __REACTOS__
569 printf("%s\n Directory has non-zero size. Fixing it.\n",
570 path_name(file));
571#else
572 printf("%s\n Directory has non-zero size.%s\n",
573 path_name(file), (rw) ? " Fixing it." : "");
574 if (rw)
575#endif
576 MODIFY(file, size, htole32(0));
577 }
578 if (file->parent
579 && !strncmp((const char *)file->dir_ent.name, MSDOS_DOT,
580 MSDOS_NAME)) {
581 expect = FSTART(file->parent, fs);
582 if (FSTART(file, fs) != expect) {
583 printf("%s\n Start (%lu) does not point to parent (%lu)\n",
584 path_name(file), (unsigned long)FSTART(file, fs), (long)expect);
585#ifdef __REACTOS__
586 if (rw)
587#endif
589 }
590 return 0;
591 }
592 if (file->parent
593 && !strncmp((const char *)file->dir_ent.name, MSDOS_DOTDOT,
594 MSDOS_NAME)) {
595 expect =
596 file->parent->parent ? FSTART(file->parent->parent, fs) : 0;
597 if (fs->root_cluster && expect == fs->root_cluster)
598 expect = 0;
599 if (FSTART(file, fs) != expect) {
600 printf("%s\n Start (%lu) does not point to .. (%lu)\n",
601 path_name(file), (unsigned long)FSTART(file, fs), (unsigned long)expect);
602#ifdef __REACTOS__
603 if (rw)
604#endif
606 }
607 return 0;
608 }
609 if (FSTART(file, fs) == 0) {
610#ifndef __REACTOS__
611 printf("%s\n Start does point to root directory. Deleting dir. \n",
612 path_name(file));
613#else
614 printf("%s\n Start does point to root directory.%s\n",
615 path_name(file), (rw) ? " Deleting dir. " : "");
616 if (rw)
617#endif
619 return 0;
620 }
621 }
622 if (FSTART(file, fs) == 1) {
623 printf("%s\n Bad start cluster 1. Truncating file.\n",
624 path_name(file));
625 if (!file->offset)
626 die("Bad FAT32 root directory! (bad start cluster 1)\n");
627#ifdef __REACTOS__
628 if (rw)
629#endif
630 MODIFY_START(file, 0, fs);
631 }
632 if (FSTART(file, fs) >= fs->data_clusters + 2) {
633 printf
634#ifndef __REACTOS__
635 ("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n",
636 path_name(file), (unsigned long)FSTART(file, fs),
637 (unsigned long)(fs->data_clusters + 1));
638#else
639 ("%s\n Start cluster beyond limit (%lu > %lu).%s\n",
640 path_name(file), (unsigned long)FSTART(file, fs),
641 (unsigned long)(fs->data_clusters + 1),
642 (rw) ? " Truncating file." : "");
643#endif
644 if (!file->offset)
645 die("Bad FAT32 root directory! (start cluster beyond limit: %lu > %lu)\n",
646 (unsigned long)FSTART(file, fs),
647 (unsigned long)(fs->data_clusters + 1));
648#ifdef __REACTOS__
649 if (rw)
650#endif
651 MODIFY_START(file, 0, fs);
652 }
653 clusters = prev = 0;
654 for (curr = FSTART(file, fs) ? FSTART(file, fs) :
655 -1; curr != -1; curr = next_cluster(fs, curr)) {
656 FAT_ENTRY curEntry;
657 get_fat(&curEntry, fs->fat, curr, fs);
658
659 if (!curEntry.value || bad_cluster(fs, curr)) {
660#ifndef __REACTOS__
661 printf("%s\n Contains a %s cluster (%lu). Assuming EOF.\n",
662 path_name(file), curEntry.value ? "bad" : "free", (unsigned long)curr);
663#else
664 printf("%s\n Contains a %s cluster (%lu).%s\n",
665 path_name(file), curEntry.value ? "bad" : "free", (unsigned long)curr,
666 (rw) ? " Assuming EOF." : "");
667#endif
668 if (prev)
669#ifdef __REACTOS__
670 {
671 if (rw)
672#endif
673 set_fat(fs, prev, -1);
674#ifdef __REACTOS__
675 }
676#endif
677 else if (!file->offset)
678 die("FAT32 root dir starts with a bad cluster!");
679 else
680#ifdef __REACTOS__
681 if (rw)
682#endif
683 MODIFY_START(file, 0, fs);
684 break;
685 }
686 if (!(file->dir_ent.attr & ATTR_DIR) && le32toh(file->dir_ent.size) <=
687 (uint64_t)clusters * fs->cluster_size) {
688#ifdef __REACTOS__
689 if (rw) {
690#endif
691 printf
692 ("%s\n File size is %u bytes, cluster chain length is > %llu "
693 "bytes.\n Truncating file to %u bytes.\n", path_name(file),
694 le32toh(file->dir_ent.size),
695 (unsigned long long)clusters * fs->cluster_size,
696 le32toh(file->dir_ent.size));
697 truncate_file(fs, file, clusters);
698#ifdef __REACTOS__
699 } else {
700 printf
701 ("%s\n File size is %u bytes, cluster chain length is > %llu "
702 "bytes.\n", path_name(file),
703 le32toh(file->dir_ent.size),
704 (unsigned long long)clusters * fs->cluster_size);
705 }
706#endif
707 break;
708 }
709 if ((owner = get_owner(fs, curr))) {
710 int do_trunc = 0;
711 printf("%s and\n", path_name(owner));
712 printf("%s\n share clusters.\n", path_name(file));
713 clusters2 = 0;
714 for (walk = FSTART(owner, fs); walk > 0 && walk != -1; walk =
715 next_cluster(fs, walk))
716 if (walk == curr)
717 break;
718 else
719 clusters2++;
720 restart = file->dir_ent.attr & ATTR_DIR;
721#ifndef __REACTOS__
722 if (!owner->offset) {
723#else
724 if (!owner->offset && rw) {
725#endif
726 printf(" Truncating second to %llu bytes because first "
727 "is FAT32 root dir.\n",
728 (unsigned long long)clusters * fs->cluster_size);
729 do_trunc = 2;
730#ifndef __REACTOS__
731 } else if (!file->offset) {
732#else
733 } else if (!file->offset && rw) {
734#endif
735 printf(" Truncating first to %llu bytes because second "
736 "is FAT32 root dir.\n",
737 (unsigned long long)clusters2 * fs->cluster_size);
738 do_trunc = 1;
739 } else if (interactive)
740 printf("1) Truncate first to %llu bytes%s\n"
741 "2) Truncate second to %llu bytes\n",
742 (unsigned long long)clusters2 * fs->cluster_size,
743 restart ? " and restart" : "",
744 (unsigned long long)clusters * fs->cluster_size);
745 else
746#ifdef __REACTOS__
747 if (rw)
748#endif
749 printf(" Truncating second to %llu bytes.\n",
750 (unsigned long long)clusters * fs->cluster_size);
751#ifndef __REACTOS__
752 if (do_trunc != 2
753 && (do_trunc == 1
754#else
755 if ((do_trunc != 2 && rw)
756 && ((do_trunc == 1 && rw)
757#endif
758 || (interactive && get_key("12", "?") == '1'))) {
759 prev = 0;
760 clusters = 0;
761 for (this = FSTART(owner, fs); this > 0 && this != -1; this =
762 next_cluster(fs, this)) {
763 if (this == curr) {
764 if (prev)
765 set_fat(fs, prev, -1);
766 else
767 MODIFY_START(owner, 0, fs);
768 MODIFY(owner, size,
769 htole32((uint64_t)clusters *
770 fs->cluster_size));
771 if (restart)
772 return 1;
773 while (this > 0 && this != -1) {
774 set_owner(fs, this, NULL);
775 this = next_cluster(fs, this);
776 }
777 this = curr;
778 break;
779 }
780 clusters++;
781 prev = this;
782 }
783 if (this != curr)
784 die("Internal error: didn't find cluster %d in chain"
785 " starting at %d", curr, FSTART(owner, fs));
786 } else {
787 if (prev)
788 set_fat(fs, prev, -1);
789 else
790 MODIFY_START(file, 0, fs);
791 break;
792 }
793 }
794 set_owner(fs, curr, file);
795 clusters++;
796 prev = curr;
797 }
798 if (!(file->dir_ent.attr & ATTR_DIR) && le32toh(file->dir_ent.size) >
799#ifndef __REACTOS__
800 (uint64_t)clusters * fs->cluster_size) {
801#else
802 (uint64_t)clusters * fs->cluster_size && rw) {
803#endif
804 printf
805 ("%s\n File size is %u bytes, cluster chain length is %llu bytes."
806 "\n Truncating file to %llu bytes.\n", path_name(file),
807 le32toh(file->dir_ent.size),
808 (unsigned long long)clusters * fs->cluster_size,
809 (unsigned long long)clusters * fs->cluster_size);
811 htole32((uint64_t)clusters * fs->cluster_size));
812 }
813 return 0;
814}
815
817{
818 while (start) {
819 if (check_file(fs, start))
820 return 1;
821 start = start->next;
822 }
823 return 0;
824}
825
826static int check_dir(DOS_FS * fs, DOS_FILE ** root, int dots)
827{
828 DOS_FILE *parent, **walk, **scan;
829 int dot, dotdot, skip, redo;
830 int good, bad;
831
832 if (!*root)
833 return 0;
834 parent = (*root)->parent;
835 good = bad = 0;
836 for (walk = root; *walk; walk = &(*walk)->next)
837 if (bad_name(*walk))
838 bad++;
839 else
840 good++;
841 if (*root && parent && good + bad > 4 && bad > good / 2) {
842 printf("%s\n Has a large number of bad entries. (%d/%d)\n",
843 path_name(parent), bad, good + bad);
844 if (!dots)
845 printf(" Not dropping root directory.\n");
846#ifndef __REACTOS__
847 else if (!interactive)
848#else
849 else if (!interactive || !rw)
850#endif
851 printf(" Not dropping it in auto-mode.\n");
852 else if (get_key("yn", "Drop directory ? (y/n)") == 'y') {
855 /* buglet: deleted directory stays in the list. */
856 return 1;
857 }
858 }
859 dot = dotdot = redo = 0;
860 walk = root;
861 while (*walk) {
862 if (!strncmp
863 ((const char *)((*walk)->dir_ent.name), MSDOS_DOT, MSDOS_NAME)
864 || !strncmp((const char *)((*walk)->dir_ent.name), MSDOS_DOTDOT,
865 MSDOS_NAME)) {
866 if (handle_dot(fs, *walk, dots)) {
867 *walk = (*walk)->next;
868 continue;
869 }
870 if (!strncmp
871 ((const char *)((*walk)->dir_ent.name), MSDOS_DOT, MSDOS_NAME))
872 dot++;
873 else
874 dotdot++;
875 }
876 if (!((*walk)->dir_ent.attr & ATTR_VOLUME) && bad_name(*walk)) {
877#ifndef __REACTOS__
878 puts(path_name(*walk));
879 printf(" Bad short file name (%s).\n",
880 file_name((*walk)->dir_ent.name));
881#else
882 printf("%s\n Bad short file name (%s).\n",
883 path_name(*walk), file_name((*walk)->dir_ent.name));
884#endif
885 if (interactive)
886 printf("1) Drop file\n2) Rename file\n3) Auto-rename\n"
887 "4) Keep it\n");
888 else
889#ifdef __REACTOS__
890 if (rw)
891#endif
892 printf(" Auto-renaming it.\n");
893#ifdef __REACTOS__
894 if (rw || interactive) {
895#endif
896 switch (interactive ? get_key("1234", "?") : '3') {
897 case '1':
898 drop_file(fs, *walk);
899 walk = &(*walk)->next;
900 continue;
901 case '2':
902 rename_file(*walk);
903 redo = 1;
904 break;
905 case '3':
906 auto_rename(*walk);
907 printf(" Renamed to %s\n", file_name((*walk)->dir_ent.name));
908 break;
909 case '4':
910 break;
911#ifdef __REACTOS__
912 }
913#endif
914 }
915 }
916 /* don't check for duplicates of the volume label */
917 if (!((*walk)->dir_ent.attr & ATTR_VOLUME)) {
918 scan = &(*walk)->next;
919 skip = 0;
920 while (*scan && !skip) {
921 if (!((*scan)->dir_ent.attr & ATTR_VOLUME) &&
922 !memcmp((*walk)->dir_ent.name, (*scan)->dir_ent.name,
923 MSDOS_NAME)) {
924 printf("%s\n Duplicate directory entry.\n First %s\n",
925 path_name(*walk), file_stat(*walk));
926 printf(" Second %s\n", file_stat(*scan));
927 if (interactive)
928 printf
929 ("1) Drop first\n2) Drop second\n3) Rename first\n"
930 "4) Rename second\n5) Auto-rename first\n"
931 "6) Auto-rename second\n");
932 else
933#ifdef __REACTOS__
934 if (rw)
935#endif
936 printf(" Auto-renaming second.\n");
937#ifdef __REACTOS__
938 if (rw || interactive) {
939#endif
940 switch (interactive ? get_key("123456", "?") : '6') {
941 case '1':
942 drop_file(fs, *walk);
943 *walk = (*walk)->next;
944 skip = 1;
945 break;
946 case '2':
947 drop_file(fs, *scan);
948 *scan = (*scan)->next;
949 continue;
950 case '3':
951 rename_file(*walk);
952 printf(" Renamed to %s\n", path_name(*walk));
953 redo = 1;
954 break;
955 case '4':
956 rename_file(*scan);
957 printf(" Renamed to %s\n", path_name(*walk));
958 redo = 1;
959 break;
960 case '5':
961 auto_rename(*walk);
962 printf(" Renamed to %s\n",
963 file_name((*walk)->dir_ent.name));
964 break;
965 case '6':
966 auto_rename(*scan);
967 printf(" Renamed to %s\n",
968 file_name((*scan)->dir_ent.name));
969 break;
970#ifdef __REACTOS__
971 }
972#endif
973 }
974 }
975 scan = &(*scan)->next;
976 }
977 if (skip)
978 continue;
979 }
980 if (!redo)
981 walk = &(*walk)->next;
982 else {
983 walk = root;
984 dot = dotdot = redo = 0;
985 }
986 }
987 if (dots && !dot)
988 printf("%s\n \".\" is missing. Can't fix this yet.\n",
990 if (dots && !dotdot)
991 printf("%s\n \"..\" is missing. Can't fix this yet.\n",
993 return 0;
994}
995
1006{
1007 DOS_FILE *owner;
1008 uint32_t walk, prev, clusters, next_clu;
1009
1010 prev = clusters = 0;
1011 for (walk = FSTART(file, fs); walk > 1 && walk < fs->data_clusters + 2;
1012 walk = next_clu) {
1013 next_clu = next_cluster(fs, walk);
1014
1015 /* In this stage we are checking only for a loop within our own
1016 * cluster chain.
1017 * Cross-linking of clusters is handled in check_file()
1018 */
1019 if ((owner = get_owner(fs, walk))) {
1020 if (owner == file) {
1021 printf("%s\n Circular cluster chain. Truncating to %lu "
1022 "cluster%s.\n", path_name(file), (unsigned long)clusters,
1023 clusters == 1 ? "" : "s");
1024 if (prev)
1025 set_fat(fs, prev, -1);
1026 else if (!file->offset)
1027 die("Bad FAT32 root directory! (bad start cluster)\n");
1028 else
1029 MODIFY_START(file, 0, fs);
1030 }
1031 break;
1032 }
1033 if (bad_cluster(fs, walk))
1034 break;
1035 if (read_test) {
1036 if (fs_test(cluster_start(fs, walk), fs->cluster_size)) {
1037 prev = walk;
1038 clusters++;
1039 } else {
1040 printf("%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n",
1041 path_name(file), (unsigned long)clusters, (unsigned long)walk);
1042 if (prev)
1043 set_fat(fs, prev, next_cluster(fs, walk));
1044 else
1046 set_fat(fs, walk, -2);
1047 }
1048 } else {
1049 prev = walk;
1050 clusters++;
1051 }
1052 set_owner(fs, walk, file);
1053 }
1054 /* Revert ownership (for now) */
1055 for (walk = FSTART(file, fs); walk > 1 && walk < fs->data_clusters + 2;
1056 walk = next_cluster(fs, walk))
1057 if (bad_cluster(fs, walk))
1058 break;
1059 else if (get_owner(fs, walk) == file)
1060 set_owner(fs, walk, NULL);
1061 else
1062 break;
1063}
1064
1065static void undelete(DOS_FS * fs, DOS_FILE * file)
1066{
1067 uint32_t clusters, left, prev, walk;
1068
1069 clusters = left = (le32toh(file->dir_ent.size) + fs->cluster_size - 1) /
1070 fs->cluster_size;
1071 prev = 0;
1072
1073 walk = FSTART(file, fs);
1074
1075 while (left && (walk >= 2) && (walk < fs->data_clusters + 2)) {
1076
1077 FAT_ENTRY curEntry;
1078 get_fat(&curEntry, fs->fat, walk, fs);
1079
1080 if (!curEntry.value)
1081 break;
1082
1083 left--;
1084 if (prev)
1085 set_fat(fs, prev, walk);
1086 prev = walk;
1087 walk++;
1088 }
1089 if (prev)
1090 set_fat(fs, prev, -1);
1091 else
1092 MODIFY_START(file, 0, fs);
1093 if (left)
1094 printf("Warning: Did only undelete %lu of %lu cluster%s.\n",
1095 (unsigned long)clusters - left, (unsigned long)clusters, clusters == 1 ? "" : "s");
1096
1097}
1098
1099static void new_dir(void)
1100{
1101 lfn_reset();
1102}
1103
1118 off_t offset, FDSC ** cp)
1119{
1120 DOS_FILE *new;
1121 DIR_ENT de;
1122 FD_TYPE type;
1123
1124 if (offset)
1125 fs_read(offset, sizeof(DIR_ENT), &de);
1126 else {
1127 /* Construct a DIR_ENT for the root directory */
1128 memset(&de, 0, sizeof de);
1129 memcpy(de.name, " ", MSDOS_NAME);
1130 de.attr = ATTR_DIR;
1131 de.start = htole16(fs->root_cluster & 0xffff);
1132 de.starthi = htole16((fs->root_cluster >> 16) & 0xffff);
1133 }
1134 if ((type = file_type(cp, (char *)de.name)) != fdt_none) {
1135 if (type == fdt_undelete && (de.attr & ATTR_DIR))
1136 die("Can't undelete directories.");
1137 file_modify(cp, (char *)de.name);
1138 fs_write(offset, 1, &de);
1139 }
1140 if (IS_FREE(de.name)) {
1142 return;
1143 }
1144 if (de.attr == VFAT_LN_ATTR) {
1145 lfn_add_slot(&de, offset);
1146 return;
1147 }
1148 new = qalloc(&mem_queue, sizeof(DOS_FILE));
1149 new->lfn = lfn_get(&de, &new->lfn_offset);
1150 new->offset = offset;
1151 memcpy(&new->dir_ent, &de, sizeof(de));
1152 new->next = new->first = NULL;
1153 new->parent = parent;
1154 if (type == fdt_undelete)
1155 undelete(fs, new);
1156 **chain = new;
1157 *chain = &new->next;
1158 if (list) {
1159 printf("Checking file %s", path_name(new));
1160 if (new->lfn)
1161 printf(" (%s)", file_name(new->dir_ent.name)); /* (8.3) */
1162 printf("\n");
1163 }
1164 /* Don't include root directory, '.', or '..' in the total file count */
1165 if (offset &&
1166 strncmp((const char *)de.name, MSDOS_DOT, MSDOS_NAME) != 0 &&
1167 strncmp((const char *)de.name, MSDOS_DOTDOT, MSDOS_NAME) != 0)
1168 ++n_files;
1169 test_file(fs, new, test); /* Bad cluster check */
1170}
1171
1172static int subdirs(DOS_FS * fs, DOS_FILE * parent, FDSC ** cp);
1173
1174static int scan_dir(DOS_FS * fs, DOS_FILE * this, FDSC ** cp)
1175{
1176 DOS_FILE **chain;
1177 int i;
1178 uint32_t clu_num;
1179
1180 chain = &this->first;
1181 i = 0;
1182 clu_num = FSTART(this, fs);
1183 new_dir();
1184 while (clu_num > 0 && clu_num != -1) {
1185 add_file(fs, &chain, this,
1186 cluster_start(fs, clu_num) + (i % fs->cluster_size), cp);
1187 i += sizeof(DIR_ENT);
1188 if (!(i % fs->cluster_size))
1189 if ((clu_num = next_cluster(fs, clu_num)) == 0 || clu_num == -1)
1190 break;
1191 }
1193 if (check_dir(fs, &this->first, this->offset))
1194 return 0;
1195 if (check_files(fs, this->first))
1196 return 1;
1197 return subdirs(fs, this, cp);
1198}
1199
1210static int subdirs(DOS_FS * fs, DOS_FILE * parent, FDSC ** cp)
1211{
1212 DOS_FILE *walk;
1213
1214 for (walk = parent ? parent->first : root; walk; walk = walk->next)
1215 if (walk->dir_ent.attr & ATTR_DIR)
1216 if (strncmp((const char *)walk->dir_ent.name, MSDOS_DOT, MSDOS_NAME)
1217 && strncmp((const char *)walk->dir_ent.name, MSDOS_DOTDOT,
1218 MSDOS_NAME))
1219 if (scan_dir(fs, walk, file_cd(cp, (char *)walk->dir_ent.name)))
1220 return 1;
1221 return 0;
1222}
1223
1233{
1234 DOS_FILE **chain;
1235 int i;
1236
1237 root = NULL;
1238 chain = &root;
1239 new_dir();
1240 if (fs->root_cluster) {
1241 add_file(fs, &chain, NULL, 0, &fp_root);
1242 } else {
1243 for (i = 0; i < fs->root_entries; i++)
1244 add_file(fs, &chain, NULL, fs->root_start + i * sizeof(DIR_ENT),
1245 &fp_root);
1246 }
1248 (void)check_dir(fs, &root, 0);
1249 if (check_files(fs, root))
1250 return 1;
1251 return subdirs(fs, NULL, &fp_root);
1252}
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define skip(...)
Definition: atltest.h:64
void restart(int argc, const char *argv[])
Definition: cmds.c:2115
Definition: list.h:37
int puts(const char *string)
Definition: crtsupp.c:23
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
static const WCHAR empty[]
Definition: main.c:47
static const WCHAR *const ext[]
Definition: module.c:53
static HRESULT get_owner(VARIANT *user, VARIANT *domain, VARIANT *retval)
Definition: process.c:34
static const WCHAR month[12][4]
Definition: session.c:2150
r parent
Definition: btrfs.c:3010
__kernel_time_t time_t
Definition: linux.h:252
__kernel_off_t off_t
Definition: linux.h:201
BOOLEAN RtlTimeToTimeFields(IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields)
#define printf
Definition: freeldr.h:93
#define VFAT_LN_ATTR
Definition: fsck.fat.h:78
#define FAT_NO_83NAME
Definition: fsck.fat.h:238
static time_t date_dos2unix(unsigned short time, unsigned short date)
Definition: check.c:235
static void add_file(DOS_FS *fs, DOS_FILE ***chain, DOS_FILE *parent, off_t offset, FDSC **cp)
Definition: check.c:1117
static int check_dir(DOS_FS *fs, DOS_FILE **root, int dots)
Definition: check.c:826
#define FSTART(p, fs)
Definition: check.c:40
static void drop_file(DOS_FS *fs, DOS_FILE *file)
Definition: check.c:388
static void rename_file(DOS_FILE *file)
Definition: check.c:462
static const int day_n[]
Definition: check.c:229
#define MODIFY(p, i, v)
Definition: check.c:44
static int scan_dir(DOS_FS *fs, DOS_FILE *this, FDSC **cp)
Definition: check.c:1174
static int bad_name(DOS_FILE *file)
Definition: check.c:296
static void new_dir(void)
Definition: check.c:1099
int scan_root(DOS_FS *fs)
Definition: check.c:1232
static int subdirs(DOS_FS *fs, DOS_FILE *parent, FDSC **cp)
Definition: check.c:1210
static DOS_FILE * root
Definition: check.c:37
static int check_file(DOS_FS *fs, DOS_FILE *file)
Definition: check.c:560
#define PATH_NAME_MAX
Definition: check.c:35
static void truncate_file(DOS_FS *fs, DOS_FILE *file, uint32_t clusters)
Definition: check.c:401
static void auto_rename(DOS_FILE *file)
Definition: check.c:419
#define MODIFY_START(p, v, fs)
Definition: check.c:53
static char * path_name(DOS_FILE *file)
Definition: check.c:208
off_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern, int gen_name)
Definition: check.c:74
static void lfn_remove(off_t from, off_t to)
Definition: check.c:372
static void undelete(DOS_FS *fs, DOS_FILE *file)
Definition: check.c:1065
static char * file_stat(DOS_FILE *file)
Definition: check.c:279
static int handle_dot(DOS_FS *fs, DOS_FILE *file, int dots)
Definition: check.c:511
static int check_files(DOS_FS *fs, DOS_FILE *start)
Definition: check.c:816
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLubyte * pattern
Definition: glext.h:7787
GLint left
Definition: glext.h:7726
const GLint * first
Definition: glext.h:5794
GLuint GLuint num
Definition: glext.h:9618
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define stdout
Definition: stdio.h:99
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
#define stdin
Definition: stdio.h:98
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
uint32_t entry
Definition: isohybrid.c:63
void lfn_add_slot(DIR_ENT *de, off_t dir_offset)
Definition: lfn.c:206
void lfn_check_orphaned(void)
Definition: lfn.c:517
void lfn_fix_checksum(off_t from, off_t to, const char *short_name)
Definition: lfn.c:181
void lfn_reset(void)
Definition: lfn.c:193
char * lfn_get(DIR_ENT *de, off_t *lfn_offset)
Definition: lfn.c:418
FD_TYPE
Definition: file.h:28
@ fdt_none
Definition: file.h:28
@ fdt_undelete
Definition: file.h:28
POINT cp
Definition: magnifier.c:59
__u16 date
Definition: mkdosfs.c:8
#define die(str)
Definition: mkdosfs.c:347
#define ATTR_DIR
Definition: mkdosfs.c:370
__u16 time
Definition: mkdosfs.c:8
#define ATTR_VOLUME
Definition: mkdosfs.c:369
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static unsigned int number
Definition: dsound.c:1479
static IBackgroundCopyFile * test_file
Definition: file.c:39
static LPCWSTR file_name
Definition: protocol.c:147
#define MSDOS_DOTDOT
Definition: msdos_fs.h:48
#define MSDOS_DOT
Definition: msdos_fs.h:47
#define DELETED_FLAG
Definition: msdos_fs.h:43
#define IS_FREE(n)
Definition: msdos_fs.h:44
#define MSDOS_NAME
Definition: msdos_fs.h:46
NTSYSAPI VOID NTAPI RtlSecondsSince1970ToTime(_In_ ULONG SecondsSince1970, _Out_ PLARGE_INTEGER Time)
const char * root_entries[]
Definition: netreg.cpp:25
static const struct notification read_test[]
Definition: notification.c:903
#define uint64_t
Definition: nsiface.idl:62
#define long
Definition: qsort.c:33
static unsigned __int64 next
Definition: rand_nt.c:6
#define mem_queue
Definition: rosglue.h:44
#define alloc
Definition: rosglue.h:13
#define n_files
Definition: rosglue.h:43
#define atari_format
Definition: rosglue.h:41
#define rw
Definition: rosglue.h:38
#define interactive
Definition: rosglue.h:34
#define test
Definition: rosglue.h:37
static calc_node_t temp
Definition: rpn_ieee.c:38
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
_CRTIMP struct tm *__cdecl localtime(const time_t *_Time)
Definition: time.h:416
void * qalloc(void **root, int size)
Definition: common.c:139
char get_key(const char *valid, const char *prompt)
Definition: common.c:184
uint32_t next_cluster(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:276
void set_owner(DOS_FS *fs, uint32_t cluster, DOS_FILE *owner)
Definition: fat.c:303
int bad_cluster(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:258
off_t cluster_start(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:289
void get_fat(FAT_ENTRY *entry, void *fat, uint32_t cluster, DOS_FS *fs)
Definition: fat.c:41
void set_fat(DOS_FS *fs, uint32_t cluster, int32_t new)
Definition: fat.c:189
void file_modify(FDSC **curr, char *fixed)
Definition: file.c:230
FDSC * fp_root
Definition: file.c:32
int file_cvt(unsigned char *name, unsigned char *fixed)
Definition: file.c:84
FD_TYPE file_type(FDSC **curr, char *fixed)
Definition: file.c:221
FDSC ** file_cd(FDSC **curr, char *fixed)
Definition: file.c:186
int fs_test(off_t pos, int size)
Definition: io.c:322
void fs_read(off_t pos, int size, void *data)
Definition: io.c:282
void fs_write(off_t pos, int size, void *data)
Definition: io.c:344
#define memset(x, y, z)
Definition: compat.h:39
CardRegion * from
Definition: spigame.cpp:19
#define htole16(x)
Definition: storage32.h:546
#define htole32(x)
Definition: storage32.h:543
size_t CDECL strftime(char *str, size_t max, const char *format, const struct tm *mstm)
Definition: strftime.c:293
Definition: fsck.fat.h:192
uint32_t value
Definition: fsck.fat.h:193
struct _dos_file * next
Definition: fsck.fat.h:188
DIR_ENT dir_ent
Definition: fsck.fat.h:183
off_t offset
Definition: fsck.fat.h:185
Definition: file.h:30
Definition: cookie.c:202
char * name
Definition: compiler.c:66
Definition: fci.c:127
cab_ULONG offset
Definition: fci.c:130
cab_UWORD date
Definition: fci.c:132
cab_ULONG size
Definition: fci.c:129
cab_UWORD time
Definition: fci.c:133
char name[1]
Definition: fci.c:135
Definition: ffs.h:70
Definition: name.c:39
WCHAR * name
Definition: name.c:42
Definition: time.h:68
struct sock * chain
Definition: tcpcore.h:1
#define new(TYPE, numElems)
Definition: treelist.c:54
VOID VfatPrint(PCHAR Format,...)
Definition: vfatlib.c:362
#define _snprintf
Definition: xmlstorage.h:200