inode.c revision 37236
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 3537000Scharnier#if 0 3623675Speterstatic const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95"; 3737000Scharnier#endif 3837000Scharnierstatic const char rcsid[] = 3937236Sbde "$Id: inode.c,v 1.14 1998/06/15 07:07:12 charnier Exp $"; 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; 6523675Speter long ret, n, ndb, offset; 661558Srgrimes struct dinode dino; 671558Srgrimes quad_t remsize, sizepb; 681558Srgrimes mode_t mode; 6918808Sguido char pathbuf[MAXPATHLEN + 1]; 701558Srgrimes 711558Srgrimes if (idesc->id_fix != IGNORE) 721558Srgrimes idesc->id_fix = DONTKNOW; 731558Srgrimes idesc->id_entryno = 0; 741558Srgrimes idesc->id_filesize = dp->di_size; 751558Srgrimes mode = dp->di_mode & IFMT; 761558Srgrimes if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 771820Sdg (dp->di_size < sblock.fs_maxsymlinklen || dp->di_blocks == 0))) 781558Srgrimes return (KEEPON); 791558Srgrimes dino = *dp; 801558Srgrimes ndb = howmany(dino.di_size, sblock.fs_bsize); 811558Srgrimes for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { 821558Srgrimes if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) 831558Srgrimes idesc->id_numfrags = 841558Srgrimes numfrags(&sblock, fragroundup(&sblock, offset)); 851558Srgrimes else 861558Srgrimes idesc->id_numfrags = sblock.fs_frag; 8718808Sguido if (*ap == 0) { 8818808Sguido if (idesc->id_type == DATA && ndb >= 0) { 8918808Sguido /* An empty block in a directory XXX */ 9018808Sguido getpathname(pathbuf, idesc->id_number, 9118808Sguido idesc->id_number); 9218808Sguido pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 9318808Sguido pathbuf); 9418808Sguido if (reply("ADJUST LENGTH") == 1) { 9518808Sguido dp = ginode(idesc->id_number); 9618808Sguido dp->di_size = (ap - &dino.di_db[0]) * 9718808Sguido sblock.fs_bsize; 9818808Sguido printf( 9918808Sguido "YOU MUST RERUN FSCK AFTERWARDS\n"); 10018808Sguido rerun = 1; 10118808Sguido inodirty(); 10218808Sguido 10318808Sguido } 10418808Sguido } 1051558Srgrimes continue; 10618808Sguido } 1071558Srgrimes idesc->id_blkno = *ap; 1081558Srgrimes if (idesc->id_type == ADDR) 1091558Srgrimes ret = (*idesc->id_func)(idesc); 1101558Srgrimes else 1111558Srgrimes ret = dirscan(idesc); 1121558Srgrimes if (ret & STOP) 1131558Srgrimes return (ret); 1141558Srgrimes } 1151558Srgrimes idesc->id_numfrags = sblock.fs_frag; 1161558Srgrimes remsize = dino.di_size - sblock.fs_bsize * NDADDR; 1171558Srgrimes sizepb = sblock.fs_bsize; 1181558Srgrimes for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { 1191558Srgrimes if (*ap) { 1201558Srgrimes idesc->id_blkno = *ap; 1211558Srgrimes ret = iblock(idesc, n, remsize); 1221558Srgrimes if (ret & STOP) 1231558Srgrimes return (ret); 12418808Sguido } else { 12518808Sguido if (idesc->id_type == DATA && remsize > 0) { 12618808Sguido /* An empty block in a directory XXX */ 12718808Sguido getpathname(pathbuf, idesc->id_number, 12818808Sguido idesc->id_number); 12918808Sguido pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 13018808Sguido pathbuf); 13118808Sguido if (reply("ADJUST LENGTH") == 1) { 13218808Sguido dp = ginode(idesc->id_number); 13318808Sguido dp->di_size -= remsize; 13418808Sguido remsize = 0; 13518808Sguido printf( 13618808Sguido "YOU MUST RERUN FSCK AFTERWARDS\n"); 13718808Sguido rerun = 1; 13818808Sguido inodirty(); 13918808Sguido break; 14018808Sguido } 14118808Sguido } 1421558Srgrimes } 1431558Srgrimes sizepb *= NINDIR(&sblock); 1441558Srgrimes remsize -= sizepb; 1451558Srgrimes } 1461558Srgrimes return (KEEPON); 1471558Srgrimes} 1481558Srgrimes 1497585Sbdestatic int 1501558Srgrimesiblock(idesc, ilevel, isize) 1511558Srgrimes struct inodesc *idesc; 1521558Srgrimes long ilevel; 1531558Srgrimes quad_t isize; 1541558Srgrimes{ 15523675Speter ufs_daddr_t *ap; 15623675Speter ufs_daddr_t *aplim; 15723675Speter struct bufarea *bp; 1581558Srgrimes int i, n, (*func)(), nif; 1591558Srgrimes quad_t sizepb; 1601558Srgrimes char buf[BUFSIZ]; 16118808Sguido char pathbuf[MAXPATHLEN + 1]; 16218808Sguido struct dinode *dp; 1631558Srgrimes 1641558Srgrimes if (idesc->id_type == ADDR) { 1651558Srgrimes func = idesc->id_func; 1661558Srgrimes if (((n = (*func)(idesc)) & KEEPON) == 0) 1671558Srgrimes return (n); 1681558Srgrimes } else 1691558Srgrimes func = dirscan; 1701558Srgrimes if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 1711558Srgrimes return (SKIP); 1721558Srgrimes bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); 1731558Srgrimes ilevel--; 1741558Srgrimes for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) 1751558Srgrimes sizepb *= NINDIR(&sblock); 1761558Srgrimes nif = howmany(isize , sizepb); 1771558Srgrimes if (nif > NINDIR(&sblock)) 1781558Srgrimes nif = NINDIR(&sblock); 1791558Srgrimes if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { 1801558Srgrimes aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; 1811558Srgrimes for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { 1821558Srgrimes if (*ap == 0) 1831558Srgrimes continue; 1841558Srgrimes (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", 18537236Sbde (u_long)idesc->id_number); 1861558Srgrimes if (dofix(idesc, buf)) { 1871558Srgrimes *ap = 0; 1881558Srgrimes dirty(bp); 1891558Srgrimes } 1901558Srgrimes } 1911558Srgrimes flush(fswritefd, bp); 1921558Srgrimes } 1931558Srgrimes aplim = &bp->b_un.b_indir[nif]; 1941558Srgrimes for (ap = bp->b_un.b_indir; ap < aplim; ap++) { 1951558Srgrimes if (*ap) { 1961558Srgrimes idesc->id_blkno = *ap; 1971558Srgrimes if (ilevel == 0) 1981558Srgrimes n = (*func)(idesc); 1991558Srgrimes else 2001558Srgrimes n = iblock(idesc, ilevel, isize); 2011558Srgrimes if (n & STOP) { 2021558Srgrimes bp->b_flags &= ~B_INUSE; 2031558Srgrimes return (n); 2041558Srgrimes } 20518808Sguido } else { 20618808Sguido if (idesc->id_type == DATA && isize > 0) { 20718808Sguido /* An empty block in a directory XXX */ 20818808Sguido getpathname(pathbuf, idesc->id_number, 20918808Sguido idesc->id_number); 21018808Sguido pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 21118808Sguido pathbuf); 21218808Sguido if (reply("ADJUST LENGTH") == 1) { 21318808Sguido dp = ginode(idesc->id_number); 21418808Sguido dp->di_size -= isize; 21518808Sguido isize = 0; 21618808Sguido printf( 21718808Sguido "YOU MUST RERUN FSCK AFTERWARDS\n"); 21818808Sguido rerun = 1; 21918808Sguido inodirty(); 22018808Sguido bp->b_flags &= ~B_INUSE; 22118808Sguido return(STOP); 22218808Sguido } 22318808Sguido } 2241558Srgrimes } 2251558Srgrimes isize -= sizepb; 2261558Srgrimes } 2271558Srgrimes bp->b_flags &= ~B_INUSE; 2281558Srgrimes return (KEEPON); 2291558Srgrimes} 2301558Srgrimes 2311558Srgrimes/* 2321558Srgrimes * Check that a block in a legal block number. 2331558Srgrimes * Return 0 if in range, 1 if out of range. 2341558Srgrimes */ 2357585Sbdeint 2361558Srgrimeschkrange(blk, cnt) 23723675Speter ufs_daddr_t blk; 2381558Srgrimes int cnt; 2391558Srgrimes{ 2401558Srgrimes register int c; 2411558Srgrimes 24231910Sbde if (blk < 0 || blk >= maxfsblock || cnt < 0 || cnt > maxfsblock - blk) 2431558Srgrimes return (1); 2441558Srgrimes c = dtog(&sblock, blk); 2451558Srgrimes if (blk < cgdmin(&sblock, c)) { 2461558Srgrimes if ((blk + cnt) > cgsblock(&sblock, c)) { 2471558Srgrimes if (debug) { 2481558Srgrimes printf("blk %ld < cgdmin %ld;", 24937236Sbde (long)blk, (long)cgdmin(&sblock, c)); 2501558Srgrimes printf(" blk + cnt %ld > cgsbase %ld\n", 25137236Sbde (long)(blk + cnt), 25237236Sbde (long)cgsblock(&sblock, c)); 2531558Srgrimes } 2541558Srgrimes return (1); 2551558Srgrimes } 2561558Srgrimes } else { 2571558Srgrimes if ((blk + cnt) > cgbase(&sblock, c+1)) { 2581558Srgrimes if (debug) { 2591558Srgrimes printf("blk %ld >= cgdmin %ld;", 26037236Sbde (long)blk, (long)cgdmin(&sblock, c)); 2611558Srgrimes printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", 26237236Sbde (long)(blk + cnt), (long)sblock.fs_fpg); 2631558Srgrimes } 2641558Srgrimes return (1); 2651558Srgrimes } 2661558Srgrimes } 2671558Srgrimes return (0); 2681558Srgrimes} 2691558Srgrimes 2701558Srgrimes/* 2711558Srgrimes * General purpose interface for reading inodes. 2721558Srgrimes */ 2731558Srgrimesstruct dinode * 2741558Srgrimesginode(inumber) 2751558Srgrimes ino_t inumber; 2761558Srgrimes{ 27723675Speter ufs_daddr_t iblk; 2781558Srgrimes 2791558Srgrimes if (inumber < ROOTINO || inumber > maxino) 28023675Speter errx(EEXIT, "bad inode number %d to ginode", inumber); 2811558Srgrimes if (startinum == 0 || 2821558Srgrimes inumber < startinum || inumber >= startinum + INOPB(&sblock)) { 2831558Srgrimes iblk = ino_to_fsba(&sblock, inumber); 2841558Srgrimes if (pbp != 0) 2851558Srgrimes pbp->b_flags &= ~B_INUSE; 2861558Srgrimes pbp = getdatablk(iblk, sblock.fs_bsize); 2871558Srgrimes startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); 2881558Srgrimes } 2891558Srgrimes return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); 2901558Srgrimes} 2911558Srgrimes 2921558Srgrimes/* 2931558Srgrimes * Special purpose version of ginode used to optimize first pass 2941558Srgrimes * over all the inodes in numerical order. 2951558Srgrimes */ 2961558Srgrimesino_t nextino, lastinum; 2971558Srgrimeslong readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 2981558Srgrimesstruct dinode *inodebuf; 2991558Srgrimes 3001558Srgrimesstruct dinode * 3011558Srgrimesgetnextinode(inumber) 3021558Srgrimes ino_t inumber; 3031558Srgrimes{ 3041558Srgrimes long size; 30523675Speter ufs_daddr_t dblk; 3061558Srgrimes static struct dinode *dp; 3071558Srgrimes 3081558Srgrimes if (inumber != nextino++ || inumber > maxino) 30923675Speter errx(EEXIT, "bad inode number %d to nextinode", inumber); 3101558Srgrimes if (inumber >= lastinum) { 3111558Srgrimes readcnt++; 3121558Srgrimes dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); 3131558Srgrimes if (readcnt % readpercg == 0) { 3141558Srgrimes size = partialsize; 3151558Srgrimes lastinum += partialcnt; 3161558Srgrimes } else { 3171558Srgrimes size = inobufsize; 3181558Srgrimes lastinum += fullcnt; 3191558Srgrimes } 3201558Srgrimes (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */ 3211558Srgrimes dp = inodebuf; 3221558Srgrimes } 3231558Srgrimes return (dp++); 3241558Srgrimes} 3251558Srgrimes 3267585Sbdevoid 3271558Srgrimesresetinodebuf() 3281558Srgrimes{ 3291558Srgrimes 3301558Srgrimes startinum = 0; 3311558Srgrimes nextino = 0; 3321558Srgrimes lastinum = 0; 3331558Srgrimes readcnt = 0; 3341558Srgrimes inobufsize = blkroundup(&sblock, INOBUFSIZE); 3351558Srgrimes fullcnt = inobufsize / sizeof(struct dinode); 3361558Srgrimes readpercg = sblock.fs_ipg / fullcnt; 3371558Srgrimes partialcnt = sblock.fs_ipg % fullcnt; 3381558Srgrimes partialsize = partialcnt * sizeof(struct dinode); 3391558Srgrimes if (partialcnt != 0) { 3401558Srgrimes readpercg++; 3411558Srgrimes } else { 3421558Srgrimes partialcnt = fullcnt; 3431558Srgrimes partialsize = inobufsize; 3441558Srgrimes } 3451558Srgrimes if (inodebuf == NULL && 3461558Srgrimes (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) 34737000Scharnier errx(EEXIT, "cannot allocate space for inode buffer"); 3481558Srgrimes while (nextino < ROOTINO) 3491558Srgrimes (void)getnextinode(nextino); 3501558Srgrimes} 3511558Srgrimes 3527585Sbdevoid 3531558Srgrimesfreeinodebuf() 3541558Srgrimes{ 3551558Srgrimes 3561558Srgrimes if (inodebuf != NULL) 3571558Srgrimes free((char *)inodebuf); 3581558Srgrimes inodebuf = NULL; 3591558Srgrimes} 3601558Srgrimes 3611558Srgrimes/* 3621558Srgrimes * Routines to maintain information about directory inodes. 3631558Srgrimes * This is built during the first pass and used during the 3641558Srgrimes * second and third passes. 3651558Srgrimes * 3661558Srgrimes * Enter inodes into the cache. 3671558Srgrimes */ 3687585Sbdevoid 3691558Srgrimescacheino(dp, inumber) 3701558Srgrimes register struct dinode *dp; 3711558Srgrimes ino_t inumber; 3721558Srgrimes{ 3731558Srgrimes register struct inoinfo *inp; 3741558Srgrimes struct inoinfo **inpp; 3751558Srgrimes unsigned int blks; 3761558Srgrimes 3771558Srgrimes blks = howmany(dp->di_size, sblock.fs_bsize); 3781558Srgrimes if (blks > NDADDR) 3791558Srgrimes blks = NDADDR + NIADDR; 3801558Srgrimes inp = (struct inoinfo *) 38123675Speter malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t)); 3821558Srgrimes if (inp == NULL) 3831558Srgrimes return; 3841558Srgrimes inpp = &inphead[inumber % numdirs]; 3851558Srgrimes inp->i_nexthash = *inpp; 3861558Srgrimes *inpp = inp; 3876404Sdg if (inumber == ROOTINO) 3886404Sdg inp->i_parent = ROOTINO; 3896404Sdg else 3906404Sdg inp->i_parent = (ino_t)0; 3911558Srgrimes inp->i_dotdot = (ino_t)0; 3921558Srgrimes inp->i_number = inumber; 3931558Srgrimes inp->i_isize = dp->di_size; 39423675Speter inp->i_numblks = blks * sizeof(ufs_daddr_t); 39523675Speter memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks); 3961558Srgrimes if (inplast == listmax) { 3971558Srgrimes listmax += 100; 3981558Srgrimes inpsort = (struct inoinfo **)realloc((char *)inpsort, 3991558Srgrimes (unsigned)listmax * sizeof(struct inoinfo *)); 4001558Srgrimes if (inpsort == NULL) 40123675Speter errx(EEXIT, "cannot increase directory list"); 4021558Srgrimes } 4031558Srgrimes inpsort[inplast++] = inp; 4041558Srgrimes} 4051558Srgrimes 4061558Srgrimes/* 4071558Srgrimes * Look up an inode cache structure. 4081558Srgrimes */ 4091558Srgrimesstruct inoinfo * 4101558Srgrimesgetinoinfo(inumber) 4111558Srgrimes ino_t inumber; 4121558Srgrimes{ 4131558Srgrimes register struct inoinfo *inp; 4141558Srgrimes 4151558Srgrimes for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) { 4161558Srgrimes if (inp->i_number != inumber) 4171558Srgrimes continue; 4181558Srgrimes return (inp); 4191558Srgrimes } 42023675Speter errx(EEXIT, "cannot find inode %d", inumber); 4211558Srgrimes return ((struct inoinfo *)0); 4221558Srgrimes} 4231558Srgrimes 4241558Srgrimes/* 4251558Srgrimes * Clean up all the inode cache structure. 4261558Srgrimes */ 4277585Sbdevoid 4281558Srgrimesinocleanup() 4291558Srgrimes{ 4301558Srgrimes register struct inoinfo **inpp; 4311558Srgrimes 4321558Srgrimes if (inphead == NULL) 4331558Srgrimes return; 4341558Srgrimes for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 4351558Srgrimes free((char *)(*inpp)); 4361558Srgrimes free((char *)inphead); 4371558Srgrimes free((char *)inpsort); 4381558Srgrimes inphead = inpsort = NULL; 4391558Srgrimes} 4408871Srgrimes 4417585Sbdevoid 4421558Srgrimesinodirty() 4431558Srgrimes{ 44423797Sbde 4451558Srgrimes dirty(pbp); 4461558Srgrimes} 4471558Srgrimes 4487585Sbdevoid 4491558Srgrimesclri(idesc, type, flag) 4501558Srgrimes register struct inodesc *idesc; 4511558Srgrimes char *type; 4521558Srgrimes int flag; 4531558Srgrimes{ 4541558Srgrimes register struct dinode *dp; 4551558Srgrimes 4561558Srgrimes dp = ginode(idesc->id_number); 4571558Srgrimes if (flag == 1) { 4581558Srgrimes pwarn("%s %s", type, 4591558Srgrimes (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); 4601558Srgrimes pinode(idesc->id_number); 4611558Srgrimes } 4621558Srgrimes if (preen || reply("CLEAR") == 1) { 4631558Srgrimes if (preen) 4641558Srgrimes printf(" (CLEARED)\n"); 4651558Srgrimes n_files--; 4661558Srgrimes (void)ckinode(dp, idesc); 4671558Srgrimes clearinode(dp); 4681558Srgrimes statemap[idesc->id_number] = USTATE; 4691558Srgrimes inodirty(); 4701558Srgrimes } 4711558Srgrimes} 4721558Srgrimes 4737585Sbdeint 4741558Srgrimesfindname(idesc) 4751558Srgrimes struct inodesc *idesc; 4761558Srgrimes{ 4771558Srgrimes register struct direct *dirp = idesc->id_dirp; 4781558Srgrimes 4791558Srgrimes if (dirp->d_ino != idesc->id_parent) 4801558Srgrimes return (KEEPON); 48123675Speter memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1); 4821558Srgrimes return (STOP|FOUND); 4831558Srgrimes} 4841558Srgrimes 4857585Sbdeint 4861558Srgrimesfindino(idesc) 4871558Srgrimes struct inodesc *idesc; 4881558Srgrimes{ 4891558Srgrimes register struct direct *dirp = idesc->id_dirp; 4901558Srgrimes 4911558Srgrimes if (dirp->d_ino == 0) 4921558Srgrimes return (KEEPON); 4931558Srgrimes if (strcmp(dirp->d_name, idesc->id_name) == 0 && 4941558Srgrimes dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { 4951558Srgrimes idesc->id_parent = dirp->d_ino; 4961558Srgrimes return (STOP|FOUND); 4971558Srgrimes } 4981558Srgrimes return (KEEPON); 4991558Srgrimes} 5001558Srgrimes 5017585Sbdevoid 5021558Srgrimespinode(ino) 5031558Srgrimes ino_t ino; 5041558Srgrimes{ 5051558Srgrimes register struct dinode *dp; 5061558Srgrimes register char *p; 5071558Srgrimes struct passwd *pw; 50824002Speter time_t t; 5091558Srgrimes 51037236Sbde printf(" I=%lu ", (u_long)ino); 5111558Srgrimes if (ino < ROOTINO || ino > maxino) 5121558Srgrimes return; 5131558Srgrimes dp = ginode(ino); 5141558Srgrimes printf(" OWNER="); 5151558Srgrimes if ((pw = getpwuid((int)dp->di_uid)) != 0) 5161558Srgrimes printf("%s ", pw->pw_name); 5171558Srgrimes else 5181558Srgrimes printf("%u ", (unsigned)dp->di_uid); 5191558Srgrimes printf("MODE=%o\n", dp->di_mode); 5201558Srgrimes if (preen) 5211558Srgrimes printf("%s: ", cdevname); 5221558Srgrimes printf("SIZE=%qu ", dp->di_size); 52324002Speter t = dp->di_mtime; 52424002Speter p = ctime(&t); 5251558Srgrimes printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); 5261558Srgrimes} 5271558Srgrimes 5287585Sbdevoid 5291558Srgrimesblkerror(ino, type, blk) 5301558Srgrimes ino_t ino; 5311558Srgrimes char *type; 53223675Speter ufs_daddr_t blk; 5331558Srgrimes{ 5341558Srgrimes 5351558Srgrimes pfatal("%ld %s I=%lu", blk, type, ino); 5361558Srgrimes printf("\n"); 5371558Srgrimes switch (statemap[ino]) { 5381558Srgrimes 5391558Srgrimes case FSTATE: 5401558Srgrimes statemap[ino] = FCLEAR; 5411558Srgrimes return; 5421558Srgrimes 5431558Srgrimes case DSTATE: 5441558Srgrimes statemap[ino] = DCLEAR; 5451558Srgrimes return; 5461558Srgrimes 5471558Srgrimes case FCLEAR: 5481558Srgrimes case DCLEAR: 5491558Srgrimes return; 5501558Srgrimes 5511558Srgrimes default: 55223675Speter errx(EEXIT, "BAD STATE %d TO BLKERR", statemap[ino]); 5531558Srgrimes /* NOTREACHED */ 5541558Srgrimes } 5551558Srgrimes} 5561558Srgrimes 5571558Srgrimes/* 5581558Srgrimes * allocate an unused inode 5591558Srgrimes */ 5601558Srgrimesino_t 5611558Srgrimesallocino(request, type) 5621558Srgrimes ino_t request; 5631558Srgrimes int type; 5641558Srgrimes{ 5651558Srgrimes register ino_t ino; 5661558Srgrimes register struct dinode *dp; 56734266Sjulian struct cg *cgp = &cgrp; 56834266Sjulian int cg; 5691558Srgrimes 5701558Srgrimes if (request == 0) 5711558Srgrimes request = ROOTINO; 5721558Srgrimes else if (statemap[request] != USTATE) 5731558Srgrimes return (0); 5741558Srgrimes for (ino = request; ino < maxino; ino++) 5751558Srgrimes if (statemap[ino] == USTATE) 5761558Srgrimes break; 5771558Srgrimes if (ino == maxino) 5781558Srgrimes return (0); 57934266Sjulian cg = ino_to_cg(&sblock, ino); 58034266Sjulian getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 58134266Sjulian if (!cg_chkmagic(cgp)) 58234266Sjulian pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 58334266Sjulian setbit(cg_inosused(cgp), ino % sblock.fs_ipg); 58434266Sjulian cgp->cg_cs.cs_nifree--; 5851558Srgrimes switch (type & IFMT) { 5861558Srgrimes case IFDIR: 5871558Srgrimes statemap[ino] = DSTATE; 58834266Sjulian cgp->cg_cs.cs_ndir++; 5891558Srgrimes break; 5901558Srgrimes case IFREG: 5911558Srgrimes case IFLNK: 5921558Srgrimes statemap[ino] = FSTATE; 5931558Srgrimes break; 5941558Srgrimes default: 5951558Srgrimes return (0); 5961558Srgrimes } 59734266Sjulian cgdirty(); 5981558Srgrimes dp = ginode(ino); 5991558Srgrimes dp->di_db[0] = allocblk((long)1); 6001558Srgrimes if (dp->di_db[0] == 0) { 6011558Srgrimes statemap[ino] = USTATE; 6021558Srgrimes return (0); 6031558Srgrimes } 60434266Sjulian dp->di_flags = 0; 6051558Srgrimes dp->di_mode = type; 60624002Speter dp->di_atime = time(NULL); 6071558Srgrimes dp->di_mtime = dp->di_ctime = dp->di_atime; 6081558Srgrimes dp->di_size = sblock.fs_fsize; 6091558Srgrimes dp->di_blocks = btodb(sblock.fs_fsize); 6101558Srgrimes n_files++; 6111558Srgrimes inodirty(); 6121558Srgrimes if (newinofmt) 6131558Srgrimes typemap[ino] = IFTODT(type); 6141558Srgrimes return (ino); 6151558Srgrimes} 6161558Srgrimes 6171558Srgrimes/* 6181558Srgrimes * deallocate an inode 6191558Srgrimes */ 6207585Sbdevoid 6211558Srgrimesfreeino(ino) 6221558Srgrimes ino_t ino; 6231558Srgrimes{ 6241558Srgrimes struct inodesc idesc; 6251558Srgrimes struct dinode *dp; 6261558Srgrimes 62723675Speter memset(&idesc, 0, sizeof(struct inodesc)); 6281558Srgrimes idesc.id_type = ADDR; 6291558Srgrimes idesc.id_func = pass4check; 6301558Srgrimes idesc.id_number = ino; 6311558Srgrimes dp = ginode(ino); 6321558Srgrimes (void)ckinode(dp, &idesc); 6331558Srgrimes clearinode(dp); 6341558Srgrimes inodirty(); 6351558Srgrimes statemap[ino] = USTATE; 6361558Srgrimes n_files--; 6371558Srgrimes} 638