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