1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. 12*7c478bd9Sstevel@tonic-gate * 13*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 14*7c478bd9Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright 15*7c478bd9Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display 16*7c478bd9Sstevel@tonic-gate * the following acknowledgement: ``This product includes software 17*7c478bd9Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors'' 18*7c478bd9Sstevel@tonic-gate * in the documentation or other materials provided with the distribution 19*7c478bd9Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this 20*7c478bd9Sstevel@tonic-gate * software. Neither the name of the University nor the names of its 21*7c478bd9Sstevel@tonic-gate * contributors may be used to endorse or promote products derived 22*7c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 23*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25*7c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #define bcopy(f, t, n) memcpy(t, f, n) 35*7c478bd9Sstevel@tonic-gate #define bzero(s, n) memset(s, 0, n) 36*7c478bd9Sstevel@tonic-gate #define bcmp(s, d, n) memcmp(s, d, n) 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #define index(s, r) strchr(s, r) 39*7c478bd9Sstevel@tonic-gate #define rindex(s, r) strrchr(s, r) 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h> 44*7c478bd9Sstevel@tonic-gate #define _KERNEL 45*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h> 46*7c478bd9Sstevel@tonic-gate #undef _KERNEL 47*7c478bd9Sstevel@tonic-gate #include "fsck.h" 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate int pass3check(); 50*7c478bd9Sstevel@tonic-gate static void setcurino(struct inodesc *, struct dinode *, struct inoinfo *); 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate pass3() 53*7c478bd9Sstevel@tonic-gate { 54*7c478bd9Sstevel@tonic-gate struct inoinfo **inpp, *inp; 55*7c478bd9Sstevel@tonic-gate ino_t orphan; 56*7c478bd9Sstevel@tonic-gate int loopcnt; 57*7c478bd9Sstevel@tonic-gate ino_t inumber; 58*7c478bd9Sstevel@tonic-gate struct shadowclientinfo *sci; 59*7c478bd9Sstevel@tonic-gate struct inodesc curino; 60*7c478bd9Sstevel@tonic-gate struct dinode *dp; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) { 64*7c478bd9Sstevel@tonic-gate inp = *inpp; 65*7c478bd9Sstevel@tonic-gate if (inp->i_number == UFSROOTINO || 66*7c478bd9Sstevel@tonic-gate !(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE)) 67*7c478bd9Sstevel@tonic-gate continue; 68*7c478bd9Sstevel@tonic-gate if (statemap[inp->i_number] == DCLEAR || 69*7c478bd9Sstevel@tonic-gate statemap[inp->i_number] == USTATE) 70*7c478bd9Sstevel@tonic-gate continue; 71*7c478bd9Sstevel@tonic-gate for (loopcnt = 0; ; loopcnt++) { 72*7c478bd9Sstevel@tonic-gate orphan = inp->i_number; 73*7c478bd9Sstevel@tonic-gate if (inp->i_parent == 0 || 74*7c478bd9Sstevel@tonic-gate statemap[inp->i_parent] != DSTATE || 75*7c478bd9Sstevel@tonic-gate loopcnt > numdirs) 76*7c478bd9Sstevel@tonic-gate break; 77*7c478bd9Sstevel@tonic-gate inp = getinoinfo(inp->i_parent); 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate dp = ginode(orphan); 80*7c478bd9Sstevel@tonic-gate /* 81*7c478bd9Sstevel@tonic-gate * A link count of 0 with parent and .. inodes of 0 82*7c478bd9Sstevel@tonic-gate * indicates a partly deleted directory. 83*7c478bd9Sstevel@tonic-gate * Clear it. 84*7c478bd9Sstevel@tonic-gate */ 85*7c478bd9Sstevel@tonic-gate if (dp->di_nlink == 0 && inp->i_dotdot == 0 && 86*7c478bd9Sstevel@tonic-gate inp->i_parent == 0) { 87*7c478bd9Sstevel@tonic-gate setcurino(&curino, dp, inp); 88*7c478bd9Sstevel@tonic-gate clri(&curino, "UNREF", 1); 89*7c478bd9Sstevel@tonic-gate continue; 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate if (linkup(orphan, inp->i_dotdot) == 1) { 93*7c478bd9Sstevel@tonic-gate if ((dp->di_mode & IFMT) == IFATTRDIR) { 94*7c478bd9Sstevel@tonic-gate dp->di_mode &= ~IFATTRDIR; 95*7c478bd9Sstevel@tonic-gate dp->di_mode |= IFDIR; 96*7c478bd9Sstevel@tonic-gate dp->di_cflags &= ~IXATTR; 97*7c478bd9Sstevel@tonic-gate dp->di_size = (u_offset_t)inp->i_isize; 98*7c478bd9Sstevel@tonic-gate setcurino(&curino, dp, inp); 99*7c478bd9Sstevel@tonic-gate (void) ckinode(dp, &curino); 100*7c478bd9Sstevel@tonic-gate inodirty(); 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate inp->i_parent = inp->i_dotdot = lfdir; 103*7c478bd9Sstevel@tonic-gate lncntp[lfdir]--; 104*7c478bd9Sstevel@tonic-gate statemap[orphan] = DFOUND; 105*7c478bd9Sstevel@tonic-gate propagate(); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate for (sci = shadowclientinfo; sci; sci = sci->next) { 110*7c478bd9Sstevel@tonic-gate lncntp[sci->shadow] -= sci->totalClients; 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate for (sci = attrclientinfo; sci; sci = sci->next) { 114*7c478bd9Sstevel@tonic-gate lncntp[sci->shadow] -= sci->totalClients; 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate /* 120*7c478bd9Sstevel@tonic-gate * This is used to verify the cflags of files 121*7c478bd9Sstevel@tonic-gate * under a directory that used to be a attrdir. 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate pass3check(idesc) 125*7c478bd9Sstevel@tonic-gate struct inodesc *idesc; 126*7c478bd9Sstevel@tonic-gate { 127*7c478bd9Sstevel@tonic-gate struct direct *dirp = idesc->id_dirp; 128*7c478bd9Sstevel@tonic-gate struct inoinfo *inp; 129*7c478bd9Sstevel@tonic-gate int n, entrysize, ret = 0; 130*7c478bd9Sstevel@tonic-gate struct dinode *dp, *pdirp; 131*7c478bd9Sstevel@tonic-gate int isattr = 0; 132*7c478bd9Sstevel@tonic-gate int dirtype = 0; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate if (dirp->d_ino == 0) 135*7c478bd9Sstevel@tonic-gate return (KEEPON); 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate idesc->id_entryno++; 138*7c478bd9Sstevel@tonic-gate if ((strcmp(dirp->d_name, ".") == 0) || 139*7c478bd9Sstevel@tonic-gate (strcmp(dirp->d_name, "..") == 0)) { 140*7c478bd9Sstevel@tonic-gate return (KEEPON); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate switch (statemap[dirp->d_ino]) { 145*7c478bd9Sstevel@tonic-gate case DSTATE: 146*7c478bd9Sstevel@tonic-gate case DFOUND: 147*7c478bd9Sstevel@tonic-gate case FSTATE: 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * For extended attribute directories .. may point 150*7c478bd9Sstevel@tonic-gate * to a file. In this situation we don't want 151*7c478bd9Sstevel@tonic-gate * to decrement link count as it was already 152*7c478bd9Sstevel@tonic-gate * decremented when entry was seen and decremented 153*7c478bd9Sstevel@tonic-gate * in the directory it actually lives in. 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate dp = ginode(dirp->d_ino); 156*7c478bd9Sstevel@tonic-gate isattr = (dp->di_cflags & IXATTR); 157*7c478bd9Sstevel@tonic-gate pdirp = ginode(idesc->id_number); 158*7c478bd9Sstevel@tonic-gate dirtype = (pdirp->di_mode & IFMT); 159*7c478bd9Sstevel@tonic-gate n = 0; 160*7c478bd9Sstevel@tonic-gate if ((dirtype == IFDIR) && isattr) { 161*7c478bd9Sstevel@tonic-gate fileerror(idesc->id_number, dirp->d_ino, 162*7c478bd9Sstevel@tonic-gate "File should NOT be marked as extended attribute"); 163*7c478bd9Sstevel@tonic-gate dp = ginode(dirp->d_ino); 164*7c478bd9Sstevel@tonic-gate dp->di_cflags &= ~IXATTR; 165*7c478bd9Sstevel@tonic-gate if ((n = reply("FIX")) == 1) { 166*7c478bd9Sstevel@tonic-gate inodirty(); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate if (n != 0) 169*7c478bd9Sstevel@tonic-gate return (KEEPON | ALTERED); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate break; 172*7c478bd9Sstevel@tonic-gate default: 173*7c478bd9Sstevel@tonic-gate errexit("PASS3: BAD STATE %d FOR INODE I=%d", 174*7c478bd9Sstevel@tonic-gate statemap[dirp->d_ino], dirp->d_ino); 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate if (n == 0) 177*7c478bd9Sstevel@tonic-gate return (ret|KEEPON); 178*7c478bd9Sstevel@tonic-gate return (ret|KEEPON|ALTERED); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate static void 182*7c478bd9Sstevel@tonic-gate setcurino(struct inodesc *ino, struct dinode *dp, struct inoinfo *inp) 183*7c478bd9Sstevel@tonic-gate { 184*7c478bd9Sstevel@tonic-gate bzero((char *)ino, sizeof (struct inodesc)); 185*7c478bd9Sstevel@tonic-gate bcopy((char *)&inp->i_blks[0], 186*7c478bd9Sstevel@tonic-gate (char *)&dp->di_db[0], 187*7c478bd9Sstevel@tonic-gate (size_t)inp->i_numblks); 188*7c478bd9Sstevel@tonic-gate ino->id_number = inp->i_number; 189*7c478bd9Sstevel@tonic-gate ino->id_parent = inp->i_parent; 190*7c478bd9Sstevel@tonic-gate ino->id_fix = DONTKNOW; 191*7c478bd9Sstevel@tonic-gate ino->id_type = DATA; 192*7c478bd9Sstevel@tonic-gate ino->id_func = pass3check; 193*7c478bd9Sstevel@tonic-gate } 194