18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1980, 1986, 1993 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 68fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 78fae3551SRodney W. Grimes * are met: 88fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 98fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 108fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 128fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 138fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 148fae3551SRodney W. Grimes * must display the following acknowledgement: 158fae3551SRodney W. Grimes * This product includes software developed by the University of 168fae3551SRodney W. Grimes * California, Berkeley and its contributors. 178fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 188fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 198fae3551SRodney W. Grimes * without specific prior written permission. 208fae3551SRodney W. Grimes * 218fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 228fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 238fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 248fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 258fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 268fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 278fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 288fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 298fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 308fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 318fae3551SRodney W. Grimes * SUCH DAMAGE. 328fae3551SRodney W. Grimes */ 338fae3551SRodney W. Grimes 348fae3551SRodney W. Grimes #ifndef lint 358fae3551SRodney W. Grimes static char sccsid[] = "@(#)utilities.c 8.1 (Berkeley) 6/5/93"; 368fae3551SRodney W. Grimes #endif /* not lint */ 378fae3551SRodney W. Grimes 388fae3551SRodney W. Grimes #include <sys/param.h> 398fae3551SRodney W. Grimes #include <sys/time.h> 408fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h> 418fae3551SRodney W. Grimes #include <ufs/ufs/dir.h> 428fae3551SRodney W. Grimes #include <ufs/ffs/fs.h> 438fae3551SRodney W. Grimes #include <stdio.h> 448fae3551SRodney W. Grimes #include <stdlib.h> 458fae3551SRodney W. Grimes #include <string.h> 468fae3551SRodney W. Grimes #include <ctype.h> 478fae3551SRodney W. Grimes #include "fsck.h" 488fae3551SRodney W. Grimes 498fae3551SRodney W. Grimes long diskreads, totalreads; /* Disk cache statistics */ 508fae3551SRodney W. Grimes 518fae3551SRodney W. Grimes ftypeok(dp) 528fae3551SRodney W. Grimes struct dinode *dp; 538fae3551SRodney W. Grimes { 548fae3551SRodney W. Grimes switch (dp->di_mode & IFMT) { 558fae3551SRodney W. Grimes 568fae3551SRodney W. Grimes case IFDIR: 578fae3551SRodney W. Grimes case IFREG: 588fae3551SRodney W. Grimes case IFBLK: 598fae3551SRodney W. Grimes case IFCHR: 608fae3551SRodney W. Grimes case IFLNK: 618fae3551SRodney W. Grimes case IFSOCK: 628fae3551SRodney W. Grimes case IFIFO: 638fae3551SRodney W. Grimes return (1); 648fae3551SRodney W. Grimes 658fae3551SRodney W. Grimes default: 668fae3551SRodney W. Grimes if (debug) 678fae3551SRodney W. Grimes printf("bad file type 0%o\n", dp->di_mode); 688fae3551SRodney W. Grimes return (0); 698fae3551SRodney W. Grimes } 708fae3551SRodney W. Grimes } 718fae3551SRodney W. Grimes 728fae3551SRodney W. Grimes reply(question) 738fae3551SRodney W. Grimes char *question; 748fae3551SRodney W. Grimes { 758fae3551SRodney W. Grimes int persevere; 768fae3551SRodney W. Grimes char c; 778fae3551SRodney W. Grimes 788fae3551SRodney W. Grimes if (preen) 798fae3551SRodney W. Grimes pfatal("INTERNAL ERROR: GOT TO reply()"); 808fae3551SRodney W. Grimes persevere = !strcmp(question, "CONTINUE"); 818fae3551SRodney W. Grimes printf("\n"); 828fae3551SRodney W. Grimes if (!persevere && (nflag || fswritefd < 0)) { 838fae3551SRodney W. Grimes printf("%s? no\n\n", question); 848fae3551SRodney W. Grimes return (0); 858fae3551SRodney W. Grimes } 868fae3551SRodney W. Grimes if (yflag || (persevere && nflag)) { 878fae3551SRodney W. Grimes printf("%s? yes\n\n", question); 888fae3551SRodney W. Grimes return (1); 898fae3551SRodney W. Grimes } 908fae3551SRodney W. Grimes do { 918fae3551SRodney W. Grimes printf("%s? [yn] ", question); 928fae3551SRodney W. Grimes (void) fflush(stdout); 938fae3551SRodney W. Grimes c = getc(stdin); 948fae3551SRodney W. Grimes while (c != '\n' && getc(stdin) != '\n') 958fae3551SRodney W. Grimes if (feof(stdin)) 968fae3551SRodney W. Grimes return (0); 978fae3551SRodney W. Grimes } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 988fae3551SRodney W. Grimes printf("\n"); 998fae3551SRodney W. Grimes if (c == 'y' || c == 'Y') 1008fae3551SRodney W. Grimes return (1); 1018fae3551SRodney W. Grimes return (0); 1028fae3551SRodney W. Grimes } 1038fae3551SRodney W. Grimes 1048fae3551SRodney W. Grimes /* 1058fae3551SRodney W. Grimes * Malloc buffers and set up cache. 1068fae3551SRodney W. Grimes */ 1078fae3551SRodney W. Grimes bufinit() 1088fae3551SRodney W. Grimes { 1098fae3551SRodney W. Grimes register struct bufarea *bp; 1108fae3551SRodney W. Grimes long bufcnt, i; 1118fae3551SRodney W. Grimes char *bufp; 1128fae3551SRodney W. Grimes 1138fae3551SRodney W. Grimes pbp = pdirbp = (struct bufarea *)0; 1148fae3551SRodney W. Grimes bufp = malloc((unsigned int)sblock.fs_bsize); 1158fae3551SRodney W. Grimes if (bufp == 0) 1168fae3551SRodney W. Grimes errexit("cannot allocate buffer pool\n"); 1178fae3551SRodney W. Grimes cgblk.b_un.b_buf = bufp; 1188fae3551SRodney W. Grimes initbarea(&cgblk); 1198fae3551SRodney W. Grimes bufhead.b_next = bufhead.b_prev = &bufhead; 1208fae3551SRodney W. Grimes bufcnt = MAXBUFSPACE / sblock.fs_bsize; 1218fae3551SRodney W. Grimes if (bufcnt < MINBUFS) 1228fae3551SRodney W. Grimes bufcnt = MINBUFS; 1238fae3551SRodney W. Grimes for (i = 0; i < bufcnt; i++) { 1248fae3551SRodney W. Grimes bp = (struct bufarea *)malloc(sizeof(struct bufarea)); 1258fae3551SRodney W. Grimes bufp = malloc((unsigned int)sblock.fs_bsize); 1268fae3551SRodney W. Grimes if (bp == NULL || bufp == NULL) { 1278fae3551SRodney W. Grimes if (i >= MINBUFS) 1288fae3551SRodney W. Grimes break; 1298fae3551SRodney W. Grimes errexit("cannot allocate buffer pool\n"); 1308fae3551SRodney W. Grimes } 1318fae3551SRodney W. Grimes bp->b_un.b_buf = bufp; 1328fae3551SRodney W. Grimes bp->b_prev = &bufhead; 1338fae3551SRodney W. Grimes bp->b_next = bufhead.b_next; 1348fae3551SRodney W. Grimes bufhead.b_next->b_prev = bp; 1358fae3551SRodney W. Grimes bufhead.b_next = bp; 1368fae3551SRodney W. Grimes initbarea(bp); 1378fae3551SRodney W. Grimes } 1388fae3551SRodney W. Grimes bufhead.b_size = i; /* save number of buffers */ 1398fae3551SRodney W. Grimes } 1408fae3551SRodney W. Grimes 1418fae3551SRodney W. Grimes /* 1428fae3551SRodney W. Grimes * Manage a cache of directory blocks. 1438fae3551SRodney W. Grimes */ 1448fae3551SRodney W. Grimes struct bufarea * 1458fae3551SRodney W. Grimes getdatablk(blkno, size) 1468fae3551SRodney W. Grimes daddr_t blkno; 1478fae3551SRodney W. Grimes long size; 1488fae3551SRodney W. Grimes { 1498fae3551SRodney W. Grimes register struct bufarea *bp; 1508fae3551SRodney W. Grimes 1518fae3551SRodney W. Grimes for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 1528fae3551SRodney W. Grimes if (bp->b_bno == fsbtodb(&sblock, blkno)) 1538fae3551SRodney W. Grimes goto foundit; 1548fae3551SRodney W. Grimes for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 1558fae3551SRodney W. Grimes if ((bp->b_flags & B_INUSE) == 0) 1568fae3551SRodney W. Grimes break; 1578fae3551SRodney W. Grimes if (bp == &bufhead) 1588fae3551SRodney W. Grimes errexit("deadlocked buffer pool\n"); 1598fae3551SRodney W. Grimes getblk(bp, blkno, size); 1608fae3551SRodney W. Grimes /* fall through */ 1618fae3551SRodney W. Grimes foundit: 1628fae3551SRodney W. Grimes totalreads++; 1638fae3551SRodney W. Grimes bp->b_prev->b_next = bp->b_next; 1648fae3551SRodney W. Grimes bp->b_next->b_prev = bp->b_prev; 1658fae3551SRodney W. Grimes bp->b_prev = &bufhead; 1668fae3551SRodney W. Grimes bp->b_next = bufhead.b_next; 1678fae3551SRodney W. Grimes bufhead.b_next->b_prev = bp; 1688fae3551SRodney W. Grimes bufhead.b_next = bp; 1698fae3551SRodney W. Grimes bp->b_flags |= B_INUSE; 1708fae3551SRodney W. Grimes return (bp); 1718fae3551SRodney W. Grimes } 1728fae3551SRodney W. Grimes 1738fae3551SRodney W. Grimes void 1748fae3551SRodney W. Grimes getblk(bp, blk, size) 1758fae3551SRodney W. Grimes register struct bufarea *bp; 1768fae3551SRodney W. Grimes daddr_t blk; 1778fae3551SRodney W. Grimes long size; 1788fae3551SRodney W. Grimes { 1798fae3551SRodney W. Grimes daddr_t dblk; 1808fae3551SRodney W. Grimes 1818fae3551SRodney W. Grimes dblk = fsbtodb(&sblock, blk); 1828fae3551SRodney W. Grimes if (bp->b_bno != dblk) { 1838fae3551SRodney W. Grimes flush(fswritefd, bp); 1848fae3551SRodney W. Grimes diskreads++; 1858fae3551SRodney W. Grimes bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 1868fae3551SRodney W. Grimes bp->b_bno = dblk; 1878fae3551SRodney W. Grimes bp->b_size = size; 1888fae3551SRodney W. Grimes } 1898fae3551SRodney W. Grimes } 1908fae3551SRodney W. Grimes 1918fae3551SRodney W. Grimes flush(fd, bp) 1928fae3551SRodney W. Grimes int fd; 1938fae3551SRodney W. Grimes register struct bufarea *bp; 1948fae3551SRodney W. Grimes { 1958fae3551SRodney W. Grimes register int i, j; 1968fae3551SRodney W. Grimes 1978fae3551SRodney W. Grimes if (!bp->b_dirty) 1988fae3551SRodney W. Grimes return; 1998fae3551SRodney W. Grimes if (bp->b_errs != 0) 2008fae3551SRodney W. Grimes pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", 2018fae3551SRodney W. Grimes (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 2028fae3551SRodney W. Grimes bp->b_bno); 2038fae3551SRodney W. Grimes bp->b_dirty = 0; 2048fae3551SRodney W. Grimes bp->b_errs = 0; 2058fae3551SRodney W. Grimes bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 2068fae3551SRodney W. Grimes if (bp != &sblk) 2078fae3551SRodney W. Grimes return; 2088fae3551SRodney W. Grimes for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 2098fae3551SRodney W. Grimes bwrite(fswritefd, (char *)sblock.fs_csp[j], 2108fae3551SRodney W. Grimes fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 2118fae3551SRodney W. Grimes sblock.fs_cssize - i < sblock.fs_bsize ? 2128fae3551SRodney W. Grimes sblock.fs_cssize - i : sblock.fs_bsize); 2138fae3551SRodney W. Grimes } 2148fae3551SRodney W. Grimes } 2158fae3551SRodney W. Grimes 2168fae3551SRodney W. Grimes rwerror(mesg, blk) 2178fae3551SRodney W. Grimes char *mesg; 2188fae3551SRodney W. Grimes daddr_t blk; 2198fae3551SRodney W. Grimes { 2208fae3551SRodney W. Grimes 2218fae3551SRodney W. Grimes if (preen == 0) 2228fae3551SRodney W. Grimes printf("\n"); 2238fae3551SRodney W. Grimes pfatal("CANNOT %s: BLK %ld", mesg, blk); 2248fae3551SRodney W. Grimes if (reply("CONTINUE") == 0) 2258fae3551SRodney W. Grimes errexit("Program terminated\n"); 2268fae3551SRodney W. Grimes } 2278fae3551SRodney W. Grimes 2288fae3551SRodney W. Grimes ckfini() 2298fae3551SRodney W. Grimes { 2308fae3551SRodney W. Grimes register struct bufarea *bp, *nbp; 2318fae3551SRodney W. Grimes int cnt = 0; 2328fae3551SRodney W. Grimes 2338fae3551SRodney W. Grimes if (fswritefd < 0) { 2348fae3551SRodney W. Grimes (void)close(fsreadfd); 2358fae3551SRodney W. Grimes return; 2368fae3551SRodney W. Grimes } 2378fae3551SRodney W. Grimes flush(fswritefd, &sblk); 2388fae3551SRodney W. Grimes if (havesb && sblk.b_bno != SBOFF / dev_bsize && 2398fae3551SRodney W. Grimes !preen && reply("UPDATE STANDARD SUPERBLOCK")) { 2408fae3551SRodney W. Grimes sblk.b_bno = SBOFF / dev_bsize; 2418fae3551SRodney W. Grimes sbdirty(); 2428fae3551SRodney W. Grimes flush(fswritefd, &sblk); 2438fae3551SRodney W. Grimes } 2448fae3551SRodney W. Grimes flush(fswritefd, &cgblk); 2458fae3551SRodney W. Grimes free(cgblk.b_un.b_buf); 2468fae3551SRodney W. Grimes for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 2478fae3551SRodney W. Grimes cnt++; 2488fae3551SRodney W. Grimes flush(fswritefd, bp); 2498fae3551SRodney W. Grimes nbp = bp->b_prev; 2508fae3551SRodney W. Grimes free(bp->b_un.b_buf); 2518fae3551SRodney W. Grimes free((char *)bp); 2528fae3551SRodney W. Grimes } 2538fae3551SRodney W. Grimes if (bufhead.b_size != cnt) 2548fae3551SRodney W. Grimes errexit("Panic: lost %d buffers\n", bufhead.b_size - cnt); 2558fae3551SRodney W. Grimes pbp = pdirbp = (struct bufarea *)0; 2568fae3551SRodney W. Grimes if (debug) 2578fae3551SRodney W. Grimes printf("cache missed %ld of %ld (%d%%)\n", diskreads, 2588fae3551SRodney W. Grimes totalreads, (int)(diskreads * 100 / totalreads)); 2598fae3551SRodney W. Grimes (void)close(fsreadfd); 2608fae3551SRodney W. Grimes (void)close(fswritefd); 2618fae3551SRodney W. Grimes } 2628fae3551SRodney W. Grimes 2638fae3551SRodney W. Grimes bread(fd, buf, blk, size) 2648fae3551SRodney W. Grimes int fd; 2658fae3551SRodney W. Grimes char *buf; 2668fae3551SRodney W. Grimes daddr_t blk; 2678fae3551SRodney W. Grimes long size; 2688fae3551SRodney W. Grimes { 2698fae3551SRodney W. Grimes char *cp; 2708fae3551SRodney W. Grimes int i, errs; 2718fae3551SRodney W. Grimes off_t offset; 2728fae3551SRodney W. Grimes 2738fae3551SRodney W. Grimes offset = blk; 2748fae3551SRodney W. Grimes offset *= dev_bsize; 2758fae3551SRodney W. Grimes if (lseek(fd, offset, 0) < 0) 2768fae3551SRodney W. Grimes rwerror("SEEK", blk); 2778fae3551SRodney W. Grimes else if (read(fd, buf, (int)size) == size) 2788fae3551SRodney W. Grimes return (0); 2798fae3551SRodney W. Grimes rwerror("READ", blk); 2808fae3551SRodney W. Grimes if (lseek(fd, offset, 0) < 0) 2818fae3551SRodney W. Grimes rwerror("SEEK", blk); 2828fae3551SRodney W. Grimes errs = 0; 2838fae3551SRodney W. Grimes bzero(buf, (size_t)size); 2848fae3551SRodney W. Grimes printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 2858fae3551SRodney W. Grimes for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 2868fae3551SRodney W. Grimes if (read(fd, cp, (int)secsize) != secsize) { 2878fae3551SRodney W. Grimes (void)lseek(fd, offset + i + secsize, 0); 2888fae3551SRodney W. Grimes if (secsize != dev_bsize && dev_bsize != 1) 2898fae3551SRodney W. Grimes printf(" %ld (%ld),", 2908fae3551SRodney W. Grimes (blk * dev_bsize + i) / secsize, 2918fae3551SRodney W. Grimes blk + i / dev_bsize); 2928fae3551SRodney W. Grimes else 2938fae3551SRodney W. Grimes printf(" %ld,", blk + i / dev_bsize); 2948fae3551SRodney W. Grimes errs++; 2958fae3551SRodney W. Grimes } 2968fae3551SRodney W. Grimes } 2978fae3551SRodney W. Grimes printf("\n"); 2988fae3551SRodney W. Grimes return (errs); 2998fae3551SRodney W. Grimes } 3008fae3551SRodney W. Grimes 3018fae3551SRodney W. Grimes bwrite(fd, buf, blk, size) 3028fae3551SRodney W. Grimes int fd; 3038fae3551SRodney W. Grimes char *buf; 3048fae3551SRodney W. Grimes daddr_t blk; 3058fae3551SRodney W. Grimes long size; 3068fae3551SRodney W. Grimes { 3078fae3551SRodney W. Grimes int i; 3088fae3551SRodney W. Grimes char *cp; 3098fae3551SRodney W. Grimes off_t offset; 3108fae3551SRodney W. Grimes 3118fae3551SRodney W. Grimes if (fd < 0) 3128fae3551SRodney W. Grimes return; 3138fae3551SRodney W. Grimes offset = blk; 3148fae3551SRodney W. Grimes offset *= dev_bsize; 3158fae3551SRodney W. Grimes if (lseek(fd, offset, 0) < 0) 3168fae3551SRodney W. Grimes rwerror("SEEK", blk); 3178fae3551SRodney W. Grimes else if (write(fd, buf, (int)size) == size) { 3188fae3551SRodney W. Grimes fsmodified = 1; 3198fae3551SRodney W. Grimes return; 3208fae3551SRodney W. Grimes } 3218fae3551SRodney W. Grimes rwerror("WRITE", blk); 3228fae3551SRodney W. Grimes if (lseek(fd, offset, 0) < 0) 3238fae3551SRodney W. Grimes rwerror("SEEK", blk); 3248fae3551SRodney W. Grimes printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 3258fae3551SRodney W. Grimes for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 3268fae3551SRodney W. Grimes if (write(fd, cp, (int)dev_bsize) != dev_bsize) { 3278fae3551SRodney W. Grimes (void)lseek(fd, offset + i + dev_bsize, 0); 3288fae3551SRodney W. Grimes printf(" %ld,", blk + i / dev_bsize); 3298fae3551SRodney W. Grimes } 3308fae3551SRodney W. Grimes printf("\n"); 3318fae3551SRodney W. Grimes return; 3328fae3551SRodney W. Grimes } 3338fae3551SRodney W. Grimes 3348fae3551SRodney W. Grimes /* 3358fae3551SRodney W. Grimes * allocate a data block with the specified number of fragments 3368fae3551SRodney W. Grimes */ 3378fae3551SRodney W. Grimes allocblk(frags) 3388fae3551SRodney W. Grimes long frags; 3398fae3551SRodney W. Grimes { 3408fae3551SRodney W. Grimes register int i, j, k; 3418fae3551SRodney W. Grimes 3428fae3551SRodney W. Grimes if (frags <= 0 || frags > sblock.fs_frag) 3438fae3551SRodney W. Grimes return (0); 3448fae3551SRodney W. Grimes for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { 3458fae3551SRodney W. Grimes for (j = 0; j <= sblock.fs_frag - frags; j++) { 3468fae3551SRodney W. Grimes if (testbmap(i + j)) 3478fae3551SRodney W. Grimes continue; 3488fae3551SRodney W. Grimes for (k = 1; k < frags; k++) 3498fae3551SRodney W. Grimes if (testbmap(i + j + k)) 3508fae3551SRodney W. Grimes break; 3518fae3551SRodney W. Grimes if (k < frags) { 3528fae3551SRodney W. Grimes j += k; 3538fae3551SRodney W. Grimes continue; 3548fae3551SRodney W. Grimes } 3558fae3551SRodney W. Grimes for (k = 0; k < frags; k++) 3568fae3551SRodney W. Grimes setbmap(i + j + k); 3578fae3551SRodney W. Grimes n_blks += frags; 3588fae3551SRodney W. Grimes return (i + j); 3598fae3551SRodney W. Grimes } 3608fae3551SRodney W. Grimes } 3618fae3551SRodney W. Grimes return (0); 3628fae3551SRodney W. Grimes } 3638fae3551SRodney W. Grimes 3648fae3551SRodney W. Grimes /* 3658fae3551SRodney W. Grimes * Free a previously allocated block 3668fae3551SRodney W. Grimes */ 3678fae3551SRodney W. Grimes freeblk(blkno, frags) 3688fae3551SRodney W. Grimes daddr_t blkno; 3698fae3551SRodney W. Grimes long frags; 3708fae3551SRodney W. Grimes { 3718fae3551SRodney W. Grimes struct inodesc idesc; 3728fae3551SRodney W. Grimes 3738fae3551SRodney W. Grimes idesc.id_blkno = blkno; 3748fae3551SRodney W. Grimes idesc.id_numfrags = frags; 3758fae3551SRodney W. Grimes (void)pass4check(&idesc); 3768fae3551SRodney W. Grimes } 3778fae3551SRodney W. Grimes 3788fae3551SRodney W. Grimes /* 3798fae3551SRodney W. Grimes * Find a pathname 3808fae3551SRodney W. Grimes */ 3818fae3551SRodney W. Grimes getpathname(namebuf, curdir, ino) 3828fae3551SRodney W. Grimes char *namebuf; 3838fae3551SRodney W. Grimes ino_t curdir, ino; 3848fae3551SRodney W. Grimes { 3858fae3551SRodney W. Grimes int len; 3868fae3551SRodney W. Grimes register char *cp; 3878fae3551SRodney W. Grimes struct inodesc idesc; 3888fae3551SRodney W. Grimes static int busy = 0; 3898fae3551SRodney W. Grimes extern int findname(); 3908fae3551SRodney W. Grimes 3918fae3551SRodney W. Grimes if (curdir == ino && ino == ROOTINO) { 3928fae3551SRodney W. Grimes (void)strcpy(namebuf, "/"); 3938fae3551SRodney W. Grimes return; 3948fae3551SRodney W. Grimes } 3958fae3551SRodney W. Grimes if (busy || 3968fae3551SRodney W. Grimes (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) { 3978fae3551SRodney W. Grimes (void)strcpy(namebuf, "?"); 3988fae3551SRodney W. Grimes return; 3998fae3551SRodney W. Grimes } 4008fae3551SRodney W. Grimes busy = 1; 4018fae3551SRodney W. Grimes bzero((char *)&idesc, sizeof(struct inodesc)); 4028fae3551SRodney W. Grimes idesc.id_type = DATA; 4038fae3551SRodney W. Grimes idesc.id_fix = IGNORE; 4048fae3551SRodney W. Grimes cp = &namebuf[MAXPATHLEN - 1]; 4058fae3551SRodney W. Grimes *cp = '\0'; 4068fae3551SRodney W. Grimes if (curdir != ino) { 4078fae3551SRodney W. Grimes idesc.id_parent = curdir; 4088fae3551SRodney W. Grimes goto namelookup; 4098fae3551SRodney W. Grimes } 4108fae3551SRodney W. Grimes while (ino != ROOTINO) { 4118fae3551SRodney W. Grimes idesc.id_number = ino; 4128fae3551SRodney W. Grimes idesc.id_func = findino; 4138fae3551SRodney W. Grimes idesc.id_name = ".."; 4148fae3551SRodney W. Grimes if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) 4158fae3551SRodney W. Grimes break; 4168fae3551SRodney W. Grimes namelookup: 4178fae3551SRodney W. Grimes idesc.id_number = idesc.id_parent; 4188fae3551SRodney W. Grimes idesc.id_parent = ino; 4198fae3551SRodney W. Grimes idesc.id_func = findname; 4208fae3551SRodney W. Grimes idesc.id_name = namebuf; 4218fae3551SRodney W. Grimes if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 4228fae3551SRodney W. Grimes break; 4238fae3551SRodney W. Grimes len = strlen(namebuf); 4248fae3551SRodney W. Grimes cp -= len; 4258fae3551SRodney W. Grimes bcopy(namebuf, cp, (size_t)len); 4268fae3551SRodney W. Grimes *--cp = '/'; 4278fae3551SRodney W. Grimes if (cp < &namebuf[MAXNAMLEN]) 4288fae3551SRodney W. Grimes break; 4298fae3551SRodney W. Grimes ino = idesc.id_number; 4308fae3551SRodney W. Grimes } 4318fae3551SRodney W. Grimes busy = 0; 4328fae3551SRodney W. Grimes if (ino != ROOTINO) 4338fae3551SRodney W. Grimes *--cp = '?'; 4348fae3551SRodney W. Grimes bcopy(cp, namebuf, (size_t)(&namebuf[MAXPATHLEN] - cp)); 4358fae3551SRodney W. Grimes } 4368fae3551SRodney W. Grimes 4378fae3551SRodney W. Grimes void 4388fae3551SRodney W. Grimes catch() 4398fae3551SRodney W. Grimes { 4408fae3551SRodney W. Grimes if (!doinglevel2) 4418fae3551SRodney W. Grimes ckfini(); 4428fae3551SRodney W. Grimes exit(12); 4438fae3551SRodney W. Grimes } 4448fae3551SRodney W. Grimes 4458fae3551SRodney W. Grimes /* 4468fae3551SRodney W. Grimes * When preening, allow a single quit to signal 4478fae3551SRodney W. Grimes * a special exit after filesystem checks complete 4488fae3551SRodney W. Grimes * so that reboot sequence may be interrupted. 4498fae3551SRodney W. Grimes */ 4508fae3551SRodney W. Grimes void 4518fae3551SRodney W. Grimes catchquit() 4528fae3551SRodney W. Grimes { 4538fae3551SRodney W. Grimes extern returntosingle; 4548fae3551SRodney W. Grimes 4558fae3551SRodney W. Grimes printf("returning to single-user after filesystem check\n"); 4568fae3551SRodney W. Grimes returntosingle = 1; 4578fae3551SRodney W. Grimes (void)signal(SIGQUIT, SIG_DFL); 4588fae3551SRodney W. Grimes } 4598fae3551SRodney W. Grimes 4608fae3551SRodney W. Grimes /* 4618fae3551SRodney W. Grimes * Ignore a single quit signal; wait and flush just in case. 4628fae3551SRodney W. Grimes * Used by child processes in preen. 4638fae3551SRodney W. Grimes */ 4648fae3551SRodney W. Grimes void 4658fae3551SRodney W. Grimes voidquit() 4668fae3551SRodney W. Grimes { 4678fae3551SRodney W. Grimes 4688fae3551SRodney W. Grimes sleep(1); 4698fae3551SRodney W. Grimes (void)signal(SIGQUIT, SIG_IGN); 4708fae3551SRodney W. Grimes (void)signal(SIGQUIT, SIG_DFL); 4718fae3551SRodney W. Grimes } 4728fae3551SRodney W. Grimes 4738fae3551SRodney W. Grimes /* 4748fae3551SRodney W. Grimes * determine whether an inode should be fixed. 4758fae3551SRodney W. Grimes */ 4768fae3551SRodney W. Grimes dofix(idesc, msg) 4778fae3551SRodney W. Grimes register struct inodesc *idesc; 4788fae3551SRodney W. Grimes char *msg; 4798fae3551SRodney W. Grimes { 4808fae3551SRodney W. Grimes 4818fae3551SRodney W. Grimes switch (idesc->id_fix) { 4828fae3551SRodney W. Grimes 4838fae3551SRodney W. Grimes case DONTKNOW: 4848fae3551SRodney W. Grimes if (idesc->id_type == DATA) 4858fae3551SRodney W. Grimes direrror(idesc->id_number, msg); 4868fae3551SRodney W. Grimes else 4878fae3551SRodney W. Grimes pwarn(msg); 4888fae3551SRodney W. Grimes if (preen) { 4898fae3551SRodney W. Grimes printf(" (SALVAGED)\n"); 4908fae3551SRodney W. Grimes idesc->id_fix = FIX; 4918fae3551SRodney W. Grimes return (ALTERED); 4928fae3551SRodney W. Grimes } 4938fae3551SRodney W. Grimes if (reply("SALVAGE") == 0) { 4948fae3551SRodney W. Grimes idesc->id_fix = NOFIX; 4958fae3551SRodney W. Grimes return (0); 4968fae3551SRodney W. Grimes } 4978fae3551SRodney W. Grimes idesc->id_fix = FIX; 4988fae3551SRodney W. Grimes return (ALTERED); 4998fae3551SRodney W. Grimes 5008fae3551SRodney W. Grimes case FIX: 5018fae3551SRodney W. Grimes return (ALTERED); 5028fae3551SRodney W. Grimes 5038fae3551SRodney W. Grimes case NOFIX: 5048fae3551SRodney W. Grimes case IGNORE: 5058fae3551SRodney W. Grimes return (0); 5068fae3551SRodney W. Grimes 5078fae3551SRodney W. Grimes default: 5088fae3551SRodney W. Grimes errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); 5098fae3551SRodney W. Grimes } 5108fae3551SRodney W. Grimes /* NOTREACHED */ 5118fae3551SRodney W. Grimes } 5128fae3551SRodney W. Grimes 5138fae3551SRodney W. Grimes /* VARARGS1 */ 5148fae3551SRodney W. Grimes errexit(s1, s2, s3, s4) 5158fae3551SRodney W. Grimes char *s1; 5168fae3551SRodney W. Grimes { 5178fae3551SRodney W. Grimes printf(s1, s2, s3, s4); 5188fae3551SRodney W. Grimes exit(8); 5198fae3551SRodney W. Grimes } 5208fae3551SRodney W. Grimes 5218fae3551SRodney W. Grimes /* 5228fae3551SRodney W. Grimes * An unexpected inconsistency occured. 5238fae3551SRodney W. Grimes * Die if preening, otherwise just print message and continue. 5248fae3551SRodney W. Grimes */ 5258fae3551SRodney W. Grimes /* VARARGS1 */ 5268fae3551SRodney W. Grimes pfatal(s, a1, a2, a3) 5278fae3551SRodney W. Grimes char *s; 5288fae3551SRodney W. Grimes { 5298fae3551SRodney W. Grimes 5308fae3551SRodney W. Grimes if (preen) { 5318fae3551SRodney W. Grimes printf("%s: ", cdevname); 5328fae3551SRodney W. Grimes printf(s, a1, a2, a3); 5338fae3551SRodney W. Grimes printf("\n"); 5348fae3551SRodney W. Grimes printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 5358fae3551SRodney W. Grimes cdevname); 5368fae3551SRodney W. Grimes exit(8); 5378fae3551SRodney W. Grimes } 5388fae3551SRodney W. Grimes printf(s, a1, a2, a3); 5398fae3551SRodney W. Grimes } 5408fae3551SRodney W. Grimes 5418fae3551SRodney W. Grimes /* 5428fae3551SRodney W. Grimes * Pwarn just prints a message when not preening, 5438fae3551SRodney W. Grimes * or a warning (preceded by filename) when preening. 5448fae3551SRodney W. Grimes */ 5458fae3551SRodney W. Grimes /* VARARGS1 */ 5468fae3551SRodney W. Grimes pwarn(s, a1, a2, a3, a4, a5, a6) 5478fae3551SRodney W. Grimes char *s; 5488fae3551SRodney W. Grimes { 5498fae3551SRodney W. Grimes 5508fae3551SRodney W. Grimes if (preen) 5518fae3551SRodney W. Grimes printf("%s: ", cdevname); 5528fae3551SRodney W. Grimes printf(s, a1, a2, a3, a4, a5, a6); 5538fae3551SRodney W. Grimes } 5548fae3551SRodney W. Grimes 5558fae3551SRodney W. Grimes #ifndef lint 5568fae3551SRodney W. Grimes /* 5578fae3551SRodney W. Grimes * Stub for routines from kernel. 5588fae3551SRodney W. Grimes */ 5598fae3551SRodney W. Grimes panic(s) 5608fae3551SRodney W. Grimes char *s; 5618fae3551SRodney W. Grimes { 5628fae3551SRodney W. Grimes 5638fae3551SRodney W. Grimes pfatal("INTERNAL INCONSISTENCY:"); 5648fae3551SRodney W. Grimes errexit(s); 5658fae3551SRodney W. Grimes } 5668fae3551SRodney W. Grimes #endif 567