1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 1999 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*0Sstevel@tonic-gate /* All Rights Reserved */ 8*0Sstevel@tonic-gate 9*0Sstevel@tonic-gate /* 10*0Sstevel@tonic-gate * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 11*0Sstevel@tonic-gate * All rights reserved. 12*0Sstevel@tonic-gate * 13*0Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 14*0Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright 15*0Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display 16*0Sstevel@tonic-gate * the following acknowledgement: ``This product includes software 17*0Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors'' 18*0Sstevel@tonic-gate * in the documentation or other materials provided with the distribution 19*0Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this 20*0Sstevel@tonic-gate * software. Neither the name of the University nor the names of its 21*0Sstevel@tonic-gate * contributors may be used to endorse or promote products derived 22*0Sstevel@tonic-gate * from this software without specific prior written permission. 23*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24*0Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25*0Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26*0Sstevel@tonic-gate */ 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #include <stdio.h> 31*0Sstevel@tonic-gate #include <string.h> 32*0Sstevel@tonic-gate #include <ctype.h> /* use isdigit macro rather than 4.1 libc routine */ 33*0Sstevel@tonic-gate #include <unistd.h> 34*0Sstevel@tonic-gate #include <stdlib.h> 35*0Sstevel@tonic-gate #include <signal.h> 36*0Sstevel@tonic-gate #include <malloc.h> 37*0Sstevel@tonic-gate #include <ustat.h> 38*0Sstevel@tonic-gate #include <sys/param.h> 39*0Sstevel@tonic-gate #include <sys/types.h> 40*0Sstevel@tonic-gate #include <sys/sysmacros.h> 41*0Sstevel@tonic-gate #include <sys/mntent.h> 42*0Sstevel@tonic-gate #include <sys/vnode.h> 43*0Sstevel@tonic-gate #include <sys/stat.h> 44*0Sstevel@tonic-gate #include <sys/wait.h> 45*0Sstevel@tonic-gate #include <sys/mnttab.h> 46*0Sstevel@tonic-gate #include <sys/signal.h> 47*0Sstevel@tonic-gate #include <sys/vfstab.h> 48*0Sstevel@tonic-gate #include <sys/fs/udf_volume.h> 49*0Sstevel@tonic-gate #include "fsck.h" 50*0Sstevel@tonic-gate #include <locale.h> 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate extern int32_t writable(char *); 53*0Sstevel@tonic-gate extern void pfatal(char *, ...); 54*0Sstevel@tonic-gate extern void printfree(); 55*0Sstevel@tonic-gate extern void pwarn(char *, ...); 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate extern void pass1(); 58*0Sstevel@tonic-gate extern void dofreemap(); 59*0Sstevel@tonic-gate extern void dolvint(); 60*0Sstevel@tonic-gate extern char *getfullblkname(); 61*0Sstevel@tonic-gate extern char *getfullrawname(); 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate static int mflag = 0; /* sanity check only */ 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate char *mntopt(); 66*0Sstevel@tonic-gate void catch(), catchquit(), voidquit(); 67*0Sstevel@tonic-gate int returntosingle; 68*0Sstevel@tonic-gate static void checkfilesys(); 69*0Sstevel@tonic-gate static void check_sanity(); 70*0Sstevel@tonic-gate static void usage(); 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate static char *subopts [] = { 73*0Sstevel@tonic-gate #define PREEN 0 74*0Sstevel@tonic-gate "p", 75*0Sstevel@tonic-gate #define DEBUG 1 76*0Sstevel@tonic-gate "d", 77*0Sstevel@tonic-gate #define READ_ONLY 2 78*0Sstevel@tonic-gate "r", 79*0Sstevel@tonic-gate #define ONLY_WRITES 3 80*0Sstevel@tonic-gate "w", 81*0Sstevel@tonic-gate #define FORCE 4 /* force checking, even if clean */ 82*0Sstevel@tonic-gate "f", 83*0Sstevel@tonic-gate #define STATS 5 /* print time and busy stats */ 84*0Sstevel@tonic-gate "s", 85*0Sstevel@tonic-gate NULL 86*0Sstevel@tonic-gate }; 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate uint32_t ecma_version = 2; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate void 91*0Sstevel@tonic-gate main(argc, argv) 92*0Sstevel@tonic-gate int argc; 93*0Sstevel@tonic-gate char *argv[]; 94*0Sstevel@tonic-gate { 95*0Sstevel@tonic-gate int c; 96*0Sstevel@tonic-gate char *suboptions, *value; 97*0Sstevel@tonic-gate int suboption; 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "mnNo:VyYz")) != EOF) { 102*0Sstevel@tonic-gate switch (c) { 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate case 'm': 105*0Sstevel@tonic-gate mflag++; 106*0Sstevel@tonic-gate break; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate case 'n': /* default no answer flag */ 109*0Sstevel@tonic-gate case 'N': 110*0Sstevel@tonic-gate nflag++; 111*0Sstevel@tonic-gate yflag = 0; 112*0Sstevel@tonic-gate break; 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate case 'o': 115*0Sstevel@tonic-gate /* 116*0Sstevel@tonic-gate * udfs specific options. 117*0Sstevel@tonic-gate */ 118*0Sstevel@tonic-gate suboptions = optarg; 119*0Sstevel@tonic-gate while (*suboptions != '\0') { 120*0Sstevel@tonic-gate suboption = getsubopt(&suboptions, 121*0Sstevel@tonic-gate subopts, &value); 122*0Sstevel@tonic-gate switch (suboption) { 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate case PREEN: 125*0Sstevel@tonic-gate preen++; 126*0Sstevel@tonic-gate break; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate case DEBUG: 129*0Sstevel@tonic-gate debug++; 130*0Sstevel@tonic-gate break; 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate case READ_ONLY: 133*0Sstevel@tonic-gate break; 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate case ONLY_WRITES: 136*0Sstevel@tonic-gate /* check only writable filesystems */ 137*0Sstevel@tonic-gate wflag++; 138*0Sstevel@tonic-gate break; 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate case FORCE: 141*0Sstevel@tonic-gate fflag++; 142*0Sstevel@tonic-gate break; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate case STATS: 145*0Sstevel@tonic-gate sflag++; 146*0Sstevel@tonic-gate break; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate default: 149*0Sstevel@tonic-gate usage(); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate break; 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate case 'V': 155*0Sstevel@tonic-gate { 156*0Sstevel@tonic-gate int opt_count; 157*0Sstevel@tonic-gate char *opt_text; 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate (void) fprintf(stdout, "fsck -F udfs "); 160*0Sstevel@tonic-gate for (opt_count = 1; opt_count < argc; 161*0Sstevel@tonic-gate opt_count++) { 162*0Sstevel@tonic-gate opt_text = argv[opt_count]; 163*0Sstevel@tonic-gate if (opt_text) 164*0Sstevel@tonic-gate (void) fprintf(stdout, " %s ", 165*0Sstevel@tonic-gate opt_text); 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate break; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate case 'y': /* default yes answer flag */ 172*0Sstevel@tonic-gate case 'Y': 173*0Sstevel@tonic-gate yflag++; 174*0Sstevel@tonic-gate nflag = 0; 175*0Sstevel@tonic-gate break; 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate case '?': 178*0Sstevel@tonic-gate usage(); 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate argc -= optind; 182*0Sstevel@tonic-gate argv = &argv[optind]; 183*0Sstevel@tonic-gate rflag++; /* check raw devices */ 184*0Sstevel@tonic-gate if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 185*0Sstevel@tonic-gate (void) signal(SIGINT, catch); 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate if (preen) { 189*0Sstevel@tonic-gate (void) signal(SIGQUIT, catchquit); 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate if (argc) { 193*0Sstevel@tonic-gate while (argc-- > 0) { 194*0Sstevel@tonic-gate if (wflag && !writable(*argv)) { 195*0Sstevel@tonic-gate (void) fprintf(stderr, 196*0Sstevel@tonic-gate gettext("not writeable '%s'\n"), *argv); 197*0Sstevel@tonic-gate argv++; 198*0Sstevel@tonic-gate } else 199*0Sstevel@tonic-gate checkfilesys(*argv++); 200*0Sstevel@tonic-gate } 201*0Sstevel@tonic-gate exit(exitstat); 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate static void 207*0Sstevel@tonic-gate checkfilesys(filesys) 208*0Sstevel@tonic-gate char *filesys; 209*0Sstevel@tonic-gate { 210*0Sstevel@tonic-gate char *devstr; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate mountfd = -1; 213*0Sstevel@tonic-gate mountedfs = 0; 214*0Sstevel@tonic-gate iscorrupt = 1; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if ((devstr = setup(filesys)) == 0) { 217*0Sstevel@tonic-gate if (iscorrupt == 0) 218*0Sstevel@tonic-gate return; 219*0Sstevel@tonic-gate if (preen) 220*0Sstevel@tonic-gate pfatal(gettext("CAN'T CHECK FILE SYSTEM.")); 221*0Sstevel@tonic-gate if ((exitstat == 0) && (mflag)) 222*0Sstevel@tonic-gate exitstat = 32; 223*0Sstevel@tonic-gate exit(exitstat); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate else 226*0Sstevel@tonic-gate devname = devstr; 227*0Sstevel@tonic-gate if (mflag) 228*0Sstevel@tonic-gate check_sanity(filesys); /* this never returns */ 229*0Sstevel@tonic-gate iscorrupt = 0; 230*0Sstevel@tonic-gate /* 231*0Sstevel@tonic-gate * 1: scan inodes tallying blocks used 232*0Sstevel@tonic-gate */ 233*0Sstevel@tonic-gate if (preen == 0) { 234*0Sstevel@tonic-gate if (mountedfs) 235*0Sstevel@tonic-gate (void) printf(gettext("** Currently Mounted on %s\n"), 236*0Sstevel@tonic-gate mountpoint); 237*0Sstevel@tonic-gate if (mflag) { 238*0Sstevel@tonic-gate (void) printf( 239*0Sstevel@tonic-gate gettext("** Phase 1 - Sanity Check only\n")); 240*0Sstevel@tonic-gate return; 241*0Sstevel@tonic-gate } else 242*0Sstevel@tonic-gate (void) printf( 243*0Sstevel@tonic-gate gettext("** Phase 1 - Check Directories " 244*0Sstevel@tonic-gate "and Blocks\n")); 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate pass1(); 247*0Sstevel@tonic-gate if (sflag) { 248*0Sstevel@tonic-gate if (preen) 249*0Sstevel@tonic-gate (void) printf("%s: ", devname); 250*0Sstevel@tonic-gate else 251*0Sstevel@tonic-gate (void) printf("** "); 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate if (debug) 254*0Sstevel@tonic-gate (void) printf("pass1 isdirty %d\n", isdirty); 255*0Sstevel@tonic-gate if (debug) 256*0Sstevel@tonic-gate printfree(); 257*0Sstevel@tonic-gate dofreemap(); 258*0Sstevel@tonic-gate dolvint(); 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate /* 261*0Sstevel@tonic-gate * print out summary statistics 262*0Sstevel@tonic-gate */ 263*0Sstevel@tonic-gate pwarn(gettext("%d files, %d dirs, %d used, %d free\n"), n_files, n_dirs, 264*0Sstevel@tonic-gate n_blks, part_len - n_blks); 265*0Sstevel@tonic-gate if (iscorrupt) 266*0Sstevel@tonic-gate exitstat = 36; 267*0Sstevel@tonic-gate if (!fsmodified) 268*0Sstevel@tonic-gate return; 269*0Sstevel@tonic-gate if (!preen) 270*0Sstevel@tonic-gate (void) printf( 271*0Sstevel@tonic-gate gettext("\n***** FILE SYSTEM WAS MODIFIED *****\n")); 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate if (mountedfs) { 274*0Sstevel@tonic-gate exitstat = 40; 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* 280*0Sstevel@tonic-gate * exit 0 - file system is unmounted and okay 281*0Sstevel@tonic-gate * exit 32 - file system is unmounted and needs checking 282*0Sstevel@tonic-gate * exit 33 - file system is mounted 283*0Sstevel@tonic-gate * for root file system 284*0Sstevel@tonic-gate * exit 34 - cannot stat device 285*0Sstevel@tonic-gate */ 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate static void 288*0Sstevel@tonic-gate check_sanity(filename) 289*0Sstevel@tonic-gate char *filename; 290*0Sstevel@tonic-gate { 291*0Sstevel@tonic-gate struct stat stbd, stbr; 292*0Sstevel@tonic-gate struct ustat usb; 293*0Sstevel@tonic-gate char *devname; 294*0Sstevel@tonic-gate struct vfstab vfsbuf; 295*0Sstevel@tonic-gate FILE *vfstab; 296*0Sstevel@tonic-gate int is_root = 0; 297*0Sstevel@tonic-gate int is_usr = 0; 298*0Sstevel@tonic-gate int is_block = 0; 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate if (stat(filename, &stbd) < 0) { 301*0Sstevel@tonic-gate (void) fprintf(stderr, 302*0Sstevel@tonic-gate gettext("udfs fsck: sanity check failed : cannot stat " 303*0Sstevel@tonic-gate "%s\n"), filename); 304*0Sstevel@tonic-gate exit(34); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate if ((stbd.st_mode & S_IFMT) == S_IFBLK) 308*0Sstevel@tonic-gate is_block = 1; 309*0Sstevel@tonic-gate else if ((stbd.st_mode & S_IFMT) == S_IFCHR) 310*0Sstevel@tonic-gate is_block = 0; 311*0Sstevel@tonic-gate else { 312*0Sstevel@tonic-gate (void) fprintf(stderr, 313*0Sstevel@tonic-gate gettext("udfs fsck: sanity check failed: %s not " 314*0Sstevel@tonic-gate "block or character device\n"), filename); 315*0Sstevel@tonic-gate exit(34); 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate /* 319*0Sstevel@tonic-gate * Determine if this is the root file system via vfstab. Give up 320*0Sstevel@tonic-gate * silently on failures. The whole point of this is not to care 321*0Sstevel@tonic-gate * if the root file system is already mounted. 322*0Sstevel@tonic-gate * 323*0Sstevel@tonic-gate * XXX - similar for /usr. This should be fixed to simply return 324*0Sstevel@tonic-gate * a new code indicating, mounted and needs to be checked. 325*0Sstevel@tonic-gate */ 326*0Sstevel@tonic-gate if ((vfstab = fopen(VFSTAB, "r")) != 0) { 327*0Sstevel@tonic-gate if (getvfsfile(vfstab, &vfsbuf, "/") == 0) { 328*0Sstevel@tonic-gate if (is_block) 329*0Sstevel@tonic-gate devname = vfsbuf.vfs_special; 330*0Sstevel@tonic-gate else 331*0Sstevel@tonic-gate devname = vfsbuf.vfs_fsckdev; 332*0Sstevel@tonic-gate if (stat(devname, &stbr) == 0) 333*0Sstevel@tonic-gate if (stbr.st_rdev == stbd.st_rdev) 334*0Sstevel@tonic-gate is_root = 1; 335*0Sstevel@tonic-gate } 336*0Sstevel@tonic-gate if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) { 337*0Sstevel@tonic-gate if (is_block) 338*0Sstevel@tonic-gate devname = vfsbuf.vfs_special; 339*0Sstevel@tonic-gate else 340*0Sstevel@tonic-gate devname = vfsbuf.vfs_fsckdev; 341*0Sstevel@tonic-gate if (stat(devname, &stbr) == 0) 342*0Sstevel@tonic-gate if (stbr.st_rdev == stbd.st_rdev) 343*0Sstevel@tonic-gate is_usr = 1; 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate /* 349*0Sstevel@tonic-gate * XXX - only works if filename is a block device or if 350*0Sstevel@tonic-gate * character and block device has the same dev_t value 351*0Sstevel@tonic-gate */ 352*0Sstevel@tonic-gate if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) { 353*0Sstevel@tonic-gate (void) fprintf(stderr, 354*0Sstevel@tonic-gate gettext("udfs fsck: sanity check: %s " 355*0Sstevel@tonic-gate "already mounted\n"), filename); 356*0Sstevel@tonic-gate exit(33); 357*0Sstevel@tonic-gate } 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate if (lvintp->lvid_int_type == LVI_CLOSE) { 360*0Sstevel@tonic-gate (void) fprintf(stderr, 361*0Sstevel@tonic-gate gettext("udfs fsck: sanity check: %s okay\n"), 362*0Sstevel@tonic-gate filename); 363*0Sstevel@tonic-gate } else { 364*0Sstevel@tonic-gate (void) fprintf(stderr, 365*0Sstevel@tonic-gate gettext("udfs fsck: sanity check: %s needs checking\n"), 366*0Sstevel@tonic-gate filename); 367*0Sstevel@tonic-gate exit(32); 368*0Sstevel@tonic-gate } 369*0Sstevel@tonic-gate exit(0); 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate char * 373*0Sstevel@tonic-gate unrawname(name) 374*0Sstevel@tonic-gate char *name; 375*0Sstevel@tonic-gate { 376*0Sstevel@tonic-gate char *dp; 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate if ((dp = getfullblkname(name)) == NULL) 380*0Sstevel@tonic-gate return (""); 381*0Sstevel@tonic-gate return (dp); 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate char * 385*0Sstevel@tonic-gate rawname(name) 386*0Sstevel@tonic-gate char *name; 387*0Sstevel@tonic-gate { 388*0Sstevel@tonic-gate char *dp; 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate if ((dp = getfullrawname(name)) == NULL) 391*0Sstevel@tonic-gate return (""); 392*0Sstevel@tonic-gate return (dp); 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate char * 396*0Sstevel@tonic-gate hasvfsopt(vfs, opt) 397*0Sstevel@tonic-gate register struct vfstab *vfs; 398*0Sstevel@tonic-gate register char *opt; 399*0Sstevel@tonic-gate { 400*0Sstevel@tonic-gate char *f, *opts; 401*0Sstevel@tonic-gate static char *tmpopts; 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate if (vfs->vfs_mntopts == NULL) 404*0Sstevel@tonic-gate return (NULL); 405*0Sstevel@tonic-gate if (tmpopts == 0) { 406*0Sstevel@tonic-gate tmpopts = (char *)calloc(256, sizeof (char)); 407*0Sstevel@tonic-gate if (tmpopts == 0) 408*0Sstevel@tonic-gate return (0); 409*0Sstevel@tonic-gate } 410*0Sstevel@tonic-gate (void) strncpy(tmpopts, vfs->vfs_mntopts, (sizeof (tmpopts) - 1)); 411*0Sstevel@tonic-gate opts = tmpopts; 412*0Sstevel@tonic-gate f = mntopt(&opts); 413*0Sstevel@tonic-gate for (; *f; f = mntopt(&opts)) { 414*0Sstevel@tonic-gate if (strncmp(opt, f, strlen(opt)) == 0) 415*0Sstevel@tonic-gate return (f - tmpopts + vfs->vfs_mntopts); 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate return (NULL); 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate static void 421*0Sstevel@tonic-gate usage() 422*0Sstevel@tonic-gate { 423*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("udfs usage: fsck [-F udfs] " 424*0Sstevel@tonic-gate "[generic options] [-o p,w,s] [special ....]\n")); 425*0Sstevel@tonic-gate exit(31+1); 426*0Sstevel@tonic-gate } 427