Annotation of coherent/d/etc/unmkfs.c, revision 1.1.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.