home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / fsck / preen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-20  |  8.7 KB  |  355 lines

  1. /*
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)preen.c    5.7 (Berkeley) 3/19/91";
  36. #endif /* not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/stat.h>
  40. #include <sys/wait.h>
  41. #include <fstab.h>
  42. #include <string.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <ctype.h>
  46.  
  47. char    *rawname(), *unrawname(), *blockcheck();
  48.  
  49. struct part {
  50.     struct    part *next;        /* forward link of partitions on disk */
  51.     char    *name;            /* device name */
  52.     char    *fsname;        /* mounted filesystem name */
  53.     long    auxdata;        /* auxillary data for application */
  54. } *badlist, **badnext = &badlist;
  55.  
  56. struct disk {
  57.     char    *name;            /* disk base name */
  58.     struct    disk *next;        /* forward link for list of disks */
  59.     struct    part *part;        /* head of list of partitions on disk */
  60.     int    pid;            /* If != 0, pid of proc working on */
  61. } *disks;
  62.  
  63. int    nrun, ndisks;
  64. char    hotroot;
  65.  
  66. checkfstab(preen, maxrun, docheck, chkit)
  67.     int preen, maxrun;
  68.     int (*docheck)(), (*chkit)();
  69. {
  70.     register struct fstab *fsp;
  71.     register struct disk *dk, *nextdisk;
  72.     register struct part *pt;
  73.     int ret, pid, retcode, passno, sumstatus, status;
  74.     long auxdata;
  75.     char *name;
  76.  
  77.     sumstatus = 0;
  78.     for (passno = 1; passno <= 2; passno++) {
  79.         if (setfsent() == 0) {
  80.             fprintf(stderr, "Can't open checklist file: %s\n",
  81.                 _PATH_FSTAB);
  82.             return (8);
  83.         }
  84.         while ((fsp = getfsent()) != 0) {
  85.             if ((auxdata = (*docheck)(fsp)) == 0)
  86.                 continue;
  87.             if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
  88.                 if (name = blockcheck(fsp->fs_spec)) {
  89.                     if (sumstatus = (*chkit)(name,
  90.                         fsp->fs_file, auxdata, 0))
  91.                         return (sumstatus);
  92.                 } else if (preen)
  93.                     return (8);
  94.             } else if (passno == 2 && fsp->fs_passno > 1) {
  95.                 if ((name = blockcheck(fsp->fs_spec)) == NULL) {
  96.                     fprintf(stderr, "BAD DISK NAME %s\n",
  97.                         fsp->fs_spec);
  98.                     sumstatus |= 8;
  99.                     continue;
  100.                 }
  101.                 addpart(name, fsp->fs_file, auxdata);
  102.             }
  103.         }
  104.         if (preen == 0)
  105.             return (0);
  106.     }
  107.     if (preen) {
  108.         if (maxrun == 0)
  109.             maxrun = ndisks;
  110.         if (maxrun > ndisks)
  111.             maxrun = ndisks;
  112.         nextdisk = disks;
  113.         for (passno = 0; passno < maxrun; ++passno) {
  114.             while (ret = startdisk(nextdisk, chkit) && nrun > 0)
  115.                 sleep(10);
  116.             if (ret)
  117.                 return (ret);
  118.             nextdisk = nextdisk->next;
  119.         }
  120.         while ((pid = wait(&status)) != -1) {
  121.             for (dk = disks; dk; dk = dk->next)
  122.                 if (dk->pid == pid)
  123.                     break;
  124.             if (dk == 0) {
  125.                 printf("Unknown pid %d\n", pid);
  126.                 continue;
  127.             }
  128.             if (WIFEXITED(status))
  129.                 retcode = WEXITSTATUS(status);
  130.             else
  131.                 retcode = 0;
  132.             if (WIFSIGNALED(status)) {
  133.                 printf("%s (%s): EXITED WITH SIGNAL %d\n",
  134.                     dk->part->name, dk->part->fsname,
  135.                     WTERMSIG(status));
  136.                 retcode = 8;
  137.             }
  138.             if (retcode != 0) {
  139.                 sumstatus |= retcode;
  140.                 *badnext = dk->part;
  141.                 badnext = &dk->part->next;
  142.                 dk->part = dk->part->next;
  143.                 *badnext = NULL;
  144.             } else
  145.                 dk->part = dk->part->next;
  146.             dk->pid = 0;
  147.             nrun--;
  148.             if (dk->part == NULL)
  149.                 ndisks--;
  150.  
  151.             if (nextdisk == NULL) {
  152.                 if (dk->part) {
  153.                     while (ret = startdisk(dk, chkit) &&
  154.                         nrun > 0)
  155.                         sleep(10);
  156.                     if (ret)
  157.                         return (ret);
  158.                 }
  159.             } else if (nrun < maxrun && nrun < ndisks) {
  160.                 for ( ;; ) {
  161.                     if ((nextdisk = nextdisk->next) == NULL)
  162.                         nextdisk = disks;
  163.                     if (nextdisk->part != NULL &&
  164.                         nextdisk->pid == 0)
  165.                         break;
  166.                 }
  167.                 while (ret = startdisk(nextdisk, chkit) &&
  168.                     nrun > 0)
  169.                     sleep(10);
  170.                 if (ret)
  171.                     return (ret);
  172.             }
  173.         }
  174.     }
  175.     if (sumstatus) {
  176.         if (badlist == 0)
  177.             return (sumstatus);
  178.         fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
  179.             badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
  180.         for (pt = badlist; pt; pt = pt->next)
  181.             fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname,
  182.                 pt->next ? ", " : "\n");
  183.         return (sumstatus);
  184.     }
  185.     (void)endfsent();
  186.     return (0);
  187. }
  188.  
  189. struct disk *
  190. finddisk(name)
  191.     char *name;
  192. {
  193.     register struct disk *dk, **dkp;
  194.     register char *p;
  195.     size_t len;
  196.  
  197.     for (p = name + strlen(name) - 1; p >= name; --p)
  198.         if (isdigit(*p)) {
  199.             len = p - name + 1;
  200.             break;
  201.         }
  202.     if (p < name)
  203.         len = strlen(name);
  204.  
  205.     for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
  206.         if (strncmp(dk->name, name, len) == 0 &&
  207.             dk->name[len] == 0)
  208.             return (dk);
  209.     }
  210.     if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
  211.         fprintf(stderr, "out of memory");
  212.         exit (8);
  213.     }
  214.     dk = *dkp;
  215.     if ((dk->name = malloc(len + 1)) == NULL) {
  216.         fprintf(stderr, "out of memory");
  217.         exit (8);
  218.     }
  219.     (void)strncpy(dk->name, name, len);
  220.     dk->name[len] = '\0';
  221.     dk->part = NULL;
  222.     dk->next = NULL;
  223.     dk->pid = 0;
  224.     ndisks++;
  225.     return (dk);
  226. }
  227.  
  228. addpart(name, fsname, auxdata)
  229.     char *name, *fsname;
  230.     long auxdata;
  231. {
  232.     struct disk *dk = finddisk(name);
  233.     register struct part *pt, **ppt = &dk->part;
  234.  
  235.     for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
  236.         if (strcmp(pt->name, name) == 0) {
  237.             printf("%s in fstab more than once!\n", name);
  238.             return;
  239.         }
  240.     if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
  241.         fprintf(stderr, "out of memory");
  242.         exit (8);
  243.     }
  244.     pt = *ppt;
  245.     if ((pt->name = malloc(strlen(name) + 1)) == NULL) {
  246.         fprintf(stderr, "out of memory");
  247.         exit (8);
  248.     }
  249.     (void)strcpy(pt->name, name);
  250.     if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) {
  251.         fprintf(stderr, "out of memory");
  252.         exit (8);
  253.     }
  254.     (void)strcpy(pt->fsname, fsname);
  255.     pt->next = NULL;
  256.     pt->auxdata = auxdata;
  257. }
  258.  
  259. startdisk(dk, checkit)
  260.     register struct disk *dk;
  261.     int (*checkit)();
  262. {
  263.     register struct part *pt = dk->part;
  264.  
  265.     dk->pid = fork();
  266.     if (dk->pid < 0) {
  267.         perror("fork");
  268.         return (8);
  269.     }
  270.     if (dk->pid == 0)
  271.         exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1));
  272.     nrun++;
  273.     return (0);
  274. }
  275.  
  276. char *
  277. blockcheck(name)
  278.     char *name;
  279. {
  280.     struct stat stslash, stblock, stchar;
  281.     char *raw;
  282.     int retried = 0;
  283.  
  284.     hotroot = 0;
  285.     if (stat("/", &stslash) < 0) {
  286.         perror("/");
  287.         printf("Can't stat root\n");
  288.         return (0);
  289.     }
  290. retry:
  291.     if (stat(name, &stblock) < 0) {
  292.         perror(name);
  293.         printf("Can't stat %s\n", name);
  294.         return (0);
  295.     }
  296.     if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
  297.         if (stslash.st_dev == stblock.st_rdev)
  298.             hotroot++;
  299.         raw = rawname(name);
  300.         if (stat(raw, &stchar) < 0) {
  301.             perror(raw);
  302.             printf("Can't stat %s\n", raw);
  303.             return (name);
  304.         }
  305.         if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
  306.             return (raw);
  307.         } else {
  308.             printf("%s is not a character device\n", raw);
  309.             return (name);
  310.         }
  311.     } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
  312.         name = unrawname(name);
  313.         retried++;
  314.         goto retry;
  315.     }
  316.     printf("Can't make sense out of name %s\n", name);
  317.     return (0);
  318. }
  319.  
  320. char *
  321. unrawname(name)
  322.     char *name;
  323. {
  324.     char *dp;
  325.     struct stat stb;
  326.  
  327.     if ((dp = rindex(name, '/')) == 0)
  328.         return (name);
  329.     if (stat(name, &stb) < 0)
  330.         return (name);
  331.     if ((stb.st_mode & S_IFMT) != S_IFCHR)
  332.         return (name);
  333.     if (dp[1] != 'r')
  334.         return (name);
  335.     (void)strcpy(&dp[1], &dp[2]);
  336.     return (name);
  337. }
  338.  
  339. char *
  340. rawname(name)
  341.     char *name;
  342. {
  343.     static char rawbuf[32];
  344.     char *dp;
  345.  
  346.     if ((dp = rindex(name, '/')) == 0)
  347.         return (0);
  348.     *dp = 0;
  349.     (void)strcpy(rawbuf, name);
  350.     *dp = '/';
  351.     (void)strcat(rawbuf, "/r");
  352.     (void)strcat(rawbuf, &dp[1]);
  353.     return (rawbuf);
  354. }
  355.