116259Smckusick #ifndef lint 2*17993Smckusick static char version[] = "@(#)dir.c 3.10 (Berkeley) 02/15/85"; 316259Smckusick #endif 416259Smckusick 516259Smckusick #include <sys/param.h> 616259Smckusick #include <sys/inode.h> 716259Smckusick #include <sys/fs.h> 816259Smckusick #define KERNEL 916259Smckusick #include <sys/dir.h> 1016259Smckusick #undef KERNEL 1116259Smckusick #include "fsck.h" 1216259Smckusick 1316259Smckusick #define MINDIRSIZE (sizeof (struct dirtemplate)) 1416259Smckusick 1516259Smckusick char *endpathname = &pathname[BUFSIZ - 2]; 1616259Smckusick char *lfname = "lost+found"; 1717944Smckusick struct dirtemplate emptydir = { 0, DIRBLKSIZ }; 1817954Smckusick struct dirtemplate dirhead = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." }; 1916259Smckusick 2016259Smckusick DIRECT *fsck_readdir(); 2116259Smckusick 2216259Smckusick descend(parentino, inumber) 2316259Smckusick struct inodesc *parentino; 2416259Smckusick ino_t inumber; 2516259Smckusick { 2616259Smckusick register DINODE *dp; 2716259Smckusick struct inodesc curino; 2816259Smckusick 2916259Smckusick bzero((char *)&curino, sizeof(struct inodesc)); 3017936Smckusick if (statemap[inumber] != DSTATE) 3117936Smckusick errexit("BAD INODE %d TO DESCEND", statemap[inumber]); 3217936Smckusick statemap[inumber] = DFOUND; 3317943Smckusick dp = ginode(inumber); 3416259Smckusick if (dp->di_size == 0) { 3516259Smckusick direrr(inumber, "ZERO LENGTH DIRECTORY"); 3616259Smckusick if (reply("REMOVE") == 1) 3717936Smckusick statemap[inumber] = DCLEAR; 3816259Smckusick return; 3916259Smckusick } 4016259Smckusick if (dp->di_size < MINDIRSIZE) { 4116259Smckusick direrr(inumber, "DIRECTORY TOO SHORT"); 4216259Smckusick dp->di_size = MINDIRSIZE; 4316259Smckusick if (reply("FIX") == 1) 4416259Smckusick inodirty(); 4516259Smckusick } 4616259Smckusick curino.id_type = DATA; 4716259Smckusick curino.id_func = parentino->id_func; 4816259Smckusick curino.id_parent = parentino->id_number; 4916259Smckusick curino.id_number = inumber; 5016259Smckusick (void)ckinode(dp, &curino); 5116259Smckusick } 5216259Smckusick 5316259Smckusick dirscan(idesc) 5416259Smckusick register struct inodesc *idesc; 5516259Smckusick { 5616259Smckusick register DIRECT *dp; 5716259Smckusick int dsize, n; 5816259Smckusick long blksiz; 5916259Smckusick char dbuf[DIRBLKSIZ]; 6016259Smckusick 6116259Smckusick if (idesc->id_type != DATA) 6216259Smckusick errexit("wrong type to dirscan %d\n", idesc->id_type); 63*17993Smckusick if (idesc->id_entryno == 0 && 64*17993Smckusick (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0) 65*17993Smckusick idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ); 6616259Smckusick blksiz = idesc->id_numfrags * sblock.fs_fsize; 6716259Smckusick if (outrange(idesc->id_blkno, idesc->id_numfrags)) { 6816259Smckusick idesc->id_filesize -= blksiz; 6916259Smckusick return (SKIP); 7016259Smckusick } 7116259Smckusick idesc->id_loc = 0; 7216259Smckusick for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) { 7316259Smckusick dsize = dp->d_reclen; 7416259Smckusick bcopy((char *)dp, dbuf, dsize); 7516259Smckusick idesc->id_dirp = (DIRECT *)dbuf; 7616259Smckusick if ((n = (*idesc->id_func)(idesc)) & ALTERED) { 7716259Smckusick if (getblk(&fileblk, idesc->id_blkno, blksiz) != NULL) { 7816259Smckusick bcopy(dbuf, (char *)dp, dsize); 7916259Smckusick dirty(&fileblk); 8016259Smckusick sbdirty(); 8116259Smckusick } else 8216259Smckusick n &= ~ALTERED; 8316259Smckusick } 8416259Smckusick if (n & STOP) 8516259Smckusick return (n); 8616259Smckusick } 8716259Smckusick return (idesc->id_filesize > 0 ? KEEPON : STOP); 8816259Smckusick } 8916259Smckusick 9016259Smckusick /* 9116259Smckusick * get next entry in a directory. 9216259Smckusick */ 9316259Smckusick DIRECT * 9416259Smckusick fsck_readdir(idesc) 9516259Smckusick register struct inodesc *idesc; 9616259Smckusick { 9716259Smckusick register DIRECT *dp, *ndp; 9816259Smckusick long size, blksiz; 9916259Smckusick 10016259Smckusick blksiz = idesc->id_numfrags * sblock.fs_fsize; 10116259Smckusick if (getblk(&fileblk, idesc->id_blkno, blksiz) == NULL) { 10216259Smckusick idesc->id_filesize -= blksiz - idesc->id_loc; 10316259Smckusick return NULL; 10416259Smckusick } 10516259Smckusick if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 && 10616259Smckusick idesc->id_loc < blksiz) { 10716259Smckusick dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); 10816259Smckusick if (dircheck(idesc, dp)) 10916259Smckusick goto dpok; 11016259Smckusick idesc->id_loc += DIRBLKSIZ; 11116259Smckusick idesc->id_filesize -= DIRBLKSIZ; 11216259Smckusick dp->d_reclen = DIRBLKSIZ; 11316259Smckusick dp->d_ino = 0; 11416259Smckusick dp->d_namlen = 0; 11516259Smckusick dp->d_name[0] = '\0'; 11617930Smckusick if (dofix(idesc, "DIRECTORY CORRUPTED")) 11716259Smckusick dirty(&fileblk); 11816259Smckusick return (dp); 11916259Smckusick } 12016259Smckusick dpok: 12116259Smckusick if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz) 12216259Smckusick return NULL; 12316259Smckusick dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); 12416259Smckusick idesc->id_loc += dp->d_reclen; 12516259Smckusick idesc->id_filesize -= dp->d_reclen; 12616259Smckusick if ((idesc->id_loc % DIRBLKSIZ) == 0) 12716259Smckusick return (dp); 12816259Smckusick ndp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); 12916259Smckusick if (idesc->id_loc < blksiz && idesc->id_filesize > 0 && 13016259Smckusick dircheck(idesc, ndp) == 0) { 13116259Smckusick size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); 13216259Smckusick dp->d_reclen += size; 13316259Smckusick idesc->id_loc += size; 13416259Smckusick idesc->id_filesize -= size; 13517930Smckusick if (dofix(idesc, "DIRECTORY CORRUPTED")) 13616259Smckusick dirty(&fileblk); 13716259Smckusick } 13816259Smckusick return (dp); 13916259Smckusick } 14016259Smckusick 14116259Smckusick /* 14216259Smckusick * Verify that a directory entry is valid. 14316259Smckusick * This is a superset of the checks made in the kernel. 14416259Smckusick */ 14516259Smckusick dircheck(idesc, dp) 14616259Smckusick struct inodesc *idesc; 14716259Smckusick register DIRECT *dp; 14816259Smckusick { 14916259Smckusick register int size; 15016259Smckusick register char *cp; 15116259Smckusick int spaceleft; 15216259Smckusick 15316259Smckusick size = DIRSIZ(dp); 15416259Smckusick spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); 15516259Smckusick if (dp->d_ino < imax && 15616259Smckusick dp->d_reclen != 0 && 15716259Smckusick dp->d_reclen <= spaceleft && 15816259Smckusick (dp->d_reclen & 0x3) == 0 && 15916259Smckusick dp->d_reclen >= size && 16016259Smckusick idesc->id_filesize >= size && 16116259Smckusick dp->d_namlen <= MAXNAMLEN) { 16216259Smckusick if (dp->d_ino == 0) 16316259Smckusick return (1); 16416259Smckusick for (cp = dp->d_name, size = 0; size < dp->d_namlen; size++) 16516259Smckusick if (*cp == 0 || (*cp++ & 0200)) 16616259Smckusick return (0); 16716259Smckusick if (*cp == 0) 16816259Smckusick return (1); 16916259Smckusick } 17016259Smckusick return (0); 17116259Smckusick } 17216259Smckusick 17316259Smckusick direrr(ino, s) 17416259Smckusick ino_t ino; 17516259Smckusick char *s; 17616259Smckusick { 17716259Smckusick register DINODE *dp; 17816259Smckusick 17916259Smckusick pwarn("%s ", s); 18016259Smckusick pinode(ino); 18116259Smckusick printf("\n"); 18217943Smckusick if (ino < ROOTINO || ino > imax) { 18317943Smckusick pfatal("NAME=%s\n", pathname); 18417943Smckusick return; 18517943Smckusick } 18617943Smckusick dp = ginode(ino); 18717943Smckusick if (ftypeok(dp)) 18817930Smckusick pfatal("%s=%s\n", DIRCT(dp) ? "DIR" : "FILE", pathname); 18916259Smckusick else 19016259Smckusick pfatal("NAME=%s\n", pathname); 19116259Smckusick } 19216259Smckusick 19316259Smckusick adjust(idesc, lcnt) 19416259Smckusick register struct inodesc *idesc; 19516259Smckusick short lcnt; 19616259Smckusick { 19716259Smckusick register DINODE *dp; 19816259Smckusick 19917943Smckusick dp = ginode(idesc->id_number); 20016259Smckusick if (dp->di_nlink == lcnt) { 20116259Smckusick if (linkup(idesc->id_number, (ino_t)0) == 0) 20216259Smckusick clri(idesc, "UNREF", 0); 20317936Smckusick } else { 20417930Smckusick pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : 20517930Smckusick (DIRCT(dp) ? "DIR" : "FILE")); 20616259Smckusick pinode(idesc->id_number); 20716259Smckusick printf(" COUNT %d SHOULD BE %d", 20816259Smckusick dp->di_nlink, dp->di_nlink-lcnt); 20916259Smckusick if (preen) { 21016259Smckusick if (lcnt < 0) { 21116259Smckusick printf("\n"); 21217930Smckusick pfatal("LINK COUNT INCREASING"); 21316259Smckusick } 21416259Smckusick printf(" (ADJUSTED)\n"); 21516259Smckusick } 21616259Smckusick if (preen || reply("ADJUST") == 1) { 21716259Smckusick dp->di_nlink -= lcnt; 21816259Smckusick inodirty(); 21916259Smckusick } 22016259Smckusick } 22116259Smckusick } 22216259Smckusick 22316259Smckusick mkentry(idesc) 22416259Smckusick struct inodesc *idesc; 22516259Smckusick { 22616259Smckusick register DIRECT *dirp = idesc->id_dirp; 22716259Smckusick DIRECT newent; 22816259Smckusick int newlen, oldlen; 22916259Smckusick 23016259Smckusick newent.d_namlen = 11; 23116259Smckusick newlen = DIRSIZ(&newent); 23216259Smckusick if (dirp->d_ino != 0) 23316259Smckusick oldlen = DIRSIZ(dirp); 23416259Smckusick else 23516259Smckusick oldlen = 0; 23616259Smckusick if (dirp->d_reclen - oldlen < newlen) 23716259Smckusick return (KEEPON); 23816259Smckusick newent.d_reclen = dirp->d_reclen - oldlen; 23916259Smckusick dirp->d_reclen = oldlen; 24016259Smckusick dirp = (struct direct *)(((char *)dirp) + oldlen); 24116259Smckusick dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */ 24216259Smckusick dirp->d_reclen = newent.d_reclen; 24317954Smckusick dirp->d_namlen = strlen(idesc->id_name); 24417954Smckusick bcopy(idesc->id_name, dirp->d_name, dirp->d_namlen + 1); 24516259Smckusick return (ALTERED|STOP); 24616259Smckusick } 24716259Smckusick 24817957Smckusick chgino(idesc) 24916259Smckusick struct inodesc *idesc; 25016259Smckusick { 25116259Smckusick register DIRECT *dirp = idesc->id_dirp; 25216259Smckusick 25317957Smckusick if (bcmp(dirp->d_name, idesc->id_name, dirp->d_namlen + 1)) 25417957Smckusick return (KEEPON); 25517957Smckusick dirp->d_ino = idesc->id_parent;; 25617957Smckusick return (ALTERED|STOP); 25716259Smckusick } 25816259Smckusick 25916259Smckusick linkup(orphan, pdir) 26016259Smckusick ino_t orphan; 26116259Smckusick ino_t pdir; 26216259Smckusick { 26316259Smckusick register DINODE *dp; 26416259Smckusick int lostdir, len; 26517954Smckusick ino_t oldlfdir; 26616259Smckusick struct inodesc idesc; 26717954Smckusick char tempname[BUFSIZ]; 26817957Smckusick extern int pass4check(); 26916259Smckusick 27016259Smckusick bzero((char *)&idesc, sizeof(struct inodesc)); 27117943Smckusick dp = ginode(orphan); 27217930Smckusick lostdir = DIRCT(dp); 27316259Smckusick pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); 27416259Smckusick pinode(orphan); 27516259Smckusick if (preen && dp->di_size == 0) 27616259Smckusick return (0); 27716259Smckusick if (preen) 27816259Smckusick printf(" (RECONNECTED)\n"); 27916259Smckusick else 28016259Smckusick if (reply("RECONNECT") == 0) 28116259Smckusick return (0); 28216259Smckusick pathp = pathname; 28316259Smckusick *pathp++ = '/'; 28416259Smckusick *pathp = '\0'; 28516259Smckusick if (lfdir == 0) { 28617943Smckusick dp = ginode(ROOTINO); 28717930Smckusick idesc.id_name = lfname; 28816259Smckusick idesc.id_type = DATA; 28916259Smckusick idesc.id_func = findino; 29016259Smckusick idesc.id_number = ROOTINO; 29116259Smckusick (void)ckinode(dp, &idesc); 29217954Smckusick if (idesc.id_parent >= ROOTINO && idesc.id_parent < imax) { 29317954Smckusick lfdir = idesc.id_parent; 29417954Smckusick } else { 29517954Smckusick pwarn("NO lost+found DIRECTORY"); 29617954Smckusick if (preen || reply("CREATE")) { 29717992Smckusick lfdir = allocdir(ROOTINO, 0); 29817992Smckusick if (lfdir != 0) { 29917992Smckusick if (makeentry(ROOTINO, lfdir, lfname) != 0) { 30017954Smckusick if (preen) 30117954Smckusick printf(" (CREATED)\n"); 30217954Smckusick } else { 30317992Smckusick freedir(lfdir, ROOTINO); 30417992Smckusick lfdir = 0; 30517954Smckusick if (preen) 30617954Smckusick printf("\n"); 30717954Smckusick } 30817954Smckusick } 30917954Smckusick } 31017954Smckusick } 31117943Smckusick if (lfdir == 0) { 31217954Smckusick pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY"); 31316259Smckusick printf("\n\n"); 31416259Smckusick return (0); 31516259Smckusick } 31616259Smckusick } 31717943Smckusick dp = ginode(lfdir); 31817957Smckusick if (!DIRCT(dp)) { 31917957Smckusick pfatal("lost+found IS NOT A DIRECTORY"); 32017957Smckusick if (reply("REALLOCATE") == 0) 32117957Smckusick return (0); 32217957Smckusick oldlfdir = lfdir; 32317957Smckusick if ((lfdir = allocdir(ROOTINO, 0)) == 0) { 32417957Smckusick pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); 32517957Smckusick return (0); 32617957Smckusick } 32717957Smckusick idesc.id_type = DATA; 32817957Smckusick idesc.id_func = chgino; 32917957Smckusick idesc.id_number = ROOTINO; 33017957Smckusick idesc.id_parent = lfdir; /* new inumber for lost+found */ 33117957Smckusick idesc.id_name = lfname; 33217957Smckusick if ((ckinode(ginode(ROOTINO), &idesc) & ALTERED) == 0) { 33317957Smckusick pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); 33417957Smckusick return (0); 33517957Smckusick } 33617957Smckusick inodirty(); 33717957Smckusick idesc.id_type = ADDR; 33817957Smckusick idesc.id_func = pass4check; 33917957Smckusick idesc.id_number = oldlfdir; 34017957Smckusick adjust(&idesc, lncntp[oldlfdir] + 1); 34117957Smckusick lncntp[oldlfdir] = 0; 34217957Smckusick dp = ginode(lfdir); 34317957Smckusick } 34417957Smckusick if (statemap[lfdir] != DFOUND) { 34517957Smckusick pfatal("SORRY. NO lost+found DIRECTORY\n\n"); 34616259Smckusick return (0); 34716259Smckusick } 34816259Smckusick len = strlen(lfname); 34916259Smckusick bcopy(lfname, pathp, len + 1); 35016259Smckusick pathp += len; 35117992Smckusick len = lftempname(tempname, orphan); 35217992Smckusick if (makeentry(lfdir, orphan, tempname) == 0) { 35316259Smckusick pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); 35416259Smckusick printf("\n\n"); 35516259Smckusick return (0); 35616259Smckusick } 35716259Smckusick lncntp[orphan]--; 35816259Smckusick *pathp++ = '/'; 35917954Smckusick bcopy(idesc.id_name, pathp, len + 1); 36017954Smckusick pathp += len; 36116259Smckusick if (lostdir) { 36216259Smckusick dp = ginode(orphan); 36316259Smckusick idesc.id_type = DATA; 36417957Smckusick idesc.id_func = chgino; 36516259Smckusick idesc.id_number = orphan; 36616259Smckusick idesc.id_fix = DONTKNOW; 36717957Smckusick idesc.id_name = ".."; 36817957Smckusick idesc.id_parent = lfdir; /* new value for ".." */ 36916259Smckusick (void)ckinode(dp, &idesc); 37017943Smckusick dp = ginode(lfdir); 37117943Smckusick dp->di_nlink++; 37217943Smckusick inodirty(); 37317943Smckusick lncntp[lfdir]++; 37416259Smckusick pwarn("DIR I=%u CONNECTED. ", orphan); 37516259Smckusick printf("PARENT WAS I=%u\n", pdir); 37616259Smckusick if (preen == 0) 37716259Smckusick printf("\n"); 37816259Smckusick } 37916259Smckusick return (1); 38016259Smckusick } 38116259Smckusick 38216259Smckusick /* 38317944Smckusick * make an entry in a directory 38417944Smckusick */ 38517992Smckusick makeentry(parent, ino, name) 38617992Smckusick ino_t parent, ino; 38717992Smckusick char *name; 38817992Smckusick { 38917944Smckusick DINODE *dp; 39017992Smckusick struct inodesc idesc; 39117944Smckusick 39217992Smckusick if (parent < ROOTINO || parent >= imax || ino < ROOTINO || ino >= imax) 39317992Smckusick return (0); 39417992Smckusick bzero(&idesc, sizeof(struct inodesc)); 39517992Smckusick idesc.id_type = DATA; 39617992Smckusick idesc.id_func = mkentry; 39717992Smckusick idesc.id_number = parent; 39817992Smckusick idesc.id_parent = ino; /* this is the inode to enter */ 39917992Smckusick idesc.id_fix = DONTKNOW; 40017992Smckusick idesc.id_name = name; 40117992Smckusick dp = ginode(parent); 402*17993Smckusick if (dp->di_size % DIRBLKSIZ) { 403*17993Smckusick dp->di_size = roundup(dp->di_size, DIRBLKSIZ); 404*17993Smckusick inodirty(); 405*17993Smckusick } 40617992Smckusick if ((ckinode(dp, &idesc) & ALTERED) != 0) 40717944Smckusick return (1); 40817944Smckusick if (expanddir(dp) == 0) 40917944Smckusick return (0); 41017992Smckusick return (ckinode(dp, &idesc) & ALTERED); 41117944Smckusick } 41217944Smckusick 41317944Smckusick /* 41417944Smckusick * Attempt to expand the size of a directory 41517944Smckusick */ 41617944Smckusick expanddir(dp) 41717944Smckusick register DINODE *dp; 41817944Smckusick { 41917944Smckusick daddr_t lastbn, newblk; 42017944Smckusick char *cp, firstblk[DIRBLKSIZ]; 42117944Smckusick 42217944Smckusick lastbn = lblkno(&sblock, dp->di_size); 42317944Smckusick if (lastbn >= NDADDR - 1) 42417944Smckusick return (0); 42517944Smckusick if ((newblk = allocblk(sblock.fs_frag)) == 0) 42617944Smckusick return (0); 42717944Smckusick dp->di_db[lastbn + 1] = dp->di_db[lastbn]; 42817944Smckusick dp->di_db[lastbn] = newblk; 42917944Smckusick dp->di_size += sblock.fs_bsize; 43017944Smckusick dp->di_blocks += btodb(sblock.fs_bsize); 43117944Smckusick if (getblk(&fileblk, dp->di_db[lastbn + 1], 43217944Smckusick dblksize(&sblock, dp, lastbn + 1)) == NULL) 43317944Smckusick goto bad; 43417944Smckusick bcopy(dirblk.b_buf, firstblk, DIRBLKSIZ); 43517944Smckusick if (getblk(&fileblk, newblk, sblock.fs_bsize) == NULL) 43617944Smckusick goto bad; 43717944Smckusick bcopy(firstblk, dirblk.b_buf, DIRBLKSIZ); 43817944Smckusick for (cp = &dirblk.b_buf[DIRBLKSIZ]; 43917944Smckusick cp < &dirblk.b_buf[sblock.fs_bsize]; 44017944Smckusick cp += DIRBLKSIZ) 44117944Smckusick bcopy((char *)&emptydir, cp, sizeof emptydir); 44217944Smckusick dirty(&fileblk); 44317944Smckusick if (getblk(&fileblk, dp->di_db[lastbn + 1], 44417944Smckusick dblksize(&sblock, dp, lastbn + 1)) == NULL) 44517944Smckusick goto bad; 44617944Smckusick bcopy((char *)&emptydir, dirblk.b_buf, sizeof emptydir); 44717944Smckusick pwarn("NO SPACE LEFT IN %s", pathname); 44817944Smckusick if (preen) 44917944Smckusick printf(" (EXPANDED)\n"); 45017944Smckusick else if (reply("EXPAND") == 0) 45117944Smckusick goto bad; 45217944Smckusick dirty(&fileblk); 45317944Smckusick inodirty(); 45417944Smckusick return (1); 45517944Smckusick bad: 45617944Smckusick dp->di_db[lastbn] = dp->di_db[lastbn + 1]; 45717944Smckusick dp->di_db[lastbn + 1] = 0; 45817944Smckusick dp->di_size -= sblock.fs_bsize; 45917944Smckusick dp->di_blocks -= btodb(sblock.fs_bsize); 46017944Smckusick freeblk(newblk, sblock.fs_frag); 46117944Smckusick return (0); 46217944Smckusick } 46317944Smckusick 46417944Smckusick /* 46517954Smckusick * allocate a new directory 46617954Smckusick */ 46717954Smckusick allocdir(parent, request) 46817954Smckusick ino_t parent, request; 46917954Smckusick { 47017954Smckusick ino_t ino; 47117954Smckusick char *cp; 47217954Smckusick DINODE *dp; 47317954Smckusick 47417954Smckusick ino = allocino(request, IFDIR|0755); 47517954Smckusick dirhead.dot_ino = ino; 47617954Smckusick dirhead.dotdot_ino = parent; 47717954Smckusick dp = ginode(ino); 47817954Smckusick if (getblk(&fileblk, dp->di_db[0], sblock.fs_fsize) == NULL) { 47917954Smckusick freeino(ino); 48017954Smckusick return (0); 48117954Smckusick } 48217954Smckusick bcopy((char *)&dirhead, dirblk.b_buf, sizeof dirhead); 48317954Smckusick for (cp = &dirblk.b_buf[DIRBLKSIZ]; 48417954Smckusick cp < &dirblk.b_buf[sblock.fs_fsize]; 48517954Smckusick cp += DIRBLKSIZ) 48617954Smckusick bcopy((char *)&emptydir, cp, sizeof emptydir); 48717954Smckusick dirty(&fileblk); 48817954Smckusick dp->di_nlink = 2; 48917954Smckusick inodirty(); 49017954Smckusick if (ino == ROOTINO) { 49117954Smckusick lncntp[ino] = dp->di_nlink; 49217954Smckusick return(ino); 49317954Smckusick } 49417954Smckusick if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) { 49517954Smckusick freeino(ino); 49617954Smckusick return (0); 49717954Smckusick } 49817954Smckusick statemap[ino] = statemap[parent]; 49917954Smckusick if (statemap[ino] == DSTATE) { 50017954Smckusick lncntp[ino] = dp->di_nlink; 50117954Smckusick lncntp[parent]++; 50217954Smckusick } 50317954Smckusick dp = ginode(parent); 50417954Smckusick dp->di_nlink++; 50517954Smckusick inodirty(); 50617954Smckusick return (ino); 50717954Smckusick } 50817954Smckusick 50917954Smckusick /* 51017954Smckusick * free a directory inode 51117954Smckusick */ 51217954Smckusick freedir(ino, parent) 51317954Smckusick ino_t ino, parent; 51417954Smckusick { 51517954Smckusick DINODE *dp; 51617954Smckusick 51717954Smckusick if (ino != parent) { 51817954Smckusick dp = ginode(parent); 51917954Smckusick dp->di_nlink--; 52017954Smckusick inodirty(); 52117954Smckusick } 52217954Smckusick freeino(ino); 52317954Smckusick } 52417954Smckusick 52517954Smckusick /* 52616259Smckusick * generate a temporary name for the lost+found directory. 52716259Smckusick */ 52816259Smckusick lftempname(bufp, ino) 52916259Smckusick char *bufp; 53016259Smckusick ino_t ino; 53116259Smckusick { 53216259Smckusick register ino_t in; 53316259Smckusick register char *cp; 53416259Smckusick int namlen; 53516259Smckusick 53616259Smckusick cp = bufp + 2; 53716259Smckusick for (in = imax; in > 0; in /= 10) 53816259Smckusick cp++; 53916259Smckusick *--cp = 0; 54016259Smckusick namlen = cp - bufp; 54116259Smckusick in = ino; 54216259Smckusick while (cp > bufp) { 54316259Smckusick *--cp = (in % 10) + '0'; 54416259Smckusick in /= 10; 54516259Smckusick } 54616259Smckusick *cp = '#'; 54716259Smckusick return (namlen); 54816259Smckusick } 549