Annotation of 42BSD/etc/restore/symtab.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)symtab.c   3.15    (Berkeley)      83/08/11";
                      3: #endif
                      4: 
                      5: /* Copyright (c) 1983 Regents of the University of California */
                      6: 
                      7: /*
                      8:  * These routines maintain the symbol table which tracks the state
                      9:  * of the file system being restored. They provide lookup by either
                     10:  * name or inode number. They also provide for creation, deletion,
                     11:  * and renaming of entries. Because of the dynamic nature of pathnames,
                     12:  * names should not be saved, but always constructed just before they
                     13:  * are needed, by calling "myname".
                     14:  */
                     15: 
                     16: #include "restore.h"
                     17: #include <sys/stat.h>
                     18: #include <sys/dir.h>
                     19: 
                     20: /*
                     21:  * The following variables define the inode symbol table.
                     22:  * The primary hash table is dynamically allocated based on
                     23:  * the number of inodes in the file system (maxino), scaled by
                     24:  * HASHFACTOR. The variable "entry" points to the hash table;
                     25:  * the variable "entrytblsize" indicates its size (in entries).
                     26:  */
                     27: #define HASHFACTOR 5
                     28: static struct entry **entry;
                     29: static long entrytblsize;
                     30: 
                     31: /*
                     32:  * Look up an entry by inode number
                     33:  */
                     34: struct entry *
                     35: lookupino(inum)
                     36:        ino_t inum;
                     37: {
                     38:        register struct entry *ep;
                     39: 
                     40:        if (inum < ROOTINO || inum >= maxino)
                     41:                return (NIL);
                     42:        for (ep = entry[inum % entrytblsize]; ep != NIL; ep = ep->e_next)
                     43:                if (ep->e_ino == inum)
                     44:                        return (ep);
                     45:        return (NIL);
                     46: }
                     47: 
                     48: /*
                     49:  * Add an entry into the entry table
                     50:  */
                     51: addino(inum, np)
                     52:        ino_t inum;
                     53:        struct entry *np;
                     54: {
                     55:        struct entry **epp;
                     56: 
                     57:        if (inum < ROOTINO || inum >= maxino)
                     58:                panic("addino: out of range %d\n", inum);
                     59:        epp = &entry[inum % entrytblsize];
                     60:        np->e_ino = inum;
                     61:        np->e_next = *epp;
                     62:        *epp = np;
                     63:        if (dflag)
                     64:                for (np = np->e_next; np != NIL; np = np->e_next)
                     65:                        if (np->e_ino == inum)
                     66:                                badentry(np, "duplicate inum");
                     67: }
                     68: 
                     69: /*
                     70:  * Delete an entry from the entry table
                     71:  */
                     72: deleteino(inum)
                     73:        ino_t inum;
                     74: {
                     75:        register struct entry *next;
                     76:        struct entry **prev;
                     77: 
                     78:        if (inum < ROOTINO || inum >= maxino)
                     79:                panic("deleteino: out of range %d\n", inum);
                     80:        prev = &entry[inum % entrytblsize];
                     81:        for (next = *prev; next != NIL; next = next->e_next) {
                     82:                if (next->e_ino == inum) {
                     83:                        next->e_ino = 0;
                     84:                        *prev = next->e_next;
                     85:                        return;
                     86:                }
                     87:                prev = &next->e_next;
                     88:        }
                     89:        panic("deleteino: %d not found\n", inum);
                     90: }
                     91: 
                     92: /*
                     93:  * Look up an entry by name
                     94:  */
                     95: struct entry *
                     96: lookupname(name)
                     97:        char *name;
                     98: {
                     99:        register struct entry *ep;
                    100:        register char *np, *cp;
                    101:        char buf[MAXPATHLEN];
                    102: 
                    103:        cp = name;
                    104:        for (ep = lookupino(ROOTINO); ep != NIL; ep = ep->e_entries) {
                    105:                for (np = buf; *cp != '/' && *cp != '\0'; )
                    106:                        *np++ = *cp++;
                    107:                *np = '\0';
                    108:                for ( ; ep != NIL; ep = ep->e_sibling)
                    109:                        if (strcmp(ep->e_name, buf) == 0)
                    110:                                break;
                    111:                if (ep == NIL)
                    112:                        break;
                    113:                if (*cp++ == '\0')
                    114:                        return (ep);
                    115:        }
                    116:        return (NIL);
                    117: }
                    118: 
                    119: /*
                    120:  * Look up the parent of a pathname
                    121:  */
                    122: struct entry *
                    123: lookupparent(name)
                    124:        char *name;
                    125: {
                    126:        struct entry *ep;
                    127:        char *tailindex;
                    128: 
                    129:        tailindex = rindex(name, '/');
                    130:        if (tailindex == 0)
                    131:                return (NIL);
                    132:        *tailindex = '\0';
                    133:        ep = lookupname(name);
                    134:        *tailindex = '/';
                    135:        if (ep == NIL)
                    136:                return (NIL);
                    137:        if (ep->e_type != NODE)
                    138:                panic("%s is not a directory\n", name);
                    139:        return (ep);
                    140: }
                    141: 
                    142: /*
                    143:  * Determine the current pathname of a node or leaf
                    144:  */
                    145: char *
                    146: myname(ep)
                    147:        register struct entry *ep;
                    148: {
                    149:        register char *cp;
                    150:        static char namebuf[MAXPATHLEN];
                    151: 
                    152:        for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) {
                    153:                cp -= ep->e_namlen;
                    154:                bcopy(ep->e_name, cp, (long)ep->e_namlen);
                    155:                if (ep == lookupino(ROOTINO))
                    156:                        return (cp);
                    157:                *(--cp) = '/';
                    158:                ep = ep->e_parent;
                    159:        }
                    160:        panic("%s: pathname too long\n", cp);
                    161:        return(cp);
                    162: }
                    163: 
                    164: /*
                    165:  * Unused symbol table entries are linked together on a freelist
                    166:  * headed by the following pointer.
                    167:  */
                    168: static struct entry *freelist = NIL;
                    169: 
                    170: /*
                    171:  * add an entry to the symbol table
                    172:  */
                    173: struct entry *
                    174: addentry(name, inum, type)
                    175:        char *name;
                    176:        ino_t inum;
                    177:        int type;
                    178: {
                    179:        register struct entry *np, *ep;
                    180: 
                    181:        if (freelist != NIL) {
                    182:                np = freelist;
                    183:                freelist = np->e_next;
                    184:                bzero((char *)np, (long)sizeof(struct entry));
                    185:        } else {
                    186:                np = (struct entry *)calloc(1, sizeof(struct entry));
                    187:                if (np == NIL)
                    188:                        panic("no memory to extend symbol table\n");
                    189:        }
                    190:        np->e_type = type & ~LINK;
                    191:        ep = lookupparent(name);
                    192:        if (ep == NIL) {
                    193:                if (inum != ROOTINO || lookupino(ROOTINO) != NIL)
                    194:                        panic("bad name to addentry %s\n", name);
                    195:                np->e_name = savename(name);
                    196:                np->e_namlen = strlen(name);
                    197:                np->e_parent = np;
                    198:                addino(ROOTINO, np);
                    199:                return (np);
                    200:        }
                    201:        np->e_name = savename(rindex(name, '/') + 1);
                    202:        np->e_namlen = strlen(np->e_name);
                    203:        np->e_parent = ep;
                    204:        np->e_sibling = ep->e_entries;
                    205:        ep->e_entries = np;
                    206:        if (type & LINK) {
                    207:                ep = lookupino(inum);
                    208:                if (ep == NIL)
                    209:                        panic("link to non-existant name\n");
                    210:                np->e_ino = inum;
                    211:                np->e_links = ep->e_links;
                    212:                ep->e_links = np;
                    213:        } else if (inum != 0) {
                    214:                if (lookupino(inum) != NIL)
                    215:                        panic("duplicate entry\n");
                    216:                addino(inum, np);
                    217:        }
                    218:        return (np);
                    219: }
                    220: 
                    221: /*
                    222:  * delete an entry from the symbol table
                    223:  */
                    224: freeentry(ep)
                    225:        register struct entry *ep;
                    226: {
                    227:        register struct entry *np;
                    228:        ino_t inum;
                    229: 
                    230:        if (ep->e_flags != REMOVED)
                    231:                badentry(ep, "not marked REMOVED");
                    232:        if (ep->e_type == NODE) {
                    233:                if (ep->e_links != NIL)
                    234:                        badentry(ep, "freeing referenced directory");
                    235:                if (ep->e_entries != NIL)
                    236:                        badentry(ep, "freeing non-empty directory");
                    237:        }
                    238:        if (ep->e_ino != 0) {
                    239:                np = lookupino(ep->e_ino);
                    240:                if (np == NIL)
                    241:                        badentry(ep, "lookupino failed");
                    242:                if (np == ep) {
                    243:                        inum = ep->e_ino;
                    244:                        deleteino(inum);
                    245:                        if (ep->e_links != NIL)
                    246:                                addino(inum, ep->e_links);
                    247:                } else {
                    248:                        for (; np != NIL; np = np->e_links) {
                    249:                                if (np->e_links == ep) {
                    250:                                        np->e_links = ep->e_links;
                    251:                                        break;
                    252:                                }
                    253:                        }
                    254:                        if (np == NIL)
                    255:                                badentry(ep, "link not found");
                    256:                }
                    257:        }
                    258:        removeentry(ep);
                    259:        freename(ep->e_name);
                    260:        ep->e_next = freelist;
                    261:        freelist = ep;
                    262: }
                    263: 
                    264: /*
                    265:  * Relocate an entry in the tree structure
                    266:  */
                    267: moveentry(ep, newname)
                    268:        register struct entry *ep;
                    269:        char *newname;
                    270: {
                    271:        struct entry *np;
                    272:        char *cp;
                    273: 
                    274:        np = lookupparent(newname);
                    275:        if (np == NIL)
                    276:                badentry(ep, "cannot move ROOT");
                    277:        if (np != ep->e_parent) {
                    278:                removeentry(ep);
                    279:                ep->e_parent = np;
                    280:                ep->e_sibling = np->e_entries;
                    281:                np->e_entries = ep;
                    282:        }
                    283:        cp = rindex(newname, '/') + 1;
                    284:        freename(ep->e_name);
                    285:        ep->e_name = savename(cp);
                    286:        ep->e_namlen = strlen(cp);
                    287:        if (strcmp(gentempname(ep), ep->e_name) == 0)
                    288:                ep->e_flags |= TMPNAME;
                    289:        else
                    290:                ep->e_flags &= ~TMPNAME;
                    291: }
                    292: 
                    293: /*
                    294:  * Remove an entry in the tree structure
                    295:  */
                    296: removeentry(ep)
                    297:        register struct entry *ep;
                    298: {
                    299:        register struct entry *np;
                    300: 
                    301:        np = ep->e_parent;
                    302:        if (np->e_entries == ep) {
                    303:                np->e_entries = ep->e_sibling;
                    304:        } else {
                    305:                for (np = np->e_entries; np != NIL; np = np->e_sibling) {
                    306:                        if (np->e_sibling == ep) {
                    307:                                np->e_sibling = ep->e_sibling;
                    308:                                break;
                    309:                        }
                    310:                }
                    311:                if (np == NIL)
                    312:                        badentry(ep, "cannot find entry in parent list");
                    313:        }
                    314: }
                    315: 
                    316: /*
                    317:  * Table of unused string entries, sorted by length.
                    318:  * 
                    319:  * Entries are allocated in STRTBLINCR sized pieces so that names
                    320:  * of similar lengths can use the same entry. The value of STRTBLINCR
                    321:  * is chosen so that every entry has at least enough space to hold
                    322:  * a "struct strtbl" header. Thus every entry can be linked onto an
                    323:  * apprpriate free list.
                    324:  *
                    325:  * NB. The macro "allocsize" below assumes that "struct strhdr"
                    326:  *     has a size that is a power of two.
                    327:  */
                    328: struct strhdr {
                    329:        struct strhdr *next;
                    330: };
                    331: 
                    332: #define STRTBLINCR     (sizeof(struct strhdr))
                    333: #define allocsize(size)        (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1))
                    334: 
                    335: static struct strhdr strtblhdr[allocsize(MAXNAMLEN) / STRTBLINCR];
                    336: 
                    337: /*
                    338:  * Allocate space for a name. It first looks to see if it already
                    339:  * has an appropriate sized entry, and if not allocates a new one.
                    340:  */
                    341: char *
                    342: savename(name)
                    343:        char *name;
                    344: {
                    345:        struct strhdr *np;
                    346:        long len;
                    347:        char *cp;
                    348: 
                    349:        if (name == NULL)
                    350:                panic("bad name\n");
                    351:        len = strlen(name);
                    352:        np = strtblhdr[len / STRTBLINCR].next;
                    353:        if (np != NULL) {
                    354:                strtblhdr[len / STRTBLINCR].next = np->next;
                    355:                cp = (char *)np;
                    356:        } else {
                    357:                cp = malloc((unsigned)allocsize(len));
                    358:                if (cp == NULL)
                    359:                        panic("no space for string table\n");
                    360:        }
                    361:        (void) strcpy(cp, name);
                    362:        return (cp);
                    363: }
                    364: 
                    365: /*
                    366:  * Free space for a name. The resulting entry is linked onto the
                    367:  * appropriate free list.
                    368:  */
                    369: freename(name)
                    370:        char *name;
                    371: {
                    372:        struct strhdr *tp, *np;
                    373:        
                    374:        tp = &strtblhdr[strlen(name) / STRTBLINCR];
                    375:        np = (struct strhdr *)name;
                    376:        np->next = tp->next;
                    377:        tp->next = np;
                    378: }
                    379: 
                    380: /*
                    381:  * Useful quantities placed at the end of a dumped symbol table.
                    382:  */
                    383: struct symtableheader {
                    384:        long    volno;
                    385:        long    stringsize;
                    386:        long    entrytblsize;
                    387:        time_t  dumptime;
                    388:        time_t  dumpdate;
                    389:        ino_t   maxino;
                    390: };
                    391: 
                    392: /*
                    393:  * dump a snapshot of the symbol table
                    394:  */
                    395: dumpsymtable(filename, checkpt)
                    396:        char *filename;
                    397:        long checkpt;
                    398: {
                    399:        register struct entry *ep, *tep;
                    400:        register ino_t i;
                    401:        struct entry temp, *tentry;
                    402:        long mynum = 1, stroff = 0;
                    403:        FILE *fd;
                    404:        struct symtableheader hdr;
                    405: 
                    406:        vprintf(stdout, "Check pointing the restore\n");
                    407:        if ((fd = fopen(filename, "w")) == NULL) {
                    408:                perror("fopen");
                    409:                panic("cannot create save file %s for symbol table\n",
                    410:                        filename);
                    411:        }
                    412:        clearerr(fd);
                    413:        /*
                    414:         * Assign indicies to each entry
                    415:         * Write out the string entries
                    416:         */
                    417:        for (i = ROOTINO; i < maxino; i++) {
                    418:                for (ep = lookupino(i); ep != NIL; ep = ep->e_links) {
                    419:                        ep->e_index = mynum++;
                    420:                        (void) fwrite(ep->e_name, sizeof(char),
                    421:                               (int)allocsize(ep->e_namlen), fd);
                    422:                }
                    423:        }
                    424:        /*
                    425:         * Convert pointers to indexes, and output
                    426:         */
                    427:        tep = &temp;
                    428:        stroff = 0;
                    429:        for (i = ROOTINO; i < maxino; i++) {
                    430:                for (ep = lookupino(i); ep != NIL; ep = ep->e_links) {
                    431:                        bcopy((char *)ep, (char *)tep,
                    432:                                (long)sizeof(struct entry));
                    433:                        tep->e_name = (char *)stroff;
                    434:                        stroff += allocsize(ep->e_namlen);
                    435:                        tep->e_parent = (struct entry *)ep->e_parent->e_index;
                    436:                        if (ep->e_links != NIL)
                    437:                                tep->e_links =
                    438:                                        (struct entry *)ep->e_links->e_index;
                    439:                        if (ep->e_sibling != NIL)
                    440:                                tep->e_sibling =
                    441:                                        (struct entry *)ep->e_sibling->e_index;
                    442:                        if (ep->e_entries != NIL)
                    443:                                tep->e_entries =
                    444:                                        (struct entry *)ep->e_entries->e_index;
                    445:                        if (ep->e_next != NIL)
                    446:                                tep->e_next =
                    447:                                        (struct entry *)ep->e_next->e_index;
                    448:                        (void) fwrite((char *)tep, sizeof(struct entry), 1, fd);
                    449:                }
                    450:        }
                    451:        /*
                    452:         * Convert entry pointers to indexes, and output
                    453:         */
                    454:        for (i = 0; i < entrytblsize; i++) {
                    455:                if (entry[i] == NIL)
                    456:                        tentry = NIL;
                    457:                else
                    458:                        tentry = (struct entry *)entry[i]->e_index;
                    459:                (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd);
                    460:        }
                    461:        hdr.volno = checkpt;
                    462:        hdr.maxino = maxino;
                    463:        hdr.entrytblsize = entrytblsize;
                    464:        hdr.stringsize = stroff;
                    465:        hdr.dumptime = dumptime;
                    466:        hdr.dumpdate = dumpdate;
                    467:        (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd);
                    468:        if (ferror(fd)) {
                    469:                perror("fwrite");
                    470:                panic("output error to file %s writing symbol table\n",
                    471:                        filename);
                    472:        }
                    473:        (void) fclose(fd);
                    474: }
                    475: 
                    476: /*
                    477:  * Initialize a symbol table from a file
                    478:  */
                    479: initsymtable(filename)
                    480:        char *filename;
                    481: {
                    482:        char *base;
                    483:        long tblsize;
                    484:        register struct entry *ep;
                    485:        struct entry *baseep, *lep;
                    486:        struct symtableheader hdr;
                    487:        struct stat stbuf;
                    488:        register long i;
                    489:        int fd;
                    490: 
                    491:        vprintf(stdout, "Initialize symbol table.\n");
                    492:        if (filename == NULL) {
                    493:                entrytblsize = maxino / HASHFACTOR;
                    494:                entry = (struct entry **)
                    495:                        calloc((unsigned)entrytblsize, sizeof(struct entry *));
                    496:                if (entry == (struct entry **)NIL)
                    497:                        panic("no memory for entry table\n");
                    498:                ep = addentry(".", ROOTINO, NODE);
                    499:                ep->e_flags |= NEW;
                    500:                return;
                    501:        }
                    502:        if ((fd = open(filename, 0)) < 0) {
                    503:                perror("open");
                    504:                panic("cannot open symbol table file %s\n", filename);
                    505:        }
                    506:        if (fstat(fd, &stbuf) < 0) {
                    507:                perror("stat");
                    508:                panic("cannot stat symbol table file %s\n", filename);
                    509:        }
                    510:        tblsize = stbuf.st_size - sizeof(struct symtableheader);
                    511:        base = calloc(sizeof(char), (unsigned)tblsize);
                    512:        if (base == NULL)
                    513:                panic("cannot allocate space for symbol table\n");
                    514:        if (read(fd, base, (int)tblsize) < 0 ||
                    515:            read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) {
                    516:                perror("read");
                    517:                panic("cannot read symbol table file %s\n", filename);
                    518:        }
                    519:        switch (command) {
                    520:        case 'r':
                    521:                /*
                    522:                 * For normal continuation, insure that we are using
                    523:                 * the next incremental tape
                    524:                 */
                    525:                if (hdr.dumpdate != dumptime) {
                    526:                        if (hdr.dumpdate < dumptime)
                    527:                                fprintf(stderr, "Incremental tape too low\n");
                    528:                        else
                    529:                                fprintf(stderr, "Incremental tape too high\n");
                    530:                        done(1);
                    531:                }
                    532:                break;
                    533:        case 'R':
                    534:                /*
                    535:                 * For restart, insure that we are using the same tape
                    536:                 */
                    537:                curfile.action = SKIP;
                    538:                dumptime = hdr.dumptime;
                    539:                dumpdate = hdr.dumpdate;
                    540:                getvol(hdr.volno);
                    541:                break;
                    542:        default:
                    543:                panic("initsymtable called from command %c\n", command);
                    544:                break;
                    545:        }
                    546:        maxino = hdr.maxino;
                    547:        entrytblsize = hdr.entrytblsize;
                    548:        entry = (struct entry **)
                    549:                (base + tblsize - (entrytblsize * sizeof(struct entry *)));
                    550:        baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry));
                    551:        lep = (struct entry *)entry;
                    552:        for (i = 0; i < entrytblsize; i++) {
                    553:                if (entry[i] == NIL)
                    554:                        continue;
                    555:                entry[i] = &baseep[(long)entry[i]];
                    556:        }
                    557:        for (ep = &baseep[1]; ep < lep; ep++) {
                    558:                ep->e_name = base + (long)ep->e_name;
                    559:                ep->e_parent = &baseep[(long)ep->e_parent];
                    560:                if (ep->e_sibling != NIL)
                    561:                        ep->e_sibling = &baseep[(long)ep->e_sibling];
                    562:                if (ep->e_links != NIL)
                    563:                        ep->e_links = &baseep[(long)ep->e_links];
                    564:                if (ep->e_entries != NIL)
                    565:                        ep->e_entries = &baseep[(long)ep->e_entries];
                    566:                if (ep->e_next != NIL)
                    567:                        ep->e_next = &baseep[(long)ep->e_next];
                    568:        }
                    569: }

unix.superglobalmegacorp.com

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