inode.c revision 50476
160812Sps/* 260786Sps * Copyright (c) 1980, 1986, 1993 360786Sps * The Regents of the University of California. All rights reserved. 460786Sps * 560786Sps * Redistribution and use in source and binary forms, with or without 660786Sps * modification, are permitted provided that the following conditions 760786Sps * are met: 860786Sps * 1. Redistributions of source code must retain the above copyright 960786Sps * notice, this list of conditions and the following disclaimer. 1060786Sps * 2. Redistributions in binary form must reproduce the above copyright 1160786Sps * notice, this list of conditions and the following disclaimer in the 1260786Sps * documentation and/or other materials provided with the distribution. 1360786Sps * 3. All advertising materials mentioning features or use of this software 1460786Sps * must display the following acknowledgement: 1560786Sps * This product includes software developed by the University of 1660786Sps * California, Berkeley and its contributors. 1760786Sps * 4. Neither the name of the University nor the names of its contributors 1860786Sps * may be used to endorse or promote products derived from this software 1960786Sps * without specific prior written permission. 2060786Sps * 2160786Sps * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2260786Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2360786Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2460786Sps * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2560786Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2660812Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2760786Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2860786Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2960786Sps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3060786Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3160786Sps * SUCH DAMAGE. 3260786Sps */ 3360786Sps 3460786Sps#ifndef lint 3560786Sps#if 0 3660786Spsstatic const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95"; 3760786Sps#endif 3860786Spsstatic const char rcsid[] = 3960786Sps "$FreeBSD: head/sbin/fsck_ffs/inode.c 50476 1999-08-28 00:22:10Z peter $"; 4060786Sps#endif /* not lint */ 4160786Sps 4260786Sps#include <sys/param.h> 4360786Sps#include <sys/time.h> 4460786Sps 4560786Sps#include <ufs/ufs/dinode.h> 4660786Sps#include <ufs/ufs/dir.h> 4760786Sps#include <ufs/ffs/fs.h> 4860786Sps 4960786Sps#include <err.h> 5060786Sps#include <pwd.h> 5160786Sps#include <string.h> 5260786Sps 5360786Sps#include "fsck.h" 5460786Sps 5560786Spsstatic ino_t startinum; 5660812Sps 5763131Spsstatic int iblock __P((struct inodesc *, long ilevel, quad_t isize)); 5860786Sps 5960786Spsint 6060786Spsckinode(dp, idesc) 6160786Sps struct dinode *dp; 6260786Sps register struct inodesc *idesc; 6360786Sps{ 6460786Sps ufs_daddr_t *ap; 6560786Sps int ret; 6660786Sps long n, ndb, offset; 6760786Sps struct dinode dino; 6860786Sps quad_t remsize, sizepb; 6960786Sps mode_t mode; 7060786Sps char pathbuf[MAXPATHLEN + 1]; 7160786Sps 7260786Sps if (idesc->id_fix != IGNORE) 7360786Sps idesc->id_fix = DONTKNOW; 7460786Sps idesc->id_entryno = 0; 7560786Sps idesc->id_filesize = dp->di_size; 7660786Sps mode = dp->di_mode & IFMT; 7760786Sps if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 7860786Sps dp->di_size < (unsigned)sblock.fs_maxsymlinklen)) 7960786Sps return (KEEPON); 8060786Sps dino = *dp; 8160786Sps ndb = howmany(dino.di_size, sblock.fs_bsize); 8260786Sps for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { 8360786Sps if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) 8460786Sps idesc->id_numfrags = 8560786Sps numfrags(&sblock, fragroundup(&sblock, offset)); 8660786Sps else 8760786Sps idesc->id_numfrags = sblock.fs_frag; 8860786Sps if (*ap == 0) { 8960786Sps if (idesc->id_type == DATA && ndb >= 0) { 9060786Sps /* An empty block in a directory XXX */ 9160786Sps getpathname(pathbuf, idesc->id_number, 9260786Sps idesc->id_number); 9360786Sps pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 9460786Sps pathbuf); 9560786Sps if (reply("ADJUST LENGTH") == 1) { 9660786Sps dp = ginode(idesc->id_number); 9760786Sps dp->di_size = (ap - &dino.di_db[0]) * 9860786Sps sblock.fs_bsize; 9960786Sps printf( 10060786Sps "YOU MUST RERUN FSCK AFTERWARDS\n"); 10160786Sps rerun = 1; 10260786Sps inodirty(); 10360786Sps 10460786Sps } 10560786Sps } 10660786Sps continue; 10760786Sps } 10860786Sps idesc->id_blkno = *ap; 10960786Sps if (idesc->id_type == ADDR) 11060786Sps ret = (*idesc->id_func)(idesc); 11160786Sps else 11260786Sps ret = dirscan(idesc); 11360786Sps if (ret & STOP) 11460786Sps return (ret); 11560786Sps } 11660786Sps idesc->id_numfrags = sblock.fs_frag; 11760786Sps remsize = dino.di_size - sblock.fs_bsize * NDADDR; 11860786Sps sizepb = sblock.fs_bsize; 11960786Sps for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { 12060786Sps if (*ap) { 12160786Sps idesc->id_blkno = *ap; 12260786Sps ret = iblock(idesc, n, remsize); 12360786Sps if (ret & STOP) 12460786Sps return (ret); 12560786Sps } else { 12660786Sps if (idesc->id_type == DATA && remsize > 0) { 12760786Sps /* An empty block in a directory XXX */ 12860786Sps getpathname(pathbuf, idesc->id_number, 12960786Sps idesc->id_number); 13060786Sps pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 13160786Sps pathbuf); 13260786Sps if (reply("ADJUST LENGTH") == 1) { 13360786Sps dp = ginode(idesc->id_number); 13460786Sps dp->di_size -= remsize; 13560786Sps remsize = 0; 13660786Sps printf( 13760786Sps "YOU MUST RERUN FSCK AFTERWARDS\n"); 13860786Sps rerun = 1; 13960786Sps inodirty(); 14060786Sps break; 14160786Sps } 14260786Sps } 14360786Sps } 14460786Sps sizepb *= NINDIR(&sblock); 14560786Sps remsize -= sizepb; 14660786Sps } 14760786Sps return (KEEPON); 14860786Sps} 14960786Sps 15060786Spsstatic int 15160786Spsiblock(idesc, ilevel, isize) 15260786Sps struct inodesc *idesc; 15360786Sps long ilevel; 15460786Sps quad_t isize; 15560786Sps{ 15660786Sps ufs_daddr_t *ap; 15760786Sps ufs_daddr_t *aplim; 15860786Sps struct bufarea *bp; 15960786Sps int i, n, (*func)(), nif; 16060786Sps quad_t sizepb; 16160786Sps char buf[BUFSIZ]; 16260786Sps char pathbuf[MAXPATHLEN + 1]; 16360786Sps struct dinode *dp; 16460786Sps 16560786Sps if (idesc->id_type == ADDR) { 16660786Sps func = idesc->id_func; 16760786Sps if (((n = (*func)(idesc)) & KEEPON) == 0) 16860786Sps return (n); 16960786Sps } else 17060786Sps func = dirscan; 17160786Sps if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 17260786Sps return (SKIP); 17360786Sps bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); 17460786Sps ilevel--; 17560786Sps for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) 17660786Sps sizepb *= NINDIR(&sblock); 17760786Sps nif = howmany(isize , sizepb); 17860786Sps if (nif > NINDIR(&sblock)) 17960786Sps nif = NINDIR(&sblock); 18060786Sps if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { 18160786Sps aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; 18260786Sps for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { 18360786Sps if (*ap == 0) 18460786Sps continue; 18560786Sps (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", 18660786Sps (u_long)idesc->id_number); 18760786Sps if (dofix(idesc, buf)) { 18860786Sps *ap = 0; 18960786Sps dirty(bp); 19060786Sps } 19160786Sps } 19260786Sps flush(fswritefd, bp); 19360786Sps } 19460786Sps aplim = &bp->b_un.b_indir[nif]; 19560786Sps for (ap = bp->b_un.b_indir; ap < aplim; ap++) { 19660786Sps if (*ap) { 19760786Sps idesc->id_blkno = *ap; 19860786Sps if (ilevel == 0) 19960786Sps n = (*func)(idesc); 20060786Sps else 20160786Sps n = iblock(idesc, ilevel, isize); 20260786Sps if (n & STOP) { 20360786Sps bp->b_flags &= ~B_INUSE; 20460786Sps return (n); 20560786Sps } 20660786Sps } else { 20760786Sps if (idesc->id_type == DATA && isize > 0) { 20860786Sps /* An empty block in a directory XXX */ 20960786Sps getpathname(pathbuf, idesc->id_number, 21060786Sps idesc->id_number); 21160786Sps pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 21260786Sps pathbuf); 21360786Sps if (reply("ADJUST LENGTH") == 1) { 21460786Sps dp = ginode(idesc->id_number); 21560786Sps dp->di_size -= isize; 21660786Sps isize = 0; 21760786Sps printf( 21860786Sps "YOU MUST RERUN FSCK AFTERWARDS\n"); 21960786Sps rerun = 1; 22060786Sps inodirty(); 22160786Sps bp->b_flags &= ~B_INUSE; 22260786Sps return(STOP); 22360786Sps } 22460786Sps } 22560786Sps } 22660786Sps isize -= sizepb; 22760786Sps } 22860786Sps bp->b_flags &= ~B_INUSE; 22960786Sps return (KEEPON); 23060786Sps} 23160786Sps 23260786Sps/* 23360786Sps * Check that a block in a legal block number. 23460786Sps * Return 0 if in range, 1 if out of range. 23560786Sps */ 23660786Spsint 23760786Spschkrange(blk, cnt) 23860786Sps ufs_daddr_t blk; 23960786Sps int cnt; 24060786Sps{ 24160786Sps register int c; 24260786Sps 24360786Sps if (cnt <= 0 || blk <= 0 || blk > maxfsblock || 24460786Sps cnt - 1 > maxfsblock - blk) 24560786Sps return (1); 24660786Sps if (cnt > sblock.fs_frag || 24760786Sps fragnum(&sblock, blk) + cnt > sblock.fs_frag) { 24860786Sps if (debug) 24960786Sps printf("bad size: blk %ld, offset %ld, size %ld\n", 25060786Sps blk, fragnum(&sblock, blk), cnt); 25160786Sps return (1); 25260786Sps } 25360786Sps c = dtog(&sblock, blk); 25460786Sps if (blk < cgdmin(&sblock, c)) { 25560786Sps if ((blk + cnt) > cgsblock(&sblock, c)) { 25660786Sps if (debug) { 25760786Sps printf("blk %ld < cgdmin %ld;", 25860786Sps (long)blk, (long)cgdmin(&sblock, c)); 25960786Sps printf(" blk + cnt %ld > cgsbase %ld\n", 26060786Sps (long)(blk + cnt), 26160786Sps (long)cgsblock(&sblock, c)); 26260786Sps } 26360786Sps return (1); 26460786Sps } 26560786Sps } else { 26660786Sps if ((blk + cnt) > cgbase(&sblock, c+1)) { 26760786Sps if (debug) { 26860786Sps printf("blk %ld >= cgdmin %ld;", 26960786Sps (long)blk, (long)cgdmin(&sblock, c)); 27060786Sps printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", 27160786Sps (long)(blk + cnt), (long)sblock.fs_fpg); 27260786Sps } 27360786Sps return (1); 27460786Sps } 27560786Sps } 27660786Sps return (0); 27760786Sps} 27860786Sps 27960786Sps/* 28060786Sps * General purpose interface for reading inodes. 28160786Sps */ 28260786Spsstruct dinode * 28360786Spsginode(inumber) 28460786Sps ino_t inumber; 28560786Sps{ 28660786Sps ufs_daddr_t iblk; 28760786Sps 28860786Sps if (inumber < ROOTINO || inumber > maxino) 28960786Sps errx(EEXIT, "bad inode number %d to ginode", inumber); 29060786Sps if (startinum == 0 || 29160786Sps inumber < startinum || inumber >= startinum + INOPB(&sblock)) { 29260786Sps iblk = ino_to_fsba(&sblock, inumber); 29360786Sps if (pbp != 0) 29460786Sps pbp->b_flags &= ~B_INUSE; 29560786Sps pbp = getdatablk(iblk, sblock.fs_bsize); 29660786Sps startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); 29760786Sps } 29860786Sps return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); 29960786Sps} 30060786Sps 30160786Sps/* 30260786Sps * Special purpose version of ginode used to optimize first pass 30360786Sps * over all the inodes in numerical order. 30460786Sps */ 30560786Spsino_t nextino, lastinum; 30660786Spslong readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 30760786Spsstruct dinode *inodebuf; 30860786Sps 30960786Spsstruct dinode * 31060786Spsgetnextinode(inumber) 31160786Sps ino_t inumber; 31260786Sps{ 31360786Sps long size; 31460786Sps ufs_daddr_t dblk; 31560786Sps static struct dinode *dp; 31660786Sps 31760786Sps if (inumber != nextino++ || inumber > maxino) 31860786Sps errx(EEXIT, "bad inode number %d to nextinode", inumber); 31960786Sps if (inumber >= lastinum) { 32060786Sps readcnt++; 32160786Sps dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); 32260786Sps if (readcnt % readpercg == 0) { 32360786Sps size = partialsize; 32460786Sps lastinum += partialcnt; 32560786Sps } else { 32660786Sps size = inobufsize; 32760786Sps lastinum += fullcnt; 32860786Sps } 32960786Sps /* 33060786Sps * If bread returns an error, it will already have zeroed 33160786Sps * out the buffer, so we do not need to do so here. 33260786Sps */ 33360786Sps (void)bread(fsreadfd, (char *)inodebuf, dblk, size); 33460786Sps dp = inodebuf; 33560786Sps } 33660786Sps return (dp++); 33760786Sps} 33860786Sps 33960786Spsvoid 34060786Spssetinodebuf(inum) 34160786Sps ino_t inum; 34260786Sps{ 34360786Sps 34460786Sps if (inum % sblock.fs_ipg != 0) 34560786Sps errx(EEXIT, "bad inode number %d to setinodebuf", inum); 34660786Sps startinum = 0; 34760786Sps nextino = inum; 34860786Sps lastinum = inum; 34960786Sps readcnt = 0; 35060786Sps if (inodebuf != NULL) 35160786Sps return; 35260786Sps inobufsize = blkroundup(&sblock, INOBUFSIZE); 35360786Sps fullcnt = inobufsize / sizeof(struct dinode); 35460786Sps readpercg = sblock.fs_ipg / fullcnt; 35560786Sps partialcnt = sblock.fs_ipg % fullcnt; 35660786Sps partialsize = partialcnt * sizeof(struct dinode); 35760786Sps if (partialcnt != 0) { 35860786Sps readpercg++; 35960786Sps } else { 36060786Sps partialcnt = fullcnt; 36160786Sps partialsize = inobufsize; 36260786Sps } 36360786Sps if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) 36460786Sps errx(EEXIT, "cannot allocate space for inode buffer"); 36560786Sps} 36660786Sps 36760786Spsvoid 36860786Spsfreeinodebuf() 36960786Sps{ 37060786Sps 37160786Sps if (inodebuf != NULL) 37260786Sps free((char *)inodebuf); 37360786Sps inodebuf = NULL; 37460786Sps} 37560786Sps 37660786Sps/* 37760786Sps * Routines to maintain information about directory inodes. 37860786Sps * This is built during the first pass and used during the 37960786Sps * second and third passes. 38060786Sps * 38160786Sps * Enter inodes into the cache. 38260786Sps */ 38360786Spsvoid 38460786Spscacheino(dp, inumber) 38560786Sps register struct dinode *dp; 38660786Sps ino_t inumber; 38760786Sps{ 38860786Sps register struct inoinfo *inp; 38960786Sps struct inoinfo **inpp; 39060786Sps int blks; 39160786Sps 39260786Sps blks = howmany(dp->di_size, sblock.fs_bsize); 39360786Sps if (blks > NDADDR) 39460786Sps blks = NDADDR + NIADDR; 39560786Sps inp = (struct inoinfo *) 39660786Sps malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t)); 39760786Sps if (inp == NULL) 39860786Sps errx(EEXIT, "cannot increase directory list"); 39960786Sps inpp = &inphead[inumber % numdirs]; 40060786Sps inp->i_nexthash = *inpp; 40160786Sps *inpp = inp; 40260786Sps inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0; 40360786Sps inp->i_dotdot = (ino_t)0; 40460786Sps inp->i_number = inumber; 40560786Sps inp->i_isize = dp->di_size; 40660786Sps inp->i_numblks = blks * sizeof(ufs_daddr_t); 40760786Sps memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks); 40860786Sps if (inplast == listmax) { 40960786Sps listmax += 100; 41060786Sps inpsort = (struct inoinfo **)realloc((char *)inpsort, 41160786Sps (unsigned)listmax * sizeof(struct inoinfo *)); 41260786Sps if (inpsort == NULL) 41360786Sps errx(EEXIT, "cannot increase directory list"); 41460786Sps } 41560786Sps inpsort[inplast++] = inp; 41660786Sps} 41760786Sps 41860786Sps/* 41960786Sps * Look up an inode cache structure. 42060786Sps */ 42160786Spsstruct inoinfo * 42260786Spsgetinoinfo(inumber) 42360786Sps ino_t inumber; 42460786Sps{ 42560786Sps register struct inoinfo *inp; 42660786Sps 42760786Sps for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) { 42860786Sps if (inp->i_number != inumber) 42960786Sps continue; 43060786Sps return (inp); 43160786Sps } 43260786Sps errx(EEXIT, "cannot find inode %d", inumber); 43360786Sps return ((struct inoinfo *)0); 43460786Sps} 43560786Sps 43660786Sps/* 43760786Sps * Clean up all the inode cache structure. 43860786Sps */ 43960786Spsvoid 44060786Spsinocleanup() 44160786Sps{ 44260786Sps register struct inoinfo **inpp; 44360786Sps 44460786Sps if (inphead == NULL) 44560786Sps return; 44660786Sps for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 44760786Sps free((char *)(*inpp)); 44860786Sps free((char *)inphead); 44960786Sps free((char *)inpsort); 45060786Sps inphead = inpsort = NULL; 45160786Sps} 45260786Sps 45360786Spsvoid 45460786Spsinodirty() 45560786Sps{ 45660786Sps 45760786Sps dirty(pbp); 45860786Sps} 45960786Sps 46060786Spsvoid 46160786Spsclri(idesc, type, flag) 46260786Sps register struct inodesc *idesc; 46360786Sps char *type; 46460786Sps int flag; 46560786Sps{ 46660786Sps register struct dinode *dp; 46760786Sps 46860786Sps dp = ginode(idesc->id_number); 46960786Sps if (flag == 1) { 47060786Sps pwarn("%s %s", type, 47160786Sps (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); 47260786Sps pinode(idesc->id_number); 47360786Sps } 47460786Sps if (preen || reply("CLEAR") == 1) { 47560786Sps if (preen) 47660786Sps printf(" (CLEARED)\n"); 47760786Sps n_files--; 47860786Sps (void)ckinode(dp, idesc); 47960786Sps clearinode(dp); 48060786Sps inoinfo(idesc->id_number)->ino_state = USTATE; 48160786Sps inodirty(); 48260786Sps } 48360786Sps} 48460786Sps 48560786Spsint 48660786Spsfindname(idesc) 48760786Sps struct inodesc *idesc; 48860786Sps{ 48960786Sps register struct direct *dirp = idesc->id_dirp; 49060786Sps 49160786Sps if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 49260786Sps idesc->id_entryno++; 49360786Sps return (KEEPON); 49460786Sps } 49560786Sps memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1); 49660786Sps return (STOP|FOUND); 49760786Sps} 49860786Sps 49960786Spsint 50060786Spsfindino(idesc) 50160786Sps struct inodesc *idesc; 50260786Sps{ 50360786Sps register struct direct *dirp = idesc->id_dirp; 50460786Sps 50560786Sps if (dirp->d_ino == 0) 50660786Sps return (KEEPON); 50760786Sps if (strcmp(dirp->d_name, idesc->id_name) == 0 && 50860786Sps dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { 50960786Sps idesc->id_parent = dirp->d_ino; 51060786Sps return (STOP|FOUND); 51160786Sps } 51260786Sps return (KEEPON); 51360786Sps} 51460786Sps 51563131Spsint 51663131Spsclearentry(idesc) 51760786Sps struct inodesc *idesc; 51860786Sps{ 51960786Sps register struct direct *dirp = idesc->id_dirp; 52060786Sps 52160786Sps if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 52260786Sps idesc->id_entryno++; 52360786Sps return (KEEPON); 52460786Sps } 52560786Sps dirp->d_ino = 0; 52660786Sps return (STOP|FOUND|ALTERED); 52760786Sps} 52860786Sps 52960786Spsvoid 53060786Spspinode(ino) 53160786Sps ino_t ino; 53260786Sps{ 53360786Sps register struct dinode *dp; 53460786Sps register char *p; 53560786Sps struct passwd *pw; 53660786Sps time_t t; 53760786Sps 53860786Sps printf(" I=%lu ", (u_long)ino); 53960786Sps if (ino < ROOTINO || ino > maxino) 54060786Sps return; 54160786Sps dp = ginode(ino); 54260786Sps printf(" OWNER="); 54360786Sps if ((pw = getpwuid((int)dp->di_uid)) != 0) 54460786Sps printf("%s ", pw->pw_name); 54560786Sps else 54660786Sps printf("%u ", (unsigned)dp->di_uid); 54760786Sps printf("MODE=%o\n", dp->di_mode); 54860786Sps if (preen) 54960786Sps printf("%s: ", cdevname); 55060786Sps printf("SIZE=%qu ", dp->di_size); 55160786Sps t = dp->di_mtime; 55260786Sps p = ctime(&t); 55360786Sps printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); 55460786Sps} 55560786Sps 55660786Spsvoid 55760786Spsblkerror(ino, type, blk) 55860786Sps ino_t ino; 55960786Sps char *type; 56060786Sps ufs_daddr_t blk; 56160786Sps{ 56260786Sps 56360786Sps pfatal("%ld %s I=%lu", blk, type, ino); 56460786Sps printf("\n"); 56560786Sps switch (inoinfo(ino)->ino_state) { 56660786Sps 56760786Sps case FSTATE: 56860786Sps inoinfo(ino)->ino_state = FCLEAR; 56960786Sps return; 57060786Sps 57160786Sps case DSTATE: 57260786Sps inoinfo(ino)->ino_state = DCLEAR; 57360786Sps return; 57460786Sps 57560786Sps case FCLEAR: 57660786Sps case DCLEAR: 57760786Sps return; 57860786Sps 57960786Sps default: 58060786Sps errx(EEXIT, "BAD STATE %d TO BLKERR", inoinfo(ino)->ino_state); 58160786Sps /* NOTREACHED */ 58260786Sps } 58360786Sps} 58460786Sps 58560786Sps/* 58660786Sps * allocate an unused inode 58760786Sps */ 58860786Spsino_t 58960786Spsallocino(request, type) 59060786Sps ino_t request; 59160786Sps int type; 59260786Sps{ 59360786Sps register ino_t ino; 59460786Sps register struct dinode *dp; 59560786Sps struct cg *cgp = &cgrp; 59660786Sps int cg; 59760786Sps 59860786Sps if (request == 0) 59960786Sps request = ROOTINO; 60060786Sps else if (inoinfo(request)->ino_state != USTATE) 60160786Sps return (0); 60260786Sps for (ino = request; ino < maxino; ino++) 60360786Sps if (inoinfo(ino)->ino_state == USTATE) 60460786Sps break; 60560786Sps if (ino == maxino) 60660786Sps return (0); 60760786Sps cg = ino_to_cg(&sblock, ino); 60860786Sps getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 60960786Sps if (!cg_chkmagic(cgp)) 61060786Sps pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 61160786Sps setbit(cg_inosused(cgp), ino % sblock.fs_ipg); 61260786Sps cgp->cg_cs.cs_nifree--; 61360786Sps switch (type & IFMT) { 61460786Sps case IFDIR: 61560786Sps inoinfo(ino)->ino_state = DSTATE; 61660786Sps cgp->cg_cs.cs_ndir++; 61760786Sps break; 61860786Sps case IFREG: 61960786Sps case IFLNK: 62060786Sps inoinfo(ino)->ino_state = FSTATE; 62160786Sps break; 62260786Sps default: 62360786Sps return (0); 62460786Sps } 62560786Sps cgdirty(); 62660786Sps dp = ginode(ino); 62760786Sps dp->di_db[0] = allocblk((long)1); 62860786Sps if (dp->di_db[0] == 0) { 62960786Sps inoinfo(ino)->ino_state = USTATE; 63060786Sps return (0); 63160786Sps } 63260786Sps dp->di_mode = type; 63360786Sps dp->di_flags = 0; 63460786Sps dp->di_atime = time(NULL); 63560786Sps dp->di_mtime = dp->di_ctime = dp->di_atime; 63660786Sps dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0; 63760786Sps dp->di_size = sblock.fs_fsize; 63860786Sps dp->di_blocks = btodb(sblock.fs_fsize); 63960786Sps n_files++; 64060786Sps inodirty(); 64160786Sps if (newinofmt) 64260786Sps inoinfo(ino)->ino_type = IFTODT(type); 64360786Sps return (ino); 64460786Sps} 64560786Sps 64660786Sps/* 64760786Sps * deallocate an inode 64860786Sps */ 64960786Spsvoid 65060786Spsfreeino(ino) 65160786Sps ino_t ino; 65260786Sps{ 65360786Sps struct inodesc idesc; 65460786Sps struct dinode *dp; 65560786Sps 65660786Sps memset(&idesc, 0, sizeof(struct inodesc)); 65760786Sps idesc.id_type = ADDR; 65860786Sps idesc.id_func = pass4check; 65960786Sps idesc.id_number = ino; 66060786Sps dp = ginode(ino); 66160786Sps (void)ckinode(dp, &idesc); 66260786Sps clearinode(dp); 66360786Sps inodirty(); 66460786Sps inoinfo(ino)->ino_state = USTATE; 66560786Sps n_files--; 66660786Sps} 66760786Sps