1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)preen.c 5.4 (Berkeley) 06/01/90"; 10 #endif /* not lint */ 11 12 #include <sys/param.h> 13 #include <sys/stat.h> 14 #include <sys/wait.h> 15 #include <fstab.h> 16 #include <string.h> 17 #include <stdio.h> 18 #include <ctype.h> 19 20 char *rawname(), *unrawname(), *blockcheck(), *malloc(); 21 22 struct part { 23 struct part *next; /* forward link of partitions on disk */ 24 char *name; /* device name */ 25 char *fsname; /* mounted filesystem name */ 26 long auxdata; /* auxillary data for application */ 27 } *badlist, **badnext = &badlist; 28 29 struct disk { 30 char *name; /* disk base name */ 31 struct disk *next; /* forward link for list of disks */ 32 struct part *part; /* head of list of partitions on disk */ 33 int pid; /* If != 0, pid of proc working on */ 34 } *disks; 35 36 int nrun, ndisks; 37 char hotroot; 38 39 checkfstab(preen, maxrun, docheck, chkit) 40 int preen, maxrun; 41 int (*docheck)(), (*chkit)(); 42 { 43 register struct fstab *fsp; 44 register struct disk *dk, *nextdisk; 45 register struct part *pt; 46 int ret, pid, retcode, passno, sumstatus, status; 47 long auxdata; 48 char *name; 49 50 sumstatus = 0; 51 for (passno = 1; passno <= 2; passno++) { 52 if (setfsent() == 0) { 53 fprintf(stderr, "Can't open checklist file: %s\n", 54 _PATH_FSTAB); 55 return (8); 56 } 57 while ((fsp = getfsent()) != 0) { 58 if ((auxdata = (*docheck)(fsp)) == 0) 59 continue; 60 if (preen == 0 || passno == 1 && fsp->fs_passno == 1) { 61 if (name = blockcheck(fsp->fs_spec)) { 62 if (sumstatus = (*chkit)(name, 63 fsp->fs_file, auxdata)) 64 return (sumstatus); 65 } else if (preen) 66 return (8); 67 } else if (passno == 2 && fsp->fs_passno > 1) { 68 if ((name = blockcheck(fsp->fs_spec)) == NULL) { 69 fprintf(stderr, "BAD DISK NAME %s\n", 70 fsp->fs_spec); 71 sumstatus |= 8; 72 continue; 73 } 74 addpart(name, fsp->fs_file, auxdata); 75 } 76 } 77 if (preen == 0) 78 return (0); 79 } 80 if (preen) { 81 if (maxrun == 0) 82 maxrun = ndisks; 83 if (maxrun > ndisks) 84 maxrun = ndisks; 85 nextdisk = disks; 86 for (passno = 0; passno < maxrun; ++passno) { 87 while (ret = startdisk(nextdisk, chkit) && nrun > 0) 88 sleep(10); 89 if (ret) 90 return (ret); 91 nextdisk = nextdisk->next; 92 } 93 while ((pid = wait(&status)) != -1) { 94 for (dk = disks; dk; dk = dk->next) 95 if (dk->pid == pid) 96 break; 97 if (dk == 0) { 98 printf("Unknown pid %d\n", pid); 99 continue; 100 } 101 if (WIFEXITED(status)) 102 retcode = WEXITSTATUS(status); 103 else 104 retcode = 0; 105 if (WIFSIGNALED(status)) { 106 printf("%s (%s): EXITED WITH SIGNAL %d\n", 107 dk->part->name, dk->part->fsname, 108 WTERMSIG(status)); 109 retcode = 8; 110 } 111 if (retcode != 0) { 112 sumstatus |= retcode; 113 *badnext = dk->part; 114 badnext = &dk->part->next; 115 dk->part = dk->part->next; 116 *badnext = NULL; 117 } else 118 dk->part = dk->part->next; 119 dk->pid = 0; 120 nrun--; 121 if (dk->part == NULL) 122 ndisks--; 123 124 if (nextdisk == NULL) { 125 if (dk->part) { 126 while (ret = startdisk(dk, chkit) && 127 nrun > 0) 128 sleep(10); 129 if (ret) 130 return (ret); 131 } 132 } else if (nrun < maxrun && nrun < ndisks) { 133 for ( ;; ) { 134 if ((nextdisk = nextdisk->next) == NULL) 135 nextdisk = disks; 136 if (nextdisk->part != NULL && 137 nextdisk->pid == 0) 138 break; 139 } 140 while (ret = startdisk(nextdisk, chkit) && 141 nrun > 0) 142 sleep(10); 143 if (ret) 144 return (ret); 145 } 146 } 147 } 148 if (sumstatus) { 149 if (badlist == 0) 150 return (sumstatus); 151 fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 152 badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); 153 for (pt = badlist; pt; pt = pt->next) 154 fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, 155 pt->next ? ", " : "\n"); 156 return (sumstatus); 157 } 158 (void)endfsent(); 159 return (0); 160 } 161 162 struct disk * 163 finddisk(name) 164 char *name; 165 { 166 register struct disk *dk, **dkp; 167 register char *p; 168 int len; 169 170 for (p = name + strlen(name) - 1; p >= name; --p) 171 if (isdigit(*p)) { 172 len = p - name + 1; 173 break; 174 } 175 if (p < name) 176 len = strlen(name); 177 178 for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { 179 if (strncmp(dk->name, name, len) == 0 && 180 dk->name[len] == 0) 181 return (dk); 182 } 183 if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { 184 fprintf(stderr, "out of memory"); 185 exit (8); 186 } 187 dk = *dkp; 188 if ((dk->name = malloc((unsigned int)len + 1)) == NULL) { 189 fprintf(stderr, "out of memory"); 190 exit (8); 191 } 192 strncpy(dk->name, name, len); 193 dk->name[len] = '\0'; 194 dk->part = NULL; 195 dk->next = NULL; 196 dk->pid = 0; 197 ndisks++; 198 return (dk); 199 } 200 201 addpart(name, fsname, auxdata) 202 char *name, *fsname; 203 long auxdata; 204 { 205 struct disk *dk = finddisk(name); 206 register struct part *pt, **ppt = &dk->part; 207 208 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) 209 if (strcmp(pt->name, name) == 0) { 210 printf("%s in fstab more than once!\n", name); 211 return; 212 } 213 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { 214 fprintf(stderr, "out of memory"); 215 exit (8); 216 } 217 pt = *ppt; 218 if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL) { 219 fprintf(stderr, "out of memory"); 220 exit (8); 221 } 222 strcpy(pt->name, name); 223 if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL) { 224 fprintf(stderr, "out of memory"); 225 exit (8); 226 } 227 strcpy(pt->fsname, fsname); 228 pt->next = NULL; 229 pt->auxdata = auxdata; 230 } 231 232 startdisk(dk, checkit) 233 register struct disk *dk; 234 int (*checkit)(); 235 { 236 register struct part *pt = dk->part; 237 238 dk->pid = fork(); 239 if (dk->pid < 0) { 240 perror("fork"); 241 return (8); 242 } 243 if (dk->pid == 0) 244 exit((*checkit)(pt->name, pt->fsname, pt->auxdata)); 245 nrun++; 246 return (0); 247 } 248 249 char * 250 blockcheck(name) 251 char *name; 252 { 253 struct stat stslash, stblock, stchar; 254 char *raw; 255 int retried = 0; 256 257 hotroot = 0; 258 if (stat("/", &stslash) < 0) { 259 perror("/"); 260 printf("Can't stat root\n"); 261 return (0); 262 } 263 retry: 264 if (stat(name, &stblock) < 0) { 265 perror(name); 266 printf("Can't stat %s\n", name); 267 return (0); 268 } 269 if ((stblock.st_mode & S_IFMT) == S_IFBLK) { 270 if (stslash.st_dev == stblock.st_rdev) 271 hotroot++; 272 raw = rawname(name); 273 if (stat(raw, &stchar) < 0) { 274 perror(raw); 275 printf("Can't stat %s\n", raw); 276 return (name); 277 } 278 if ((stchar.st_mode & S_IFMT) == S_IFCHR) { 279 return (raw); 280 } else { 281 printf("%s is not a character device\n", raw); 282 return (name); 283 } 284 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { 285 name = unrawname(name); 286 retried++; 287 goto retry; 288 } 289 printf("Can't make sense out of name %s\n", name); 290 return (0); 291 } 292 293 char * 294 unrawname(name) 295 char *name; 296 { 297 char *dp; 298 struct stat stb; 299 300 if ((dp = rindex(name, '/')) == 0) 301 return (name); 302 if (stat(name, &stb) < 0) 303 return (name); 304 if ((stb.st_mode & S_IFMT) != S_IFCHR) 305 return (name); 306 if (*(dp + 1) != 'r') 307 return (name); 308 (void)strcpy(dp + 1, dp + 2); 309 return (name); 310 } 311 312 char * 313 rawname(name) 314 char *name; 315 { 316 static char rawbuf[32]; 317 char *dp; 318 319 if ((dp = rindex(name, '/')) == 0) 320 return (0); 321 *dp = 0; 322 (void)strcpy(rawbuf, name); 323 *dp = '/'; 324 (void)strcat(rawbuf, "/r"); 325 (void)strcat(rawbuf, dp + 1); 326 return (rawbuf); 327 } 328