inode.c revision 57573
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1986, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 3541477Sjulian#if 0 3623675Speterstatic const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95"; 3741477Sjulian#endif 3841477Sjulianstatic const char rcsid[] = 3950476Speter "$FreeBSD: head/sbin/fsck_ffs/inode.c 57573 2000-02-28 20:02:41Z mckusick $"; 401558Srgrimes#endif /* not lint */ 411558Srgrimes 421558Srgrimes#include <sys/param.h> 431558Srgrimes#include <sys/time.h> 4423675Speter 451558Srgrimes#include <ufs/ufs/dinode.h> 461558Srgrimes#include <ufs/ufs/dir.h> 471558Srgrimes#include <ufs/ffs/fs.h> 4823675Speter 4923675Speter#include <err.h> 501558Srgrimes#include <pwd.h> 511558Srgrimes#include <string.h> 5223675Speter 531558Srgrimes#include "fsck.h" 541558Srgrimes 551558Srgrimesstatic ino_t startinum; 561558Srgrimes 5723675Speterstatic int iblock __P((struct inodesc *, long ilevel, quad_t isize)); 587585Sbde 597585Sbdeint 601558Srgrimesckinode(dp, idesc) 611558Srgrimes struct dinode *dp; 621558Srgrimes register struct inodesc *idesc; 631558Srgrimes{ 6423675Speter ufs_daddr_t *ap; 6541474Sjulian int ret; 6641474Sjulian long n, ndb, offset; 671558Srgrimes struct dinode dino; 681558Srgrimes quad_t remsize, sizepb; 691558Srgrimes mode_t mode; 7018808Sguido char pathbuf[MAXPATHLEN + 1]; 711558Srgrimes 721558Srgrimes if (idesc->id_fix != IGNORE) 731558Srgrimes idesc->id_fix = DONTKNOW; 741558Srgrimes idesc->id_entryno = 0; 751558Srgrimes idesc->id_filesize = dp->di_size; 761558Srgrimes mode = dp->di_mode & IFMT; 771558Srgrimes if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 7841474Sjulian dp->di_size < (unsigned)sblock.fs_maxsymlinklen)) 791558Srgrimes return (KEEPON); 801558Srgrimes dino = *dp; 811558Srgrimes ndb = howmany(dino.di_size, sblock.fs_bsize); 821558Srgrimes for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { 831558Srgrimes if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) 841558Srgrimes idesc->id_numfrags = 851558Srgrimes numfrags(&sblock, fragroundup(&sblock, offset)); 861558Srgrimes else 871558Srgrimes idesc->id_numfrags = sblock.fs_frag; 8818808Sguido if (*ap == 0) { 8918808Sguido if (idesc->id_type == DATA && ndb >= 0) { 9018808Sguido /* An empty block in a directory XXX */ 9118808Sguido getpathname(pathbuf, idesc->id_number, 9218808Sguido idesc->id_number); 9318808Sguido pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 9418808Sguido pathbuf); 9518808Sguido if (reply("ADJUST LENGTH") == 1) { 9618808Sguido dp = ginode(idesc->id_number); 9718808Sguido dp->di_size = (ap - &dino.di_db[0]) * 9818808Sguido sblock.fs_bsize; 9918808Sguido printf( 10018808Sguido "YOU MUST RERUN FSCK AFTERWARDS\n"); 10118808Sguido rerun = 1; 10218808Sguido inodirty(); 10318808Sguido 10418808Sguido } 10518808Sguido } 1061558Srgrimes continue; 10718808Sguido } 1081558Srgrimes idesc->id_blkno = *ap; 1091558Srgrimes if (idesc->id_type == ADDR) 1101558Srgrimes ret = (*idesc->id_func)(idesc); 1111558Srgrimes else 1121558Srgrimes ret = dirscan(idesc); 1131558Srgrimes if (ret & STOP) 1141558Srgrimes return (ret); 1151558Srgrimes } 1161558Srgrimes idesc->id_numfrags = sblock.fs_frag; 1171558Srgrimes remsize = dino.di_size - sblock.fs_bsize * NDADDR; 1181558Srgrimes sizepb = sblock.fs_bsize; 1191558Srgrimes for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { 1201558Srgrimes if (*ap) { 1211558Srgrimes idesc->id_blkno = *ap; 1221558Srgrimes ret = iblock(idesc, n, remsize); 1231558Srgrimes if (ret & STOP) 1241558Srgrimes return (ret); 12518808Sguido } else { 12618808Sguido if (idesc->id_type == DATA && remsize > 0) { 12718808Sguido /* An empty block in a directory XXX */ 12818808Sguido getpathname(pathbuf, idesc->id_number, 12918808Sguido idesc->id_number); 13018808Sguido pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 13118808Sguido pathbuf); 13218808Sguido if (reply("ADJUST LENGTH") == 1) { 13318808Sguido dp = ginode(idesc->id_number); 13418808Sguido dp->di_size -= remsize; 13518808Sguido remsize = 0; 13618808Sguido printf( 13718808Sguido "YOU MUST RERUN FSCK AFTERWARDS\n"); 13818808Sguido rerun = 1; 13918808Sguido inodirty(); 14018808Sguido break; 14118808Sguido } 14218808Sguido } 1431558Srgrimes } 1441558Srgrimes sizepb *= NINDIR(&sblock); 1451558Srgrimes remsize -= sizepb; 1461558Srgrimes } 1471558Srgrimes return (KEEPON); 1481558Srgrimes} 1491558Srgrimes 1507585Sbdestatic int 1511558Srgrimesiblock(idesc, ilevel, isize) 1521558Srgrimes struct inodesc *idesc; 1531558Srgrimes long ilevel; 1541558Srgrimes quad_t isize; 1551558Srgrimes{ 15623675Speter ufs_daddr_t *ap; 15723675Speter ufs_daddr_t *aplim; 15823675Speter struct bufarea *bp; 1591558Srgrimes int i, n, (*func)(), nif; 1601558Srgrimes quad_t sizepb; 1611558Srgrimes char buf[BUFSIZ]; 16218808Sguido char pathbuf[MAXPATHLEN + 1]; 16318808Sguido struct dinode *dp; 1641558Srgrimes 1651558Srgrimes if (idesc->id_type == ADDR) { 1661558Srgrimes func = idesc->id_func; 1671558Srgrimes if (((n = (*func)(idesc)) & KEEPON) == 0) 1681558Srgrimes return (n); 1691558Srgrimes } else 1701558Srgrimes func = dirscan; 1711558Srgrimes if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 1721558Srgrimes return (SKIP); 1731558Srgrimes bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); 1741558Srgrimes ilevel--; 1751558Srgrimes for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) 1761558Srgrimes sizepb *= NINDIR(&sblock); 1771558Srgrimes nif = howmany(isize , sizepb); 1781558Srgrimes if (nif > NINDIR(&sblock)) 1791558Srgrimes nif = NINDIR(&sblock); 1801558Srgrimes if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { 1811558Srgrimes aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; 1821558Srgrimes for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { 1831558Srgrimes if (*ap == 0) 1841558Srgrimes continue; 1851558Srgrimes (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", 18637236Sbde (u_long)idesc->id_number); 1871558Srgrimes if (dofix(idesc, buf)) { 1881558Srgrimes *ap = 0; 1891558Srgrimes dirty(bp); 1901558Srgrimes } 1911558Srgrimes } 1921558Srgrimes flush(fswritefd, bp); 1931558Srgrimes } 1941558Srgrimes aplim = &bp->b_un.b_indir[nif]; 1951558Srgrimes for (ap = bp->b_un.b_indir; ap < aplim; ap++) { 1961558Srgrimes if (*ap) { 1971558Srgrimes idesc->id_blkno = *ap; 1981558Srgrimes if (ilevel == 0) 1991558Srgrimes n = (*func)(idesc); 2001558Srgrimes else 2011558Srgrimes n = iblock(idesc, ilevel, isize); 2021558Srgrimes if (n & STOP) { 2031558Srgrimes bp->b_flags &= ~B_INUSE; 2041558Srgrimes return (n); 2051558Srgrimes } 20618808Sguido } else { 20718808Sguido if (idesc->id_type == DATA && isize > 0) { 20818808Sguido /* An empty block in a directory XXX */ 20918808Sguido getpathname(pathbuf, idesc->id_number, 21018808Sguido idesc->id_number); 21118808Sguido pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 21218808Sguido pathbuf); 21318808Sguido if (reply("ADJUST LENGTH") == 1) { 21418808Sguido dp = ginode(idesc->id_number); 21518808Sguido dp->di_size -= isize; 21618808Sguido isize = 0; 21718808Sguido printf( 21818808Sguido "YOU MUST RERUN FSCK AFTERWARDS\n"); 21918808Sguido rerun = 1; 22018808Sguido inodirty(); 22118808Sguido bp->b_flags &= ~B_INUSE; 22218808Sguido return(STOP); 22318808Sguido } 22418808Sguido } 2251558Srgrimes } 2261558Srgrimes isize -= sizepb; 2271558Srgrimes } 2281558Srgrimes bp->b_flags &= ~B_INUSE; 2291558Srgrimes return (KEEPON); 2301558Srgrimes} 2311558Srgrimes 2321558Srgrimes/* 2331558Srgrimes * Check that a block in a legal block number. 2341558Srgrimes * Return 0 if in range, 1 if out of range. 2351558Srgrimes */ 2367585Sbdeint 2371558Srgrimeschkrange(blk, cnt) 23823675Speter ufs_daddr_t blk; 2391558Srgrimes int cnt; 2401558Srgrimes{ 2411558Srgrimes register int c; 2421558Srgrimes 24341474Sjulian if (cnt <= 0 || blk <= 0 || blk > maxfsblock || 24441474Sjulian cnt - 1 > maxfsblock - blk) 2451558Srgrimes return (1); 24641474Sjulian if (cnt > sblock.fs_frag || 24741474Sjulian fragnum(&sblock, blk) + cnt > sblock.fs_frag) { 24841474Sjulian if (debug) 24941474Sjulian printf("bad size: blk %ld, offset %ld, size %ld\n", 25041474Sjulian blk, fragnum(&sblock, blk), cnt); 25141474Sjulian return (1); 25241474Sjulian } 2531558Srgrimes c = dtog(&sblock, blk); 2541558Srgrimes if (blk < cgdmin(&sblock, c)) { 2551558Srgrimes if ((blk + cnt) > cgsblock(&sblock, c)) { 2561558Srgrimes if (debug) { 2571558Srgrimes printf("blk %ld < cgdmin %ld;", 25837236Sbde (long)blk, (long)cgdmin(&sblock, c)); 2591558Srgrimes printf(" blk + cnt %ld > cgsbase %ld\n", 26037236Sbde (long)(blk + cnt), 26137236Sbde (long)cgsblock(&sblock, c)); 2621558Srgrimes } 2631558Srgrimes return (1); 2641558Srgrimes } 2651558Srgrimes } else { 2661558Srgrimes if ((blk + cnt) > cgbase(&sblock, c+1)) { 2671558Srgrimes if (debug) { 2681558Srgrimes printf("blk %ld >= cgdmin %ld;", 26937236Sbde (long)blk, (long)cgdmin(&sblock, c)); 2701558Srgrimes printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", 27137236Sbde (long)(blk + cnt), (long)sblock.fs_fpg); 2721558Srgrimes } 2731558Srgrimes return (1); 2741558Srgrimes } 2751558Srgrimes } 2761558Srgrimes return (0); 2771558Srgrimes} 2781558Srgrimes 2791558Srgrimes/* 2801558Srgrimes * General purpose interface for reading inodes. 2811558Srgrimes */ 2821558Srgrimesstruct dinode * 2831558Srgrimesginode(inumber) 2841558Srgrimes ino_t inumber; 2851558Srgrimes{ 28623675Speter ufs_daddr_t iblk; 2871558Srgrimes 2881558Srgrimes if (inumber < ROOTINO || inumber > maxino) 28923675Speter errx(EEXIT, "bad inode number %d to ginode", inumber); 2901558Srgrimes if (startinum == 0 || 2911558Srgrimes inumber < startinum || inumber >= startinum + INOPB(&sblock)) { 2921558Srgrimes iblk = ino_to_fsba(&sblock, inumber); 2931558Srgrimes if (pbp != 0) 2941558Srgrimes pbp->b_flags &= ~B_INUSE; 2951558Srgrimes pbp = getdatablk(iblk, sblock.fs_bsize); 2961558Srgrimes startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); 2971558Srgrimes } 2981558Srgrimes return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); 2991558Srgrimes} 3001558Srgrimes 3011558Srgrimes/* 3021558Srgrimes * Special purpose version of ginode used to optimize first pass 3031558Srgrimes * over all the inodes in numerical order. 3041558Srgrimes */ 3051558Srgrimesino_t nextino, lastinum; 3061558Srgrimeslong readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 3071558Srgrimesstruct dinode *inodebuf; 3081558Srgrimes 3091558Srgrimesstruct dinode * 3101558Srgrimesgetnextinode(inumber) 3111558Srgrimes ino_t inumber; 3121558Srgrimes{ 3131558Srgrimes long size; 31423675Speter ufs_daddr_t dblk; 3151558Srgrimes static struct dinode *dp; 3161558Srgrimes 3171558Srgrimes if (inumber != nextino++ || inumber > maxino) 31823675Speter errx(EEXIT, "bad inode number %d to nextinode", inumber); 3191558Srgrimes if (inumber >= lastinum) { 3201558Srgrimes readcnt++; 3211558Srgrimes dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); 3221558Srgrimes if (readcnt % readpercg == 0) { 3231558Srgrimes size = partialsize; 3241558Srgrimes lastinum += partialcnt; 3251558Srgrimes } else { 3261558Srgrimes size = inobufsize; 3271558Srgrimes lastinum += fullcnt; 3281558Srgrimes } 32941474Sjulian /* 33041474Sjulian * If bread returns an error, it will already have zeroed 33141474Sjulian * out the buffer, so we do not need to do so here. 33241474Sjulian */ 33341474Sjulian (void)bread(fsreadfd, (char *)inodebuf, dblk, size); 3341558Srgrimes dp = inodebuf; 3351558Srgrimes } 3361558Srgrimes return (dp++); 3371558Srgrimes} 3381558Srgrimes 3397585Sbdevoid 34041474Sjuliansetinodebuf(inum) 34141474Sjulian ino_t inum; 3421558Srgrimes{ 3431558Srgrimes 34441474Sjulian if (inum % sblock.fs_ipg != 0) 34541474Sjulian errx(EEXIT, "bad inode number %d to setinodebuf", inum); 3461558Srgrimes startinum = 0; 34741474Sjulian nextino = inum; 34841474Sjulian lastinum = inum; 3491558Srgrimes readcnt = 0; 35041474Sjulian if (inodebuf != NULL) 35141474Sjulian return; 3521558Srgrimes inobufsize = blkroundup(&sblock, INOBUFSIZE); 3531558Srgrimes fullcnt = inobufsize / sizeof(struct dinode); 3541558Srgrimes readpercg = sblock.fs_ipg / fullcnt; 3551558Srgrimes partialcnt = sblock.fs_ipg % fullcnt; 3561558Srgrimes partialsize = partialcnt * sizeof(struct dinode); 3571558Srgrimes if (partialcnt != 0) { 3581558Srgrimes readpercg++; 3591558Srgrimes } else { 3601558Srgrimes partialcnt = fullcnt; 3611558Srgrimes partialsize = inobufsize; 3621558Srgrimes } 36341474Sjulian if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) 36437000Scharnier errx(EEXIT, "cannot allocate space for inode buffer"); 3651558Srgrimes} 3661558Srgrimes 3677585Sbdevoid 3681558Srgrimesfreeinodebuf() 3691558Srgrimes{ 3701558Srgrimes 3711558Srgrimes if (inodebuf != NULL) 3721558Srgrimes free((char *)inodebuf); 3731558Srgrimes inodebuf = NULL; 3741558Srgrimes} 3751558Srgrimes 3761558Srgrimes/* 3771558Srgrimes * Routines to maintain information about directory inodes. 3781558Srgrimes * This is built during the first pass and used during the 3791558Srgrimes * second and third passes. 3801558Srgrimes * 3811558Srgrimes * Enter inodes into the cache. 3821558Srgrimes */ 3837585Sbdevoid 3841558Srgrimescacheino(dp, inumber) 3851558Srgrimes register struct dinode *dp; 3861558Srgrimes ino_t inumber; 3871558Srgrimes{ 3881558Srgrimes register struct inoinfo *inp; 3891558Srgrimes struct inoinfo **inpp; 39038002Sdfr int blks; 3911558Srgrimes 3921558Srgrimes blks = howmany(dp->di_size, sblock.fs_bsize); 3931558Srgrimes if (blks > NDADDR) 3941558Srgrimes blks = NDADDR + NIADDR; 3951558Srgrimes inp = (struct inoinfo *) 39623675Speter malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t)); 3971558Srgrimes if (inp == NULL) 39841474Sjulian errx(EEXIT, "cannot increase directory list"); 39957573Smckusick inpp = &inphead[inumber % dirhash]; 4001558Srgrimes inp->i_nexthash = *inpp; 4011558Srgrimes *inpp = inp; 40241474Sjulian inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0; 4031558Srgrimes inp->i_dotdot = (ino_t)0; 4041558Srgrimes inp->i_number = inumber; 4051558Srgrimes inp->i_isize = dp->di_size; 40623675Speter inp->i_numblks = blks * sizeof(ufs_daddr_t); 40723675Speter memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks); 4081558Srgrimes if (inplast == listmax) { 4091558Srgrimes listmax += 100; 4101558Srgrimes inpsort = (struct inoinfo **)realloc((char *)inpsort, 4111558Srgrimes (unsigned)listmax * sizeof(struct inoinfo *)); 4121558Srgrimes if (inpsort == NULL) 41323675Speter errx(EEXIT, "cannot increase directory list"); 4141558Srgrimes } 4151558Srgrimes inpsort[inplast++] = inp; 4161558Srgrimes} 4171558Srgrimes 4181558Srgrimes/* 4191558Srgrimes * Look up an inode cache structure. 4201558Srgrimes */ 4211558Srgrimesstruct inoinfo * 4221558Srgrimesgetinoinfo(inumber) 4231558Srgrimes ino_t inumber; 4241558Srgrimes{ 4251558Srgrimes register struct inoinfo *inp; 4261558Srgrimes 42757573Smckusick for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) { 4281558Srgrimes if (inp->i_number != inumber) 4291558Srgrimes continue; 4301558Srgrimes return (inp); 4311558Srgrimes } 43223675Speter errx(EEXIT, "cannot find inode %d", inumber); 4331558Srgrimes return ((struct inoinfo *)0); 4341558Srgrimes} 4351558Srgrimes 4361558Srgrimes/* 4371558Srgrimes * Clean up all the inode cache structure. 4381558Srgrimes */ 4397585Sbdevoid 4401558Srgrimesinocleanup() 4411558Srgrimes{ 4421558Srgrimes register struct inoinfo **inpp; 4431558Srgrimes 4441558Srgrimes if (inphead == NULL) 4451558Srgrimes return; 4461558Srgrimes for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 4471558Srgrimes free((char *)(*inpp)); 4481558Srgrimes free((char *)inphead); 4491558Srgrimes free((char *)inpsort); 4501558Srgrimes inphead = inpsort = NULL; 4511558Srgrimes} 4528871Srgrimes 4537585Sbdevoid 4541558Srgrimesinodirty() 4551558Srgrimes{ 45623797Sbde 4571558Srgrimes dirty(pbp); 4581558Srgrimes} 4591558Srgrimes 4607585Sbdevoid 4611558Srgrimesclri(idesc, type, flag) 4621558Srgrimes register struct inodesc *idesc; 4631558Srgrimes char *type; 4641558Srgrimes int flag; 4651558Srgrimes{ 4661558Srgrimes register struct dinode *dp; 4671558Srgrimes 4681558Srgrimes dp = ginode(idesc->id_number); 4691558Srgrimes if (flag == 1) { 4701558Srgrimes pwarn("%s %s", type, 4711558Srgrimes (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); 4721558Srgrimes pinode(idesc->id_number); 4731558Srgrimes } 4741558Srgrimes if (preen || reply("CLEAR") == 1) { 4751558Srgrimes if (preen) 4761558Srgrimes printf(" (CLEARED)\n"); 4771558Srgrimes n_files--; 4781558Srgrimes (void)ckinode(dp, idesc); 4791558Srgrimes clearinode(dp); 48041474Sjulian inoinfo(idesc->id_number)->ino_state = USTATE; 4811558Srgrimes inodirty(); 4821558Srgrimes } 4831558Srgrimes} 4841558Srgrimes 4857585Sbdeint 4861558Srgrimesfindname(idesc) 4871558Srgrimes struct inodesc *idesc; 4881558Srgrimes{ 4891558Srgrimes register struct direct *dirp = idesc->id_dirp; 4901558Srgrimes 49141474Sjulian if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 49241474Sjulian idesc->id_entryno++; 4931558Srgrimes return (KEEPON); 49441474Sjulian } 49523675Speter memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1); 4961558Srgrimes return (STOP|FOUND); 4971558Srgrimes} 4981558Srgrimes 4997585Sbdeint 5001558Srgrimesfindino(idesc) 5011558Srgrimes struct inodesc *idesc; 5021558Srgrimes{ 5031558Srgrimes register struct direct *dirp = idesc->id_dirp; 5041558Srgrimes 5051558Srgrimes if (dirp->d_ino == 0) 5061558Srgrimes return (KEEPON); 5071558Srgrimes if (strcmp(dirp->d_name, idesc->id_name) == 0 && 5081558Srgrimes dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { 5091558Srgrimes idesc->id_parent = dirp->d_ino; 5101558Srgrimes return (STOP|FOUND); 5111558Srgrimes } 5121558Srgrimes return (KEEPON); 5131558Srgrimes} 5141558Srgrimes 51541474Sjulianint 51641474Sjulianclearentry(idesc) 51741474Sjulian struct inodesc *idesc; 51841474Sjulian{ 51941474Sjulian register struct direct *dirp = idesc->id_dirp; 52041474Sjulian 52141474Sjulian if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 52241474Sjulian idesc->id_entryno++; 52341474Sjulian return (KEEPON); 52441474Sjulian } 52541474Sjulian dirp->d_ino = 0; 52641474Sjulian return (STOP|FOUND|ALTERED); 52741474Sjulian} 52841474Sjulian 5297585Sbdevoid 5301558Srgrimespinode(ino) 5311558Srgrimes ino_t ino; 5321558Srgrimes{ 5331558Srgrimes register struct dinode *dp; 5341558Srgrimes register char *p; 5351558Srgrimes struct passwd *pw; 53624002Speter time_t t; 5371558Srgrimes 53837236Sbde printf(" I=%lu ", (u_long)ino); 5391558Srgrimes if (ino < ROOTINO || ino > maxino) 5401558Srgrimes return; 5411558Srgrimes dp = ginode(ino); 5421558Srgrimes printf(" OWNER="); 5431558Srgrimes if ((pw = getpwuid((int)dp->di_uid)) != 0) 5441558Srgrimes printf("%s ", pw->pw_name); 5451558Srgrimes else 5461558Srgrimes printf("%u ", (unsigned)dp->di_uid); 5471558Srgrimes printf("MODE=%o\n", dp->di_mode); 5481558Srgrimes if (preen) 5491558Srgrimes printf("%s: ", cdevname); 5501558Srgrimes printf("SIZE=%qu ", dp->di_size); 55124002Speter t = dp->di_mtime; 55224002Speter p = ctime(&t); 5531558Srgrimes printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); 5541558Srgrimes} 5551558Srgrimes 5567585Sbdevoid 5571558Srgrimesblkerror(ino, type, blk) 5581558Srgrimes ino_t ino; 5591558Srgrimes char *type; 56023675Speter ufs_daddr_t blk; 5611558Srgrimes{ 5621558Srgrimes 5631558Srgrimes pfatal("%ld %s I=%lu", blk, type, ino); 5641558Srgrimes printf("\n"); 56541474Sjulian switch (inoinfo(ino)->ino_state) { 5661558Srgrimes 5671558Srgrimes case FSTATE: 56841474Sjulian inoinfo(ino)->ino_state = FCLEAR; 5691558Srgrimes return; 5701558Srgrimes 5711558Srgrimes case DSTATE: 57241474Sjulian inoinfo(ino)->ino_state = DCLEAR; 5731558Srgrimes return; 5741558Srgrimes 5751558Srgrimes case FCLEAR: 5761558Srgrimes case DCLEAR: 5771558Srgrimes return; 5781558Srgrimes 5791558Srgrimes default: 58041474Sjulian errx(EEXIT, "BAD STATE %d TO BLKERR", inoinfo(ino)->ino_state); 5811558Srgrimes /* NOTREACHED */ 5821558Srgrimes } 5831558Srgrimes} 5841558Srgrimes 5851558Srgrimes/* 5861558Srgrimes * allocate an unused inode 5871558Srgrimes */ 5881558Srgrimesino_t 5891558Srgrimesallocino(request, type) 5901558Srgrimes ino_t request; 5911558Srgrimes int type; 5921558Srgrimes{ 5931558Srgrimes register ino_t ino; 5941558Srgrimes register struct dinode *dp; 59534266Sjulian struct cg *cgp = &cgrp; 59634266Sjulian int cg; 5971558Srgrimes 5981558Srgrimes if (request == 0) 5991558Srgrimes request = ROOTINO; 60041474Sjulian else if (inoinfo(request)->ino_state != USTATE) 6011558Srgrimes return (0); 6021558Srgrimes for (ino = request; ino < maxino; ino++) 60341474Sjulian if (inoinfo(ino)->ino_state == USTATE) 6041558Srgrimes break; 6051558Srgrimes if (ino == maxino) 6061558Srgrimes return (0); 60734266Sjulian cg = ino_to_cg(&sblock, ino); 60834266Sjulian getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 60934266Sjulian if (!cg_chkmagic(cgp)) 61034266Sjulian pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 61134266Sjulian setbit(cg_inosused(cgp), ino % sblock.fs_ipg); 61234266Sjulian cgp->cg_cs.cs_nifree--; 6131558Srgrimes switch (type & IFMT) { 6141558Srgrimes case IFDIR: 61541474Sjulian inoinfo(ino)->ino_state = DSTATE; 61634266Sjulian cgp->cg_cs.cs_ndir++; 6171558Srgrimes break; 6181558Srgrimes case IFREG: 6191558Srgrimes case IFLNK: 62041474Sjulian inoinfo(ino)->ino_state = FSTATE; 6211558Srgrimes break; 6221558Srgrimes default: 6231558Srgrimes return (0); 6241558Srgrimes } 62534266Sjulian cgdirty(); 6261558Srgrimes dp = ginode(ino); 6271558Srgrimes dp->di_db[0] = allocblk((long)1); 6281558Srgrimes if (dp->di_db[0] == 0) { 62941474Sjulian inoinfo(ino)->ino_state = USTATE; 6301558Srgrimes return (0); 6311558Srgrimes } 63241474Sjulian dp->di_mode = type; 63334266Sjulian dp->di_flags = 0; 63424002Speter dp->di_atime = time(NULL); 6351558Srgrimes dp->di_mtime = dp->di_ctime = dp->di_atime; 63641477Sjulian dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0; 6371558Srgrimes dp->di_size = sblock.fs_fsize; 6381558Srgrimes dp->di_blocks = btodb(sblock.fs_fsize); 6391558Srgrimes n_files++; 6401558Srgrimes inodirty(); 6411558Srgrimes if (newinofmt) 64241474Sjulian inoinfo(ino)->ino_type = IFTODT(type); 6431558Srgrimes return (ino); 6441558Srgrimes} 6451558Srgrimes 6461558Srgrimes/* 6471558Srgrimes * deallocate an inode 6481558Srgrimes */ 6497585Sbdevoid 6501558Srgrimesfreeino(ino) 6511558Srgrimes ino_t ino; 6521558Srgrimes{ 6531558Srgrimes struct inodesc idesc; 6541558Srgrimes struct dinode *dp; 6551558Srgrimes 65623675Speter memset(&idesc, 0, sizeof(struct inodesc)); 6571558Srgrimes idesc.id_type = ADDR; 6581558Srgrimes idesc.id_func = pass4check; 6591558Srgrimes idesc.id_number = ino; 6601558Srgrimes dp = ginode(ino); 6611558Srgrimes (void)ckinode(dp, &idesc); 6621558Srgrimes clearinode(dp); 6631558Srgrimes inodirty(); 66441474Sjulian inoinfo(ino)->ino_state = USTATE; 6651558Srgrimes n_files--; 6661558Srgrimes} 667