ReactOS  0.4.12-dev-375-g61fed54
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
char * name
Definition: wpp.c:36
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:47
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:35
#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
uint8_t entry
Definition: isohybrid.c:63
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
static const WCHAR empty[]
Definition: task.c:29
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
GLenum GLclampf GLint i
Definition: glfuncs.h:14
void * mem_queue
char name[1]
Definition: fci.c:135
static size_t double number
Definition: printf.c:64
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:2659
static char * gen_name(void)
Definition: parser.tab.c:6118
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
GLuint GLuint num
Definition: glext.h:9618
GLint left
Definition: glext.h:7726
#define PATH_NAME_MAX
Definition: check.c:35
Definition: cookie.c:170
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
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
Definition: _list.h:228
static stack_node_t temp
Definition: rpn.c:18
Definition: time.h:76
_CRTIMP struct tm *__cdecl localtime(const time_t *_Time)
Definition: time.h:426
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
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
#define skip(...)
Definition: CString.cpp:57
Definition: services.c:325
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
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:146
#define MODIFY_START(p, v, fs)
Definition: check.c:53
#define ATTR_DIR
Definition: mkdosfs.c:370
POINT cp
Definition: magnifier.c:60
Definition: name.c:36
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
GLubyte * pattern
Definition: glext.h:7787
#define VFAT_LN_ATTR
Definition: fsck.fat.h:78
WCHAR * name
Definition: name.c:40
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