1 #ifndef lint 2 static char version[] = "@(#)pass2.c 3.2 (Berkeley) 02/07/85"; 3 #endif 4 5 #include <sys/param.h> 6 #include <sys/inode.h> 7 #include <sys/fs.h> 8 #include <sys/dir.h> 9 #include <strings.h> 10 #include "fsck.h" 11 12 int pass2check(); 13 14 pass2() 15 { 16 register DINODE *dp; 17 struct inodesc rootdesc; 18 19 bzero((char *)&rootdesc, sizeof(struct inodesc)); 20 rootdesc.id_type = ADDR; 21 rootdesc.id_func = pass2check; 22 rootdesc.id_number = ROOTINO; 23 pathp = pathname; 24 switch (statemap[ROOTINO]) { 25 26 case USTATE: 27 errexit("ROOT INODE UNALLOCATED. TERMINATING.\n"); 28 29 case FSTATE: 30 pfatal("ROOT INODE NOT DIRECTORY"); 31 if (reply("FIX") == 0 || (dp = ginode(ROOTINO)) == NULL) 32 errexit(""); 33 dp->di_mode &= ~IFMT; 34 dp->di_mode |= IFDIR; 35 inodirty(); 36 inosumbad++; 37 statemap[ROOTINO] = DSTATE; 38 /* fall into ... */ 39 40 case DSTATE: 41 descend(&rootdesc, ROOTINO); 42 break; 43 44 case CLEAR: 45 pfatal("DUPS/BAD IN ROOT INODE"); 46 printf("\n"); 47 if (reply("CONTINUE") == 0) 48 errexit(""); 49 statemap[ROOTINO] = DSTATE; 50 descend(&rootdesc, ROOTINO); 51 } 52 } 53 54 pass2check(idesc) 55 struct inodesc *idesc; 56 { 57 register DIRECT *dirp = idesc->id_dirp; 58 char *curpathloc; 59 int n, entrysize, ret = 0; 60 DINODE *dp; 61 DIRECT proto; 62 63 /* 64 * check for "." 65 */ 66 if (idesc->id_entryno != 0) 67 goto chk1; 68 if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { 69 if (dirp->d_ino != idesc->id_number) { 70 direrr(idesc->id_number, "BAD INODE NUMBER FOR '.'"); 71 dirp->d_ino = idesc->id_number; 72 if (reply("FIX") == 1) 73 ret |= ALTERED; 74 } 75 goto chk1; 76 } 77 direrr(idesc->id_number, "MISSING '.'"); 78 proto.d_ino = idesc->id_number; 79 proto.d_namlen = 1; 80 (void)strcpy(proto.d_name, "."); 81 entrysize = DIRSIZ(&proto); 82 if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { 83 pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", 84 dirp->d_name); 85 } else if (dirp->d_reclen < entrysize) { 86 pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); 87 } else if (dirp->d_reclen < 2 * entrysize) { 88 proto.d_reclen = dirp->d_reclen; 89 bcopy((char *)&proto, (char *)dirp, entrysize); 90 if (reply("FIX") == 1) 91 ret |= ALTERED; 92 } else { 93 n = dirp->d_reclen - entrysize; 94 proto.d_reclen = entrysize; 95 bcopy((char *)&proto, (char *)dirp, entrysize); 96 idesc->id_entryno++; 97 lncntp[dirp->d_ino]--; 98 dirp = (DIRECT *)((char *)(dirp) + entrysize); 99 bzero((char *)dirp, n); 100 dirp->d_reclen = n; 101 if (reply("FIX") == 1) 102 ret |= ALTERED; 103 } 104 chk1: 105 if (idesc->id_entryno > 1) 106 goto chk2; 107 proto.d_ino = idesc->id_parent; 108 proto.d_namlen = 2; 109 (void)strcpy(proto.d_name, ".."); 110 entrysize = DIRSIZ(&proto); 111 if (idesc->id_entryno == 0) { 112 n = DIRSIZ(dirp); 113 if (dirp->d_reclen < n + entrysize) 114 goto chk2; 115 proto.d_reclen = dirp->d_reclen - n; 116 dirp->d_reclen = n; 117 idesc->id_entryno++; 118 lncntp[dirp->d_ino]--; 119 dirp = (DIRECT *)((char *)(dirp) + n); 120 bzero((char *)dirp, n); 121 dirp->d_reclen = n; 122 } 123 if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { 124 if (dirp->d_ino != idesc->id_parent) { 125 direrr(idesc->id_number, "BAD INODE NUMBER FOR '..'"); 126 dirp->d_ino = idesc->id_parent; 127 if (reply("FIX") == 1) 128 ret |= ALTERED; 129 } 130 goto chk2; 131 } 132 direrr(idesc->id_number, "MISSING '..'"); 133 if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) { 134 pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", 135 dirp->d_name); 136 } else if (dirp->d_reclen < entrysize) { 137 pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); 138 } else { 139 proto.d_reclen = dirp->d_reclen; 140 bcopy((char *)&proto, (char *)dirp, entrysize); 141 if (reply("FIX") == 1) 142 ret |= ALTERED; 143 } 144 chk2: 145 if (dirp->d_ino == 0) 146 return (ret|KEEPON); 147 if (dirp->d_namlen <= 2 && 148 dirp->d_name[0] == '.' && 149 idesc->id_entryno >= 2) { 150 if (dirp->d_namlen == 1) { 151 direrr(idesc->id_number, "EXTRA '.' ENTRY"); 152 dirp->d_ino = 0; 153 if (reply("FIX") == 1) 154 ret |= ALTERED; 155 return (KEEPON | ret); 156 } 157 if (dirp->d_name[1] == '.') { 158 direrr(idesc->id_number, "EXTRA '..' ENTRY"); 159 dirp->d_ino = 0; 160 if (reply("FIX") == 1) 161 ret |= ALTERED; 162 return (KEEPON | ret); 163 } 164 } 165 curpathloc = pathp; 166 *pathp++ = '/'; 167 if (pathp + dirp->d_namlen >= endpathname) { 168 *pathp = '\0'; 169 errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name); 170 } 171 bcopy(dirp->d_name, pathp, dirp->d_namlen + 1); 172 pathp += dirp->d_namlen; 173 idesc->id_entryno++; 174 n = 0; 175 if (dirp->d_ino > imax || dirp->d_ino <= 0) { 176 direrr(dirp->d_ino, "I OUT OF RANGE"); 177 n = reply("REMOVE"); 178 } else { 179 again: 180 switch (statemap[dirp->d_ino]) { 181 case USTATE: 182 direrr(dirp->d_ino, "UNALLOCATED"); 183 n = reply("REMOVE"); 184 break; 185 186 case CLEAR: 187 direrr(dirp->d_ino, "DUP/BAD"); 188 if ((n = reply("REMOVE")) == 1) 189 break; 190 if ((dp = ginode(dirp->d_ino)) == NULL) 191 break; 192 statemap[dirp->d_ino] = DIRCT(dp) ? DSTATE : FSTATE; 193 goto again; 194 195 case FSTATE: 196 lncntp[dirp->d_ino]--; 197 break; 198 199 case DSTATE: 200 descend(idesc, dirp->d_ino); 201 if (statemap[dirp->d_ino] != CLEAR) { 202 lncntp[dirp->d_ino]--; 203 } else { 204 dirp->d_ino = 0; 205 ret |= ALTERED; 206 } 207 break; 208 } 209 } 210 pathp = curpathloc; 211 *pathp = '\0'; 212 if (n == 0) 213 return (ret|KEEPON); 214 dirp->d_ino = 0; 215 return (ret|KEEPON|ALTERED); 216 } 217