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