1*fdc43e97SToomas Soome /*
2*fdc43e97SToomas Soome * CDDL HEADER START
3*fdc43e97SToomas Soome *
4*fdc43e97SToomas Soome * The contents of this file are subject to the terms of the
5*fdc43e97SToomas Soome * Common Development and Distribution License, Version 1.0 only
6*fdc43e97SToomas Soome * (the "License"). You may not use this file except in compliance
7*fdc43e97SToomas Soome * with the License.
8*fdc43e97SToomas Soome *
9*fdc43e97SToomas Soome * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*fdc43e97SToomas Soome * or http://www.opensolaris.org/os/licensing.
11*fdc43e97SToomas Soome * See the License for the specific language governing permissions
12*fdc43e97SToomas Soome * and limitations under the License.
13*fdc43e97SToomas Soome *
14*fdc43e97SToomas Soome * When distributing Covered Code, include this CDDL HEADER in each
15*fdc43e97SToomas Soome * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*fdc43e97SToomas Soome * If applicable, add the following below this CDDL HEADER, with the
17*fdc43e97SToomas Soome * fields enclosed by brackets "[]" replaced with your own identifying
18*fdc43e97SToomas Soome * information: Portions Copyright [yyyy] [name of copyright owner]
19*fdc43e97SToomas Soome *
20*fdc43e97SToomas Soome * CDDL HEADER END
21*fdc43e97SToomas Soome */
22*fdc43e97SToomas Soome /*
23*fdc43e97SToomas Soome * Copyright (c) 1999,2001 by Sun Microsystems, Inc.
24*fdc43e97SToomas Soome * All rights reserved.
25*fdc43e97SToomas Soome * Copyright 2024 MNX Cloud, Inc.
26*fdc43e97SToomas Soome */
27*fdc43e97SToomas Soome
28*fdc43e97SToomas Soome /*
29*fdc43e97SToomas Soome * fsck_pcfs -- main routines.
30*fdc43e97SToomas Soome */
31*fdc43e97SToomas Soome
32*fdc43e97SToomas Soome #include <stdio.h>
33*fdc43e97SToomas Soome #include <errno.h>
34*fdc43e97SToomas Soome #include <err.h>
35*fdc43e97SToomas Soome #include <stdlib.h>
36*fdc43e97SToomas Soome #include <sys/types.h>
37*fdc43e97SToomas Soome #include <sys/stat.h>
38*fdc43e97SToomas Soome #include <fcntl.h>
39*fdc43e97SToomas Soome #include <strings.h>
40*fdc43e97SToomas Soome #include <libintl.h>
41*fdc43e97SToomas Soome #include <locale.h>
42*fdc43e97SToomas Soome #include <unistd.h>
43*fdc43e97SToomas Soome #include <stropts.h>
44*fdc43e97SToomas Soome #include <sys/fcntl.h>
45*fdc43e97SToomas Soome #include <sys/dktp/fdisk.h>
46*fdc43e97SToomas Soome #include "getresponse.h"
47*fdc43e97SToomas Soome #include "pcfs_common.h"
48*fdc43e97SToomas Soome #include "fsck_pcfs.h"
49*fdc43e97SToomas Soome #include "pcfs_bpb.h"
50*fdc43e97SToomas Soome
51*fdc43e97SToomas Soome size_t bpsec = MINBPS;
52*fdc43e97SToomas Soome int32_t BytesPerCluster;
53*fdc43e97SToomas Soome int32_t TotalClusters;
54*fdc43e97SToomas Soome int32_t LastCluster;
55*fdc43e97SToomas Soome off64_t FirstClusterOffset;
56*fdc43e97SToomas Soome off64_t PartitionOffset;
57*fdc43e97SToomas Soome bpb_t TheBIOSParameterBlock;
58*fdc43e97SToomas Soome
59*fdc43e97SToomas Soome /*
60*fdc43e97SToomas Soome * {Output,Input}Image are the file names where we should write the
61*fdc43e97SToomas Soome * checked fs image and from which we should read the initial fs.
62*fdc43e97SToomas Soome * The image capability is designed for debugging purposes.
63*fdc43e97SToomas Soome */
64*fdc43e97SToomas Soome static char *OutputImage = NULL;
65*fdc43e97SToomas Soome static char *InputImage = NULL;
66*fdc43e97SToomas Soome static int WritableOnly = 0; /* -o w, check writable fs' only */
67*fdc43e97SToomas Soome static int Mflag = 0; /* -m, sanity check if fs is mountable */
68*fdc43e97SToomas Soome static int Preen = 0; /* -o p, preen; non-interactive */
69*fdc43e97SToomas Soome /*
70*fdc43e97SToomas Soome * By default be quick; skip verify reads.
71*fdc43e97SToomas Soome * If the user wants more exhaustive checking,
72*fdc43e97SToomas Soome * they should run with the -o v option.
73*fdc43e97SToomas Soome */
74*fdc43e97SToomas Soome static int Quick = 1;
75*fdc43e97SToomas Soome
76*fdc43e97SToomas Soome int ReadOnly = 0;
77*fdc43e97SToomas Soome int IsFAT32 = 0;
78*fdc43e97SToomas Soome int Verbose = 0;
79*fdc43e97SToomas Soome
80*fdc43e97SToomas Soome bool AlwaysYes = false; /* -y or -Y, assume a yes answer to all questions */
81*fdc43e97SToomas Soome bool AlwaysNo = false; /* -n or -N, assume a no answer to all questions */
82*fdc43e97SToomas Soome
83*fdc43e97SToomas Soome extern ClusterContents TheRootDir;
84*fdc43e97SToomas Soome
85*fdc43e97SToomas Soome /*
86*fdc43e97SToomas Soome * Function definitions
87*fdc43e97SToomas Soome */
88*fdc43e97SToomas Soome
89*fdc43e97SToomas Soome static void
passOne(int fd)90*fdc43e97SToomas Soome passOne(int fd)
91*fdc43e97SToomas Soome {
92*fdc43e97SToomas Soome if (!Quick)
93*fdc43e97SToomas Soome findBadClusters(fd);
94*fdc43e97SToomas Soome scanAndFixMetadata(fd);
95*fdc43e97SToomas Soome }
96*fdc43e97SToomas Soome
97*fdc43e97SToomas Soome static void
writeBackChanges(int fd)98*fdc43e97SToomas Soome writeBackChanges(int fd)
99*fdc43e97SToomas Soome {
100*fdc43e97SToomas Soome writeFATMods(fd);
101*fdc43e97SToomas Soome if (!IsFAT32)
102*fdc43e97SToomas Soome writeRootDirMods(fd);
103*fdc43e97SToomas Soome writeClusterMods(fd);
104*fdc43e97SToomas Soome }
105*fdc43e97SToomas Soome
106*fdc43e97SToomas Soome static void
tryOpen(int * fd,char * openMe,int oflag,int exitOnFailure)107*fdc43e97SToomas Soome tryOpen(int *fd, char *openMe, int oflag, int exitOnFailure)
108*fdc43e97SToomas Soome {
109*fdc43e97SToomas Soome int saveError;
110*fdc43e97SToomas Soome
111*fdc43e97SToomas Soome if ((*fd = open(openMe, oflag)) < 0) {
112*fdc43e97SToomas Soome if (exitOnFailure == RETURN_ON_OPEN_FAILURE)
113*fdc43e97SToomas Soome return;
114*fdc43e97SToomas Soome saveError = errno;
115*fdc43e97SToomas Soome mountSanityCheckFails();
116*fdc43e97SToomas Soome (void) fprintf(stderr, "%s: ", openMe);
117*fdc43e97SToomas Soome (void) fprintf(stderr, strerror(saveError));
118*fdc43e97SToomas Soome (void) fprintf(stderr, "\n");
119*fdc43e97SToomas Soome exit(1);
120*fdc43e97SToomas Soome }
121*fdc43e97SToomas Soome }
122*fdc43e97SToomas Soome
123*fdc43e97SToomas Soome static void
doOpen(int * inFD,int * outFD,char * name,char * outName)124*fdc43e97SToomas Soome doOpen(int *inFD, int *outFD, char *name, char *outName)
125*fdc43e97SToomas Soome {
126*fdc43e97SToomas Soome if (ReadOnly) {
127*fdc43e97SToomas Soome tryOpen(inFD, name, O_RDONLY, EXIT_ON_OPEN_FAILURE);
128*fdc43e97SToomas Soome *outFD = -1;
129*fdc43e97SToomas Soome } else {
130*fdc43e97SToomas Soome tryOpen(inFD, name, O_RDWR, RETURN_ON_OPEN_FAILURE);
131*fdc43e97SToomas Soome if (*inFD < 0) {
132*fdc43e97SToomas Soome if (errno != EACCES || WritableOnly) {
133*fdc43e97SToomas Soome int saveError = errno;
134*fdc43e97SToomas Soome mountSanityCheckFails();
135*fdc43e97SToomas Soome (void) fprintf(stderr,
136*fdc43e97SToomas Soome gettext("%s: "), name);
137*fdc43e97SToomas Soome (void) fprintf(stderr, strerror(saveError));
138*fdc43e97SToomas Soome (void) fprintf(stderr, "\n");
139*fdc43e97SToomas Soome exit(2);
140*fdc43e97SToomas Soome } else {
141*fdc43e97SToomas Soome tryOpen(inFD, name, O_RDONLY,
142*fdc43e97SToomas Soome EXIT_ON_OPEN_FAILURE);
143*fdc43e97SToomas Soome AlwaysYes = false;
144*fdc43e97SToomas Soome AlwaysNo = true;
145*fdc43e97SToomas Soome ReadOnly = 1;
146*fdc43e97SToomas Soome *outFD = -1;
147*fdc43e97SToomas Soome }
148*fdc43e97SToomas Soome } else {
149*fdc43e97SToomas Soome *outFD = *inFD;
150*fdc43e97SToomas Soome }
151*fdc43e97SToomas Soome }
152*fdc43e97SToomas Soome
153*fdc43e97SToomas Soome if (outName != NULL) {
154*fdc43e97SToomas Soome tryOpen(outFD, outName, (O_RDWR | O_CREAT),
155*fdc43e97SToomas Soome EXIT_ON_OPEN_FAILURE);
156*fdc43e97SToomas Soome }
157*fdc43e97SToomas Soome
158*fdc43e97SToomas Soome (void) printf("** %s %s\n", name,
159*fdc43e97SToomas Soome ReadOnly ? gettext("(NO WRITE)") : "");
160*fdc43e97SToomas Soome }
161*fdc43e97SToomas Soome
162*fdc43e97SToomas Soome static void
openFS(char * special,int * inFD,int * outFD)163*fdc43e97SToomas Soome openFS(char *special, int *inFD, int *outFD)
164*fdc43e97SToomas Soome {
165*fdc43e97SToomas Soome struct stat dinfo;
166*fdc43e97SToomas Soome char *actualDisk = NULL;
167*fdc43e97SToomas Soome char *suffix = NULL;
168*fdc43e97SToomas Soome int rv;
169*fdc43e97SToomas Soome
170*fdc43e97SToomas Soome if (Verbose)
171*fdc43e97SToomas Soome (void) fprintf(stderr, gettext("Opening file system.\n"));
172*fdc43e97SToomas Soome
173*fdc43e97SToomas Soome if (InputImage == NULL) {
174*fdc43e97SToomas Soome actualDisk = stat_actual_disk(special, &dinfo, &suffix);
175*fdc43e97SToomas Soome /*
176*fdc43e97SToomas Soome * Destination exists, now find more about it.
177*fdc43e97SToomas Soome */
178*fdc43e97SToomas Soome if (!(S_ISCHR(dinfo.st_mode))) {
179*fdc43e97SToomas Soome mountSanityCheckFails();
180*fdc43e97SToomas Soome (void) fprintf(stderr,
181*fdc43e97SToomas Soome gettext("\n%s: device name must be a "
182*fdc43e97SToomas Soome "character special device.\n"), actualDisk);
183*fdc43e97SToomas Soome exit(2);
184*fdc43e97SToomas Soome }
185*fdc43e97SToomas Soome } else {
186*fdc43e97SToomas Soome actualDisk = InputImage;
187*fdc43e97SToomas Soome }
188*fdc43e97SToomas Soome doOpen(inFD, outFD, actualDisk, OutputImage);
189*fdc43e97SToomas Soome rv = get_media_sector_size(*inFD, &bpsec);
190*fdc43e97SToomas Soome if (rv != 0) {
191*fdc43e97SToomas Soome (void) fprintf(stderr,
192*fdc43e97SToomas Soome gettext("error detecting device sector size: %s\n"),
193*fdc43e97SToomas Soome strerror(rv));
194*fdc43e97SToomas Soome exit(2);
195*fdc43e97SToomas Soome }
196*fdc43e97SToomas Soome if (!is_sector_size_valid(bpsec)) {
197*fdc43e97SToomas Soome (void) fprintf(stderr,
198*fdc43e97SToomas Soome gettext("unsupported sector size: %zu\n"), bpsec);
199*fdc43e97SToomas Soome exit(2);
200*fdc43e97SToomas Soome }
201*fdc43e97SToomas Soome
202*fdc43e97SToomas Soome if (suffix) {
203*fdc43e97SToomas Soome if ((PartitionOffset =
204*fdc43e97SToomas Soome findPartitionOffset(*inFD, bpsec, suffix)) < 0) {
205*fdc43e97SToomas Soome mountSanityCheckFails();
206*fdc43e97SToomas Soome (void) fprintf(stderr,
207*fdc43e97SToomas Soome gettext("Unable to find logical drive %s\n"),
208*fdc43e97SToomas Soome suffix);
209*fdc43e97SToomas Soome exit(2);
210*fdc43e97SToomas Soome } else if (Verbose) {
211*fdc43e97SToomas Soome (void) fprintf(stderr,
212*fdc43e97SToomas Soome gettext("Partition starts at offset %lld\n"),
213*fdc43e97SToomas Soome PartitionOffset);
214*fdc43e97SToomas Soome }
215*fdc43e97SToomas Soome } else {
216*fdc43e97SToomas Soome PartitionOffset = 0;
217*fdc43e97SToomas Soome }
218*fdc43e97SToomas Soome }
219*fdc43e97SToomas Soome
220*fdc43e97SToomas Soome void
usage(void)221*fdc43e97SToomas Soome usage(void)
222*fdc43e97SToomas Soome {
223*fdc43e97SToomas Soome (void) fprintf(stderr,
224*fdc43e97SToomas Soome gettext("pcfs Usage: fsck -F pcfs [-o v|p|w] special-file\n"));
225*fdc43e97SToomas Soome exit(1);
226*fdc43e97SToomas Soome }
227*fdc43e97SToomas Soome
228*fdc43e97SToomas Soome static
229*fdc43e97SToomas Soome char *LegalOpts[] = {
230*fdc43e97SToomas Soome #define VFLAG 0
231*fdc43e97SToomas Soome "v",
232*fdc43e97SToomas Soome #define PFLAG 1
233*fdc43e97SToomas Soome "p",
234*fdc43e97SToomas Soome #define WFLAG 2
235*fdc43e97SToomas Soome "w",
236*fdc43e97SToomas Soome #define DFLAG 3
237*fdc43e97SToomas Soome "d",
238*fdc43e97SToomas Soome #define IFLAG 4
239*fdc43e97SToomas Soome "i",
240*fdc43e97SToomas Soome #define OFLAG 5
241*fdc43e97SToomas Soome "o",
242*fdc43e97SToomas Soome NULL
243*fdc43e97SToomas Soome };
244*fdc43e97SToomas Soome
245*fdc43e97SToomas Soome static void
parseSubOptions(char * optsstr)246*fdc43e97SToomas Soome parseSubOptions(char *optsstr)
247*fdc43e97SToomas Soome {
248*fdc43e97SToomas Soome char *value;
249*fdc43e97SToomas Soome int c;
250*fdc43e97SToomas Soome
251*fdc43e97SToomas Soome while (*optsstr != '\0') {
252*fdc43e97SToomas Soome switch (c = getsubopt(&optsstr, LegalOpts, &value)) {
253*fdc43e97SToomas Soome case VFLAG:
254*fdc43e97SToomas Soome Quick = 0;
255*fdc43e97SToomas Soome break;
256*fdc43e97SToomas Soome case PFLAG:
257*fdc43e97SToomas Soome Preen++;
258*fdc43e97SToomas Soome break;
259*fdc43e97SToomas Soome case WFLAG:
260*fdc43e97SToomas Soome WritableOnly++;
261*fdc43e97SToomas Soome break;
262*fdc43e97SToomas Soome case DFLAG:
263*fdc43e97SToomas Soome Verbose++;
264*fdc43e97SToomas Soome break;
265*fdc43e97SToomas Soome case IFLAG:
266*fdc43e97SToomas Soome if (value == NULL) {
267*fdc43e97SToomas Soome missing_arg(LegalOpts[c]);
268*fdc43e97SToomas Soome } else {
269*fdc43e97SToomas Soome InputImage = value;
270*fdc43e97SToomas Soome }
271*fdc43e97SToomas Soome break;
272*fdc43e97SToomas Soome case OFLAG:
273*fdc43e97SToomas Soome if (value == NULL) {
274*fdc43e97SToomas Soome missing_arg(LegalOpts[c]);
275*fdc43e97SToomas Soome } else {
276*fdc43e97SToomas Soome OutputImage = value;
277*fdc43e97SToomas Soome }
278*fdc43e97SToomas Soome break;
279*fdc43e97SToomas Soome default:
280*fdc43e97SToomas Soome bad_arg(value);
281*fdc43e97SToomas Soome break;
282*fdc43e97SToomas Soome }
283*fdc43e97SToomas Soome }
284*fdc43e97SToomas Soome }
285*fdc43e97SToomas Soome
286*fdc43e97SToomas Soome static void
sanityCheckOpts(void)287*fdc43e97SToomas Soome sanityCheckOpts(void)
288*fdc43e97SToomas Soome {
289*fdc43e97SToomas Soome if (WritableOnly && ReadOnly) {
290*fdc43e97SToomas Soome (void) fprintf(stderr,
291*fdc43e97SToomas Soome gettext("-w option may not be used with the -n "
292*fdc43e97SToomas Soome "or -m options\n"));
293*fdc43e97SToomas Soome exit(4);
294*fdc43e97SToomas Soome }
295*fdc43e97SToomas Soome }
296*fdc43e97SToomas Soome
297*fdc43e97SToomas Soome static void
confirmMountable(char * special,int fd)298*fdc43e97SToomas Soome confirmMountable(char *special, int fd)
299*fdc43e97SToomas Soome {
300*fdc43e97SToomas Soome char *printName;
301*fdc43e97SToomas Soome int okayToMount = 1;
302*fdc43e97SToomas Soome
303*fdc43e97SToomas Soome printName = InputImage ? InputImage : special;
304*fdc43e97SToomas Soome
305*fdc43e97SToomas Soome if (!IsFAT32) {
306*fdc43e97SToomas Soome /* make sure we can at least read the root directory */
307*fdc43e97SToomas Soome getRootDirectory(fd);
308*fdc43e97SToomas Soome if (TheRootDir.bytes == NULL)
309*fdc43e97SToomas Soome okayToMount = 0;
310*fdc43e97SToomas Soome } else {
311*fdc43e97SToomas Soome /* check the bit designed into FAT32 for this purpose */
312*fdc43e97SToomas Soome okayToMount = checkFAT32CleanBit(fd);
313*fdc43e97SToomas Soome }
314*fdc43e97SToomas Soome if (okayToMount) {
315*fdc43e97SToomas Soome (void) fprintf(stderr,
316*fdc43e97SToomas Soome gettext("pcfs fsck: sanity check: %s okay\n"), printName);
317*fdc43e97SToomas Soome exit(0);
318*fdc43e97SToomas Soome } else {
319*fdc43e97SToomas Soome (void) fprintf(stderr,
320*fdc43e97SToomas Soome gettext("pcfs fsck: sanity check: %s needs checking\n"),
321*fdc43e97SToomas Soome printName);
322*fdc43e97SToomas Soome exit(32);
323*fdc43e97SToomas Soome }
324*fdc43e97SToomas Soome }
325*fdc43e97SToomas Soome
326*fdc43e97SToomas Soome void
mountSanityCheckFails(void)327*fdc43e97SToomas Soome mountSanityCheckFails(void)
328*fdc43e97SToomas Soome {
329*fdc43e97SToomas Soome if (Mflag) {
330*fdc43e97SToomas Soome (void) fprintf(stderr,
331*fdc43e97SToomas Soome gettext("pcfs fsck: sanity check failed: "));
332*fdc43e97SToomas Soome }
333*fdc43e97SToomas Soome }
334*fdc43e97SToomas Soome
335*fdc43e97SToomas Soome /*
336*fdc43e97SToomas Soome * preenBail
337*fdc43e97SToomas Soome * Routine that other routines can call if they would go into a
338*fdc43e97SToomas Soome * state where they need user input. They can send an optional
339*fdc43e97SToomas Soome * message string to be printed before the exit. Caller should
340*fdc43e97SToomas Soome * send a NULL string if they don't have an exit message.
341*fdc43e97SToomas Soome */
342*fdc43e97SToomas Soome void
preenBail(char * outString)343*fdc43e97SToomas Soome preenBail(char *outString)
344*fdc43e97SToomas Soome {
345*fdc43e97SToomas Soome /*
346*fdc43e97SToomas Soome * If we are running in the 'preen' mode, we got here because
347*fdc43e97SToomas Soome * we reached a situation that would require user intervention.
348*fdc43e97SToomas Soome * We have no choice but to bail at this point.
349*fdc43e97SToomas Soome */
350*fdc43e97SToomas Soome if (Preen) {
351*fdc43e97SToomas Soome if (outString)
352*fdc43e97SToomas Soome (void) printf("%s", outString);
353*fdc43e97SToomas Soome (void) printf(gettext("FILE SYSTEM FIX REQUIRES USER "
354*fdc43e97SToomas Soome "INTERVENTION; RUN fsck MANUALLY.\n"));
355*fdc43e97SToomas Soome exit(36);
356*fdc43e97SToomas Soome }
357*fdc43e97SToomas Soome }
358*fdc43e97SToomas Soome
359*fdc43e97SToomas Soome int
main(int argc,char * argv[])360*fdc43e97SToomas Soome main(int argc, char *argv[])
361*fdc43e97SToomas Soome {
362*fdc43e97SToomas Soome char *string;
363*fdc43e97SToomas Soome int ifd, ofd;
364*fdc43e97SToomas Soome int c;
365*fdc43e97SToomas Soome
366*fdc43e97SToomas Soome (void) setlocale(LC_ALL, "");
367*fdc43e97SToomas Soome
368*fdc43e97SToomas Soome #if !defined(TEXT_DOMAIN)
369*fdc43e97SToomas Soome #define TEXT_DOMAIN "SYS_TEST"
370*fdc43e97SToomas Soome #endif
371*fdc43e97SToomas Soome (void) textdomain(TEXT_DOMAIN);
372*fdc43e97SToomas Soome if (init_yes() < 0)
373*fdc43e97SToomas Soome errx(2, gettext(ERR_MSG_INIT_YES), strerror(errno));
374*fdc43e97SToomas Soome
375*fdc43e97SToomas Soome if (argc < 2)
376*fdc43e97SToomas Soome usage();
377*fdc43e97SToomas Soome
378*fdc43e97SToomas Soome while ((c = getopt(argc, argv, "F:VYNynmo:")) != EOF) {
379*fdc43e97SToomas Soome switch (c) {
380*fdc43e97SToomas Soome case 'F':
381*fdc43e97SToomas Soome string = optarg;
382*fdc43e97SToomas Soome if (strcmp(string, "pcfs") != 0)
383*fdc43e97SToomas Soome usage();
384*fdc43e97SToomas Soome break;
385*fdc43e97SToomas Soome case 'V': {
386*fdc43e97SToomas Soome char *opt_text;
387*fdc43e97SToomas Soome int opt_count;
388*fdc43e97SToomas Soome
389*fdc43e97SToomas Soome (void) printf(gettext("fsck -F pcfs "));
390*fdc43e97SToomas Soome for (opt_count = 1; opt_count < argc;
391*fdc43e97SToomas Soome opt_count++) {
392*fdc43e97SToomas Soome opt_text = argv[opt_count];
393*fdc43e97SToomas Soome if (opt_text)
394*fdc43e97SToomas Soome (void) printf(" %s ",
395*fdc43e97SToomas Soome opt_text);
396*fdc43e97SToomas Soome }
397*fdc43e97SToomas Soome (void) printf("\n");
398*fdc43e97SToomas Soome fini_yes();
399*fdc43e97SToomas Soome exit(0);
400*fdc43e97SToomas Soome }
401*fdc43e97SToomas Soome break;
402*fdc43e97SToomas Soome case 'N':
403*fdc43e97SToomas Soome case 'n':
404*fdc43e97SToomas Soome AlwaysYes = false;
405*fdc43e97SToomas Soome AlwaysNo = true;
406*fdc43e97SToomas Soome ReadOnly = 1;
407*fdc43e97SToomas Soome break;
408*fdc43e97SToomas Soome case 'Y':
409*fdc43e97SToomas Soome case 'y':
410*fdc43e97SToomas Soome AlwaysYes = true;
411*fdc43e97SToomas Soome AlwaysNo = false;
412*fdc43e97SToomas Soome break;
413*fdc43e97SToomas Soome case 'm':
414*fdc43e97SToomas Soome Mflag++;
415*fdc43e97SToomas Soome ReadOnly = 1;
416*fdc43e97SToomas Soome break;
417*fdc43e97SToomas Soome case 'o':
418*fdc43e97SToomas Soome string = optarg;
419*fdc43e97SToomas Soome parseSubOptions(string);
420*fdc43e97SToomas Soome break;
421*fdc43e97SToomas Soome }
422*fdc43e97SToomas Soome }
423*fdc43e97SToomas Soome
424*fdc43e97SToomas Soome sanityCheckOpts();
425*fdc43e97SToomas Soome if (InputImage == NULL && (optind < 0 || optind >= argc))
426*fdc43e97SToomas Soome usage();
427*fdc43e97SToomas Soome
428*fdc43e97SToomas Soome openFS(argv[optind], &ifd, &ofd);
429*fdc43e97SToomas Soome readBPB(ifd);
430*fdc43e97SToomas Soome
431*fdc43e97SToomas Soome /*
432*fdc43e97SToomas Soome * -m mountable fs check. This call will not return.
433*fdc43e97SToomas Soome */
434*fdc43e97SToomas Soome if (Mflag)
435*fdc43e97SToomas Soome confirmMountable(argv[optind], ifd);
436*fdc43e97SToomas Soome
437*fdc43e97SToomas Soome /*
438*fdc43e97SToomas Soome * Pass 1: Find any bad clusters and adjust the FAT and directory
439*fdc43e97SToomas Soome * entries accordingly
440*fdc43e97SToomas Soome */
441*fdc43e97SToomas Soome passOne(ifd);
442*fdc43e97SToomas Soome
443*fdc43e97SToomas Soome /*
444*fdc43e97SToomas Soome * XXX - future passes?
445*fdc43e97SToomas Soome * Ideas:
446*fdc43e97SToomas Soome * Data relocation for bad clusters with partial read success?
447*fdc43e97SToomas Soome * Syncing backup FAT copies with main copy?
448*fdc43e97SToomas Soome * Syncing backup root sector for FAT32?
449*fdc43e97SToomas Soome */
450*fdc43e97SToomas Soome
451*fdc43e97SToomas Soome /*
452*fdc43e97SToomas Soome * No problems if we made it this far.
453*fdc43e97SToomas Soome */
454*fdc43e97SToomas Soome printSummary(stdout);
455*fdc43e97SToomas Soome writeBackChanges(ofd);
456*fdc43e97SToomas Soome fini_yes();
457*fdc43e97SToomas Soome return (0);
458*fdc43e97SToomas Soome }
459