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