/* * fs-util A simple generic frontend for the for the fsck and mkfs * programs under Linux. See the manual pages for details. * * Usage: fsck [-AV] [-t fstype] [fs-options] device * mkfs [-V] [-t fstype] [fs-options] device< [size] * * Authors: David Engel, * Fred N. van Kempen, */ #include #include #include #include #include #include #include #include #include #include #include #ifndef DEFAULT_FSTYPE # define DEFAULT_FSTYPE "minix" #endif #define _PATH_PROG "%s.%s" #define _PROG_FSCK "fsck" #define EXIT_OK 0 #define EXIT_NONDESTRUCT 1 #define EXIT_DESTRUCT 2 #define EXIT_UNCORRECTED 4 #define EXIT_ERROR 8 #define EXIT_USAGE 16 #define EXIT_LIBRARY 128 static char *Version = "1.8"; static char *ignored_types[] = { "ignore", "iso9660", "msdos", "nfs", "proc", "sw", "swap", NULL }; /* Execute a program. */ int do_exec(char *prog, char **argv, int verbose) { char *args[33]; register int i; int pid, status; /* Build the vector. */ i = 0; args[i++] = prog; while(*argv != NULL && i < 32) args[i++] = *argv++; args[i] = NULL; if (verbose) { i = 0; while(args[i] != NULL) { printf("%s ", args[i]); i++; } printf("\n"); if (verbose > 1) return EXIT_OK; } /* Fork and execute the correct program. */ if ((pid = fork()) < 0) { perror("fork"); status = EXIT_ERROR; } else if (pid == 0) { (void) execvp(args[0], args); perror(args[0]); exit(EXIT_ERROR); } else { while(wait(&status) != pid) ; status = WEXITSTATUS(status); } return status; } /* Check if we have to ignore a file system type. */ int ignore(char *type, char *opts) { char *cp; char **ip; ip = ignored_types; while (*ip != NULL) { if (!strcmp(type, *ip)) return 1; ip++; } for (cp = strtok(opts, ","); cp != NULL; cp = strtok(NULL, ",")) { if (!strcmp(cp, "noauto")) return 1; } return 0; } /* Check all file systems, using the /etc/fstab table. */ int check_all(int verbose, char **argv) { char path[PATH_MAX]; char *args[33]; FILE *mntfile; struct mntent *mp; register int i; int status = EXIT_OK; if (verbose) printf("Checking all file systems.\n"); /* Create an array of arguments. */ i = 0; while (*argv != NULL && i < 32) args[i++] = *argv++; args[i] = NULL; args[i + 1] = NULL; /* Open the mount table. */ if ((mntfile = setmntent(MNTTAB, "r")) == NULL) { perror(MNTTAB); exit(EXIT_ERROR); } /* Walk through the /etc/fstab file. */ while ((mp = getmntent(mntfile)) != NULL) { if (verbose) printf("%-7s %-15s %-15s ", mp->mnt_type, mp->mnt_fsname, mp->mnt_dir); if (ignore(mp->mnt_type, mp->mnt_opts)) { if (verbose) printf("(ignored)\n"); continue; } /* Build program name. */ sprintf(path, _PATH_PROG, _PROG_FSCK, mp->mnt_type); args[i] = mp->mnt_fsname; status |= do_exec(path, args, verbose); } (void) endmntent(mntfile); return status; } /* Lookup filesys in /etc/fstab and return the corresponding entry. */ struct mntent *lookup(char *filesys) { FILE *mntfile; struct mntent *mp; /* No filesys name given. */ if (filesys == NULL) return NULL; /* Open the mount table. */ if ((mntfile = setmntent(MNTTAB, "r")) == NULL) { perror(MNTTAB); exit(EXIT_ERROR); } while ((mp = getmntent(mntfile)) != NULL) { if (!strcmp(filesys, mp->mnt_fsname) || !strcmp(filesys, mp->mnt_dir)) break; } (void) endmntent(mntfile); return mp; } void usage(int fsck, char *prog) { if (fsck) { fprintf(stderr, "Usage: fsck [-AV] [-t fstype] [fs-options] filesys\n"); } else { fprintf(stderr, "Usage: mkfs [-V] [-t fstype] [fs-options] filesys [size]\n"); } exit(EXIT_USAGE); } void main(int argc, char *argv[]) { char path[PATH_MAX]; char *oldpath, newpath[PATH_MAX]; register char *sp; struct mntent *fsent; char *fstype = NULL; int verbose = 0; int doall = 0; int i, fsck, more; /* Must be 1 for "fsck" and 0 for "mkfs". */ if ((sp = strrchr(argv[0], '/')) != NULL) sp++; else sp = argv[0]; if (!strcmp(sp, _PROG_FSCK)) fsck = 1; else fsck = 0; /* Check commandline options. */ opterr = 0; more = 0; while ((more == 0) && ((i = getopt(argc, argv, "AVt:")) != EOF)) switch(i) { case 'A': doall++; break; case 'V': verbose++; break; case 't': if (optarg == NULL) usage(fsck, sp); fstype = optarg; break; default: more = 1; break; /* start of specific arguments */ } /* Did we get any specific arguments? */ if (more) optind--; /* Print our version number if requested. */ if (verbose) printf("%s (fsutil) version %s (%s)\n", argv[0], Version, __DATE__); /* Update our PATH to include /etc/fs and /etc. */ strcpy(newpath, "PATH=/etc/fs:/etc:"); if ((oldpath = getenv("PATH")) != NULL) strcat(newpath, oldpath); putenv(newpath); /* If -A was specified ("check all"), double-check. */ if (doall) { if (!fsck || (fstype != NULL)) usage(fsck, sp); exit(check_all(verbose, &argv[optind])); } else { /* If -t wasn't specified, we must deduce fstype. */ if (fstype == NULL) { /* make sure that "filesys" was specified */ if (optind >= argc) usage(fsck, sp); /* then try looking for it in /etc/fstab */ if ((fsent = lookup(argv[argc - 1])) != NULL) { argv[argc - 1] = fsent->mnt_fsname; fstype = fsent->mnt_type; } else { if (!fsck && optind < argc-1) { if ((fsent = lookup(argv[argc - 2])) != NULL) { argv[argc - 2] = fsent->mnt_fsname; fstype = fsent->mnt_type; } } } /* if we still don't know, use the default */ if (fstype == NULL) fstype = DEFAULT_FSTYPE; } /* Build program name. */ sprintf(path, _PATH_PROG, sp, fstype); exit(do_exec(path, &argv[optind], verbose)); } /*NOTREACHED*/ }