Annotation of coherent/d/etc/unmkfs.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * $Header: /usr.src/local/unmkfs.c,v 1.4 90/07/06 11:43:38 root Exp $
        !             3:  * $Log:       /usr.src/local/unmkfs.c,v $
        !             4:  * Revision 1.4        90/07/06  11:43:38      root
        !             5:  * steve 7/6/90
        !             6:  * Changed usage to
        !             7:  *     /etc/unmkfs [ -prefix ] directory nblocks [ file ]
        !             8:  * Corrected bug with 14-character filenames, which caused garbage in
        !             9:  * some lines (because of missing NUL terminator).  Changed error messages.
        !            10:  * Added forward declarations of all functions.
        !            11:  * This corresponds to V3.0.1 object.
        !            12:  * ,.
        !            13:  * 
        !            14:  * Revision 1.3        89/02/24  12:44:05      bin
        !            15:  * Defined realloc to remove integer pointer pun message.
        !            16:  * 
        !            17:  * Revision 1.2        89/02/24  12:40:52      bin
        !            18:  * Change to generate file names for multiple prototypes based on
        !            19:  * a command-line supplied prefix.
        !            20:  * 
        !            21:  * Revision 1.1        89/02/24  12:32:32      wgl
        !            22:  * Initial revision
        !            23:  * 
        !            24:  */
        !            25: static char    *revision = "$Revision 1.1 $";
        !            26: static char *header =
        !            27:        "$Header: /usr.src/local/unmkfs.c,v 1.4 90/07/06 11:43:38 root Exp $";
        !            28: 
        !            29: /*
        !            30:  * Given a directory tree root and a filesystem size,
        !            31:  * write the fewest mkfs proto files necessary to
        !            32:  * copy the directory tree onto floppies.
        !            33:  * Preserve the ownerships, modes, dates, links, and order of links
        !            34:  * within a directory.
        !            35:  * Make each fragment root based so that a series of
        !            36:  *     mount /dev/fd0 /f0; cpdir /f0 destination; umount /dev/fd0
        !            37:  * can be used to reinstall the original directory.
        !            38:  *
        !            39:  * The algorithm for partitioning is empirical and may not work very
        !            40:  * well for directories other than the pc coherent distribution.
        !            41:  * Some degree of interaction is probably desirable for getting
        !            42:  * reasonable partitioning of arbitrary directory trees.
        !            43:  *
        !            44:  * Overview:
        !            45:  *     After minimal checks for necessary conditions,
        !            46:  *     Read the source directory tree into a memory
        !            47:  *             resident pseudo file system in which MINODE inumbers
        !            48:  *             identify unique files and replace dp->d_ino in the
        !            49:  *             directories.
        !            50:  *     While the original root directory is not flagged I_DONE,
        !            51:  *             copy those parts of the tree that are not flagged I_DONE.
        !            52:  *             While the copy is too big for the floppy partition
        !            53:  *                     prune the copy.
        !            54:  *     For each pruned copy produced, write the mkfs proto.
        !            55:  *
        !            56:  * -- rec 26.VI.84 -- invent cpfrag.
        !            57:  * -- rec 12.IX.84 -- reconstruct cpfrag -> unmkfs.
        !            58:  * -- norm 04.I.85 -- fix misc. bugs for z8000
        !            59:  */
        !            60: #include <stdio.h>
        !            61: #include <sys/dir.h>
        !            62: #include <assert.h>
        !            63: #include <sys/const.h>
        !            64: #include <sys/types.h>
        !            65: #include <sys/stat.h>
        !            66: #include <sys/filsys.h>
        !            67: #include <sys/ino.h>
        !            68: 
        !            69: extern char    *realloc();
        !            70: extern char edata[];
        !            71: 
        !            72: #define        USAGE           "Usage: /etc/unmkfs [ -prefix ] directory nblocks [ file ]\n"
        !            73: #define IHASH          128
        !            74: #define MAXFNAME       512
        !            75: #define NDISK          32
        !            76: 
        !            77: typedef struct MINODE {
        !            78:        struct MINODE *i_link1; /* dev x ino hash linkage */
        !            79:        struct MINODE *i_link2; /* my inumbering hash linkage */
        !            80:        char    *i_linkname;    /* Name of first instance of file in copy */
        !            81:        int     i_mino;         /* My inumber */
        !            82:        int     i_flag;         /* Miscellaneous flags */
        !            83:        int     i_blks;         /* Cumulative block size, includes indirects */
        !            84:        int     i_inos;         /* Cumulative inodes used */
        !            85:        int     i_size;         /* Total data, indir, and inode blocks */
        !            86:        int     i_isdir;        /* Simplify many tests */
        !            87:        dev_t   i_dev;          /* Some fields from stat() */
        !            88:        ino_t   i_ino;
        !            89:        int     i_mode;
        !            90:        int     i_nlink;
        !            91:        int     i_uid;
        !            92:        int     i_gid;
        !            93:        int     i_rdev;
        !            94:        time_t  i_mtime;
        !            95:        int     i_nent;         /* Number of directory entries */
        !            96:        struct direct i_elem[]; /* Directory entries */
        !            97: } MINODE;
        !            98: 
        !            99: #define I_DONE 1       /* Inode is done */
        !           100: #define I_COUNT        2       /* Inode is counted */
        !           101: #define I_PUT  8       /* Inode size reported */
        !           102: #define I_DONE1        16      /* Inode has been done once, for directories */
        !           103: #define I_PURGE        32      /* Inode should be purged */
        !           104: #define I_KEEP 64      /* Keep entire subdirectory */
        !           105: #define I_CANFIT 128   /* Subdirectory could fit on disk */
        !           106: #define I_ISMADE 256   /* Inode is made, do link */
        !           107: 
        !           108: MINODE *disks[NDISK];
        !           109: int    dsize;
        !           110: int    dused;
        !           111: int    vflag = 1;
        !           112: int    outf = 0;       /* Use file outpre.outsuf instead of stdout */
        !           113: int    excess;
        !           114: int    ndisk;
        !           115: int    myuid;
        !           116: int    mygid;
        !           117: 
        !           118: char   outpre[64];             /* Settable output file prefix */
        !           119: char   outsuf[] = ".p??";      /* Suffix for output file name */
        !           120: 
        !           121: FILE *ofp;
        !           122: 
        !           123: /* Forward. */
        !           124: MINODE *makeroot();
        !           125: void   makedir();
        !           126: void   printroot();
        !           127: void   printdir();
        !           128: void   splat();
        !           129: void   makedisk();
        !           130: void   mkfs();
        !           131: void   insdir();
        !           132: void   indent();
        !           133: void   uflagroot();
        !           134: void   uflagdir();
        !           135: void   flagroot();
        !           136: void   flagdir();
        !           137: void   sizeroot();
        !           138: void   sizedir();
        !           139: MINODE *cpyroot();
        !           140: MINODE *cpydir();
        !           141: void   keepers();
        !           142: MINODE *select();
        !           143: void   purge();
        !           144: void   donedir();
        !           145: void   markdir();
        !           146: int    entermi();
        !           147: int    duplmi();
        !           148: MINODE *fetchmi();
        !           149: void   freemi();
        !           150: long   blkuse();
        !           151: char   *string();
        !           152: char   *myalloc();
        !           153: void   usage();
        !           154: void   fatal();
        !           155: 
        !           156: char fname[MAXFNAME];  /* Filename buffer */
        !           157: char fname1[MAXFNAME]; /* Second file name buffer */
        !           158: char cmdbuf[128];
        !           159: struct stat sbuf;      /* Stat buffer */
        !           160: struct stat tbuf;      /* Time buffer, leave zero for all times */
        !           161: char *argv0;           /* For error recovery */
        !           162: 
        !           163: main(argc, argv) int argc; char *argv[];
        !           164: {
        !           165:        int i;
        !           166:        MINODE *rip, *tip, *sip;
        !           167: 
        !           168:        argv0 = argv[0];
        !           169:        if (argc > 1 && argv[1][0] == '-') {
        !           170:                strcpy(outpre, &argv[1][1]);
        !           171:                outf = 1;
        !           172:                ++argv;
        !           173:                --argc;
        !           174:        }
        !           175:        if (argc < 3 || argc > 4)
        !           176:                usage();
        !           177:        if ((dsize = atoi(argv[2])) <= 0)
        !           178:                fatal("illegal size \"%s\"", argv[2]);
        !           179:        if (argc == 4) {
        !           180:                if (stat(argv[3], &tbuf) < 0)
        !           181:                        fatal("cannot stat \"%s\"", argv[3]);
        !           182:        } else
        !           183:                tbuf.st_mtime = 0;      /* make time == 0 to get all files */
        !           184:        rip = makeroot(argv[1]);
        !           185:        while ((rip->i_flag & I_DONE) == 0) {
        !           186:                tip = cpyroot(rip);
        !           187:                dused = 4;
        !           188:                keepers(tip);
        !           189:                excess = tip->i_size + 2 - dsize;
        !           190:                while (excess > 0) {
        !           191:                        while ((sip = select(tip)) == NULL) {
        !           192:                                excess += 1;
        !           193:                        }
        !           194:                        flagroot(sip, I_PURGE);
        !           195:                        purge(tip);
        !           196:                        sizeroot(tip);
        !           197:                        excess = tip->i_size + 2 - dsize;
        !           198:                }
        !           199:                donedir(tip);
        !           200:                markdir(rip);
        !           201:                disks[ndisk] = tip;
        !           202:                ndisk += 1;
        !           203:        }
        !           204:        for (i = 0; i < ndisk; i += 1)
        !           205:                makedisk(i, argv[1]);
        !           206: }
        !           207: 
        !           208: /*
        !           209: ** Get the MINODE * corresponding to fname, and call
        !           210: ** makedir() to build the in-memory tree.  Call sizeroot()
        !           211: ** return the MINODE corresponding to the root.
        !           212: */
        !           213: MINODE *
        !           214: makeroot(cp) char *cp;
        !           215: {
        !           216:        MINODE *rip;
        !           217: 
        !           218:        if (strlen(cp) >= MAXFNAME)
        !           219:                fatal("directory path name too long");
        !           220:        strcpy(fname, cp);
        !           221:        if (stat(fname, &sbuf) < 0)
        !           222:                fatal("cannot stat \"%s\"", fname);
        !           223:        if ((sbuf.st_mode&S_IFMT) != S_IFDIR)
        !           224:                fatal("\"%s\" is not a directory");
        !           225:        rip = fetchmi(entermi());
        !           226:        if (cp[0] == '/' && cp[1] == '\0')
        !           227:                fname[0] = 0;
        !           228:        makedir(rip);
        !           229:        sizeroot(rip);
        !           230:        return (rip);
        !           231: }
        !           232: 
        !           233: /*
        !           234: ** Recursively build a tree of MINODE pointers
        !           235: ** for the directory ip.
        !           236: */
        !           237: void
        !           238: makedir(ip) MINODE *ip;
        !           239: {
        !           240:        int     fd;
        !           241:        int     i;
        !           242:        struct direct *dp1, *dp2;
        !           243:        MINODE *tip;
        !           244:        char *cp;
        !           245: 
        !           246:        cp = fname + strlen(fname);
        !           247:        if (cp + DIRSIZ + 2 >= fname + MAXFNAME)
        !           248:                fatal("directory tree too deep");
        !           249:        if ((fd = open(fname, 0)) < 0)
        !           250:                fatal("cannot open \"%s\"", fname);
        !           251:        i = ip->i_nent * sizeof(struct direct);
        !           252:        if (read(fd, ip->i_elem, i) != i)
        !           253:                fatal("%s: read error", fname);
        !           254:        close(fd);
        !           255:        *cp = '/';
        !           256:        dp1 = dp2 = ip->i_elem;
        !           257:        for (i = 0; i < ip->i_nent; i += 1) {
        !           258:                if (dp2->d_name[0] == '.') {
        !           259:                        if (dp2->d_name[1] == 0
        !           260:                         || (dp2->d_name[1] == '.' && dp2->d_name[2] == 0))
        !           261:                                dp2->d_ino = 0;
        !           262:                }
        !           263:                if (dp2->d_ino != 0) {
        !           264:                        strncpy(cp+1, dp2->d_name, DIRSIZ);
        !           265:                        if (stat(fname, &sbuf) < 0)
        !           266:                                fatal("cannot stat \"%s\"", fname);
        !           267:                        dp2->d_ino = entermi();
        !           268:                }
        !           269:                if (dp2->d_ino != 0) {
        !           270:                        if (dp1 != dp2)
        !           271:                                *dp1 = *dp2;
        !           272:                        dp1 += 1;
        !           273:                }
        !           274:                dp2 += 1;
        !           275:        }
        !           276:        ip->i_nent = dp1 - ip->i_elem;
        !           277:        i = sizeof(MINODE) + ip->i_nent * sizeof(struct direct);
        !           278:        if (realloc(ip, i) != ip)
        !           279:                fatal("realloc moved block");
        !           280:        dp1 = ip->i_elem;
        !           281:        for (i = 0; i < ip->i_nent; i += 1) {
        !           282:                tip = fetchmi(dp1->d_ino);
        !           283:                if (tip->i_isdir) {
        !           284:                        strncpy(cp+1, dp1->d_name, DIRSIZ);
        !           285:                        makedir(tip);
        !           286:                }
        !           287:                dp1 += 1;
        !           288:        }
        !           289:        *cp = 0;
        !           290: }
        !           291: 
        !           292: void
        !           293: printroot(cp, rip) char *cp; MINODE *rip;
        !           294: {
        !           295:        uflagroot(rip, I_PUT);
        !           296:        strcpy(fname, cp);
        !           297:        splat(rip);
        !           298:        if (cp[0] == '/' && cp[1] == 0)
        !           299:                fname[0] = 0;
        !           300:        printdir(rip);
        !           301: }
        !           302: 
        !           303: void
        !           304: printdir(ip) MINODE *ip;
        !           305: {
        !           306:        int i;
        !           307:        MINODE *tip;
        !           308:        struct direct *dp;
        !           309:        char *cp;
        !           310: 
        !           311:        dp = ip->i_elem;
        !           312:        cp = fname + strlen(fname);
        !           313:        *cp = '/';
        !           314:        for (i = 0; i < ip->i_nent; i += 1) {
        !           315:                tip = fetchmi(dp->d_ino);
        !           316:                strncpy(cp+1, dp->d_name, DIRSIZ);
        !           317:                splat(tip);
        !           318:                if (tip->i_isdir)
        !           319:                        printdir(tip);
        !           320:                dp += 1;
        !           321:        }
        !           322:        *cp = 0;
        !           323: }
        !           324: 
        !           325: void
        !           326: splat(ip) MINODE *ip;
        !           327: {
        !           328:        printf("(%2d,%2d,%4d) ",
        !           329:                major(ip->i_dev), minor(ip->i_dev), ip->i_ino);
        !           330:        if ((ip->i_flag & I_PUT) != 0)
        !           331:                printf("%6d %4d %6d ", 0, 0, 0);
        !           332:        else
        !           333:                printf("%6d %4d %6d ", ip->i_size, ip->i_inos, ip->i_blks);
        !           334:        printf("%s\n", fname);
        !           335:        ip->i_flag |= I_PUT;
        !           336: }
        !           337: 
        !           338: void
        !           339: makedisk(n, cp) char *cp;
        !           340: {
        !           341:        MINODE *ip;
        !           342:        char outfile[72];
        !           343: 
        !           344:        ip = disks[n];
        !           345:        fprintf(stderr, "Disk %d: %d inodes, %d data blocks\n",
        !           346:                n+1, ip->i_inos, ip->i_blks);
        !           347:        if (outf == 1)  {
        !           348:                outsuf[2] = (n+1)/10 + '0';
        !           349:                outsuf[3] = (n+1)%10 + '0';
        !           350:                outsuf[4] = '\0';
        !           351:                strcpy(outfile, outpre);
        !           352:                strcat(outfile, outsuf);
        !           353:                if ((ofp = fopen(outfile, "w")) == NULL)
        !           354:                        fatal("cannot open output file \"%s\"", outfile);
        !           355:        } else
        !           356:                ofp = stdout;
        !           357:        mkfs(ip->i_inos);
        !           358:        if (cp[0] == '/' && cp[1] == 0)
        !           359:                fname[0] = 0;
        !           360:        else
        !           361:                strcpy(fname, cp);
        !           362:        fprintf(ofp, "d--%03o %3d %3d\n", ip->i_mode&0777, ip->i_uid,
        !           363:                ip->i_gid);
        !           364:        indent(1);
        !           365:        insdir(ip);
        !           366:        indent(-1);
        !           367:        fprintf(ofp, "$\n");
        !           368: }
        !           369: 
        !           370: void
        !           371: mkfs(nino)
        !           372: {
        !           373:        fprintf(ofp, "/dev/null xxxxx xxxxx\n");
        !           374:        fprintf(ofp, "%d %d 1 1\n", dsize, nino);
        !           375: }
        !           376: 
        !           377: void
        !           378: insdir(ip) MINODE *ip;
        !           379: {
        !           380:        int i;
        !           381:        MINODE *tip;
        !           382:        struct direct *dp;
        !           383:        char *cp, *cp1, buf[DIRSIZ+1];
        !           384:        char dtype;
        !           385: 
        !           386:        cp = fname + strlen(fname);
        !           387:        cp1 = fname1 + strlen(fname1);
        !           388:        *cp = '/';
        !           389:        *cp1 = '/';
        !           390:        dp = ip->i_elem;
        !           391:        for (i = 0; i < ip->i_nent; i += 1) {
        !           392:                tip = fetchmi(dp->d_ino);
        !           393:                strncpy(buf, dp->d_name, DIRSIZ);
        !           394:                buf[DIRSIZ] = '\0';
        !           395:                strcpy(cp+1, buf);
        !           396:                strcpy(cp1+1, buf);
        !           397:                indent(0);
        !           398:                fprintf(ofp, "%-14s", buf);
        !           399:                if (tip->i_flag & I_ISMADE) {
        !           400:                        fprintf(ofp, " l-----   0   0 %s\n", tip->i_linkname);
        !           401:                        dp += 1;
        !           402:                        continue;
        !           403:                }
        !           404:                switch (tip->i_mode & S_IFMT) {
        !           405:                case S_IFDIR:
        !           406:                        dtype = 'd';
        !           407:                        break;
        !           408:                case S_IFCHR:
        !           409:                        dtype = 'c';
        !           410:                        break;
        !           411:                case S_IFBLK:
        !           412:                        dtype = 'b';
        !           413:                        break;
        !           414:                case S_IFREG:
        !           415:                        dtype = '-';
        !           416:                        break;
        !           417:                default:
        !           418:                        fatal("%s: bad file type %d", fname, tip->i_mode&S_IFMT);
        !           419:                }
        !           420: 
        !           421:                fprintf(ofp, " %c%c%c%03o %3d %3d",
        !           422:                        dtype,
        !           423:                        (tip->i_mode&ISUID) ? 'u' : '-',
        !           424:                        (tip->i_mode&ISGID) ? 'g' : '-',
        !           425:                        tip->i_mode&0777,
        !           426:                        tip->i_uid, tip->i_gid);
        !           427:                switch (tip->i_mode & S_IFMT) {
        !           428:                case S_IFDIR:
        !           429:                        fputc('\n', ofp);
        !           430:                        indent(1);
        !           431:                        insdir(tip);
        !           432:                        indent(-1);
        !           433:                        indent(0);
        !           434:                        fprintf(ofp, "$\n");
        !           435:                        break;
        !           436:                case S_IFCHR:
        !           437:                case S_IFBLK:
        !           438:                        fprintf(ofp, "%3d %3d\n", major(tip->i_rdev),
        !           439:                                minor(tip->i_rdev));
        !           440:                        break;
        !           441:                case S_IFREG:
        !           442:                        fprintf(ofp, " %s\n", fname);
        !           443:                        break;
        !           444:                }
        !           445:                if (tip->i_nlink > 1)
        !           446:                        tip->i_linkname = string(fname1);
        !           447:                tip->i_flag |= I_ISMADE;
        !           448:                dp += 1;
        !           449:        }
        !           450:        *cp = 0;
        !           451:        *cp1 = 0;
        !           452: }
        !           453: 
        !           454: void
        !           455: indent(n) int n;
        !           456: {
        !           457:        static int indent;
        !           458: 
        !           459:        if (n < 0)
        !           460:                indent -= 1;
        !           461:        else if (n > 0)
        !           462:                indent += 1;
        !           463:        else for (n = indent; --n >= 0; fprintf(ofp, " "));
        !           464: }
        !           465: 
        !           466: void
        !           467: uflagroot(rip, flag) MINODE *rip;
        !           468: {
        !           469:        uflagdir(rip, flag);
        !           470:        rip->i_flag &= ~flag;
        !           471: }
        !           472: 
        !           473: /*
        !           474: ** Recursively turn off flag in ip and
        !           475: ** all directories below ip.
        !           476: */
        !           477: void
        !           478: uflagdir(ip, flag) MINODE *ip;
        !           479: {
        !           480:        int i;
        !           481:        MINODE *tip;
        !           482:        struct direct *dp;
        !           483: 
        !           484:        dp = ip->i_elem;
        !           485:        for (i = 0; i < ip->i_nent; i += 1) {
        !           486:                tip = fetchmi(dp->d_ino);
        !           487:                tip->i_flag &= ~flag;
        !           488:                if (tip->i_isdir)
        !           489:                        uflagdir(tip, flag);
        !           490:                dp += 1;
        !           491:        }
        !           492: }
        !           493: 
        !           494: void
        !           495: flagroot(ip, flag) MINODE *ip; int flag;
        !           496: {
        !           497:        if (ip->i_isdir)
        !           498:                flagdir(ip, flag);
        !           499:        ip->i_flag |= flag;
        !           500: }
        !           501: 
        !           502: void
        !           503: flagdir(ip, flag) MINODE *ip; int flag;
        !           504: {
        !           505:        int i;
        !           506:        MINODE *tip;
        !           507:        struct direct *dp;
        !           508: 
        !           509:        dp = ip->i_elem;
        !           510:        for (i = 0; i < ip->i_nent; i += 1) {
        !           511:                tip = fetchmi(dp->d_ino);
        !           512:                if (tip->i_isdir)
        !           513:                        flagdir(tip, flag);
        !           514:                tip->i_flag |= flag;
        !           515:                dp += 1;
        !           516:        }
        !           517: }
        !           518: 
        !           519: void
        !           520: sizeroot(rip) MINODE *rip;
        !           521: {
        !           522:        uflagroot(rip, I_COUNT);
        !           523:        sizedir(rip);
        !           524:        /* Add in bad block inode */
        !           525:        rip->i_size = rip->i_blks + (++rip->i_inos+INOPB-1) / INOPB;
        !           526: }
        !           527: 
        !           528: /*
        !           529: ** For subdirectories not flagged I_COUNT,
        !           530: ** add the isize and blksize to that of ip.
        !           531: */
        !           532: void
        !           533: sizedir(ip) MINODE *ip;
        !           534: {
        !           535:        int i;
        !           536:        MINODE *tip;
        !           537:        struct direct *dp;
        !           538: 
        !           539:        ip->i_blks = 0;
        !           540:        ip->i_inos = 0;
        !           541:        dp = ip->i_elem;
        !           542:        for (i = 0; i < ip->i_nent; i += 1) {
        !           543:                tip = fetchmi(dp->d_ino);
        !           544:                if (tip->i_isdir)
        !           545:                        sizedir(tip);
        !           546:                if ((tip->i_flag&I_COUNT) == 0) {
        !           547:                        ip->i_inos += tip->i_inos;
        !           548:                        ip->i_blks += tip->i_blks;
        !           549:                        tip->i_flag |= I_COUNT;
        !           550:                }
        !           551:                dp += 1;
        !           552:        }
        !           553:        ip->i_inos += 1;        /* For me */
        !           554:        ip->i_blks += blkuse((long)(ip->i_nent+2)*sizeof(struct direct));
        !           555:        ip->i_size = ip->i_blks + (ip->i_inos+INOPB-1) / INOPB;
        !           556: }
        !           557: 
        !           558: MINODE *
        !           559: cpyroot(rip) MINODE *rip;
        !           560: {
        !           561:        uflagdir(rip, I_PURGE|I_KEEP);
        !           562:        rip = cpydir(rip);
        !           563:        sizeroot(rip);
        !           564:        return (rip);
        !           565: }
        !           566: 
        !           567: MINODE *
        !           568: cpydir(ip) MINODE *ip;
        !           569: {
        !           570:        int i;
        !           571:        MINODE *nip, *tip;
        !           572:        struct direct *dp1, *dp2;
        !           573: 
        !           574:        nip = fetchmi(duplmi(ip));
        !           575:        nip->i_nent = 0;
        !           576:        dp1 = ip->i_elem;
        !           577:        dp2 = nip->i_elem;
        !           578:        for (i = 0; i < ip->i_nent; i += 1) {
        !           579:                tip = fetchmi(dp1->d_ino);
        !           580:                if ((tip->i_flag&I_DONE) != 0)
        !           581:                        tip = NULL;
        !           582:                else if (tip->i_isdir)
        !           583:                        tip = cpydir(tip);
        !           584:                if (tip != NULL) {
        !           585:                        dp2->d_ino = tip->i_mino;
        !           586:                        strncpy(dp2->d_name, dp1->d_name, DIRSIZ);
        !           587:                        nip->i_nent += 1;
        !           588:                        dp2 += 1;
        !           589:                }
        !           590:                dp1 += 1;
        !           591:        }
        !           592:        if (nip->i_nent < ip->i_nent) {
        !           593:                i = sizeof(MINODE) + nip->i_nent * sizeof(struct direct);
        !           594:                if (realloc(nip, i) != nip)
        !           595:                        fatal("realloc moved block");
        !           596:        }
        !           597:        return (nip);
        !           598: }
        !           599: 
        !           600: void
        !           601: keepers(ip) MINODE *ip;
        !           602: {
        !           603:        int i;
        !           604:        MINODE *tip;
        !           605:        struct direct *dp;
        !           606: 
        !           607:        dp = ip->i_elem;
        !           608:        for (i = 0; i < ip->i_nent; i += 1) {
        !           609:                tip = fetchmi(dp->d_ino);
        !           610:                if (tip->i_isdir == 0) {
        !           611:                        dp += 1;
        !           612:                        continue;
        !           613:                }
        !           614:                if (tip->i_size < dsize - 4)
        !           615:                        tip->i_flag |= I_CANFIT;
        !           616:                if (dused + tip->i_size < dsize) {
        !           617:                        tip->i_flag |= I_KEEP;
        !           618:                        dused += tip->i_size;
        !           619:                }
        !           620:                dp += 1;
        !           621:        }
        !           622:        dp = ip->i_elem;
        !           623:        for (i = 0; i < ip->i_nent; i += 1) {
        !           624:                tip = fetchmi(dp->d_ino);
        !           625:                if (tip->i_isdir != 0
        !           626:                 && (tip->i_flag & (I_CANFIT|I_KEEP)) == 0)
        !           627:                        keepers(tip);
        !           628:                dp += 1;
        !           629:        }
        !           630: }
        !           631: 
        !           632: MINODE *
        !           633: select(ip) MINODE *ip;
        !           634: {
        !           635:        int i;
        !           636:        MINODE *uip, *lip, *tip;
        !           637:        struct direct *dp;
        !           638: 
        !           639:        uip = lip = NULL;
        !           640:        dp = ip->i_elem;
        !           641:        for (i = 0; i < ip->i_nent; i += 1) {
        !           642:                tip = fetchmi(dp->d_ino);
        !           643:                if (tip->i_flag & I_KEEP) {
        !           644:                        dp += 1;
        !           645:                        continue;
        !           646:                }
        !           647:                if (tip->i_flag & I_CANFIT)
        !           648:                        return (tip);
        !           649:                if (tip->i_size == excess)
        !           650:                        return (tip);
        !           651:                else if (tip->i_size > excess) {
        !           652:                        if (uip == NULL || uip->i_size > tip->i_size)
        !           653:                                uip = tip;
        !           654:                } else {
        !           655:                        if (lip == NULL || lip->i_size < tip->i_size)
        !           656:                                lip = tip;
        !           657:                }
        !           658:                dp += 1;
        !           659:        }
        !           660:        if (lip != NULL)
        !           661:                return (lip);
        !           662:        if (uip->i_isdir)
        !           663:                return (select(uip));
        !           664:        return (uip);
        !           665: }
        !           666: 
        !           667: void
        !           668: purge(rip) MINODE *rip;
        !           669: {
        !           670:        int i;
        !           671:        MINODE *tip;
        !           672:        struct direct *dp1, *dp2;
        !           673: 
        !           674:        assert(rip->i_isdir);
        !           675: #if I8086
        !           676:        assert((char *)&dp2 > edata + 16);
        !           677: #endif
        !           678:        dp1 = dp2 = rip->i_elem;
        !           679:        for (i = 0; i < rip->i_nent; i += 1) {
        !           680:                tip = fetchmi(dp1->d_ino);
        !           681:                if (tip->i_isdir) {
        !           682:                        purge(tip);
        !           683:                        if ((tip->i_flag & I_PURGE) && tip->i_nent == 0) {
        !           684:                                dp1->d_ino = 0;
        !           685:                                freemi(tip->i_mino);
        !           686:                        }
        !           687:                } else if (tip->i_flag & I_PURGE)
        !           688:                        dp1->d_ino = 0;
        !           689:                if (dp1->d_ino != 0) {
        !           690:                        if (dp1 != dp2)
        !           691:                                *dp2 = *dp1;
        !           692:                        dp2 += 1;
        !           693:                }
        !           694:                dp1 += 1;
        !           695:        }
        !           696:        rip->i_nent = dp2 - rip->i_elem;
        !           697: }
        !           698: 
        !           699: void
        !           700: donedir(ip)
        !           701: MINODE *ip;
        !           702: {
        !           703:        int i;
        !           704:        MINODE *tip;
        !           705:        struct direct *dp;
        !           706: 
        !           707:        ip->i_link1->i_flag |= I_DONE1;
        !           708:        dp = ip->i_elem;
        !           709:        for (i = 0; i < ip->i_nent; i += 1) {
        !           710:                tip = fetchmi(dp->d_ino);
        !           711:                if (tip->i_isdir)
        !           712:                        donedir(tip);
        !           713:                else
        !           714:                        tip->i_flag |= I_DONE|I_DONE1;
        !           715:                dp += 1;
        !           716:        }
        !           717: }
        !           718: 
        !           719: void
        !           720: markdir(ip) MINODE *ip;
        !           721: {
        !           722:        int i;
        !           723:        MINODE *tip;
        !           724:        struct direct *dp;
        !           725:        int flag;
        !           726: 
        !           727:        if (ip->i_flag & I_DONE)
        !           728:                return;
        !           729:        dp = ip->i_elem;
        !           730:        flag = I_DONE;
        !           731:        for (i = 0; i < ip->i_nent; i += 1) {
        !           732:                tip = fetchmi(dp->d_ino);
        !           733:                if (tip->i_isdir)
        !           734:                        markdir(tip);
        !           735:                flag &= tip->i_flag;
        !           736:                dp += 1;
        !           737:        }
        !           738:        if ((flag & I_DONE) != 0 && (ip->i_flag & I_DONE1) != 0)
        !           739:                ip->i_flag |= I_DONE;
        !           740: }
        !           741: 
        !           742: MINODE *ihash1[IHASH]; /* dev x ino hash */
        !           743: MINODE *ihash2[IHASH]; /* mino hash */
        !           744: int    minumber = 1;
        !           745: 
        !           746: /*
        !           747: ** Return the mino in the hash table ihash1 corresponding to 
        !           748: ** the statbuf.  If not found, enter it and return the resulting
        !           749: ** entry.
        !           750: */
        !           751: int
        !           752: entermi()
        !           753: {
        !           754:        MINODE *ip, **ipp;
        !           755:        int     nent;
        !           756: 
        !           757:        ipp = &ihash1[sbuf.st_ino % IHASH];
        !           758:        while ((ip = *ipp) != NULL) {
        !           759:                if (ip->i_ino == sbuf.st_ino
        !           760:                 && ip->i_dev == sbuf.st_dev)
        !           761:                        return (ip->i_mino);
        !           762:                ipp = &ip->i_link1;
        !           763:        }
        !           764:        nent = 0;
        !           765:        if ((sbuf.st_mode&S_IFMT) == S_IFDIR)
        !           766:                nent = sbuf.st_size / sizeof(struct direct);
        !           767:        else if (sbuf.st_mtime < tbuf.st_mtime)
        !           768:                return 0;
        !           769:        else if (blkuse(sbuf.st_size) > dsize-5) {
        !           770:                fprintf(stderr, "unmkfs: file %s too large - omitted\n", fname);
        !           771:                return 0;
        !           772:        }
        !           773:        *ipp = ip = myalloc(sizeof(MINODE) + nent * sizeof(struct direct));
        !           774:        ip->i_dev = sbuf.st_dev;
        !           775:        ip->i_ino = sbuf.st_ino;
        !           776:        ip->i_mode = sbuf.st_mode;
        !           777:        ip->i_nlink = sbuf.st_nlink;
        !           778:        ip->i_uid = sbuf.st_uid;
        !           779:        ip->i_gid = sbuf.st_gid;
        !           780:        ip->i_rdev = sbuf.st_rdev;
        !           781:        ip->i_mtime = sbuf.st_mtime;
        !           782:        ip->i_blks = blkuse(sbuf.st_size);
        !           783:        ip->i_inos = 1;
        !           784:        ip->i_size = ip->i_blks;
        !           785:        ip->i_nent = nent;
        !           786:        ip->i_mino = minumber++;
        !           787:        ip->i_isdir = (nent != 0);
        !           788:        ipp = &ihash2[ip->i_mino % IHASH];
        !           789:        ip->i_link2 = *ipp;
        !           790:        *ipp = ip;
        !           791:        return (ip->i_mino);
        !           792: }
        !           793: 
        !           794: int
        !           795: duplmi(ip) MINODE *ip;
        !           796: {
        !           797:        MINODE *nip, **ipp;
        !           798: 
        !           799:        nip = myalloc(sizeof(MINODE) + ip->i_nent * sizeof(struct direct));
        !           800:        nip->i_dev = ip->i_dev;
        !           801:        nip->i_ino = ip->i_ino;
        !           802:        nip->i_mode = ip->i_mode;
        !           803:        nip->i_nlink = ip->i_nlink;
        !           804:        nip->i_uid = ip->i_uid;
        !           805:        nip->i_gid = ip->i_gid;
        !           806:        nip->i_rdev = ip->i_rdev;
        !           807:        nip->i_blks = ip->i_blks;
        !           808:        nip->i_inos = ip->i_inos;
        !           809:        nip->i_size = ip->i_size;
        !           810:        nip->i_nent = ip->i_nent;
        !           811:        nip->i_mino = minumber++;
        !           812:        nip->i_isdir = ip->i_isdir;
        !           813:        ipp = &ihash2[nip->i_mino % IHASH];
        !           814:        nip->i_link2 = *ipp;
        !           815:        *ipp = nip;
        !           816:        nip->i_link1 = ip;
        !           817:        return (nip->i_mino);
        !           818: }
        !           819: 
        !           820: /*
        !           821: ** Find the entry i ihash2 corresponding to mino.
        !           822: ** Die with message if not there.
        !           823: */
        !           824: MINODE *
        !           825: fetchmi(mino) int mino;
        !           826: {
        !           827:        MINODE *ip, **ipp;
        !           828: 
        !           829:        ipp = &ihash2[mino % IHASH];
        !           830:        while ((ip = *ipp) != NULL)
        !           831:                if (ip->i_mino == mino)
        !           832:                        return (ip);
        !           833:                else
        !           834:                        ipp = &ip->i_link2;
        !           835:        fatal("nonexistent internal inumber %d", mino);
        !           836: }
        !           837: 
        !           838: void
        !           839: freemi(mino) int mino;
        !           840: {
        !           841:        MINODE *ip, **ipp;
        !           842: 
        !           843:        ipp = &ihash2[mino % IHASH];
        !           844:        while ((ip = *ipp) != NULL)
        !           845:                if (ip->i_mino == mino) {
        !           846:                        *ipp = ip->i_link2;
        !           847:                        free(ip);
        !           848:                        return;
        !           849:                } else
        !           850:                        ipp = &ip->i_link2;
        !           851:        fatal("nonexistent internal inumber %d", mino);
        !           852: }
        !           853: 
        !           854: /*
        !           855:  * A corrected disk usage computation
        !           856:  * for retrofit into /usr/src/cmd/du.c, /usr/src/cmd/ls.c/prsize(),
        !           857:  * and /usr/src/cmd/quot.c since they are all wrong.
        !           858:  *
        !           859:  * And this is not quite right either since it doesn't deal with sparse
        !           860:  * blocks.
        !           861:  */
        !           862: long
        !           863: blkuse(nb) long nb;
        !           864: {
        !           865: #undef NBN
        !           866: #define NBN    128L
        !           867: #define nindir(x)      (((x)+NBN-1)/NBN)
        !           868: #define nblock(x)      (((x)+BSIZE-1)/BSIZE)
        !           869: #define min(x, y)      ((x)<(y) ? (x) : (y))
        !           870:        long bu, ndir, nidir, niidir;
        !           871: 
        !           872:        nb = nblock(nb);
        !           873:        ndir = min(nb, ND);
        !           874:        nb -= ndir;
        !           875:        bu = ndir;
        !           876:        if (nb) {
        !           877:                nidir = min(nb, NBN);
        !           878:                nb -= nidir;
        !           879:                bu += nidir + 1;
        !           880:                if (nb) {
        !           881:                        niidir = min(nb, NBN*NBN);
        !           882:                        nb -= niidir;
        !           883:                        bu += niidir + 1 + nindir(niidir);
        !           884:                        if (nb)
        !           885:                                bu += nb + 1 + nindir(nindir(nb)) + nindir(nb);
        !           886:                }
        !           887:        }
        !           888:        return (bu);
        !           889: }
        !           890: 
        !           891: char *
        !           892: string(cp) char *cp;
        !           893: {
        !           894:        char *sp;
        !           895: 
        !           896:        sp = myalloc(strlen(cp)+1);
        !           897:        strcpy(sp, cp);
        !           898:        return (sp);
        !           899: }
        !           900: 
        !           901: char *
        !           902: myalloc(nb) int nb;
        !           903: {
        !           904:        char *p;
        !           905: 
        !           906:        if ((p = malloc(nb)) == NULL)
        !           907:                fatal("out of space");
        !           908:        while (--nb >= 0)
        !           909:                p[nb] = 0;
        !           910:        return (p);
        !           911: }
        !           912: 
        !           913: void
        !           914: usage()
        !           915: {
        !           916:        fprintf(stderr, USAGE);
        !           917:        exit(1);
        !           918: }
        !           919: 
        !           920: void
        !           921: fatal(args) char *args;
        !           922: {
        !           923:        fprintf(stderr, "%s: %r\n", argv0, &args);
        !           924:        exit(1);
        !           925: }

unix.superglobalmegacorp.com

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