116259Smckusick #ifndef lint 2*21742Smckusick static char version[] = "@(#)dir.c 3.11 (Berkeley) 05/31/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 } 46*21742Smckusick if ((dp->di_size & (DIRBLKSIZ - 1)) != 0) { 47*21742Smckusick pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d", 48*21742Smckusick pathname, dp->di_size, DIRBLKSIZ); 49*21742Smckusick dp->di_size = roundup(dp->di_size, DIRBLKSIZ); 50*21742Smckusick if (preen) 51*21742Smckusick printf(" (ADJUSTED)\n"); 52*21742Smckusick if (preen || reply("ADJUST") == 1) 53*21742Smckusick inodirty(); 54*21742Smckusick } 5516259Smckusick curino.id_type = DATA; 5616259Smckusick curino.id_func = parentino->id_func; 5716259Smckusick curino.id_parent = parentino->id_number; 5816259Smckusick curino.id_number = inumber; 5916259Smckusick (void)ckinode(dp, &curino); 6016259Smckusick } 6116259Smckusick 6216259Smckusick dirscan(idesc) 6316259Smckusick register struct inodesc *idesc; 6416259Smckusick { 6516259Smckusick register DIRECT *dp; 6616259Smckusick int dsize, n; 6716259Smckusick long blksiz; 6816259Smckusick char dbuf[DIRBLKSIZ]; 6916259Smckusick 7016259Smckusick if (idesc->id_type != DATA) 7116259Smckusick errexit("wrong type to dirscan %d\n", idesc->id_type); 7217993Smckusick if (idesc->id_entryno == 0 && 7317993Smckusick (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0) 7417993Smckusick idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ); 7516259Smckusick blksiz = idesc->id_numfrags * sblock.fs_fsize; 7616259Smckusick if (outrange(idesc->id_blkno, idesc->id_numfrags)) { 7716259Smckusick idesc->id_filesize -= blksiz; 7816259Smckusick return (SKIP); 7916259Smckusick } 8016259Smckusick idesc->id_loc = 0; 8116259Smckusick for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) { 8216259Smckusick dsize = dp->d_reclen; 8316259Smckusick bcopy((char *)dp, dbuf, dsize); 8416259Smckusick idesc->id_dirp = (DIRECT *)dbuf; 8516259Smckusick if ((n = (*idesc->id_func)(idesc)) & ALTERED) { 86*21742Smckusick getblk(&fileblk, idesc->id_blkno, blksiz); 87*21742Smckusick if (fileblk.b_errs != NULL) { 88*21742Smckusick n &= ~ALTERED; 89*21742Smckusick } else { 9016259Smckusick bcopy(dbuf, (char *)dp, dsize); 9116259Smckusick dirty(&fileblk); 9216259Smckusick sbdirty(); 93*21742Smckusick } 9416259Smckusick } 9516259Smckusick if (n & STOP) 9616259Smckusick return (n); 9716259Smckusick } 9816259Smckusick return (idesc->id_filesize > 0 ? KEEPON : STOP); 9916259Smckusick } 10016259Smckusick 10116259Smckusick /* 10216259Smckusick * get next entry in a directory. 10316259Smckusick */ 10416259Smckusick DIRECT * 10516259Smckusick fsck_readdir(idesc) 10616259Smckusick register struct inodesc *idesc; 10716259Smckusick { 10816259Smckusick register DIRECT *dp, *ndp; 10916259Smckusick long size, blksiz; 11016259Smckusick 11116259Smckusick blksiz = idesc->id_numfrags * sblock.fs_fsize; 112*21742Smckusick getblk(&fileblk, idesc->id_blkno, blksiz); 113*21742Smckusick if (fileblk.b_errs != NULL) { 11416259Smckusick idesc->id_filesize -= blksiz - idesc->id_loc; 11516259Smckusick return NULL; 11616259Smckusick } 11716259Smckusick if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 && 11816259Smckusick idesc->id_loc < blksiz) { 11916259Smckusick dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); 12016259Smckusick if (dircheck(idesc, dp)) 12116259Smckusick goto dpok; 12216259Smckusick idesc->id_loc += DIRBLKSIZ; 12316259Smckusick idesc->id_filesize -= DIRBLKSIZ; 12416259Smckusick dp->d_reclen = DIRBLKSIZ; 12516259Smckusick dp->d_ino = 0; 12616259Smckusick dp->d_namlen = 0; 12716259Smckusick dp->d_name[0] = '\0'; 12817930Smckusick if (dofix(idesc, "DIRECTORY CORRUPTED")) 12916259Smckusick dirty(&fileblk); 13016259Smckusick return (dp); 13116259Smckusick } 13216259Smckusick dpok: 13316259Smckusick if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz) 13416259Smckusick return NULL; 13516259Smckusick dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); 13616259Smckusick idesc->id_loc += dp->d_reclen; 13716259Smckusick idesc->id_filesize -= dp->d_reclen; 13816259Smckusick if ((idesc->id_loc % DIRBLKSIZ) == 0) 13916259Smckusick return (dp); 14016259Smckusick ndp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); 14116259Smckusick if (idesc->id_loc < blksiz && idesc->id_filesize > 0 && 14216259Smckusick dircheck(idesc, ndp) == 0) { 14316259Smckusick size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); 14416259Smckusick dp->d_reclen += size; 14516259Smckusick idesc->id_loc += size; 14616259Smckusick idesc->id_filesize -= size; 14717930Smckusick if (dofix(idesc, "DIRECTORY CORRUPTED")) 14816259Smckusick dirty(&fileblk); 14916259Smckusick } 15016259Smckusick return (dp); 15116259Smckusick } 15216259Smckusick 15316259Smckusick /* 15416259Smckusick * Verify that a directory entry is valid. 15516259Smckusick * This is a superset of the checks made in the kernel. 15616259Smckusick */ 15716259Smckusick dircheck(idesc, dp) 15816259Smckusick struct inodesc *idesc; 15916259Smckusick register DIRECT *dp; 16016259Smckusick { 16116259Smckusick register int size; 16216259Smckusick register char *cp; 16316259Smckusick int spaceleft; 16416259Smckusick 16516259Smckusick size = DIRSIZ(dp); 16616259Smckusick spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); 16716259Smckusick if (dp->d_ino < imax && 16816259Smckusick dp->d_reclen != 0 && 16916259Smckusick dp->d_reclen <= spaceleft && 17016259Smckusick (dp->d_reclen & 0x3) == 0 && 17116259Smckusick dp->d_reclen >= size && 17216259Smckusick idesc->id_filesize >= size && 17316259Smckusick dp->d_namlen <= MAXNAMLEN) { 17416259Smckusick if (dp->d_ino == 0) 17516259Smckusick return (1); 17616259Smckusick for (cp = dp->d_name, size = 0; size < dp->d_namlen; size++) 17716259Smckusick if (*cp == 0 || (*cp++ & 0200)) 17816259Smckusick return (0); 17916259Smckusick if (*cp == 0) 18016259Smckusick return (1); 18116259Smckusick } 18216259Smckusick return (0); 18316259Smckusick } 18416259Smckusick 18516259Smckusick direrr(ino, s) 18616259Smckusick ino_t ino; 18716259Smckusick char *s; 18816259Smckusick { 18916259Smckusick register DINODE *dp; 19016259Smckusick 19116259Smckusick pwarn("%s ", s); 19216259Smckusick pinode(ino); 19316259Smckusick printf("\n"); 19417943Smckusick if (ino < ROOTINO || ino > imax) { 19517943Smckusick pfatal("NAME=%s\n", pathname); 19617943Smckusick return; 19717943Smckusick } 19817943Smckusick dp = ginode(ino); 19917943Smckusick if (ftypeok(dp)) 20017930Smckusick pfatal("%s=%s\n", DIRCT(dp) ? "DIR" : "FILE", pathname); 20116259Smckusick else 20216259Smckusick pfatal("NAME=%s\n", pathname); 20316259Smckusick } 20416259Smckusick 20516259Smckusick adjust(idesc, lcnt) 20616259Smckusick register struct inodesc *idesc; 20716259Smckusick short lcnt; 20816259Smckusick { 20916259Smckusick register DINODE *dp; 21016259Smckusick 21117943Smckusick dp = ginode(idesc->id_number); 21216259Smckusick if (dp->di_nlink == lcnt) { 21316259Smckusick if (linkup(idesc->id_number, (ino_t)0) == 0) 21416259Smckusick clri(idesc, "UNREF", 0); 21517936Smckusick } else { 21617930Smckusick pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : 21717930Smckusick (DIRCT(dp) ? "DIR" : "FILE")); 21816259Smckusick pinode(idesc->id_number); 21916259Smckusick printf(" COUNT %d SHOULD BE %d", 22016259Smckusick dp->di_nlink, dp->di_nlink-lcnt); 22116259Smckusick if (preen) { 22216259Smckusick if (lcnt < 0) { 22316259Smckusick printf("\n"); 22417930Smckusick pfatal("LINK COUNT INCREASING"); 22516259Smckusick } 22616259Smckusick printf(" (ADJUSTED)\n"); 22716259Smckusick } 22816259Smckusick if (preen || reply("ADJUST") == 1) { 22916259Smckusick dp->di_nlink -= lcnt; 23016259Smckusick inodirty(); 23116259Smckusick } 23216259Smckusick } 23316259Smckusick } 23416259Smckusick 23516259Smckusick mkentry(idesc) 23616259Smckusick struct inodesc *idesc; 23716259Smckusick { 23816259Smckusick register DIRECT *dirp = idesc->id_dirp; 23916259Smckusick DIRECT newent; 24016259Smckusick int newlen, oldlen; 24116259Smckusick 24216259Smckusick newent.d_namlen = 11; 24316259Smckusick newlen = DIRSIZ(&newent); 24416259Smckusick if (dirp->d_ino != 0) 24516259Smckusick oldlen = DIRSIZ(dirp); 24616259Smckusick else 24716259Smckusick oldlen = 0; 24816259Smckusick if (dirp->d_reclen - oldlen < newlen) 24916259Smckusick return (KEEPON); 25016259Smckusick newent.d_reclen = dirp->d_reclen - oldlen; 25116259Smckusick dirp->d_reclen = oldlen; 25216259Smckusick dirp = (struct direct *)(((char *)dirp) + oldlen); 25316259Smckusick dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */ 25416259Smckusick dirp->d_reclen = newent.d_reclen; 25517954Smckusick dirp->d_namlen = strlen(idesc->id_name); 25617954Smckusick bcopy(idesc->id_name, dirp->d_name, dirp->d_namlen + 1); 25716259Smckusick return (ALTERED|STOP); 25816259Smckusick } 25916259Smckusick 26017957Smckusick chgino(idesc) 26116259Smckusick struct inodesc *idesc; 26216259Smckusick { 26316259Smckusick register DIRECT *dirp = idesc->id_dirp; 26416259Smckusick 26517957Smckusick if (bcmp(dirp->d_name, idesc->id_name, dirp->d_namlen + 1)) 26617957Smckusick return (KEEPON); 26717957Smckusick dirp->d_ino = idesc->id_parent;; 26817957Smckusick return (ALTERED|STOP); 26916259Smckusick } 27016259Smckusick 27116259Smckusick linkup(orphan, pdir) 27216259Smckusick ino_t orphan; 27316259Smckusick ino_t pdir; 27416259Smckusick { 27516259Smckusick register DINODE *dp; 27616259Smckusick int lostdir, len; 27717954Smckusick ino_t oldlfdir; 27816259Smckusick struct inodesc idesc; 27917954Smckusick char tempname[BUFSIZ]; 28017957Smckusick extern int pass4check(); 28116259Smckusick 28216259Smckusick bzero((char *)&idesc, sizeof(struct inodesc)); 28317943Smckusick dp = ginode(orphan); 28417930Smckusick lostdir = DIRCT(dp); 28516259Smckusick pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); 28616259Smckusick pinode(orphan); 28716259Smckusick if (preen && dp->di_size == 0) 28816259Smckusick return (0); 28916259Smckusick if (preen) 29016259Smckusick printf(" (RECONNECTED)\n"); 29116259Smckusick else 29216259Smckusick if (reply("RECONNECT") == 0) 29316259Smckusick return (0); 29416259Smckusick pathp = pathname; 29516259Smckusick *pathp++ = '/'; 29616259Smckusick *pathp = '\0'; 29716259Smckusick if (lfdir == 0) { 29817943Smckusick dp = ginode(ROOTINO); 29917930Smckusick idesc.id_name = lfname; 30016259Smckusick idesc.id_type = DATA; 30116259Smckusick idesc.id_func = findino; 30216259Smckusick idesc.id_number = ROOTINO; 30316259Smckusick (void)ckinode(dp, &idesc); 30417954Smckusick if (idesc.id_parent >= ROOTINO && idesc.id_parent < imax) { 30517954Smckusick lfdir = idesc.id_parent; 30617954Smckusick } else { 30717954Smckusick pwarn("NO lost+found DIRECTORY"); 30817954Smckusick if (preen || reply("CREATE")) { 30917992Smckusick lfdir = allocdir(ROOTINO, 0); 31017992Smckusick if (lfdir != 0) { 31117992Smckusick if (makeentry(ROOTINO, lfdir, lfname) != 0) { 31217954Smckusick if (preen) 31317954Smckusick printf(" (CREATED)\n"); 31417954Smckusick } else { 31517992Smckusick freedir(lfdir, ROOTINO); 31617992Smckusick lfdir = 0; 31717954Smckusick if (preen) 31817954Smckusick printf("\n"); 31917954Smckusick } 32017954Smckusick } 32117954Smckusick } 32217954Smckusick } 32317943Smckusick if (lfdir == 0) { 32417954Smckusick pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY"); 32516259Smckusick printf("\n\n"); 32616259Smckusick return (0); 32716259Smckusick } 32816259Smckusick } 32917943Smckusick dp = ginode(lfdir); 33017957Smckusick if (!DIRCT(dp)) { 33117957Smckusick pfatal("lost+found IS NOT A DIRECTORY"); 33217957Smckusick if (reply("REALLOCATE") == 0) 33317957Smckusick return (0); 33417957Smckusick oldlfdir = lfdir; 33517957Smckusick if ((lfdir = allocdir(ROOTINO, 0)) == 0) { 33617957Smckusick pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); 33717957Smckusick return (0); 33817957Smckusick } 33917957Smckusick idesc.id_type = DATA; 34017957Smckusick idesc.id_func = chgino; 34117957Smckusick idesc.id_number = ROOTINO; 34217957Smckusick idesc.id_parent = lfdir; /* new inumber for lost+found */ 34317957Smckusick idesc.id_name = lfname; 34417957Smckusick if ((ckinode(ginode(ROOTINO), &idesc) & ALTERED) == 0) { 34517957Smckusick pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); 34617957Smckusick return (0); 34717957Smckusick } 34817957Smckusick inodirty(); 34917957Smckusick idesc.id_type = ADDR; 35017957Smckusick idesc.id_func = pass4check; 35117957Smckusick idesc.id_number = oldlfdir; 35217957Smckusick adjust(&idesc, lncntp[oldlfdir] + 1); 35317957Smckusick lncntp[oldlfdir] = 0; 35417957Smckusick dp = ginode(lfdir); 35517957Smckusick } 35617957Smckusick if (statemap[lfdir] != DFOUND) { 35717957Smckusick pfatal("SORRY. NO lost+found DIRECTORY\n\n"); 35816259Smckusick return (0); 35916259Smckusick } 36016259Smckusick len = strlen(lfname); 36116259Smckusick bcopy(lfname, pathp, len + 1); 36216259Smckusick pathp += len; 36317992Smckusick len = lftempname(tempname, orphan); 36417992Smckusick if (makeentry(lfdir, orphan, tempname) == 0) { 36516259Smckusick pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); 36616259Smckusick printf("\n\n"); 36716259Smckusick return (0); 36816259Smckusick } 36916259Smckusick lncntp[orphan]--; 37016259Smckusick *pathp++ = '/'; 37117954Smckusick bcopy(idesc.id_name, pathp, len + 1); 37217954Smckusick pathp += len; 37316259Smckusick if (lostdir) { 37416259Smckusick dp = ginode(orphan); 37516259Smckusick idesc.id_type = DATA; 37617957Smckusick idesc.id_func = chgino; 37716259Smckusick idesc.id_number = orphan; 37816259Smckusick idesc.id_fix = DONTKNOW; 37917957Smckusick idesc.id_name = ".."; 38017957Smckusick idesc.id_parent = lfdir; /* new value for ".." */ 38116259Smckusick (void)ckinode(dp, &idesc); 38217943Smckusick dp = ginode(lfdir); 38317943Smckusick dp->di_nlink++; 38417943Smckusick inodirty(); 38517943Smckusick lncntp[lfdir]++; 38616259Smckusick pwarn("DIR I=%u CONNECTED. ", orphan); 38716259Smckusick printf("PARENT WAS I=%u\n", pdir); 38816259Smckusick if (preen == 0) 38916259Smckusick printf("\n"); 39016259Smckusick } 39116259Smckusick return (1); 39216259Smckusick } 39316259Smckusick 39416259Smckusick /* 39517944Smckusick * make an entry in a directory 39617944Smckusick */ 39717992Smckusick makeentry(parent, ino, name) 39817992Smckusick ino_t parent, ino; 39917992Smckusick char *name; 40017992Smckusick { 40117944Smckusick DINODE *dp; 40217992Smckusick struct inodesc idesc; 40317944Smckusick 40417992Smckusick if (parent < ROOTINO || parent >= imax || ino < ROOTINO || ino >= imax) 40517992Smckusick return (0); 40617992Smckusick bzero(&idesc, sizeof(struct inodesc)); 40717992Smckusick idesc.id_type = DATA; 40817992Smckusick idesc.id_func = mkentry; 40917992Smckusick idesc.id_number = parent; 41017992Smckusick idesc.id_parent = ino; /* this is the inode to enter */ 41117992Smckusick idesc.id_fix = DONTKNOW; 41217992Smckusick idesc.id_name = name; 41317992Smckusick dp = ginode(parent); 41417993Smckusick if (dp->di_size % DIRBLKSIZ) { 41517993Smckusick dp->di_size = roundup(dp->di_size, DIRBLKSIZ); 41617993Smckusick inodirty(); 41717993Smckusick } 41817992Smckusick if ((ckinode(dp, &idesc) & ALTERED) != 0) 41917944Smckusick return (1); 42017944Smckusick if (expanddir(dp) == 0) 42117944Smckusick return (0); 42217992Smckusick return (ckinode(dp, &idesc) & ALTERED); 42317944Smckusick } 42417944Smckusick 42517944Smckusick /* 42617944Smckusick * Attempt to expand the size of a directory 42717944Smckusick */ 42817944Smckusick expanddir(dp) 42917944Smckusick register DINODE *dp; 43017944Smckusick { 43117944Smckusick daddr_t lastbn, newblk; 43217944Smckusick char *cp, firstblk[DIRBLKSIZ]; 43317944Smckusick 43417944Smckusick lastbn = lblkno(&sblock, dp->di_size); 43517944Smckusick if (lastbn >= NDADDR - 1) 43617944Smckusick return (0); 43717944Smckusick if ((newblk = allocblk(sblock.fs_frag)) == 0) 43817944Smckusick return (0); 43917944Smckusick dp->di_db[lastbn + 1] = dp->di_db[lastbn]; 44017944Smckusick dp->di_db[lastbn] = newblk; 44117944Smckusick dp->di_size += sblock.fs_bsize; 44217944Smckusick dp->di_blocks += btodb(sblock.fs_bsize); 443*21742Smckusick getblk(&fileblk, dp->di_db[lastbn + 1], 444*21742Smckusick dblksize(&sblock, dp, lastbn + 1)); 445*21742Smckusick if (fileblk.b_errs != NULL) 44617944Smckusick goto bad; 44717944Smckusick bcopy(dirblk.b_buf, firstblk, DIRBLKSIZ); 448*21742Smckusick getblk(&fileblk, newblk, sblock.fs_bsize); 449*21742Smckusick if (fileblk.b_errs != NULL) 45017944Smckusick goto bad; 45117944Smckusick bcopy(firstblk, dirblk.b_buf, DIRBLKSIZ); 45217944Smckusick for (cp = &dirblk.b_buf[DIRBLKSIZ]; 45317944Smckusick cp < &dirblk.b_buf[sblock.fs_bsize]; 45417944Smckusick cp += DIRBLKSIZ) 45517944Smckusick bcopy((char *)&emptydir, cp, sizeof emptydir); 45617944Smckusick dirty(&fileblk); 457*21742Smckusick getblk(&fileblk, dp->di_db[lastbn + 1], 458*21742Smckusick dblksize(&sblock, dp, lastbn + 1)); 459*21742Smckusick if (fileblk.b_errs != NULL) 46017944Smckusick goto bad; 46117944Smckusick bcopy((char *)&emptydir, dirblk.b_buf, sizeof emptydir); 46217944Smckusick pwarn("NO SPACE LEFT IN %s", pathname); 46317944Smckusick if (preen) 46417944Smckusick printf(" (EXPANDED)\n"); 46517944Smckusick else if (reply("EXPAND") == 0) 46617944Smckusick goto bad; 46717944Smckusick dirty(&fileblk); 46817944Smckusick inodirty(); 46917944Smckusick return (1); 47017944Smckusick bad: 47117944Smckusick dp->di_db[lastbn] = dp->di_db[lastbn + 1]; 47217944Smckusick dp->di_db[lastbn + 1] = 0; 47317944Smckusick dp->di_size -= sblock.fs_bsize; 47417944Smckusick dp->di_blocks -= btodb(sblock.fs_bsize); 47517944Smckusick freeblk(newblk, sblock.fs_frag); 47617944Smckusick return (0); 47717944Smckusick } 47817944Smckusick 47917944Smckusick /* 48017954Smckusick * allocate a new directory 48117954Smckusick */ 48217954Smckusick allocdir(parent, request) 48317954Smckusick ino_t parent, request; 48417954Smckusick { 48517954Smckusick ino_t ino; 48617954Smckusick char *cp; 48717954Smckusick DINODE *dp; 48817954Smckusick 48917954Smckusick ino = allocino(request, IFDIR|0755); 49017954Smckusick dirhead.dot_ino = ino; 49117954Smckusick dirhead.dotdot_ino = parent; 49217954Smckusick dp = ginode(ino); 493*21742Smckusick getblk(&fileblk, dp->di_db[0], sblock.fs_fsize); 494*21742Smckusick if (fileblk.b_errs != NULL) { 49517954Smckusick freeino(ino); 49617954Smckusick return (0); 49717954Smckusick } 49817954Smckusick bcopy((char *)&dirhead, dirblk.b_buf, sizeof dirhead); 49917954Smckusick for (cp = &dirblk.b_buf[DIRBLKSIZ]; 50017954Smckusick cp < &dirblk.b_buf[sblock.fs_fsize]; 50117954Smckusick cp += DIRBLKSIZ) 50217954Smckusick bcopy((char *)&emptydir, cp, sizeof emptydir); 50317954Smckusick dirty(&fileblk); 50417954Smckusick dp->di_nlink = 2; 50517954Smckusick inodirty(); 50617954Smckusick if (ino == ROOTINO) { 50717954Smckusick lncntp[ino] = dp->di_nlink; 50817954Smckusick return(ino); 50917954Smckusick } 51017954Smckusick if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) { 51117954Smckusick freeino(ino); 51217954Smckusick return (0); 51317954Smckusick } 51417954Smckusick statemap[ino] = statemap[parent]; 51517954Smckusick if (statemap[ino] == DSTATE) { 51617954Smckusick lncntp[ino] = dp->di_nlink; 51717954Smckusick lncntp[parent]++; 51817954Smckusick } 51917954Smckusick dp = ginode(parent); 52017954Smckusick dp->di_nlink++; 52117954Smckusick inodirty(); 52217954Smckusick return (ino); 52317954Smckusick } 52417954Smckusick 52517954Smckusick /* 52617954Smckusick * free a directory inode 52717954Smckusick */ 52817954Smckusick freedir(ino, parent) 52917954Smckusick ino_t ino, parent; 53017954Smckusick { 53117954Smckusick DINODE *dp; 53217954Smckusick 53317954Smckusick if (ino != parent) { 53417954Smckusick dp = ginode(parent); 53517954Smckusick dp->di_nlink--; 53617954Smckusick inodirty(); 53717954Smckusick } 53817954Smckusick freeino(ino); 53917954Smckusick } 54017954Smckusick 54117954Smckusick /* 54216259Smckusick * generate a temporary name for the lost+found directory. 54316259Smckusick */ 54416259Smckusick lftempname(bufp, ino) 54516259Smckusick char *bufp; 54616259Smckusick ino_t ino; 54716259Smckusick { 54816259Smckusick register ino_t in; 54916259Smckusick register char *cp; 55016259Smckusick int namlen; 55116259Smckusick 55216259Smckusick cp = bufp + 2; 55316259Smckusick for (in = imax; in > 0; in /= 10) 55416259Smckusick cp++; 55516259Smckusick *--cp = 0; 55616259Smckusick namlen = cp - bufp; 55716259Smckusick in = ino; 55816259Smckusick while (cp > bufp) { 55916259Smckusick *--cp = (in % 10) + '0'; 56016259Smckusick in /= 10; 56116259Smckusick } 56216259Smckusick *cp = '#'; 56316259Smckusick return (namlen); 56416259Smckusick } 565