| /* |
| * 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, <david@ods.com> |
| * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> |
| */ |
| |
| |
| #include <sys/types.h> |
| #include <sys/wait.h> |
| #include <errno.h> |
| #include <limits.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <mntent.h> |
| #include <unistd.h> |
| #include <getopt.h> |
| |
| |
| #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*/ |
| } |