blob: 2bc3dc216dea904383137cde5883145bdf8e4775 [file] [log] [blame]
Matt Mower18794c82015-11-11 16:22:45 -06001/* fsck.fat.c - User interface
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002
3 Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
4 Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
Matt Mower18794c82015-11-11 16:22:45 -06005 Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
bigbiff bigbiff9c754052013-01-09 09:09:08 -05006
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19
Matt Mower18794c82015-11-11 16:22:45 -060020 The complete text of the GNU General Public License
bigbiff bigbiff9c754052013-01-09 09:09:08 -050021 can be found in /usr/share/common-licenses/GPL-3 file.
22*/
23
24/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
25 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
26
27#include "version.h"
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include <getopt.h>
35
36#include "common.h"
Matt Mower18794c82015-11-11 16:22:45 -060037#include "fsck.fat.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050038#include "io.h"
39#include "boot.h"
40#include "fat.h"
41#include "file.h"
42#include "check.h"
43
44int interactive = 0, rw = 0, list = 0, test = 0, verbose = 0, write_immed = 0;
Matt Mower18794c82015-11-11 16:22:45 -060045int atari_format = 0, boot_only = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -050046unsigned n_files = 0;
47void *mem_queue = NULL;
48
bigbiff bigbiff9c754052013-01-09 09:09:08 -050049static void usage(char *name)
50{
Matt Mower18794c82015-11-11 16:22:45 -060051 fprintf(stderr, "usage: %s [-aAbflrtvVwy] [-d path -d ...] "
bigbiff bigbiff9c754052013-01-09 09:09:08 -050052 "[-u path -u ...]\n%15sdevice\n", name, "");
Matt Mower18794c82015-11-11 16:22:45 -060053 fprintf(stderr, " -a automatically repair the filesystem\n");
54 fprintf(stderr, " -A toggle Atari filesystem format\n");
55 fprintf(stderr, " -b make read-only boot sector check\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -050056 fprintf(stderr, " -d path drop that file\n");
Matt Mower18794c82015-11-11 16:22:45 -060057 fprintf(stderr, " -f salvage unused chains to files\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -050058 fprintf(stderr, " -l list path names\n");
59 fprintf(stderr,
60 " -n no-op, check non-interactively without changing\n");
61 fprintf(stderr, " -p same as -a, for compat with other *fsck\n");
Matt Mower18794c82015-11-11 16:22:45 -060062 fprintf(stderr, " -r interactively repair the filesystem (default)\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -050063 fprintf(stderr, " -t test for bad clusters\n");
64 fprintf(stderr, " -u path try to undelete that (non-directory) file\n");
65 fprintf(stderr, " -v verbose mode\n");
66 fprintf(stderr, " -V perform a verification pass\n");
67 fprintf(stderr, " -w write changes to disk immediately\n");
68 fprintf(stderr, " -y same as -a, for compat with other *fsck\n");
Matt Mower18794c82015-11-11 16:22:45 -060069 exit(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -050070}
71
72/*
73 * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
74 * of MS-DOS filesystem by default.
75 */
76static void check_atari(void)
77{
78#ifdef __mc68000__
79 FILE *f;
80 char line[128], *p;
81
82 if (!(f = fopen("/proc/hardware", "r"))) {
83 perror("/proc/hardware");
84 return;
85 }
86
87 while (fgets(line, sizeof(line), f)) {
88 if (strncmp(line, "Model:", 6) == 0) {
89 p = line + 6;
90 p += strspn(p, " \t");
91 if (strncmp(p, "Atari ", 6) == 0)
92 atari_format = 1;
93 break;
94 }
95 }
96 fclose(f);
97#endif
98}
99
100int main(int argc, char **argv)
101{
102 DOS_FS fs;
103 int salvage_files, verify, c;
Matt Mower18794c82015-11-11 16:22:45 -0600104 uint32_t free_clusters = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500105
106 memset(&fs, 0, sizeof(fs));
Matt Mower18794c82015-11-11 16:22:45 -0600107 salvage_files = verify = 0;
108 rw = interactive = 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500109 check_atari();
110
Matt Mower18794c82015-11-11 16:22:45 -0600111 while ((c = getopt(argc, argv, "Aad:bflnprtu:vVwy")) != -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500112 switch (c) {
113 case 'A': /* toggle Atari format */
114 atari_format = !atari_format;
115 break;
116 case 'a':
117 case 'p':
118 case 'y':
119 rw = 1;
120 interactive = 0;
121 salvage_files = 1;
122 break;
Matt Mower18794c82015-11-11 16:22:45 -0600123 case 'b':
124 rw = 0;
125 interactive = 0;
126 boot_only = 1;
127 break;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500128 case 'd':
129 file_add(optarg, fdt_drop);
130 break;
131 case 'f':
132 salvage_files = 1;
133 break;
134 case 'l':
135 list = 1;
136 break;
137 case 'n':
138 rw = 0;
139 interactive = 0;
140 break;
141 case 'r':
142 rw = 1;
143 interactive = 1;
144 break;
145 case 't':
146 test = 1;
147 break;
148 case 'u':
149 file_add(optarg, fdt_undelete);
150 break;
151 case 'v':
152 verbose = 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500153 break;
154 case 'V':
155 verify = 1;
156 break;
157 case 'w':
158 write_immed = 1;
159 break;
160 default:
161 usage(argv[0]);
162 }
163 if ((test || write_immed) && !rw) {
Matt Mower18794c82015-11-11 16:22:45 -0600164 fprintf(stderr, "-t and -w can not be used in read only mode\n");
165 exit(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500166 }
167 if (optind != argc - 1)
168 usage(argv[0]);
169
Matt Mower18794c82015-11-11 16:22:45 -0600170 printf("fsck.fat " VERSION " (" VERSION_DATE ")\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500171 fs_open(argv[optind], rw);
Matt Mower18794c82015-11-11 16:22:45 -0600172
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500173 read_boot(&fs);
Matt Mower18794c82015-11-11 16:22:45 -0600174 if (boot_only)
175 goto exit;
176
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500177 if (verify)
178 printf("Starting check/repair pass.\n");
179 while (read_fat(&fs), scan_root(&fs))
180 qfree(&mem_queue);
181 if (test)
182 fix_bad(&fs);
Matt Mower18794c82015-11-11 16:22:45 -0600183 if (salvage_files)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500184 reclaim_file(&fs);
185 else
186 reclaim_free(&fs);
187 free_clusters = update_free(&fs);
188 file_unused();
189 qfree(&mem_queue);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500190 if (verify) {
191 n_files = 0;
192 printf("Starting verification pass.\n");
193 read_fat(&fs);
194 scan_root(&fs);
195 reclaim_free(&fs);
196 qfree(&mem_queue);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500197 }
198
Matt Mower18794c82015-11-11 16:22:45 -0600199exit:
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500200 if (fs_changed()) {
201 if (rw) {
202 if (interactive)
203 rw = get_key("yn", "Perform changes ? (y/n)") == 'y';
204 else
205 printf("Performing changes.\n");
206 } else
Matt Mower18794c82015-11-11 16:22:45 -0600207 printf("Leaving filesystem unchanged.\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500208 }
209
Matt Mower18794c82015-11-11 16:22:45 -0600210 if (!boot_only)
211 printf("%s: %u files, %lu/%lu clusters\n", argv[optind],
212 n_files, (unsigned long)fs.clusters - free_clusters, (unsigned long)fs.clusters);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500213
Matt Mower18794c82015-11-11 16:22:45 -0600214 return fs_close(rw) ? 1 : 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500215}