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