dosfstools  4.2
About: dosfstools are utilities to create, check and label (MS-DOS) FAT filesystems.
  Fossies Dox: dosfstools-4.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

fsck.fat.c
Go to the documentation of this file.
1 /* fsck.fat.c - User interface
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) 2018-2021 Pali Roh├ír <pali.rohar@gmail.com>
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 "version.h"
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <ctype.h>
36 #include <limits.h>
37 #include <unistd.h>
38 #include <termios.h>
39 #include <getopt.h>
40 
41 #include "common.h"
42 #include "fsck.fat.h"
43 #include "io.h"
44 #include "boot.h"
45 #include "fat.h"
46 #include "file.h"
47 #include "check.h"
48 #include "charconv.h"
49 
50 int rw = 0, list = 0, test = 0, verbose = 0;
51 long fat_table = 0;
54 int boot_only = 0;
55 unsigned n_files = 0;
56 void *mem_queue = NULL;
57 
58 static struct termios original_termios;
59 
60 
61 static void restore_termios(void)
62 {
63  tcsetattr(0, TCSAFLUSH, &original_termios);
64 }
65 
66 
67 static void usage(char *name, int exitval)
68 {
69  fprintf(stderr, "Usage: %s [OPTIONS] DEVICE\n", name);
70  fprintf(stderr, "Check FAT filesystem on DEVICE for errors.\n");
71  fprintf(stderr, "\n");
72  fprintf(stderr, "Options:\n");
73  fprintf(stderr, " -a automatically repair the filesystem\n");
74  fprintf(stderr, " -A toggle Atari variant of the FAT filesystem\n");
75  fprintf(stderr, " -b make read-only boot sector check\n");
76  fprintf(stderr, " -c N use DOS codepage N to decode short file names (default: %d)\n",
78  fprintf(stderr, " -d PATH drop file with name PATH (can be given multiple times)\n");
79  fprintf(stderr, " -f salvage unused chains to files\n");
80  fprintf(stderr, " -F NUM specify FAT table NUM used for filesystem access\n");
81  fprintf(stderr, " -l list path names\n");
82  fprintf(stderr, " -n no-op, check non-interactively without changing\n");
83  fprintf(stderr, " -p same as -a, for compat with other *fsck\n");
84  fprintf(stderr, " -r interactively repair the filesystem (default)\n");
85  fprintf(stderr, " -S disallow spaces in the middle of short file names\n");
86  fprintf(stderr, " -t test for bad clusters\n");
87  fprintf(stderr, " -u PATH try to undelete (non-directory) file that was named PATH (can be\n");
88  fprintf(stderr, " given multiple times)\n");
89  fprintf(stderr, " -U allow only uppercase characters in volume and boot label\n");
90  fprintf(stderr, " -v verbose mode\n");
91  fprintf(stderr, " -V perform a verification pass\n");
92  fprintf(stderr, " --variant=TYPE handle variant TYPE of the filesystem\n");
93  fprintf(stderr, " -w write changes to disk immediately\n");
94  fprintf(stderr, " -y same as -a, for compat with other *fsck\n");
95  fprintf(stderr, " --help print this message\n");
96  exit(exitval);
97 }
98 
99 int main(int argc, char **argv)
100 {
101  DOS_FS fs;
102  int salvage_files, verify, c;
103  uint32_t free_clusters = 0;
104  struct termios tio;
105  char *tmp;
106  long codepage;
107 
108  enum {OPT_HELP=1000, OPT_VARIANT};
109  const struct option long_options[] = {
110  {"variant", required_argument, NULL, OPT_VARIANT},
111  {"help", no_argument, NULL, OPT_HELP},
112  {0,}
113  };
114 
115  if (!tcgetattr(0, &original_termios)) {
116  tio = original_termios;
117  tio.c_lflag &= ~(ICANON | ECHO);
118  tcsetattr(0, TCSAFLUSH, &tio);
119  atexit(restore_termios);
120  }
121 
122  memset(&fs, 0, sizeof(fs));
123  salvage_files = verify = 0;
124  rw = interactive = 1;
125  check_atari();
126 
127  while ((c = getopt_long(argc, argv, "Aac:d:bfF:lnprStu:UvVwy",
128  long_options, NULL)) != -1)
129  switch (c) {
130  case 'A': /* toggle Atari format */
132  break;
133  case 'a':
134  case 'p':
135  case 'y':
136  rw = 1;
137  interactive = 0;
138  salvage_files = 1;
139  break;
140  case 'b':
141  rw = 0;
142  interactive = 0;
143  boot_only = 1;
144  break;
145  case 'c':
146  errno = 0;
147  codepage = strtol(optarg, &tmp, 10);
148  if (!*optarg || isspace(*optarg) || *tmp || errno || codepage < 0 || codepage > INT_MAX) {
149  fprintf(stderr, "Invalid codepage : %s\n", optarg);
150  usage(argv[0], 2);
151  }
152  if (!set_dos_codepage(codepage))
153  usage(argv[0], 2);
154  break;
155  case 'd':
156  file_add(optarg, fdt_drop);
157  break;
158  case 'f':
159  salvage_files = 1;
160  break;
161  case 'F':
162  errno = 0;
163  fat_table = strtol(optarg, &tmp, 10);
164  if (!*optarg || isspace(*optarg) || *tmp || errno || fat_table < 0 || fat_table > 255) {
165  fprintf(stderr, "Invalid FAT table : %s\n", optarg);
166  usage(argv[0], 2);
167  }
168  break;
169  case 'l':
170  list = 1;
171  break;
172  case 'n':
173  rw = 0;
174  interactive = 0;
175  break;
176  case 'r':
177  rw = 1;
178  interactive = 1;
179  break;
180  case 'S':
181  no_spaces_in_sfns = 1;
182  break;
183  case 't':
184  test = 1;
185  break;
186  case 'u':
187  file_add(optarg, fdt_undelete);
188  break;
189  case 'U':
191  break;
192  case 'v':
193  verbose = 1;
194  break;
195  case 'V':
196  verify = 1;
197  break;
198  case OPT_VARIANT:
199  if (!strcasecmp(optarg, "standard")) {
200  atari_format = 0;
201  } else if (!strcasecmp(optarg, "atari")) {
202  atari_format = 1;
203  } else {
204  fprintf(stderr, "Unknown variant: %s\n", optarg);
205  usage(argv[0], 2);
206  }
207  break;
208  case 'w':
209  write_immed = 1;
210  break;
211  case OPT_HELP:
212  usage(argv[0], 0);
213  break;
214  case '?':
215  usage(argv[0], 2);
216  break;
217  default:
218  fprintf(stderr,
219  "Internal error: getopt_long() returned unexpected value %d\n", c);
220  exit(3);
221  }
222  if (!set_dos_codepage(-1)) /* set default codepage if none was given in command line */
223  exit(2);
224  if ((test || write_immed) && !rw) {
225  fprintf(stderr, "-t and -w can not be used in read only mode\n");
226  exit(2);
227  }
228  if (optind != argc - 1)
229  usage(argv[0], 2);
230 
231  printf("fsck.fat " VERSION " (" VERSION_DATE ")\n");
232  fs_open(argv[optind], rw);
233 
234  read_boot(&fs);
235  if (boot_only)
236  goto exit;
237 
238  if (verify)
239  printf("Starting check/repair pass.\n");
240  while (read_fat(&fs, 2), scan_root(&fs))
241  qfree(&mem_queue);
242  check_label(&fs);
243  if (test)
244  fix_bad(&fs);
245  if (salvage_files)
246  reclaim_file(&fs);
247  else
248  reclaim_free(&fs);
249  if (!atari_format)
250  check_dirty_bits(&fs);
251  free_clusters = update_free(&fs);
252  file_unused();
253  qfree(&mem_queue);
254  if (verify) {
255  n_files = 0;
256  printf("Starting verification pass.\n");
257  read_fat(&fs, 2);
258  scan_root(&fs);
259  check_label(&fs);
260  reclaim_free(&fs);
261  if (!atari_format)
262  check_dirty_bits(&fs);
263  qfree(&mem_queue);
264  }
265  release_fat(&fs);
266 
267 exit:
268  if (!write_immed && fs_changed()) {
269  if (rw) {
270  printf("\n*** Filesystem was changed ***\n");
271  if (interactive)
272  printf("The changes have not yet been written, you can still choose to leave the\n"
273  "filesystem unmodified:\n");
274 
275  rw = get_choice(1, "Writing changes.",
276  2,
277  1, "Write changes",
278  2, "Leave filesystem unchanged") == 1;
279  } else
280  printf("\nLeaving filesystem unchanged.\n");
281  }
282 
283  if (!boot_only)
284  printf("%s: %u files, %lu/%lu clusters\n", argv[optind],
285  n_files, (unsigned long)fs.data_clusters - free_clusters,
286  (unsigned long)fs.data_clusters);
287 
288  return fs_close(rw) ? 1 : 0;
289 }
void read_boot(DOS_FS *fs)
Definition: boot.c:415
int set_dos_codepage(int codepage)
Definition: charconv.c:339
#define DEFAULT_DOS_CODEPAGE
Definition: charconv.h:28
int scan_root(DOS_FS *fs)
Definition: check.c:1032
void check_label(DOS_FS *fs)
Definition: check.c:1216
void check_dirty_bits(DOS_FS *fs)
Definition: check.c:1065
void qfree(void **root)
Definition: common.c:101
void check_atari(void)
Definition: common.c:273
int atari_format
Definition: common.c:44
int write_immed
Definition: common.c:43
int interactive
Definition: common.c:42
int get_choice(int noninteractive_result, const char *noninteractive_msg, int choices,...)
Definition: common.c:157
void fix_bad(DOS_FS *fs)
Definition: fat.c:402
void reclaim_free(DOS_FS *fs)
Definition: fat.c:420
void release_fat(DOS_FS *fs)
Definition: fat.c:80
uint32_t update_free(DOS_FS *fs)
Definition: fat.c:601
void read_fat(DOS_FS *fs, int mode)
Definition: fat.c:114
void reclaim_file(DOS_FS *fs)
Definition: fat.c:502
void file_add(char *path, FD_TYPE type)
Definition: file.c:156
void file_unused(void)
Definition: file.c:283
@ fdt_undelete
Definition: file.h:28
@ fdt_drop
Definition: file.h:28
static struct termios original_termios
Definition: fsck.fat.c:58
int verbose
Definition: fsck.fat.c:50
int only_uppercase_label
Definition: fsck.fat.c:53
static void restore_termios(void)
Definition: fsck.fat.c:61
int test
Definition: fsck.fat.c:50
static void usage(char *name, int exitval)
Definition: fsck.fat.c:67
int main(int argc, char **argv)
Definition: fsck.fat.c:99
int rw
Definition: fsck.fat.c:50
int list
Definition: fsck.fat.c:50
int no_spaces_in_sfns
Definition: fsck.fat.c:52
void * mem_queue
Definition: fsck.fat.c:56
int boot_only
Definition: fsck.fat.c:54
long fat_table
Definition: fsck.fat.c:51
unsigned n_files
Definition: fsck.fat.c:55
int fs_changed(void)
Definition: io.c:183
int fs_close(int write)
Definition: io.c:163
void fs_open(const char *path, int rw)
Definition: io.c:59
uint32_t data_clusters
Definition: fsck.fat.h:168