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 35780a5c1eSPeter Wemm static const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95"; 368fae3551SRodney W. Grimes #endif /* not lint */ 378fae3551SRodney W. Grimes 388fae3551SRodney W. Grimes #include <sys/param.h> 398fae3551SRodney W. Grimes #include <sys/time.h> 40780a5c1eSPeter Wemm 418fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h> 428fae3551SRodney W. Grimes #include <ufs/ufs/dir.h> 438fae3551SRodney W. Grimes #include <ufs/ffs/fs.h> 448fae3551SRodney W. Grimes #include <stdio.h> 458fae3551SRodney W. Grimes #include <stdlib.h> 4631f4ab50SBruce Evans #include <unistd.h> 4731f4ab50SBruce Evans #include <stdarg.h> 488fae3551SRodney W. Grimes #include <string.h> 49780a5c1eSPeter Wemm #include <ctype.h> 50780a5c1eSPeter Wemm #include <err.h> 51780a5c1eSPeter Wemm 528fae3551SRodney W. Grimes #include "fsck.h" 538fae3551SRodney W. Grimes 548fae3551SRodney W. Grimes long diskreads, totalreads; /* Disk cache statistics */ 558fae3551SRodney W. Grimes 56780a5c1eSPeter Wemm static void rwerror __P((char *mesg, ufs_daddr_t blk)); 5731f4ab50SBruce Evans 5831f4ab50SBruce Evans int 598fae3551SRodney W. Grimes ftypeok(dp) 608fae3551SRodney W. Grimes struct dinode *dp; 618fae3551SRodney W. Grimes { 628fae3551SRodney W. Grimes switch (dp->di_mode & IFMT) { 638fae3551SRodney W. Grimes 648fae3551SRodney W. Grimes case IFDIR: 658fae3551SRodney W. Grimes case IFREG: 668fae3551SRodney W. Grimes case IFBLK: 678fae3551SRodney W. Grimes case IFCHR: 688fae3551SRodney W. Grimes case IFLNK: 698fae3551SRodney W. Grimes case IFSOCK: 708fae3551SRodney W. Grimes case IFIFO: 718fae3551SRodney W. Grimes return (1); 728fae3551SRodney W. Grimes 738fae3551SRodney W. Grimes default: 748fae3551SRodney W. Grimes if (debug) 758fae3551SRodney W. Grimes printf("bad file type 0%o\n", dp->di_mode); 768fae3551SRodney W. Grimes return (0); 778fae3551SRodney W. Grimes } 788fae3551SRodney W. Grimes } 798fae3551SRodney W. Grimes 8031f4ab50SBruce Evans int 818fae3551SRodney W. Grimes reply(question) 828fae3551SRodney W. Grimes char *question; 838fae3551SRodney W. Grimes { 848fae3551SRodney W. Grimes int persevere; 858fae3551SRodney W. Grimes char c; 868fae3551SRodney W. Grimes 878fae3551SRodney W. Grimes if (preen) 888fae3551SRodney W. Grimes pfatal("INTERNAL ERROR: GOT TO reply()"); 898fae3551SRodney W. Grimes persevere = !strcmp(question, "CONTINUE"); 908fae3551SRodney W. Grimes printf("\n"); 918fae3551SRodney W. Grimes if (!persevere && (nflag || fswritefd < 0)) { 928fae3551SRodney W. Grimes printf("%s? no\n\n", question); 938fae3551SRodney W. Grimes return (0); 948fae3551SRodney W. Grimes } 958fae3551SRodney W. Grimes if (yflag || (persevere && nflag)) { 968fae3551SRodney W. Grimes printf("%s? yes\n\n", question); 978fae3551SRodney W. Grimes return (1); 988fae3551SRodney W. Grimes } 998fae3551SRodney W. Grimes do { 1008fae3551SRodney W. Grimes printf("%s? [yn] ", question); 1018fae3551SRodney W. Grimes (void) fflush(stdout); 1028fae3551SRodney W. Grimes c = getc(stdin); 1038fae3551SRodney W. Grimes while (c != '\n' && getc(stdin) != '\n') 1048fae3551SRodney W. Grimes if (feof(stdin)) 1058fae3551SRodney W. Grimes return (0); 1068fae3551SRodney W. Grimes } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 1078fae3551SRodney W. Grimes printf("\n"); 1088fae3551SRodney W. Grimes if (c == 'y' || c == 'Y') 1098fae3551SRodney W. Grimes return (1); 1108fae3551SRodney W. Grimes return (0); 1118fae3551SRodney W. Grimes } 1128fae3551SRodney W. Grimes 1138fae3551SRodney W. Grimes /* 1148fae3551SRodney W. Grimes * Malloc buffers and set up cache. 1158fae3551SRodney W. Grimes */ 11631f4ab50SBruce Evans void 1178fae3551SRodney W. Grimes bufinit() 1188fae3551SRodney W. Grimes { 1198fae3551SRodney W. Grimes register struct bufarea *bp; 1208fae3551SRodney W. Grimes long bufcnt, i; 1218fae3551SRodney W. Grimes char *bufp; 1228fae3551SRodney W. Grimes 1238fae3551SRodney W. Grimes pbp = pdirbp = (struct bufarea *)0; 1248fae3551SRodney W. Grimes bufp = malloc((unsigned int)sblock.fs_bsize); 1258fae3551SRodney W. Grimes if (bufp == 0) 126780a5c1eSPeter Wemm errx(EEXIT, "cannot allocate buffer pool"); 1278fae3551SRodney W. Grimes cgblk.b_un.b_buf = bufp; 1288fae3551SRodney W. Grimes initbarea(&cgblk); 1298fae3551SRodney W. Grimes bufhead.b_next = bufhead.b_prev = &bufhead; 1308fae3551SRodney W. Grimes bufcnt = MAXBUFSPACE / sblock.fs_bsize; 1318fae3551SRodney W. Grimes if (bufcnt < MINBUFS) 1328fae3551SRodney W. Grimes bufcnt = MINBUFS; 1338fae3551SRodney W. Grimes for (i = 0; i < bufcnt; i++) { 1348fae3551SRodney W. Grimes bp = (struct bufarea *)malloc(sizeof(struct bufarea)); 1358fae3551SRodney W. Grimes bufp = malloc((unsigned int)sblock.fs_bsize); 1368fae3551SRodney W. Grimes if (bp == NULL || bufp == NULL) { 1378fae3551SRodney W. Grimes if (i >= MINBUFS) 1388fae3551SRodney W. Grimes break; 139780a5c1eSPeter Wemm errx(EEXIT, "cannot allocate buffer pool"); 1408fae3551SRodney W. Grimes } 1418fae3551SRodney W. Grimes bp->b_un.b_buf = bufp; 1428fae3551SRodney W. Grimes bp->b_prev = &bufhead; 1438fae3551SRodney W. Grimes bp->b_next = bufhead.b_next; 1448fae3551SRodney W. Grimes bufhead.b_next->b_prev = bp; 1458fae3551SRodney W. Grimes bufhead.b_next = bp; 1468fae3551SRodney W. Grimes initbarea(bp); 1478fae3551SRodney W. Grimes } 1488fae3551SRodney W. Grimes bufhead.b_size = i; /* save number of buffers */ 1498fae3551SRodney W. Grimes } 1508fae3551SRodney W. Grimes 1518fae3551SRodney W. Grimes /* 1528fae3551SRodney W. Grimes * Manage a cache of directory blocks. 1538fae3551SRodney W. Grimes */ 1548fae3551SRodney W. Grimes struct bufarea * 1558fae3551SRodney W. Grimes getdatablk(blkno, size) 156780a5c1eSPeter Wemm ufs_daddr_t blkno; 1578fae3551SRodney W. Grimes long size; 1588fae3551SRodney W. Grimes { 1598fae3551SRodney W. Grimes register struct bufarea *bp; 1608fae3551SRodney W. Grimes 1618fae3551SRodney W. Grimes for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) 1628fae3551SRodney W. Grimes if (bp->b_bno == fsbtodb(&sblock, blkno)) 1638fae3551SRodney W. Grimes goto foundit; 1648fae3551SRodney W. Grimes for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) 1658fae3551SRodney W. Grimes if ((bp->b_flags & B_INUSE) == 0) 1668fae3551SRodney W. Grimes break; 1678fae3551SRodney W. Grimes if (bp == &bufhead) 168780a5c1eSPeter Wemm errx(EEXIT, "deadlocked buffer pool"); 1698fae3551SRodney W. Grimes getblk(bp, blkno, size); 1708fae3551SRodney W. Grimes /* fall through */ 1718fae3551SRodney W. Grimes foundit: 1728fae3551SRodney W. Grimes totalreads++; 1738fae3551SRodney W. Grimes bp->b_prev->b_next = bp->b_next; 1748fae3551SRodney W. Grimes bp->b_next->b_prev = bp->b_prev; 1758fae3551SRodney W. Grimes bp->b_prev = &bufhead; 1768fae3551SRodney W. Grimes bp->b_next = bufhead.b_next; 1778fae3551SRodney W. Grimes bufhead.b_next->b_prev = bp; 1788fae3551SRodney W. Grimes bufhead.b_next = bp; 1798fae3551SRodney W. Grimes bp->b_flags |= B_INUSE; 1808fae3551SRodney W. Grimes return (bp); 1818fae3551SRodney W. Grimes } 1828fae3551SRodney W. Grimes 1838fae3551SRodney W. Grimes void 1848fae3551SRodney W. Grimes getblk(bp, blk, size) 1858fae3551SRodney W. Grimes register struct bufarea *bp; 186780a5c1eSPeter Wemm ufs_daddr_t blk; 1878fae3551SRodney W. Grimes long size; 1888fae3551SRodney W. Grimes { 189780a5c1eSPeter Wemm ufs_daddr_t dblk; 1908fae3551SRodney W. Grimes 1918fae3551SRodney W. Grimes dblk = fsbtodb(&sblock, blk); 1928fae3551SRodney W. Grimes if (bp->b_bno != dblk) { 1938fae3551SRodney W. Grimes flush(fswritefd, bp); 1948fae3551SRodney W. Grimes diskreads++; 1958fae3551SRodney W. Grimes bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); 1968fae3551SRodney W. Grimes bp->b_bno = dblk; 1978fae3551SRodney W. Grimes bp->b_size = size; 1988fae3551SRodney W. Grimes } 1998fae3551SRodney W. Grimes } 2008fae3551SRodney W. Grimes 20131f4ab50SBruce Evans void 2028fae3551SRodney W. Grimes flush(fd, bp) 2038fae3551SRodney W. Grimes int fd; 2048fae3551SRodney W. Grimes register struct bufarea *bp; 2058fae3551SRodney W. Grimes { 2068fae3551SRodney W. Grimes register int i, j; 2078fae3551SRodney W. Grimes 2088fae3551SRodney W. Grimes if (!bp->b_dirty) 2098fae3551SRodney W. Grimes return; 2108fae3551SRodney W. Grimes if (bp->b_errs != 0) 2118fae3551SRodney W. Grimes pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", 2128fae3551SRodney W. Grimes (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 2138fae3551SRodney W. Grimes bp->b_bno); 2148fae3551SRodney W. Grimes bp->b_dirty = 0; 2158fae3551SRodney W. Grimes bp->b_errs = 0; 2168fae3551SRodney W. Grimes bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 2178fae3551SRodney W. Grimes if (bp != &sblk) 2188fae3551SRodney W. Grimes return; 2198fae3551SRodney W. Grimes for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 2208fae3551SRodney W. Grimes bwrite(fswritefd, (char *)sblock.fs_csp[j], 2218fae3551SRodney W. Grimes fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 2228fae3551SRodney W. Grimes sblock.fs_cssize - i < sblock.fs_bsize ? 2238fae3551SRodney W. Grimes sblock.fs_cssize - i : sblock.fs_bsize); 2248fae3551SRodney W. Grimes } 2258fae3551SRodney W. Grimes } 2268fae3551SRodney W. Grimes 227780a5c1eSPeter Wemm static void 2288fae3551SRodney W. Grimes rwerror(mesg, blk) 2298fae3551SRodney W. Grimes char *mesg; 230780a5c1eSPeter Wemm ufs_daddr_t blk; 2318fae3551SRodney W. Grimes { 2328fae3551SRodney W. Grimes 2338fae3551SRodney W. Grimes if (preen == 0) 2348fae3551SRodney W. Grimes printf("\n"); 2358fae3551SRodney W. Grimes pfatal("CANNOT %s: BLK %ld", mesg, blk); 2368fae3551SRodney W. Grimes if (reply("CONTINUE") == 0) 237780a5c1eSPeter Wemm exit(EEXIT); 2388fae3551SRodney W. Grimes } 2398fae3551SRodney W. Grimes 24031f4ab50SBruce Evans void 241780a5c1eSPeter Wemm ckfini(markclean) 242780a5c1eSPeter Wemm int markclean; 2438fae3551SRodney W. Grimes { 2448fae3551SRodney W. Grimes register struct bufarea *bp, *nbp; 245780a5c1eSPeter Wemm int ofsmodified, cnt = 0; 2468fae3551SRodney W. Grimes 2478fae3551SRodney W. Grimes if (fswritefd < 0) { 2488fae3551SRodney W. Grimes (void)close(fsreadfd); 2498fae3551SRodney W. Grimes return; 2508fae3551SRodney W. Grimes } 2518fae3551SRodney W. Grimes flush(fswritefd, &sblk); 2528fae3551SRodney W. Grimes if (havesb && sblk.b_bno != SBOFF / dev_bsize && 2538fae3551SRodney W. Grimes !preen && reply("UPDATE STANDARD SUPERBLOCK")) { 2548fae3551SRodney W. Grimes sblk.b_bno = SBOFF / dev_bsize; 2558fae3551SRodney W. Grimes sbdirty(); 2568fae3551SRodney W. Grimes flush(fswritefd, &sblk); 2578fae3551SRodney W. Grimes } 2588fae3551SRodney W. Grimes flush(fswritefd, &cgblk); 2598fae3551SRodney W. Grimes free(cgblk.b_un.b_buf); 2608fae3551SRodney W. Grimes for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { 2618fae3551SRodney W. Grimes cnt++; 2628fae3551SRodney W. Grimes flush(fswritefd, bp); 2638fae3551SRodney W. Grimes nbp = bp->b_prev; 2648fae3551SRodney W. Grimes free(bp->b_un.b_buf); 2658fae3551SRodney W. Grimes free((char *)bp); 2668fae3551SRodney W. Grimes } 2678fae3551SRodney W. Grimes if (bufhead.b_size != cnt) 268780a5c1eSPeter Wemm errx(EEXIT, "Panic: lost %d buffers", bufhead.b_size - cnt); 2698fae3551SRodney W. Grimes pbp = pdirbp = (struct bufarea *)0; 270780a5c1eSPeter Wemm if (markclean && sblock.fs_clean == 0) { 271780a5c1eSPeter Wemm sblock.fs_clean = 1; 272780a5c1eSPeter Wemm sbdirty(); 273780a5c1eSPeter Wemm ofsmodified = fsmodified; 274780a5c1eSPeter Wemm flush(fswritefd, &sblk); 275780a5c1eSPeter Wemm fsmodified = ofsmodified; 276780a5c1eSPeter Wemm if (!preen) 277780a5c1eSPeter Wemm printf("\n***** FILE SYSTEM MARKED CLEAN *****\n"); 278780a5c1eSPeter Wemm } 2798fae3551SRodney W. Grimes if (debug) 2808fae3551SRodney W. Grimes printf("cache missed %ld of %ld (%d%%)\n", diskreads, 2818fae3551SRodney W. Grimes totalreads, (int)(diskreads * 100 / totalreads)); 2828fae3551SRodney W. Grimes (void)close(fsreadfd); 2838fae3551SRodney W. Grimes (void)close(fswritefd); 2848fae3551SRodney W. Grimes } 2858fae3551SRodney W. Grimes 28631f4ab50SBruce Evans int 2878fae3551SRodney W. Grimes bread(fd, buf, blk, size) 2888fae3551SRodney W. Grimes int fd; 2898fae3551SRodney W. Grimes char *buf; 290780a5c1eSPeter Wemm ufs_daddr_t blk; 2918fae3551SRodney W. Grimes long size; 2928fae3551SRodney W. Grimes { 2938fae3551SRodney W. Grimes char *cp; 2948fae3551SRodney W. Grimes int i, errs; 2958fae3551SRodney W. Grimes off_t offset; 2968fae3551SRodney W. Grimes 2978fae3551SRodney W. Grimes offset = blk; 2988fae3551SRodney W. Grimes offset *= dev_bsize; 2998fae3551SRodney W. Grimes if (lseek(fd, offset, 0) < 0) 3008fae3551SRodney W. Grimes rwerror("SEEK", blk); 3018fae3551SRodney W. Grimes else if (read(fd, buf, (int)size) == size) 3028fae3551SRodney W. Grimes return (0); 3038fae3551SRodney W. Grimes rwerror("READ", blk); 3048fae3551SRodney W. Grimes if (lseek(fd, offset, 0) < 0) 3058fae3551SRodney W. Grimes rwerror("SEEK", blk); 3068fae3551SRodney W. Grimes errs = 0; 307780a5c1eSPeter Wemm memset(buf, 0, (size_t)size); 3088fae3551SRodney W. Grimes printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 3098fae3551SRodney W. Grimes for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 3108fae3551SRodney W. Grimes if (read(fd, cp, (int)secsize) != secsize) { 3118fae3551SRodney W. Grimes (void)lseek(fd, offset + i + secsize, 0); 3128fae3551SRodney W. Grimes if (secsize != dev_bsize && dev_bsize != 1) 3138fae3551SRodney W. Grimes printf(" %ld (%ld),", 3148fae3551SRodney W. Grimes (blk * dev_bsize + i) / secsize, 3158fae3551SRodney W. Grimes blk + i / dev_bsize); 3168fae3551SRodney W. Grimes else 3178fae3551SRodney W. Grimes printf(" %ld,", blk + i / dev_bsize); 3188fae3551SRodney W. Grimes errs++; 3198fae3551SRodney W. Grimes } 3208fae3551SRodney W. Grimes } 3218fae3551SRodney W. Grimes printf("\n"); 3228fae3551SRodney W. Grimes return (errs); 3238fae3551SRodney W. Grimes } 3248fae3551SRodney W. Grimes 32531f4ab50SBruce Evans void 3268fae3551SRodney W. Grimes bwrite(fd, buf, blk, size) 3278fae3551SRodney W. Grimes int fd; 3288fae3551SRodney W. Grimes char *buf; 329780a5c1eSPeter Wemm ufs_daddr_t blk; 3308fae3551SRodney W. Grimes long size; 3318fae3551SRodney W. Grimes { 3328fae3551SRodney W. Grimes int i; 3338fae3551SRodney W. Grimes char *cp; 3348fae3551SRodney W. Grimes off_t offset; 3358fae3551SRodney W. Grimes 3368fae3551SRodney W. Grimes if (fd < 0) 3378fae3551SRodney W. Grimes return; 3388fae3551SRodney W. Grimes offset = blk; 3398fae3551SRodney W. Grimes offset *= dev_bsize; 3408fae3551SRodney W. Grimes if (lseek(fd, offset, 0) < 0) 3418fae3551SRodney W. Grimes rwerror("SEEK", blk); 3428fae3551SRodney W. Grimes else if (write(fd, buf, (int)size) == size) { 3438fae3551SRodney W. Grimes fsmodified = 1; 3448fae3551SRodney W. Grimes return; 3458fae3551SRodney W. Grimes } 3468fae3551SRodney W. Grimes rwerror("WRITE", blk); 3478fae3551SRodney W. Grimes if (lseek(fd, offset, 0) < 0) 3488fae3551SRodney W. Grimes rwerror("SEEK", blk); 3498fae3551SRodney W. Grimes printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 3508fae3551SRodney W. Grimes for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 3518fae3551SRodney W. Grimes if (write(fd, cp, (int)dev_bsize) != dev_bsize) { 3528fae3551SRodney W. Grimes (void)lseek(fd, offset + i + dev_bsize, 0); 3538fae3551SRodney W. Grimes printf(" %ld,", blk + i / dev_bsize); 3548fae3551SRodney W. Grimes } 3558fae3551SRodney W. Grimes printf("\n"); 3568fae3551SRodney W. Grimes return; 3578fae3551SRodney W. Grimes } 3588fae3551SRodney W. Grimes 3598fae3551SRodney W. Grimes /* 3608fae3551SRodney W. Grimes * allocate a data block with the specified number of fragments 3618fae3551SRodney W. Grimes */ 362780a5c1eSPeter Wemm ufs_daddr_t 3638fae3551SRodney W. Grimes allocblk(frags) 3648fae3551SRodney W. Grimes long frags; 3658fae3551SRodney W. Grimes { 3668fae3551SRodney W. Grimes register int i, j, k; 3678fae3551SRodney W. Grimes 3688fae3551SRodney W. Grimes if (frags <= 0 || frags > sblock.fs_frag) 3698fae3551SRodney W. Grimes return (0); 3708fae3551SRodney W. Grimes for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { 3718fae3551SRodney W. Grimes for (j = 0; j <= sblock.fs_frag - frags; j++) { 3728fae3551SRodney W. Grimes if (testbmap(i + j)) 3738fae3551SRodney W. Grimes continue; 3748fae3551SRodney W. Grimes for (k = 1; k < frags; k++) 3758fae3551SRodney W. Grimes if (testbmap(i + j + k)) 3768fae3551SRodney W. Grimes break; 3778fae3551SRodney W. Grimes if (k < frags) { 3788fae3551SRodney W. Grimes j += k; 3798fae3551SRodney W. Grimes continue; 3808fae3551SRodney W. Grimes } 3818fae3551SRodney W. Grimes for (k = 0; k < frags; k++) 3828fae3551SRodney W. Grimes setbmap(i + j + k); 3838fae3551SRodney W. Grimes n_blks += frags; 3848fae3551SRodney W. Grimes return (i + j); 3858fae3551SRodney W. Grimes } 3868fae3551SRodney W. Grimes } 3878fae3551SRodney W. Grimes return (0); 3888fae3551SRodney W. Grimes } 3898fae3551SRodney W. Grimes 3908fae3551SRodney W. Grimes /* 3918fae3551SRodney W. Grimes * Free a previously allocated block 3928fae3551SRodney W. Grimes */ 39331f4ab50SBruce Evans void 3948fae3551SRodney W. Grimes freeblk(blkno, frags) 395780a5c1eSPeter Wemm ufs_daddr_t blkno; 3968fae3551SRodney W. Grimes long frags; 3978fae3551SRodney W. Grimes { 3988fae3551SRodney W. Grimes struct inodesc idesc; 3998fae3551SRodney W. Grimes 4008fae3551SRodney W. Grimes idesc.id_blkno = blkno; 4018fae3551SRodney W. Grimes idesc.id_numfrags = frags; 4028fae3551SRodney W. Grimes (void)pass4check(&idesc); 4038fae3551SRodney W. Grimes } 4048fae3551SRodney W. Grimes 4058fae3551SRodney W. Grimes /* 4068fae3551SRodney W. Grimes * Find a pathname 4078fae3551SRodney W. Grimes */ 40831f4ab50SBruce Evans void 4098fae3551SRodney W. Grimes getpathname(namebuf, curdir, ino) 4108fae3551SRodney W. Grimes char *namebuf; 4118fae3551SRodney W. Grimes ino_t curdir, ino; 4128fae3551SRodney W. Grimes { 4138fae3551SRodney W. Grimes int len; 4148fae3551SRodney W. Grimes register char *cp; 4158fae3551SRodney W. Grimes struct inodesc idesc; 4168fae3551SRodney W. Grimes static int busy = 0; 4178fae3551SRodney W. Grimes 4188fae3551SRodney W. Grimes if (curdir == ino && ino == ROOTINO) { 4198fae3551SRodney W. Grimes (void)strcpy(namebuf, "/"); 4208fae3551SRodney W. Grimes return; 4218fae3551SRodney W. Grimes } 4228fae3551SRodney W. Grimes if (busy || 4238fae3551SRodney W. Grimes (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) { 4248fae3551SRodney W. Grimes (void)strcpy(namebuf, "?"); 4258fae3551SRodney W. Grimes return; 4268fae3551SRodney W. Grimes } 4278fae3551SRodney W. Grimes busy = 1; 428780a5c1eSPeter Wemm memset(&idesc, 0, sizeof(struct inodesc)); 4298fae3551SRodney W. Grimes idesc.id_type = DATA; 4308fae3551SRodney W. Grimes idesc.id_fix = IGNORE; 4318fae3551SRodney W. Grimes cp = &namebuf[MAXPATHLEN - 1]; 4328fae3551SRodney W. Grimes *cp = '\0'; 4338fae3551SRodney W. Grimes if (curdir != ino) { 4348fae3551SRodney W. Grimes idesc.id_parent = curdir; 4358fae3551SRodney W. Grimes goto namelookup; 4368fae3551SRodney W. Grimes } 4378fae3551SRodney W. Grimes while (ino != ROOTINO) { 4388fae3551SRodney W. Grimes idesc.id_number = ino; 4398fae3551SRodney W. Grimes idesc.id_func = findino; 4408fae3551SRodney W. Grimes idesc.id_name = ".."; 4418fae3551SRodney W. Grimes if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) 4428fae3551SRodney W. Grimes break; 4438fae3551SRodney W. Grimes namelookup: 4448fae3551SRodney W. Grimes idesc.id_number = idesc.id_parent; 4458fae3551SRodney W. Grimes idesc.id_parent = ino; 4468fae3551SRodney W. Grimes idesc.id_func = findname; 4478fae3551SRodney W. Grimes idesc.id_name = namebuf; 4488fae3551SRodney W. Grimes if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) 4498fae3551SRodney W. Grimes break; 4508fae3551SRodney W. Grimes len = strlen(namebuf); 4518fae3551SRodney W. Grimes cp -= len; 452780a5c1eSPeter Wemm memmove(cp, namebuf, (size_t)len); 4538fae3551SRodney W. Grimes *--cp = '/'; 4548fae3551SRodney W. Grimes if (cp < &namebuf[MAXNAMLEN]) 4558fae3551SRodney W. Grimes break; 4568fae3551SRodney W. Grimes ino = idesc.id_number; 4578fae3551SRodney W. Grimes } 4588fae3551SRodney W. Grimes busy = 0; 4598fae3551SRodney W. Grimes if (ino != ROOTINO) 4608fae3551SRodney W. Grimes *--cp = '?'; 461780a5c1eSPeter Wemm memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); 4628fae3551SRodney W. Grimes } 4638fae3551SRodney W. Grimes 4648fae3551SRodney W. Grimes void 465780a5c1eSPeter Wemm catch(sig) 466780a5c1eSPeter Wemm int sig; 4678fae3551SRodney W. Grimes { 4688fae3551SRodney W. Grimes if (!doinglevel2) 469780a5c1eSPeter Wemm ckfini(0); 4708fae3551SRodney W. Grimes exit(12); 4718fae3551SRodney W. Grimes } 4728fae3551SRodney W. Grimes 4738fae3551SRodney W. Grimes /* 4748fae3551SRodney W. Grimes * When preening, allow a single quit to signal 4758fae3551SRodney W. Grimes * a special exit after filesystem checks complete 4768fae3551SRodney W. Grimes * so that reboot sequence may be interrupted. 4778fae3551SRodney W. Grimes */ 4788fae3551SRodney W. Grimes void 479780a5c1eSPeter Wemm catchquit(sig) 480780a5c1eSPeter Wemm int sig; 4818fae3551SRodney W. Grimes { 4828fae3551SRodney W. Grimes printf("returning to single-user after filesystem check\n"); 4838fae3551SRodney W. Grimes returntosingle = 1; 4848fae3551SRodney W. Grimes (void)signal(SIGQUIT, SIG_DFL); 4858fae3551SRodney W. Grimes } 4868fae3551SRodney W. Grimes 4878fae3551SRodney W. Grimes /* 4888fae3551SRodney W. Grimes * Ignore a single quit signal; wait and flush just in case. 4898fae3551SRodney W. Grimes * Used by child processes in preen. 4908fae3551SRodney W. Grimes */ 4918fae3551SRodney W. Grimes void 492780a5c1eSPeter Wemm voidquit(sig) 493780a5c1eSPeter Wemm int sig; 4948fae3551SRodney W. Grimes { 4958fae3551SRodney W. Grimes 4968fae3551SRodney W. Grimes sleep(1); 4978fae3551SRodney W. Grimes (void)signal(SIGQUIT, SIG_IGN); 4988fae3551SRodney W. Grimes (void)signal(SIGQUIT, SIG_DFL); 4998fae3551SRodney W. Grimes } 5008fae3551SRodney W. Grimes 5018fae3551SRodney W. Grimes /* 5028fae3551SRodney W. Grimes * determine whether an inode should be fixed. 5038fae3551SRodney W. Grimes */ 50431f4ab50SBruce Evans int 5058fae3551SRodney W. Grimes dofix(idesc, msg) 5068fae3551SRodney W. Grimes register struct inodesc *idesc; 5078fae3551SRodney W. Grimes char *msg; 5088fae3551SRodney W. Grimes { 5098fae3551SRodney W. Grimes 5108fae3551SRodney W. Grimes switch (idesc->id_fix) { 5118fae3551SRodney W. Grimes 5128fae3551SRodney W. Grimes case DONTKNOW: 5138fae3551SRodney W. Grimes if (idesc->id_type == DATA) 5148fae3551SRodney W. Grimes direrror(idesc->id_number, msg); 5158fae3551SRodney W. Grimes else 5168fae3551SRodney W. Grimes pwarn(msg); 5178fae3551SRodney W. Grimes if (preen) { 5188fae3551SRodney W. Grimes printf(" (SALVAGED)\n"); 5198fae3551SRodney W. Grimes idesc->id_fix = FIX; 5208fae3551SRodney W. Grimes return (ALTERED); 5218fae3551SRodney W. Grimes } 5228fae3551SRodney W. Grimes if (reply("SALVAGE") == 0) { 5238fae3551SRodney W. Grimes idesc->id_fix = NOFIX; 5248fae3551SRodney W. Grimes return (0); 5258fae3551SRodney W. Grimes } 5268fae3551SRodney W. Grimes idesc->id_fix = FIX; 5278fae3551SRodney W. Grimes return (ALTERED); 5288fae3551SRodney W. Grimes 5298fae3551SRodney W. Grimes case FIX: 5308fae3551SRodney W. Grimes return (ALTERED); 5318fae3551SRodney W. Grimes 5328fae3551SRodney W. Grimes case NOFIX: 5338fae3551SRodney W. Grimes case IGNORE: 5348fae3551SRodney W. Grimes return (0); 5358fae3551SRodney W. Grimes 5368fae3551SRodney W. Grimes default: 537780a5c1eSPeter Wemm errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix); 5388fae3551SRodney W. Grimes } 5398fae3551SRodney W. Grimes /* NOTREACHED */ 540780a5c1eSPeter Wemm return (0); 5418fae3551SRodney W. Grimes } 5428fae3551SRodney W. Grimes 543780a5c1eSPeter Wemm #if __STDC__ 544780a5c1eSPeter Wemm #include <stdarg.h> 545780a5c1eSPeter Wemm #else 546780a5c1eSPeter Wemm #include <varargs.h> 547780a5c1eSPeter Wemm #endif 5488fae3551SRodney W. Grimes 5498fae3551SRodney W. Grimes /* 5508fae3551SRodney W. Grimes * An unexpected inconsistency occured. 5518fae3551SRodney W. Grimes * Die if preening, otherwise just print message and continue. 5528fae3551SRodney W. Grimes */ 55331f4ab50SBruce Evans void 554780a5c1eSPeter Wemm #if __STDC__ 555780a5c1eSPeter Wemm pfatal(const char *fmt, ...) 556780a5c1eSPeter Wemm #else 557780a5c1eSPeter Wemm pfatal(fmt, va_alist) 558780a5c1eSPeter Wemm char *fmt; 559780a5c1eSPeter Wemm va_dcl 560780a5c1eSPeter Wemm #endif 5618fae3551SRodney W. Grimes { 56231f4ab50SBruce Evans va_list ap; 563780a5c1eSPeter Wemm #if __STDC__ 564780a5c1eSPeter Wemm va_start(ap, fmt); 565780a5c1eSPeter Wemm #else 566780a5c1eSPeter Wemm va_start(ap); 567780a5c1eSPeter Wemm #endif 568780a5c1eSPeter Wemm if (!preen) { 569780a5c1eSPeter Wemm (void)vfprintf(stderr, fmt, ap); 57031f4ab50SBruce Evans va_end(ap); 571780a5c1eSPeter Wemm return; 572780a5c1eSPeter Wemm } 573780a5c1eSPeter Wemm (void)fprintf(stderr, "%s: ", cdevname); 574780a5c1eSPeter Wemm (void)vfprintf(stderr, fmt, ap); 575780a5c1eSPeter Wemm (void)fprintf(stderr, 576780a5c1eSPeter Wemm "\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 577780a5c1eSPeter Wemm cdevname); 578780a5c1eSPeter Wemm exit(EEXIT); 5798fae3551SRodney W. Grimes } 5808fae3551SRodney W. Grimes 5818fae3551SRodney W. Grimes /* 5828fae3551SRodney W. Grimes * Pwarn just prints a message when not preening, 5838fae3551SRodney W. Grimes * or a warning (preceded by filename) when preening. 5848fae3551SRodney W. Grimes */ 58531f4ab50SBruce Evans void 586780a5c1eSPeter Wemm #if __STDC__ 587780a5c1eSPeter Wemm pwarn(const char *fmt, ...) 588780a5c1eSPeter Wemm #else 589780a5c1eSPeter Wemm pwarn(fmt, va_alist) 590780a5c1eSPeter Wemm char *fmt; 591780a5c1eSPeter Wemm va_dcl 592780a5c1eSPeter Wemm #endif 5938fae3551SRodney W. Grimes { 59431f4ab50SBruce Evans va_list ap; 595780a5c1eSPeter Wemm #if __STDC__ 596780a5c1eSPeter Wemm va_start(ap, fmt); 597780a5c1eSPeter Wemm #else 598780a5c1eSPeter Wemm va_start(ap); 599780a5c1eSPeter Wemm #endif 6008fae3551SRodney W. Grimes if (preen) 601780a5c1eSPeter Wemm (void)fprintf(stderr, "%s: ", cdevname); 602780a5c1eSPeter Wemm (void)vfprintf(stderr, fmt, ap); 60331f4ab50SBruce Evans va_end(ap); 6048fae3551SRodney W. Grimes } 6058fae3551SRodney W. Grimes 6068fae3551SRodney W. Grimes /* 6078fae3551SRodney W. Grimes * Stub for routines from kernel. 6088fae3551SRodney W. Grimes */ 609eaa86f9dSBruce Evans void 610780a5c1eSPeter Wemm #if __STDC__ 61131f4ab50SBruce Evans panic(const char *fmt, ...) 61231f4ab50SBruce Evans #else 61331f4ab50SBruce Evans panic(fmt, va_alist) 61431f4ab50SBruce Evans char *fmt; 615780a5c1eSPeter Wemm va_dcl 61631f4ab50SBruce Evans #endif 6178fae3551SRodney W. Grimes { 618780a5c1eSPeter Wemm va_list ap; 619780a5c1eSPeter Wemm #if __STDC__ 620780a5c1eSPeter Wemm va_start(ap, fmt); 621780a5c1eSPeter Wemm #else 622780a5c1eSPeter Wemm va_start(ap); 6238fae3551SRodney W. Grimes #endif 624780a5c1eSPeter Wemm pfatal("INTERNAL INCONSISTENCY:"); 625780a5c1eSPeter Wemm (void)vfprintf(stderr, fmt, ap); 626780a5c1eSPeter Wemm va_end(ap); 627780a5c1eSPeter Wemm exit(EEXIT); 628780a5c1eSPeter Wemm } 629