update and correct nits
[unix-history] / usr / src / sbin / fsck / main.c
index 510f82b..b163b24 100644 (file)
@@ -1,6 +1,18 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1980 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif not lint
+
 #ifndef lint
 #ifndef lint
-static char version[] = "@(#)main.c    3.3 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)main.c     5.10 (Berkeley) %G%";
+#endif not lint
 
 #include <sys/param.h>
 #include <sys/inode.h>
 
 #include <sys/param.h>
 #include <sys/inode.h>
@@ -9,10 +21,12 @@ static char version[] = "@(#)main.c  3.3 (Berkeley) %G%";
 #include <sys/wait.h>
 #include <fstab.h>
 #include <strings.h>
 #include <sys/wait.h>
 #include <fstab.h>
 #include <strings.h>
+#include <ctype.h>
 #include "fsck.h"
 
 char   *rawname(), *unrawname(), *blockcheck();
 #include "fsck.h"
 
 char   *rawname(), *unrawname(), *blockcheck();
-int    catch();
+int    catch(), catchquit(), voidquit();
+int    returntosingle;
 int    (*signal())();
 
 main(argc, argv)
 int    (*signal())();
 
 main(argc, argv)
@@ -22,6 +36,12 @@ main(argc, argv)
        struct fstab *fsp;
        int pid, passno, anygtr, sumstatus;
        char *name;
        struct fstab *fsp;
        int pid, passno, anygtr, sumstatus;
        char *name;
+       struct worklist {
+               int     pid;            /* pid of child doing the check */
+               struct  worklist *next; /* next in list */
+               char    name[MAXMNTLEN];/* name of file system */
+       } *listhead = 0, *freelist = 0, *badlist = 0;
+       register struct worklist *wp, *pwp;
 
        sync();
        while (--argc > 0 && **++argv == '-') {
 
        sync();
        while (--argc > 0 && **++argv == '-') {
@@ -41,10 +61,24 @@ main(argc, argv)
                        printf("Alternate super block location: %d\n", bflag);
                        break;
 
                        printf("Alternate super block location: %d\n", bflag);
                        break;
 
+               case 'c':
+                       cvtflag++;
+                       break;
+
                case 'd':
                        debug++;
                        break;
 
                case 'd':
                        debug++;
                        break;
 
+               case 'm':
+                       if (!isdigit(argv[1][0]))
+                               errexit("-m flag requires a mode\n");
+                       sscanf(*++argv, "%o", &lfmode);
+                       if (lfmode &~ 07777)
+                               errexit("bad mode to -m: %o\n", lfmode);
+                       argc--;
+                       printf("** lost+found creation mode %o\n", lfmode);
+                       break;
+
                case 'n':       /* default no answer flag */
                case 'N':
                        nflag++;
                case 'n':       /* default no answer flag */
                case 'N':
                        nflag++;
@@ -63,6 +97,8 @@ main(argc, argv)
        }
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                (void)signal(SIGINT, catch);
        }
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                (void)signal(SIGINT, catch);
+       if (preen)
+               (void)signal(SIGQUIT, catchquit);
        if (argc) {
                while (argc-- > 0) {
                        hotroot = 0;
        if (argc) {
                while (argc-- > 0) {
                        hotroot = 0;
@@ -91,30 +127,85 @@ main(argc, argv)
                        } else if (fsp->fs_passno > passno) {
                                anygtr = 1;
                        } else if (fsp->fs_passno == passno) {
                        } else if (fsp->fs_passno > passno) {
                                anygtr = 1;
                        } else if (fsp->fs_passno == passno) {
+                               name = blockcheck(fsp->fs_spec);
+                               if (name == NULL) {
+                                       pwarn("BAD DISK NAME %s\n",
+                                               fsp->fs_spec);
+                                       sumstatus |= 8;
+                                       continue;
+                               }
                                pid = fork();
                                if (pid < 0) {
                                        perror("fork");
                                        exit(8);
                                }
                                if (pid == 0) {
                                pid = fork();
                                if (pid < 0) {
                                        perror("fork");
                                        exit(8);
                                }
                                if (pid == 0) {
-                                       name = blockcheck(fsp->fs_spec);
-                                       if (name == NULL)
-                                               exit(8);
+                                       (void)signal(SIGQUIT, voidquit);
                                        checkfilesys(name);
                                        exit(0);
                                        checkfilesys(name);
                                        exit(0);
+                               } else {
+                                       if (freelist == 0) {
+                                               wp = (struct worklist *) malloc
+                                                   (sizeof(struct worklist));
+                                       } else {
+                                               wp = freelist;
+                                               freelist = wp->next;
+                                       }
+                                       wp->next = listhead;
+                                       listhead = wp;
+                                       wp->pid = pid;
+                                       sprintf(wp->name, "%s (%s)", name,
+                                           fsp->fs_file);
                                }
                        }
                }
                if (preen) {
                        union wait status;
                                }
                        }
                }
                if (preen) {
                        union wait status;
-                       while (wait(&status) != -1)
-                               sumstatus |= status.w_retcode;
+                       while ((pid = wait(&status)) != -1) {
+                               if (status.w_termsig)
+                                       sumstatus |= 8;
+                               else
+                                       sumstatus |= status.w_retcode;
+                               pwp = 0;
+                               for (wp = listhead; wp; pwp = wp, wp = wp->next)
+                                       if (wp->pid == pid)
+                                               break;
+                               if (wp == 0) {
+                                       printf("Unknown pid %d\n", pid);
+                                       continue;
+                               }
+                               if (pwp == 0)
+                                       listhead = wp->next;
+                               else
+                                       pwp->next = wp->next;
+                               if (status.w_termsig) {
+                                       printf("%s: EXITED WITH SIGNAL %d\n",
+                                               wp->name, status.w_termsig);
+                                       status.w_retcode = 8;
+                               }
+                               if (status.w_retcode != 0) {
+                                       wp->next = badlist;
+                                       badlist = wp;
+                               } else {
+                                       wp->next = freelist;
+                                       freelist = wp;
+                               }
+                       }
                }
                passno++;
        } while (anygtr);
                }
                passno++;
        } while (anygtr);
