Annotation of 43BSDReno/sbin/restore/symtab.c, revision 1.1

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

unix.superglobalmegacorp.com

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