Annotation of 43BSDReno/sbin/fsck/dir.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980, 1986 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted provided
        !             6:  * that: (1) source distributions retain this entire copyright notice and
        !             7:  * comment, and (2) distributions including binaries display the following
        !             8:  * acknowledgement:  ``This product includes software developed by the
        !             9:  * University of California, Berkeley and its contributors'' in the
        !            10:  * documentation or other materials provided with the distribution and in
        !            11:  * all advertising materials mentioning features or use of this software.
        !            12:  * Neither the name of the University nor the names of its contributors may
        !            13:  * be used to endorse or promote products derived from this software without
        !            14:  * specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: static char sccsid[] = "@(#)dir.c      5.18 (Berkeley) 7/20/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #include <sys/param.h>
        !            25: #include <ufs/dinode.h>
        !            26: #include <ufs/fs.h>
        !            27: #define KERNEL
        !            28: #include <ufs/dir.h>
        !            29: #undef KERNEL
        !            30: #include <stdlib.h>
        !            31: #include <string.h>
        !            32: #include "fsck.h"
        !            33: 
        !            34: char   *lfname = "lost+found";
        !            35: int    lfmode = 01777;
        !            36: struct dirtemplate emptydir = { 0, DIRBLKSIZ };
        !            37: struct dirtemplate dirhead = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." };
        !            38: 
        !            39: struct direct  *fsck_readdir();
        !            40: struct bufarea *getdirblk();
        !            41: 
        !            42: /*
        !            43:  * Propagate connected state through the tree.
        !            44:  */
        !            45: propagate()
        !            46: {
        !            47:        register struct inoinfo **inpp, *inp;
        !            48:        struct inoinfo **inpend;
        !            49:        long change;
        !            50: 
        !            51:        inpend = &inpsort[inplast];
        !            52:        do {
        !            53:                change = 0;
        !            54:                for (inpp = inpsort; inpp < inpend; inpp++) {
        !            55:                        inp = *inpp;
        !            56:                        if (inp->i_parent == 0)
        !            57:                                continue;
        !            58:                        if (statemap[inp->i_parent] == DFOUND &&
        !            59:                            statemap[inp->i_number] == DSTATE) {
        !            60:                                statemap[inp->i_number] = DFOUND;
        !            61:                                change++;
        !            62:                        }
        !            63:                }
        !            64:        } while (change > 0);
        !            65: }
        !            66: 
        !            67: /*
        !            68:  * Scan each entry in a directory block.
        !            69:  */
        !            70: dirscan(idesc)
        !            71:        register struct inodesc *idesc;
        !            72: {
        !            73:        register struct direct *dp;
        !            74:        register struct bufarea *bp;
        !            75:        int dsize, n;
        !            76:        long blksiz;
        !            77:        char dbuf[DIRBLKSIZ];
        !            78: 
        !            79:        if (idesc->id_type != DATA)
        !            80:                errexit("wrong type to dirscan %d\n", idesc->id_type);
        !            81:        if (idesc->id_entryno == 0 &&
        !            82:            (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0)
        !            83:                idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ);
        !            84:        blksiz = idesc->id_numfrags * sblock.fs_fsize;
        !            85:        if (chkrange(idesc->id_blkno, idesc->id_numfrags)) {
        !            86:                idesc->id_filesize -= blksiz;
        !            87:                return (SKIP);
        !            88:        }
        !            89:        idesc->id_loc = 0;
        !            90:        for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
        !            91:                dsize = dp->d_reclen;
        !            92:                bcopy((char *)dp, dbuf, (size_t)dsize);
        !            93:                idesc->id_dirp = (struct direct *)dbuf;
        !            94:                if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
        !            95:                        bp = getdirblk(idesc->id_blkno, blksiz);
        !            96:                        bcopy(dbuf, bp->b_un.b_buf + idesc->id_loc - dsize,
        !            97:                            (size_t)dsize);
        !            98:                        dirty(bp);
        !            99:                        sbdirty();
        !           100:                }
        !           101:                if (n & STOP) 
        !           102:                        return (n);
        !           103:        }
        !           104:        return (idesc->id_filesize > 0 ? KEEPON : STOP);
        !           105: }
        !           106: 
        !           107: /*
        !           108:  * get next entry in a directory.
        !           109:  */
        !           110: struct direct *
        !           111: fsck_readdir(idesc)
        !           112:        register struct inodesc *idesc;
        !           113: {
        !           114:        register struct direct *dp, *ndp;
        !           115:        register struct bufarea *bp;
        !           116:        long size, blksiz, fix;
        !           117: 
        !           118:        blksiz = idesc->id_numfrags * sblock.fs_fsize;
        !           119:        bp = getdirblk(idesc->id_blkno, blksiz);
        !           120:        if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
        !           121:            idesc->id_loc < blksiz) {
        !           122:                dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
        !           123:                if (dircheck(idesc, dp))
        !           124:                        goto dpok;
        !           125:                idesc->id_loc += DIRBLKSIZ;
        !           126:                idesc->id_filesize -= DIRBLKSIZ;
        !           127:                fix = dofix(idesc, "DIRECTORY CORRUPTED");
        !           128:                bp = getdirblk(idesc->id_blkno, blksiz);
        !           129:                dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
        !           130:                dp->d_reclen = DIRBLKSIZ;
        !           131:                dp->d_ino = 0;
        !           132:                dp->d_namlen = 0;
        !           133:                dp->d_name[0] = '\0';
        !           134:                if (fix)
        !           135:                        dirty(bp);
        !           136:                return (dp);
        !           137:        }
        !           138: dpok:
        !           139:        if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
        !           140:                return NULL;
        !           141:        dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
        !           142:        idesc->id_loc += dp->d_reclen;
        !           143:        idesc->id_filesize -= dp->d_reclen;
        !           144:        if ((idesc->id_loc % DIRBLKSIZ) == 0)
        !           145:                return (dp);
        !           146:        ndp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
        !           147:        if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
        !           148:            dircheck(idesc, ndp) == 0) {
        !           149:                size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
        !           150:                idesc->id_loc += size;
        !           151:                idesc->id_filesize -= size;
        !           152:                fix = dofix(idesc, "DIRECTORY CORRUPTED");
        !           153:                bp = getdirblk(idesc->id_blkno, blksiz);
        !           154:                dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
        !           155:                dp->d_reclen += size;
        !           156:                if (fix)
        !           157:                        dirty(bp);
        !           158:        }
        !           159:        return (dp);
        !           160: }
        !           161: 
        !           162: /*
        !           163:  * Verify that a directory entry is valid.
        !           164:  * This is a superset of the checks made in the kernel.
        !           165:  */
        !           166: dircheck(idesc, dp)
        !           167:        struct inodesc *idesc;
        !           168:        register struct direct *dp;
        !           169: {
        !           170:        register int size;
        !           171:        register char *cp;
        !           172:        int spaceleft;
        !           173: 
        !           174:        size = DIRSIZ(dp);
        !           175:        spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
        !           176:        if (dp->d_ino < maxino &&
        !           177:            dp->d_reclen != 0 &&
        !           178:            dp->d_reclen <= spaceleft &&
        !           179:            (dp->d_reclen & 0x3) == 0 &&
        !           180:            dp->d_reclen >= size &&
        !           181:            idesc->id_filesize >= size &&
        !           182:            dp->d_namlen <= MAXNAMLEN) {
        !           183:                if (dp->d_ino == 0)
        !           184:                        return (1);
        !           185:                for (cp = dp->d_name, size = 0; size < dp->d_namlen; size++)
        !           186:                        if (*cp == 0 || (*cp++ == '/'))
        !           187:                                return (0);
        !           188:                if (*cp == 0)
        !           189:                        return (1);
        !           190:        }
        !           191:        return (0);
        !           192: }
        !           193: 
        !           194: direrror(ino, errmesg)
        !           195:        ino_t ino;
        !           196:        char *errmesg;
        !           197: {
        !           198: 
        !           199:        fileerror(ino, ino, errmesg);
        !           200: }
        !           201: 
        !           202: fileerror(cwd, ino, errmesg)
        !           203:        ino_t cwd, ino;
        !           204:        char *errmesg;
        !           205: {
        !           206:        register struct dinode *dp;
        !           207:        char pathbuf[MAXPATHLEN + 1];
        !           208: 
        !           209:        pwarn("%s ", errmesg);
        !           210:        pinode(ino);
        !           211:        printf("\n");
        !           212:        getpathname(pathbuf, cwd, ino);
        !           213:        if (ino < ROOTINO || ino > maxino) {
        !           214:                pfatal("NAME=%s\n", pathbuf);
        !           215:                return;
        !           216:        }
        !           217:        dp = ginode(ino);
        !           218:        if (ftypeok(dp))
        !           219:                pfatal("%s=%s\n",
        !           220:                    (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf);
        !           221:        else
        !           222:                pfatal("NAME=%s\n", pathbuf);
        !           223: }
        !           224: 
        !           225: adjust(idesc, lcnt)
        !           226:        register struct inodesc *idesc;
        !           227:        short lcnt;
        !           228: {
        !           229:        register struct dinode *dp;
        !           230: 
        !           231:        dp = ginode(idesc->id_number);
        !           232:        if (dp->di_nlink == lcnt) {
        !           233:                if (linkup(idesc->id_number, (ino_t)0) == 0)
        !           234:                        clri(idesc, "UNREF", 0);
        !           235:        } else {
        !           236:                pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
        !           237:                        ((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"));
        !           238:                pinode(idesc->id_number);
        !           239:                printf(" COUNT %d SHOULD BE %d",
        !           240:                        dp->di_nlink, dp->di_nlink - lcnt);
        !           241:                if (preen) {
        !           242:                        if (lcnt < 0) {
        !           243:                                printf("\n");
        !           244:                                pfatal("LINK COUNT INCREASING");
        !           245:                        }
        !           246:                        printf(" (ADJUSTED)\n");
        !           247:                }
        !           248:                if (preen || reply("ADJUST") == 1) {
        !           249:                        dp->di_nlink -= lcnt;
        !           250:                        inodirty();
        !           251:                }
        !           252:        }
        !           253: }
        !           254: 
        !           255: mkentry(idesc)
        !           256:        struct inodesc *idesc;
        !           257: {
        !           258:        register struct direct *dirp = idesc->id_dirp;
        !           259:        struct direct newent;
        !           260:        int newlen, oldlen;
        !           261: 
        !           262:        newent.d_namlen = strlen(idesc->id_name);
        !           263:        newlen = DIRSIZ(&newent);
        !           264:        if (dirp->d_ino != 0)
        !           265:                oldlen = DIRSIZ(dirp);
        !           266:        else
        !           267:                oldlen = 0;
        !           268:        if (dirp->d_reclen - oldlen < newlen)
        !           269:                return (KEEPON);
        !           270:        newent.d_reclen = dirp->d_reclen - oldlen;
        !           271:        dirp->d_reclen = oldlen;
        !           272:        dirp = (struct direct *)(((char *)dirp) + oldlen);
        !           273:        dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
        !           274:        dirp->d_reclen = newent.d_reclen;
        !           275:        dirp->d_namlen = newent.d_namlen;
        !           276:        bcopy(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1);
        !           277:        return (ALTERED|STOP);
        !           278: }
        !           279: 
        !           280: chgino(idesc)
        !           281:        struct inodesc *idesc;
        !           282: {
        !           283:        register struct direct *dirp = idesc->id_dirp;
        !           284: 
        !           285:        if (bcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1))
        !           286:                return (KEEPON);
        !           287:        dirp->d_ino = idesc->id_parent;
        !           288:        return (ALTERED|STOP);
        !           289: }
        !           290: 
        !           291: linkup(orphan, parentdir)
        !           292:        ino_t orphan;
        !           293:        ino_t parentdir;
        !           294: {
        !           295:        register struct dinode *dp;
        !           296:        int lostdir;
        !           297:        ino_t oldlfdir;
        !           298:        struct inodesc idesc;
        !           299:        char tempname[BUFSIZ];
        !           300:        extern int pass4check();
        !           301: 
        !           302:        bzero((char *)&idesc, sizeof(struct inodesc));
        !           303:        dp = ginode(orphan);
        !           304:        lostdir = (dp->di_mode & IFMT) == IFDIR;
        !           305:        pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
        !           306:        pinode(orphan);
        !           307:        if (preen && dp->di_size == 0)
        !           308:                return (0);
        !           309:        if (preen)
        !           310:                printf(" (RECONNECTED)\n");
        !           311:        else
        !           312:                if (reply("RECONNECT") == 0)
        !           313:                        return (0);
        !           314:        if (lfdir == 0) {
        !           315:                dp = ginode(ROOTINO);
        !           316:                idesc.id_name = lfname;
        !           317:                idesc.id_type = DATA;
        !           318:                idesc.id_func = findino;
        !           319:                idesc.id_number = ROOTINO;
        !           320:                if ((ckinode(dp, &idesc) & FOUND) != 0) {
        !           321:                        lfdir = idesc.id_parent;
        !           322:                } else {
        !           323:                        pwarn("NO lost+found DIRECTORY");
        !           324:                        if (preen || reply("CREATE")) {
        !           325:                                lfdir = allocdir(ROOTINO, (ino_t)0, lfmode);
        !           326:                                if (lfdir != 0) {
        !           327:                                        if (makeentry(ROOTINO, lfdir, lfname) != 0) {
        !           328:                                                if (preen)
        !           329:                                                        printf(" (CREATED)\n");
        !           330:                                        } else {
        !           331:                                                freedir(lfdir, ROOTINO);
        !           332:                                                lfdir = 0;
        !           333:                                                if (preen)
        !           334:                                                        printf("\n");
        !           335:                                        }
        !           336:                                }
        !           337:                        }
        !           338:                }
        !           339:                if (lfdir == 0) {
        !           340:                        pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY");
        !           341:                        printf("\n\n");
        !           342:                        return (0);
        !           343:                }
        !           344:        }
        !           345:        dp = ginode(lfdir);
        !           346:        if ((dp->di_mode & IFMT) != IFDIR) {
        !           347:                pfatal("lost+found IS NOT A DIRECTORY");
        !           348:                if (reply("REALLOCATE") == 0)
        !           349:                        return (0);
        !           350:                oldlfdir = lfdir;
        !           351:                if ((lfdir = allocdir(ROOTINO, (ino_t)0, lfmode)) == 0) {
        !           352:                        pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
        !           353:                        return (0);
        !           354:                }
        !           355:                if ((changeino(ROOTINO, lfname, lfdir) & ALTERED) == 0) {
        !           356:                        pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
        !           357:                        return (0);
        !           358:                }
        !           359:                inodirty();
        !           360:                idesc.id_type = ADDR;
        !           361:                idesc.id_func = pass4check;
        !           362:                idesc.id_number = oldlfdir;
        !           363:                adjust(&idesc, lncntp[oldlfdir] + 1);
        !           364:                lncntp[oldlfdir] = 0;
        !           365:                dp = ginode(lfdir);
        !           366:        }
        !           367:        if (statemap[lfdir] != DFOUND) {
        !           368:                pfatal("SORRY. NO lost+found DIRECTORY\n\n");
        !           369:                return (0);
        !           370:        }
        !           371:        (void)lftempname(tempname, orphan);
        !           372:        if (makeentry(lfdir, orphan, tempname) == 0) {
        !           373:                pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
        !           374:                printf("\n\n");
        !           375:                return (0);
        !           376:        }
        !           377:        lncntp[orphan]--;
        !           378:        if (lostdir) {
        !           379:                if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 &&
        !           380:                    parentdir != (ino_t)-1)
        !           381:                        (void)makeentry(orphan, lfdir, "..");
        !           382:                dp = ginode(lfdir);
        !           383:                dp->di_nlink++;
        !           384:                inodirty();
        !           385:                lncntp[lfdir]++;
        !           386:                pwarn("DIR I=%lu CONNECTED. ", orphan);
        !           387:                if (parentdir != (ino_t)-1)
        !           388:                        printf("PARENT WAS I=%lu\n", parentdir);
        !           389:                if (preen == 0)
        !           390:                        printf("\n");
        !           391:        }
        !           392:        return (1);
        !           393: }
        !           394: 
        !           395: /*
        !           396:  * fix an entry in a directory.
        !           397:  */
        !           398: changeino(dir, name, newnum)
        !           399:        ino_t dir;
        !           400:        char *name;
        !           401:        ino_t newnum;
        !           402: {
        !           403:        struct inodesc idesc;
        !           404: 
        !           405:        bzero((char *)&idesc, sizeof(struct inodesc));
        !           406:        idesc.id_type = DATA;
        !           407:        idesc.id_func = chgino;
        !           408:        idesc.id_number = dir;
        !           409:        idesc.id_fix = DONTKNOW;
        !           410:        idesc.id_name = name;
        !           411:        idesc.id_parent = newnum;       /* new value for name */
        !           412:        return (ckinode(ginode(dir), &idesc));
        !           413: }
        !           414: 
        !           415: /*
        !           416:  * make an entry in a directory
        !           417:  */
        !           418: makeentry(parent, ino, name)
        !           419:        ino_t parent, ino;
        !           420:        char *name;
        !           421: {
        !           422:        struct dinode *dp;
        !           423:        struct inodesc idesc;
        !           424:        char pathbuf[MAXPATHLEN + 1];
        !           425:        
        !           426:        if (parent < ROOTINO || parent >= maxino ||
        !           427:            ino < ROOTINO || ino >= maxino)
        !           428:                return (0);
        !           429:        bzero((char *)&idesc, sizeof(struct inodesc));
        !           430:        idesc.id_type = DATA;
        !           431:        idesc.id_func = mkentry;
        !           432:        idesc.id_number = parent;
        !           433:        idesc.id_parent = ino;  /* this is the inode to enter */
        !           434:        idesc.id_fix = DONTKNOW;
        !           435:        idesc.id_name = name;
        !           436:        dp = ginode(parent);
        !           437:        if (dp->di_size % DIRBLKSIZ) {
        !           438:                dp->di_size = roundup(dp->di_size, DIRBLKSIZ);
        !           439:                inodirty();
        !           440:        }
        !           441:        if ((ckinode(dp, &idesc) & ALTERED) != 0)
        !           442:                return (1);
        !           443:        getpathname(pathbuf, parent, parent);
        !           444:        dp = ginode(parent);
        !           445:        if (expanddir(dp, pathbuf) == 0)
        !           446:                return (0);
        !           447:        return (ckinode(dp, &idesc) & ALTERED);
        !           448: }
        !           449: 
        !           450: /*
        !           451:  * Attempt to expand the size of a directory
        !           452:  */
        !           453: expanddir(dp, name)
        !           454:        register struct dinode *dp;
        !           455:        char *name;
        !           456: {
        !           457:        daddr_t lastbn, newblk;
        !           458:        register struct bufarea *bp;
        !           459:        char *cp, firstblk[DIRBLKSIZ];
        !           460: 
        !           461:        lastbn = lblkno(&sblock, dp->di_size);
        !           462:        if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0)
        !           463:                return (0);
        !           464:        if ((newblk = allocblk(sblock.fs_frag)) == 0)
        !           465:                return (0);
        !           466:        dp->di_db[lastbn + 1] = dp->di_db[lastbn];
        !           467:        dp->di_db[lastbn] = newblk;
        !           468:        dp->di_size += sblock.fs_bsize;
        !           469:        dp->di_blocks += btodb(sblock.fs_bsize);
        !           470:        bp = getdirblk(dp->di_db[lastbn + 1],
        !           471:                (long)dblksize(&sblock, dp, lastbn + 1));
        !           472:        if (bp->b_errs)
        !           473:                goto bad;
        !           474:        bcopy(bp->b_un.b_buf, firstblk, DIRBLKSIZ);
        !           475:        bp = getdirblk(newblk, sblock.fs_bsize);
        !           476:        if (bp->b_errs)
        !           477:                goto bad;
        !           478:        bcopy(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
        !           479:        for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
        !           480:             cp < &bp->b_un.b_buf[sblock.fs_bsize];
        !           481:             cp += DIRBLKSIZ)
        !           482:                bcopy((char *)&emptydir, cp, sizeof emptydir);
        !           483:        dirty(bp);
        !           484:        bp = getdirblk(dp->di_db[lastbn + 1],
        !           485:                (long)dblksize(&sblock, dp, lastbn + 1));
        !           486:        if (bp->b_errs)
        !           487:                goto bad;
        !           488:        bcopy((char *)&emptydir, bp->b_un.b_buf, sizeof emptydir);
        !           489:        pwarn("NO SPACE LEFT IN %s", name);
        !           490:        if (preen)
        !           491:                printf(" (EXPANDED)\n");
        !           492:        else if (reply("EXPAND") == 0)
        !           493:                goto bad;
        !           494:        dirty(bp);
        !           495:        inodirty();
        !           496:        return (1);
        !           497: bad:
        !           498:        dp->di_db[lastbn] = dp->di_db[lastbn + 1];
        !           499:        dp->di_db[lastbn + 1] = 0;
        !           500:        dp->di_size -= sblock.fs_bsize;
        !           501:        dp->di_blocks -= btodb(sblock.fs_bsize);
        !           502:        freeblk(newblk, sblock.fs_frag);
        !           503:        return (0);
        !           504: }
        !           505: 
        !           506: /*
        !           507:  * allocate a new directory
        !           508:  */
        !           509: allocdir(parent, request, mode)
        !           510:        ino_t parent, request;
        !           511:        int mode;
        !           512: {
        !           513:        ino_t ino;
        !           514:        char *cp;
        !           515:        struct dinode *dp;
        !           516:        register struct bufarea *bp;
        !           517: 
        !           518:        ino = allocino(request, IFDIR|mode);
        !           519:        dirhead.dot_ino = ino;
        !           520:        dirhead.dotdot_ino = parent;
        !           521:        dp = ginode(ino);
        !           522:        bp = getdirblk(dp->di_db[0], sblock.fs_fsize);
        !           523:        if (bp->b_errs) {
        !           524:                freeino(ino);
        !           525:                return (0);
        !           526:        }
        !           527:        bcopy((char *)&dirhead, bp->b_un.b_buf, sizeof dirhead);
        !           528:        for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
        !           529:             cp < &bp->b_un.b_buf[sblock.fs_fsize];
        !           530:             cp += DIRBLKSIZ)
        !           531:                bcopy((char *)&emptydir, cp, sizeof emptydir);
        !           532:        dirty(bp);
        !           533:        dp->di_nlink = 2;
        !           534:        inodirty();
        !           535:        if (ino == ROOTINO) {
        !           536:                lncntp[ino] = dp->di_nlink;
        !           537:                return(ino);
        !           538:        }
        !           539:        if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) {
        !           540:                freeino(ino);
        !           541:                return (0);
        !           542:        }
        !           543:        statemap[ino] = statemap[parent];
        !           544:        if (statemap[ino] == DSTATE) {
        !           545:                lncntp[ino] = dp->di_nlink;
        !           546:                lncntp[parent]++;
        !           547:        }
        !           548:        dp = ginode(parent);
        !           549:        dp->di_nlink++;
        !           550:        inodirty();
        !           551:        return (ino);
        !           552: }
        !           553: 
        !           554: /*
        !           555:  * free a directory inode
        !           556:  */
        !           557: freedir(ino, parent)
        !           558:        ino_t ino, parent;
        !           559: {
        !           560:        struct dinode *dp;
        !           561: 
        !           562:        if (ino != parent) {
        !           563:                dp = ginode(parent);
        !           564:                dp->di_nlink--;
        !           565:                inodirty();
        !           566:        }
        !           567:        freeino(ino);
        !           568: }
        !           569: 
        !           570: /*
        !           571:  * generate a temporary name for the lost+found directory.
        !           572:  */
        !           573: lftempname(bufp, ino)
        !           574:        char *bufp;
        !           575:        ino_t ino;
        !           576: {
        !           577:        register ino_t in;
        !           578:        register char *cp;
        !           579:        int namlen;
        !           580: 
        !           581:        cp = bufp + 2;
        !           582:        for (in = maxino; in > 0; in /= 10)
        !           583:                cp++;
        !           584:        *--cp = 0;
        !           585:        namlen = cp - bufp;
        !           586:        in = ino;
        !           587:        while (cp > bufp) {
        !           588:                *--cp = (in % 10) + '0';
        !           589:                in /= 10;
        !           590:        }
        !           591:        *cp = '#';
        !           592:        return (namlen);
        !           593: }
        !           594: 
        !           595: /*
        !           596:  * Get a directory block.
        !           597:  * Insure that it is held until another is requested.
        !           598:  */
        !           599: struct bufarea *
        !           600: getdirblk(blkno, size)
        !           601:        daddr_t blkno;
        !           602:        long size;
        !           603: {
        !           604: 
        !           605:        if (pdirbp != 0)
        !           606:                pdirbp->b_flags &= ~B_INUSE;
        !           607:        pdirbp = getdatablk(blkno, size);
        !           608:        return (pdirbp);
        !           609: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.