preen.c revision 19212
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1990, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 351590Srgrimesstatic const char sccsid[] = "@(#)preen.c 8.1 (Berkeley) 6/5/93"; 361590Srgrimes#endif /* not lint */ 371590Srgrimes 381590Srgrimes#include <sys/param.h> 391590Srgrimes#include <sys/stat.h> 401590Srgrimes#include <sys/wait.h> 411590Srgrimes#include <ufs/ufs/dinode.h> 421590Srgrimes#include <fstab.h> 431590Srgrimes#include <string.h> 441590Srgrimes#include <stdio.h> 451590Srgrimes#include <unistd.h> 461590Srgrimes#include <stdlib.h> 471590Srgrimes#include <ctype.h> 481590Srgrimes#include <fstab.h> 491590Srgrimes#include "fsck.h" 501590Srgrimes 511590Srgrimesstruct part { 521590Srgrimes struct part *next; /* forward link of partitions on disk */ 531590Srgrimes char *name; /* device name */ 541590Srgrimes char *fsname; /* mounted filesystem name */ 551590Srgrimes long auxdata; /* auxillary data for application */ 561590Srgrimes} *badlist, **badnext = &badlist; 571590Srgrimes 581590Srgrimesstruct disk { 591590Srgrimes char *name; /* disk base name */ 601590Srgrimes struct disk *next; /* forward link for list of disks */ 611590Srgrimes struct part *part; /* head of list of partitions on disk */ 621590Srgrimes int pid; /* If != 0, pid of proc working on */ 631590Srgrimes} *disks; 641590Srgrimes 651590Srgrimesstatic void addpart __P((char *name, char *fsname, long auxdata)); 6624360Simpstatic int startdisk __P((struct disk *dk, int (*checkit)())); 671590Srgrimesstatic struct disk *finddisk __P((char *name)); 681590Srgrimesstatic char *unrawname __P((char *name)); 691590Srgrimesstatic char *rawname __P((char *name)); 701590Srgrimes 711590Srgrimesint nrun, ndisks; 721590Srgrimeschar hotroot; 731590Srgrimes 741590Srgrimesint 751590Srgrimescheckfstab(preen, maxrun, docheck, chkit) 761590Srgrimes int preen, maxrun; 771590Srgrimes int (*docheck)(), (*chkit)(); 781590Srgrimes{ 791590Srgrimes register struct fstab *fsp; 801590Srgrimes register struct disk *dk, *nextdisk; 811590Srgrimes register struct part *pt; 821590Srgrimes int ret, pid, retcode, passno, sumstatus, status; 831590Srgrimes long auxdata; 841590Srgrimes char *name; 851590Srgrimes 861590Srgrimes sumstatus = 0; 871590Srgrimes for (passno = 1; passno <= 2; passno++) { 881590Srgrimes if (setfsent() == 0) { 891590Srgrimes fprintf(stderr, "Can't open checklist file: %s\n", 901590Srgrimes _PATH_FSTAB); 911590Srgrimes return (8); 921590Srgrimes } 931590Srgrimes while ((fsp = getfsent()) != 0) { 941590Srgrimes if ((auxdata = (*docheck)(fsp)) == 0) 951590Srgrimes continue; 961590Srgrimes if (!preen || (passno == 1 && fsp->fs_passno == 1)) { 971590Srgrimes name = blockcheck(fsp->fs_spec); 981590Srgrimes if (name) { 991590Srgrimes sumstatus = (*chkit)(name, 1001590Srgrimes fsp->fs_file, auxdata, 0); 1011590Srgrimes if (sumstatus) 1021590Srgrimes return (sumstatus); 1031590Srgrimes } else if (preen) 1041590Srgrimes return (8); 1051590Srgrimes } else if (passno == 2 && fsp->fs_passno > 1) { 1061590Srgrimes if ((name = blockcheck(fsp->fs_spec)) == NULL) { 1071590Srgrimes fprintf(stderr, "BAD DISK NAME %s\n", 1081590Srgrimes fsp->fs_spec); 1091590Srgrimes sumstatus |= 8; 1101590Srgrimes continue; 1111590Srgrimes } 1121590Srgrimes addpart(name, fsp->fs_file, auxdata); 1131590Srgrimes } 1148874Srgrimes } 1151590Srgrimes if (preen == 0) 1161590Srgrimes return (0); 1171590Srgrimes } 1181590Srgrimes if (preen) { 1191590Srgrimes if (maxrun == 0) 1201590Srgrimes maxrun = ndisks; 1211590Srgrimes if (maxrun > ndisks) 1221590Srgrimes maxrun = ndisks; 1231590Srgrimes nextdisk = disks; 1241590Srgrimes for (passno = 0; passno < maxrun; ++passno) { 1251590Srgrimes while ((ret = startdisk(nextdisk, chkit)) != 0 && 1261590Srgrimes nrun > 0) 1271590Srgrimes sleep(10); 1281590Srgrimes if (ret) 1291590Srgrimes return (ret); 1301590Srgrimes nextdisk = nextdisk->next; 1311590Srgrimes } 1321590Srgrimes while ((pid = wait(&status)) != -1) { 1331590Srgrimes for (dk = disks; dk; dk = dk->next) 1341590Srgrimes if (dk->pid == pid) 1351590Srgrimes break; 1361590Srgrimes if (dk == 0) { 1371590Srgrimes printf("Unknown pid %d\n", pid); 1381590Srgrimes continue; 1391590Srgrimes } 1401590Srgrimes if (WIFEXITED(status)) 1411590Srgrimes retcode = WEXITSTATUS(status); 1421590Srgrimes else 1431590Srgrimes retcode = 0; 1441590Srgrimes if (WIFSIGNALED(status)) { 1451590Srgrimes printf("%s (%s): EXITED WITH SIGNAL %d\n", 1461590Srgrimes dk->part->name, dk->part->fsname, 1471590Srgrimes WTERMSIG(status)); 1481590Srgrimes retcode = 8; 1491590Srgrimes } 1501590Srgrimes if (retcode != 0) { 1511590Srgrimes sumstatus |= retcode; 1521590Srgrimes *badnext = dk->part; 1531590Srgrimes badnext = &dk->part->next; 1541590Srgrimes dk->part = dk->part->next; 1551590Srgrimes *badnext = NULL; 1561590Srgrimes } else 1571590Srgrimes dk->part = dk->part->next; 1581590Srgrimes dk->pid = 0; 1591590Srgrimes nrun--; 1601590Srgrimes if (dk->part == NULL) 1611590Srgrimes ndisks--; 1621590Srgrimes 1631590Srgrimes if (nextdisk == NULL) { 1641590Srgrimes if (dk->part) { 1651590Srgrimes while ((ret = startdisk(dk, chkit)) != 0 1661590Srgrimes && nrun > 0) 1671590Srgrimes sleep(10); 1681590Srgrimes if (ret) 1691590Srgrimes return (ret); 1701590Srgrimes } 1711590Srgrimes } else if (nrun < maxrun && nrun < ndisks) { 1721590Srgrimes for ( ;; ) { 1731590Srgrimes if ((nextdisk = nextdisk->next) == NULL) 1741590Srgrimes nextdisk = disks; 1751590Srgrimes if (nextdisk->part != NULL && 1761590Srgrimes nextdisk->pid == 0) 1771590Srgrimes break; 1781590Srgrimes } 1791590Srgrimes while ((ret = startdisk(nextdisk, chkit)) != 0 1801590Srgrimes && nrun > 0) 1811590Srgrimes sleep(10); 1821590Srgrimes if (ret) 1831590Srgrimes return (ret); 1841590Srgrimes } 1851590Srgrimes } 1861590Srgrimes } 1871590Srgrimes if (sumstatus) { 1881590Srgrimes if (badlist == 0) 1891590Srgrimes return (sumstatus); 1901590Srgrimes fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", 1911590Srgrimes badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); 1921590Srgrimes for (pt = badlist; pt; pt = pt->next) 1931590Srgrimes fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, 1941590Srgrimes pt->next ? ", " : "\n"); 1951590Srgrimes return (sumstatus); 1961590Srgrimes } 1971590Srgrimes (void)endfsent(); 1981590Srgrimes return (0); 1991590Srgrimes} 2001590Srgrimes 2011590Srgrimesstruct disk * 2021590Srgrimesfinddisk(name) 2031590Srgrimes char *name; 2041590Srgrimes{ 2051590Srgrimes register struct disk *dk, **dkp; 2061590Srgrimes register char *p; 2071590Srgrimes size_t len = 0; 2081590Srgrimes 2091590Srgrimes for (p = name + strlen(name) - 1; p >= name; --p) 21040301Sdes if (isdigit(*p)) { 2111590Srgrimes len = p - name + 1; 2121590Srgrimes break; 2131590Srgrimes } 2141590Srgrimes if (p < name) 2151590Srgrimes len = strlen(name); 2161590Srgrimes 2171590Srgrimes for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { 2181590Srgrimes if (strncmp(dk->name, name, len) == 0 && 2191590Srgrimes dk->name[len] == 0) 2201590Srgrimes return (dk); 2211590Srgrimes } 2221590Srgrimes if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { 2231590Srgrimes fprintf(stderr, "out of memory"); 2241590Srgrimes exit (8); 2251590Srgrimes } 2261590Srgrimes dk = *dkp; 2271590Srgrimes if ((dk->name = malloc(len + 1)) == NULL) { 2281590Srgrimes fprintf(stderr, "out of memory"); 2291590Srgrimes exit (8); 2301590Srgrimes } 2311590Srgrimes (void)strncpy(dk->name, name, len); 2321590Srgrimes dk->name[len] = '\0'; 2331590Srgrimes dk->part = NULL; 2341590Srgrimes dk->next = NULL; 235 dk->pid = 0; 236 ndisks++; 237 return (dk); 238} 239 240void 241addpart(name, fsname, auxdata) 242 char *name, *fsname; 243 long auxdata; 244{ 245 struct disk *dk = finddisk(name); 246 register struct part *pt, **ppt = &dk->part; 247 248 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) 249 if (strcmp(pt->name, name) == 0) { 250 printf("%s in fstab more than once!\n", name); 251 return; 252 } 253 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { 254 fprintf(stderr, "out of memory"); 255 exit (8); 256 } 257 pt = *ppt; 258 if ((pt->name = malloc(strlen(name) + 1)) == NULL) { 259 fprintf(stderr, "out of memory"); 260 exit (8); 261 } 262 (void)strcpy(pt->name, name); 263 if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) { 264 fprintf(stderr, "out of memory"); 265 exit (8); 266 } 267 (void)strcpy(pt->fsname, fsname); 268 pt->next = NULL; 269 pt->auxdata = auxdata; 270} 271 272int 273startdisk(dk, checkit) 274 register struct disk *dk; 275 int (*checkit)(); 276{ 277 register struct part *pt = dk->part; 278 279 dk->pid = fork(); 280 if (dk->pid < 0) { 281 perror("fork"); 282 return (8); 283 } 284 if (dk->pid == 0) 285 exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); 286 nrun++; 287 return (0); 288} 289 290char * 291blockcheck(name) 292 char *name; 293{ 294 struct stat stslash, stblock, stchar; 295 char *raw; 296 struct fstab *fsinfo; 297 int retried = 0, l; 298 299 hotroot = 0; 300 if (stat("/", &stslash) < 0) { 301 perror("/"); 302 printf("Can't stat root\n"); 303 return (0); 304 } 305retry: 306 if (stat(name, &stblock) < 0) { 307 perror(name); 308 printf("Can't stat %s\n", name); 309 return (0); 310 } 311 if ((stblock.st_mode & S_IFMT) == S_IFBLK) { 312 if (stslash.st_dev == stblock.st_rdev) 313 hotroot++; 314 raw = rawname(name); 315 if (stat(raw, &stchar) < 0) { 316 perror(raw); 317 printf("Can't stat %s\n", raw); 318 return (name); 319 } 320 if ((stchar.st_mode & S_IFMT) == S_IFCHR) { 321 return (raw); 322 } else { 323 printf("%s is not a character device\n", raw); 324 return (name); 325 } 326 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { 327 name = unrawname(name); 328 retried++; 329 goto retry; 330 } else if ((stblock.st_mode & S_IFMT) == S_IFDIR && !retried) { 331 l = strlen(name) - 1; 332 if (l > 0 && name[l] == '/') 333 /* remove trailing slash */ 334 name[l] = '\0'; 335 if(!(fsinfo=getfsfile(name))) { 336 printf("Can't resolve %s to character special device", 337 name); 338 return (0); 339 } 340 name = fsinfo->fs_spec; 341 retried++; 342 goto retry; 343 } 344 printf("Warning: Can't find blockdevice corresponding to name %s\n", 345 name); 346 return (name); 347} 348 349char * 350unrawname(name) 351 char *name; 352{ 353 char *dp; 354 struct stat stb; 355 356 if ((dp = rindex(name, '/')) == 0) 357 return (name); 358 if (stat(name, &stb) < 0) 359 return (name); 360 if ((stb.st_mode & S_IFMT) != S_IFCHR) 361 return (name); 362 if (dp[1] != 'r') 363 return (name); 364 (void)strcpy(&dp[1], &dp[2]); 365 return (name); 366} 367 368char * 369rawname(name) 370 char *name; 371{ 372 static char rawbuf[32]; 373 char *dp; 374 375 if ((dp = rindex(name, '/')) == 0) 376 return (0); 377 *dp = 0; 378 (void)strcpy(rawbuf, name); 379 *dp = '/'; 380 (void)strcat(rawbuf, "/r"); 381 (void)strcat(rawbuf, &dp[1]); 382 return (rawbuf); 383} 384