-       if (sumstatus)
+       if (sumstatus) {
+               if (badlist == 0)
+                       exit(8);
+               printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
+                       badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
+               for (wp = badlist; wp; wp = wp->next)
+                       printf("%s%s", wp->name, wp->next ? ", " : "\n");
                exit(8);
                exit(8);
+       }
        (void)endfsent();
        (void)endfsent();
+       if (returntosingle)
+               exit(2);
        exit(0);
 }
 
        exit(0);
 }
 
@@ -122,6 +213,8 @@ checkfilesys(filesys)
        char *filesys;
 {
        daddr_t n_ffree, n_bfree;
        char *filesys;
 {
        daddr_t n_ffree, n_bfree;
+       struct dups *dp;
+       struct zlncnt *zlnp;
 
        devname = filesys;
        if (setup(filesys) == 0) {
 
        devname = filesys;
        if (setup(filesys) == 0) {
@@ -143,7 +236,7 @@ checkfilesys(filesys)
        /*
         * 1b: locate first references to duplicates, if any
         */
        /*
         * 1b: locate first references to duplicates, if any
         */
-       if (enddup != &duplist[0]) {
+       if (duplist) {
                if (preen)
                        pfatal("INTERNAL ERROR: dups with -p");
                printf("** Phase 1b - Rescan For More DUPS\n");
                if (preen)
                        pfatal("INTERNAL ERROR: dups with -p");
                printf("** Phase 1b - Rescan For More DUPS\n");
@@ -183,8 +276,10 @@ checkfilesys(filesys)
         */
        n_ffree = sblock.fs_cstotal.cs_nffree;
        n_bfree = sblock.fs_cstotal.cs_nbfree;
         */
        n_ffree = sblock.fs_cstotal.cs_nffree;
        n_bfree = sblock.fs_cstotal.cs_nbfree;
-       pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n", n_files,
-           n_blks, n_ffree + sblock.fs_frag * n_bfree, n_ffree, n_bfree);
+       pwarn("%d files, %d used, %d free ",
+           n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
+       printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
+           n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
        if (debug && (n_files -= imax - ROOTINO - sblock.fs_cstotal.cs_nifree))
                printf("%d files missing\n", n_files);
        if (debug) {
        if (debug && (n_files -= imax - ROOTINO - sblock.fs_cstotal.cs_nifree))
                printf("%d files missing\n", n_files);
        if (debug) {
@@ -194,7 +289,21 @@ checkfilesys(filesys)
                n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
                if (n_blks -= fmax - (n_ffree + sblock.fs_frag * n_bfree))
                        printf("%d blocks missing\n", n_blks);
                n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
                if (n_blks -= fmax - (n_ffree + sblock.fs_frag * n_bfree))
                        printf("%d blocks missing\n", n_blks);
+               if (duplist != NULL) {
+                       printf("The following duplicate blocks remain:");
+                       for (dp = duplist; dp; dp = dp->next)
+                               printf(" %d,", dp->dup);
+                       printf("\n");
+               }
+               if (zlnhead != NULL) {
+                       printf("The following zero link count inodes remain:");
+                       for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
+                               printf(" %d,", zlnp->zlncnt);
+                       printf("\n");
+               }
        }
        }
+       zlnhead = (struct zlncnt *)0;
+       duplist = (struct dups *)0;
        if (dfile.mod) {
                (void)time(&sblock.fs_time);
                sbdirty();
        if (dfile.mod) {
                (void)time(&sblock.fs_time);
                sbdirty();
@@ -226,31 +335,34 @@ blockcheck(name)
 
        hotroot = 0;
        if (stat("/", &stslash) < 0){
 
        hotroot = 0;
        if (stat("/", &stslash) < 0){
+               perror("/");
                printf("Can't stat root\n");
                return (0);
        }
 retry:
        if (stat(name, &stblock) < 0){
                printf("Can't stat root\n");
                return (0);
        }
 retry:
        if (stat(name, &stblock) < 0){
+               perror(name);
                printf("Can't stat %s\n", name);
                return (0);
        }
                printf("Can't stat %s\n", name);
                return (0);
        }
-       if (stblock.st_mode & S_IFBLK) {
+       if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
+               if (stslash.st_dev == stblock.st_rdev) {
+                       hotroot++;
+                       return (name);
+               }
                raw = rawname(name);
                if (stat(raw, &stchar) < 0){
                raw = rawname(name);
                if (stat(raw, &stchar) < 0){
+                       perror(raw);
                        printf("Can't stat %s\n", raw);
                        printf("Can't stat %s\n", raw);
-                       return (0);
+                       return (name);
                }
                }
-               if (stchar.st_mode & S_IFCHR) {
-                       if (stslash.st_dev == stblock.st_rdev) {
-                               hotroot++;
-                               raw = unrawname(name);
-                       }
+               if ((stchar.st_mode & S_IFMT) == S_IFCHR)
                        return (raw);
                        return (raw);
-               else {
+               else {
                        printf("%s is not a character device\n", raw);
                        printf("%s is not a character device\n", raw);
-                       return (0);
+                       return (name);
                }
                }
-       } else if (stblock.st_mode & S_IFCHR) {
+       } else if ((stblock.st_mode & S_IFMT) == S_IFCHR) {
                if (looped) {
                        printf("Can't make sense out of name %s\n", name);
                        return (0);
                if (looped) {
                        printf("Can't make sense out of name %s\n", name);
                        return (0);