ReactOS  0.4.14-dev-599-g2d4d3f5
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 
37 static 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 
74 off_t alloc_rootdir_entry(DOS_FS * fs, DIR_ENT * de, const char *pattern, int gen_name)
75 {
76  static int curr_num = 0;
77  off_t offset;
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 
208 static 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 
229 static 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 
235 static 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 
256 static 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 
279 static 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 
296 static 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 
372 static 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 
388 static 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 
401 static 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 
419 static void auto_rename(DOS_FILE * file)
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 
462 static void rename_file(DOS_FILE * file)
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 
511 static 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':
537  auto_rename(file);
538  printf(" Renamed to %s\n", file_name(file->dir_ent.name));
539  return 0;
540  case '3':
541  rename_file(file);
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 
560 static int check_file(DOS_FS * fs, DOS_FILE * file)
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);
810  MODIFY(file, 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 
826 static 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') {
853  truncate_file(fs, parent, 0);
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",
989  path_name(parent));
990  if (dots && !dotdot)
991  printf("%s\n \"..\" is missing. Can't fix this yet.\n",
992  path_name(parent));
993  return 0;
994 }
995 
1005 static void test_file(DOS_FS * fs, DOS_FILE * file, int read_test)
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
1045  MODIFY_START(file, next_cluster(fs, walk), fs);
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 
1065 static 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 
1099 static 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 
1172 static int subdirs(DOS_FS * fs, DOS_FILE * parent, FDSC ** cp);
1173 
1174 static 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 
1210 static 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 DELETED_FLAG
Definition: msdos_fs.h:43
off_t offset
Definition: fsck.fat.h:185
void lfn_fix_checksum(off_t from, off_t to, const char *short_name)
Definition: lfn.c:181
static void undelete(DOS_FS *fs, DOS_FILE *file)
Definition: check.c:1065
off_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern, int gen_name)
Definition: check.c:74
static time_t date_dos2unix(unsigned short time, unsigned short date)
Definition: check.c:235
#define ATTR_VOLUME
Definition: mkdosfs.c:369
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define new(TYPE, numElems)
Definition: treelist.c:54
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
static int check_file(DOS_FS *fs, DOS_FILE *file)
Definition: check.c:560
static void truncate_file(DOS_FS *fs, DOS_FILE *file, uint32_t clusters)
Definition: check.c:401
static int subdirs(DOS_FS *fs, DOS_FILE *parent, FDSC **cp)
Definition: check.c:1210
static int scan_dir(DOS_FS *fs, DOS_FILE *this, FDSC **cp)
Definition: check.c:1174
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
unsigned n_files
GLsizei const GLchar ** path
Definition: glext.h:7234
NTSYSAPI VOID NTAPI RtlSecondsSince1970ToTime(_In_ ULONG SecondsSince1970, _Out_ PLARGE_INTEGER Time)
static HRESULT get_owner(VARIANT *user, VARIANT *domain, VARIANT *retval)
Definition: process.c:34
#define free
Definition: debug_ros.c:5
static const struct notification read_test[]
Definition: notification.c:903
__kernel_off_t off_t
Definition: linux.h:201
const GLint * first
Definition: glext.h:5794
GLintptr offset
Definition: glext.h:5920
#define MODIFY(p, i, v)
Definition: check.c:44
void set_fat(DOS_FS *fs, uint32_t cluster, int32_t new)
Definition: fat.c:189
#define htole16(x)
Definition: storage32.h:546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
FD_TYPE
Definition: file.h:28
static void add_file(DOS_FS *fs, DOS_FILE ***chain, DOS_FILE *parent, off_t offset, FDSC **cp)
Definition: check.c:1117
VOID VfatPrint(PCHAR Format,...)
Definition: vfatlib.c:363
FILE * stdin
static void auto_rename(DOS_FILE *file)
Definition: check.c:419
#define test
Definition: rosglue.h:37
#define interactive
Definition: rosglue.h:34
void * qalloc(void **root, int size)
Definition: common.c:139
cab_UWORD date
Definition: fci.c:132
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
__u16 time
Definition: mkdosfs.c:366
Definition: fs.h:235
static void drop_file(DOS_FS *fs, DOS_FILE *file)
Definition: check.c:388
FILE * stdout
FDSC * fp_root
Definition: file.c:32
DIR_ENT dir_ent
Definition: fsck.fat.h:183
void fs_write(off_t pos, int size, void *data)
Definition: io.c:344
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define FAT_NO_83NAME
Definition: fsck.fat.h:238
int fs_test(off_t pos, int size)
Definition: io.c:322
#define _snprintf
Definition: xmlstorage.h:200
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
void * mem_queue
char name[1]
Definition: fci.c:135
static size_t double number
Definition: printf.c:69
int scan_root(DOS_FS *fs)
Definition: check.c:1232
static int handle_dot(DOS_FS *fs, DOS_FILE *file, int dots)
Definition: check.c:511
smooth NULL
Definition: ftsmooth.c:416
char ext[3]
Definition: mkdosfs.c:358
#define htole32(x)
Definition: storage32.h:543
static void lfn_remove(off_t from, off_t to)
Definition: check.c:372
struct sock * chain
Definition: tcpcore.h:1164
int atari_format
FDSC ** file_cd(FDSC **curr, char *fixed)
Definition: file.c:186
static void rename_file(DOS_FILE *file)
Definition: check.c:462
Definition: file.h:28
char * lfn_get(DIR_ENT *de, off_t *lfn_offset)
Definition: lfn.c:418
uint32_t next_cluster(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:276
void restart(int argc, const char *argv[])
Definition: cmds.c:2115
size_t CDECL strftime(char *str, size_t max, const char *format, const struct tm *mstm)
Definition: strftime.c:293
static int bad_name(DOS_FILE *file)
Definition: check.c:296
BOOLEAN RtlTimeToTimeFields(IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields)
#define IS_FREE(n)
Definition: msdos_fs.h:44
GLsizeiptr size
Definition: glext.h:5919
char get_key(const char *valid, const char *prompt)
Definition: common.c:184
#define MSDOS_NAME
Definition: msdos_fs.h:46
r parent
Definition: btrfs.c:2869
static char * gen_name(void)
Definition: parser.tab.c:6236
static char * path_name(DOS_FILE *file)
Definition: check.c:208
struct _dos_file * next
Definition: fsck.fat.h:188
void fs_read(off_t pos, int size, void *data)
Definition: io.c:282
const char file[]
Definition: icontest.c:11
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
void set_owner(DOS_FS *fs, uint32_t cluster, DOS_FILE *owner)
Definition: fat.c:303
char * name
Definition: compiler.c:66
GLuint GLuint num
Definition: glext.h:9618
GLint left
Definition: glext.h:7726
#define PATH_NAME_MAX
Definition: check.c:35
Definition: cookie.c:201
FD_TYPE file_type(FDSC **curr, char *fixed)
Definition: file.c:221
cab_ULONG offset
Definition: fci.c:130
cab_ULONG size
Definition: fci.c:129
int rw
#define MSDOS_DOTDOT
Definition: msdos_fs.h:48
void lfn_check_orphaned(void)
Definition: lfn.c:517
const char * root_entries[]
Definition: netreg.cpp:25
Definition: fsck.fat.h:192
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
Definition: _list.h:228
Definition: time.h:76
_CRTIMP struct tm *__cdecl localtime(const time_t *_Time)
Definition: time.h:424
cab_UWORD time
Definition: fci.c:133
int puts(const char *string)
Definition: crtsupp.c:23
#define uint64_t
Definition: nsiface.idl:62
static void test_file(DOS_FS *fs, DOS_FILE *file, int read_test)
Definition: check.c:1005
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
static char * file_stat(DOS_FILE *file)
Definition: check.c:279
int bad_cluster(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:258
static unsigned __int64 next
Definition: rand_nt.c:6
UINT64 uint64_t
Definition: types.h:77
static int check_files(DOS_FS *fs, DOS_FILE *start)
Definition: check.c:816
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
__kernel_time_t time_t
Definition: linux.h:252
static calc_node_t temp
Definition: rpn_ieee.c:38
GLuint start
Definition: gl.h:1545
__u16 date
Definition: mkdosfs.c:366
static int check_dir(DOS_FS *fs, DOS_FILE **root, int dots)
Definition: check.c:826
#define long
Definition: qsort.c:33
void file_modify(FDSC **curr, char *fixed)
Definition: file.c:230
uint32_t value
Definition: fsck.fat.h:193
#define expect(expected, got)
Definition: combo.c:36
void lfn_reset(void)
Definition: lfn.c:193
static const int day_n[]
Definition: check.c:229
#define alloc
Definition: rosglue.h:13
static DOS_FILE * root
Definition: check.c:37
static void new_dir(void)
Definition: check.c:1099
BOOL empty
Definition: button.c:170
UINT32 uint32_t
Definition: types.h:75
off_t cluster_start(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:289
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static LPCWSTR file_name
Definition: protocol.c:147
#define MODIFY_START(p, v, fs)
Definition: check.c:53
#define ATTR_DIR
Definition: mkdosfs.c:370
#define skip(...)
Definition: atltest.h:64
POINT cp
Definition: magnifier.c:59
Definition: name.c:38
void lfn_add_slot(DIR_ENT *de, off_t dir_offset)
Definition: lfn.c:206
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define MSDOS_DOT
Definition: msdos_fs.h:47
#define die(str)
Definition: mkdosfs.c:347
int month[12]
Definition: systime.c:13
#define FSTART(p, fs)
Definition: check.c:40
CardRegion * from
Definition: spigame.cpp:19
Definition: file.h:30
#define memset(x, y, z)
Definition: compat.h:39
int file_cvt(unsigned char *name, unsigned char *fixed)
Definition: file.c:84
#define VFAT_LN_ATTR
Definition: fsck.fat.h:78
GLubyte * pattern
Definition: glext.h:7787
WCHAR * name
Definition: name.c:42
void get_fat(FAT_ENTRY *entry, void *fat, uint32_t cluster, DOS_FS *fs)
Definition: fat.c:41
#define printf
Definition: config.h:203
Definition: fci.c:126
GLuint const GLchar * name
Definition: glext.h:6031