121169Sdist /* 2*36105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*36105Sbostic * All rights reserved. 4*36105Sbostic * 5*36105Sbostic * Redistribution and use in source and binary forms are permitted 6*36105Sbostic * provided that the above copyright notice and this paragraph are 7*36105Sbostic * duplicated in all such forms and that any documentation, 8*36105Sbostic * advertising materials, and other materials related to such 9*36105Sbostic * distribution and use acknowledge that the software was developed 10*36105Sbostic * by the University of California, Berkeley. The name of the 11*36105Sbostic * University may not be used to endorse or promote products derived 12*36105Sbostic * from this software without specific prior written permission. 13*36105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*36105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*36105Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621169Sdist */ 1721169Sdist 1810314Smckusick #ifndef lint 19*36105Sbostic static char sccsid[] = "@(#)symtab.c 5.3 (Berkeley) 10/24/88"; 20*36105Sbostic #endif /* not lint */ 2110314Smckusick 2211646Smckusick /* 2311646Smckusick * These routines maintain the symbol table which tracks the state 2411646Smckusick * of the file system being restored. They provide lookup by either 2511646Smckusick * name or inode number. They also provide for creation, deletion, 2611646Smckusick * and renaming of entries. Because of the dynamic nature of pathnames, 2711646Smckusick * names should not be saved, but always constructed just before they 2811646Smckusick * are needed, by calling "myname". 2911646Smckusick */ 3011646Smckusick 3110314Smckusick #include "restore.h" 3210314Smckusick #include <sys/stat.h> 3310314Smckusick 3411646Smckusick /* 3511646Smckusick * The following variables define the inode symbol table. 3611646Smckusick * The primary hash table is dynamically allocated based on 3711646Smckusick * the number of inodes in the file system (maxino), scaled by 3811646Smckusick * HASHFACTOR. The variable "entry" points to the hash table; 3911646Smckusick * the variable "entrytblsize" indicates its size (in entries). 4011646Smckusick */ 4111646Smckusick #define HASHFACTOR 5 4211440Smckusick static struct entry **entry; 4311440Smckusick static long entrytblsize; 4410314Smckusick 4510314Smckusick /* 4610314Smckusick * Look up an entry by inode number 4710314Smckusick */ 4810314Smckusick struct entry * 4910314Smckusick lookupino(inum) 5010314Smckusick ino_t inum; 5110314Smckusick { 5211440Smckusick register struct entry *ep; 5310314Smckusick 5411440Smckusick if (inum < ROOTINO || inum >= maxino) 5511440Smckusick return (NIL); 5611440Smckusick for (ep = entry[inum % entrytblsize]; ep != NIL; ep = ep->e_next) 5711440Smckusick if (ep->e_ino == inum) 5811440Smckusick return (ep); 5911440Smckusick return (NIL); 6010314Smckusick } 6110314Smckusick 6210314Smckusick /* 6310314Smckusick * Add an entry into the entry table 6410314Smckusick */ 6510314Smckusick addino(inum, np) 6611440Smckusick ino_t inum; 6710314Smckusick struct entry *np; 6810314Smckusick { 6911440Smckusick struct entry **epp; 7010314Smckusick 7111440Smckusick if (inum < ROOTINO || inum >= maxino) 7211440Smckusick panic("addino: out of range %d\n", inum); 7311440Smckusick epp = &entry[inum % entrytblsize]; 7411440Smckusick np->e_ino = inum; 7511440Smckusick np->e_next = *epp; 7611440Smckusick *epp = np; 7711440Smckusick if (dflag) 7811440Smckusick for (np = np->e_next; np != NIL; np = np->e_next) 7911440Smckusick if (np->e_ino == inum) 8011440Smckusick badentry(np, "duplicate inum"); 8110314Smckusick } 8210314Smckusick 8310314Smckusick /* 8410314Smckusick * Delete an entry from the entry table 8510314Smckusick */ 8610314Smckusick deleteino(inum) 8711440Smckusick ino_t inum; 8810314Smckusick { 8911440Smckusick register struct entry *next; 9011440Smckusick struct entry **prev; 9110314Smckusick 9211440Smckusick if (inum < ROOTINO || inum >= maxino) 9311440Smckusick panic("deleteino: out of range %d\n", inum); 9411440Smckusick prev = &entry[inum % entrytblsize]; 9511440Smckusick for (next = *prev; next != NIL; next = next->e_next) { 9611440Smckusick if (next->e_ino == inum) { 9711440Smckusick next->e_ino = 0; 9811440Smckusick *prev = next->e_next; 9911440Smckusick return; 10011440Smckusick } 10111440Smckusick prev = &next->e_next; 10211440Smckusick } 10311440Smckusick panic("deleteino: %d not found\n", inum); 10410314Smckusick } 10510314Smckusick 10610314Smckusick /* 10710314Smckusick * Look up an entry by name 10810314Smckusick */ 10910314Smckusick struct entry * 11010314Smckusick lookupname(name) 11110314Smckusick char *name; 11210314Smckusick { 11310314Smckusick register struct entry *ep; 11410314Smckusick register char *np, *cp; 11511646Smckusick char buf[MAXPATHLEN]; 11610314Smckusick 11710314Smckusick cp = name; 11810314Smckusick for (ep = lookupino(ROOTINO); ep != NIL; ep = ep->e_entries) { 11910314Smckusick for (np = buf; *cp != '/' && *cp != '\0'; ) 12010314Smckusick *np++ = *cp++; 12110314Smckusick *np = '\0'; 12210314Smckusick for ( ; ep != NIL; ep = ep->e_sibling) 12310314Smckusick if (strcmp(ep->e_name, buf) == 0) 12410314Smckusick break; 12510314Smckusick if (ep == NIL) 12610314Smckusick break; 12711311Smckusick if (*cp++ == '\0') 12810314Smckusick return (ep); 12910314Smckusick } 13011311Smckusick return (NIL); 13110314Smckusick } 13210314Smckusick 13310314Smckusick /* 13410314Smckusick * Look up the parent of a pathname 13510314Smckusick */ 13610314Smckusick struct entry * 13710314Smckusick lookupparent(name) 13810314Smckusick char *name; 13910314Smckusick { 14010314Smckusick struct entry *ep; 14110314Smckusick char *tailindex; 14210314Smckusick 14310314Smckusick tailindex = rindex(name, '/'); 14410314Smckusick if (tailindex == 0) 14510314Smckusick return (NIL); 14610314Smckusick *tailindex = '\0'; 14710314Smckusick ep = lookupname(name); 14811311Smckusick *tailindex = '/'; 14910314Smckusick if (ep == NIL) 15010314Smckusick return (NIL); 15110314Smckusick if (ep->e_type != NODE) 15210314Smckusick panic("%s is not a directory\n", name); 15310314Smckusick return (ep); 15410314Smckusick } 15510314Smckusick 15610314Smckusick /* 15710314Smckusick * Determine the current pathname of a node or leaf 15810314Smckusick */ 15910314Smckusick char * 16010314Smckusick myname(ep) 16110314Smckusick register struct entry *ep; 16210314Smckusick { 16310314Smckusick register char *cp; 16411646Smckusick static char namebuf[MAXPATHLEN]; 16510314Smckusick 16611646Smckusick for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) { 16710314Smckusick cp -= ep->e_namlen; 16810314Smckusick bcopy(ep->e_name, cp, (long)ep->e_namlen); 16910314Smckusick if (ep == lookupino(ROOTINO)) 17010314Smckusick return (cp); 17110314Smckusick *(--cp) = '/'; 17210314Smckusick ep = ep->e_parent; 17310314Smckusick } 17410314Smckusick panic("%s: pathname too long\n", cp); 17510314Smckusick return(cp); 17610314Smckusick } 17710314Smckusick 17810314Smckusick /* 17911646Smckusick * Unused symbol table entries are linked together on a freelist 18011646Smckusick * headed by the following pointer. 18111646Smckusick */ 18211646Smckusick static struct entry *freelist = NIL; 18311646Smckusick 18411646Smckusick /* 18510314Smckusick * add an entry to the symbol table 18610314Smckusick */ 18710314Smckusick struct entry * 18810314Smckusick addentry(name, inum, type) 18910314Smckusick char *name; 19010314Smckusick ino_t inum; 19110314Smckusick int type; 19210314Smckusick { 19310314Smckusick register struct entry *np, *ep; 19410314Smckusick 19510314Smckusick if (freelist != NIL) { 19610314Smckusick np = freelist; 19711440Smckusick freelist = np->e_next; 19810314Smckusick bzero((char *)np, (long)sizeof(struct entry)); 19910314Smckusick } else { 20010314Smckusick np = (struct entry *)calloc(1, sizeof(struct entry)); 20113860Smckusick if (np == NIL) 20213860Smckusick panic("no memory to extend symbol table\n"); 20310314Smckusick } 20410314Smckusick np->e_type = type & ~LINK; 20510314Smckusick ep = lookupparent(name); 20610314Smckusick if (ep == NIL) { 20710314Smckusick if (inum != ROOTINO || lookupino(ROOTINO) != NIL) 20810314Smckusick panic("bad name to addentry %s\n", name); 20910314Smckusick np->e_name = savename(name); 21010314Smckusick np->e_namlen = strlen(name); 21110314Smckusick np->e_parent = np; 21210314Smckusick addino(ROOTINO, np); 21310314Smckusick return (np); 21410314Smckusick } 21510314Smckusick np->e_name = savename(rindex(name, '/') + 1); 21610314Smckusick np->e_namlen = strlen(np->e_name); 21710314Smckusick np->e_parent = ep; 21810314Smckusick np->e_sibling = ep->e_entries; 21910314Smckusick ep->e_entries = np; 22010314Smckusick if (type & LINK) { 22110314Smckusick ep = lookupino(inum); 22210314Smckusick if (ep == NIL) 22310314Smckusick panic("link to non-existant name\n"); 22411741Smckusick np->e_ino = inum; 22510314Smckusick np->e_links = ep->e_links; 22610314Smckusick ep->e_links = np; 22710314Smckusick } else if (inum != 0) { 22810314Smckusick if (lookupino(inum) != NIL) 22910314Smckusick panic("duplicate entry\n"); 23010314Smckusick addino(inum, np); 23110314Smckusick } 23210314Smckusick return (np); 23310314Smckusick } 23410314Smckusick 23510314Smckusick /* 23610314Smckusick * delete an entry from the symbol table 23710314Smckusick */ 23810314Smckusick freeentry(ep) 23910314Smckusick register struct entry *ep; 24010314Smckusick { 24110314Smckusick register struct entry *np; 24212456Smckusick ino_t inum; 24310314Smckusick 24410314Smckusick if (ep->e_flags != REMOVED) 24510314Smckusick badentry(ep, "not marked REMOVED"); 24611440Smckusick if (ep->e_type == NODE) { 24711440Smckusick if (ep->e_links != NIL) 24810314Smckusick badentry(ep, "freeing referenced directory"); 24910314Smckusick if (ep->e_entries != NIL) 25010314Smckusick badentry(ep, "freeing non-empty directory"); 25110314Smckusick } 25211440Smckusick if (ep->e_ino != 0) { 25311440Smckusick np = lookupino(ep->e_ino); 25411440Smckusick if (np == NIL) 25511440Smckusick badentry(ep, "lookupino failed"); 25611440Smckusick if (np == ep) { 25712456Smckusick inum = ep->e_ino; 25812456Smckusick deleteino(inum); 25911440Smckusick if (ep->e_links != NIL) 26012456Smckusick addino(inum, ep->e_links); 26111440Smckusick } else { 26211440Smckusick for (; np != NIL; np = np->e_links) { 26311440Smckusick if (np->e_links == ep) { 26411440Smckusick np->e_links = ep->e_links; 26511440Smckusick break; 26611440Smckusick } 26710314Smckusick } 26811440Smckusick if (np == NIL) 26911440Smckusick badentry(ep, "link not found"); 27010314Smckusick } 27110314Smckusick } 27210314Smckusick removeentry(ep); 27311646Smckusick freename(ep->e_name); 27411440Smckusick ep->e_next = freelist; 27510314Smckusick freelist = ep; 27610314Smckusick } 27710314Smckusick 27810314Smckusick /* 27910314Smckusick * Relocate an entry in the tree structure 28010314Smckusick */ 28110314Smckusick moveentry(ep, newname) 28210314Smckusick register struct entry *ep; 28310314Smckusick char *newname; 28410314Smckusick { 28510314Smckusick struct entry *np; 28610314Smckusick char *cp; 28710314Smckusick 28810314Smckusick np = lookupparent(newname); 28910314Smckusick if (np == NIL) 29010314Smckusick badentry(ep, "cannot move ROOT"); 29110314Smckusick if (np != ep->e_parent) { 29210314Smckusick removeentry(ep); 29310314Smckusick ep->e_parent = np; 29410314Smckusick ep->e_sibling = np->e_entries; 29510314Smckusick np->e_entries = ep; 29610314Smckusick } 29710314Smckusick cp = rindex(newname, '/') + 1; 29811646Smckusick freename(ep->e_name); 29911646Smckusick ep->e_name = savename(cp); 30011646Smckusick ep->e_namlen = strlen(cp); 30111646Smckusick if (strcmp(gentempname(ep), ep->e_name) == 0) 30210314Smckusick ep->e_flags |= TMPNAME; 30310314Smckusick else 30410314Smckusick ep->e_flags &= ~TMPNAME; 30510314Smckusick } 30610314Smckusick 30710314Smckusick /* 30810314Smckusick * Remove an entry in the tree structure 30910314Smckusick */ 31010314Smckusick removeentry(ep) 31110314Smckusick register struct entry *ep; 31210314Smckusick { 31310314Smckusick register struct entry *np; 31410314Smckusick 31510314Smckusick np = ep->e_parent; 31610314Smckusick if (np->e_entries == ep) { 31710314Smckusick np->e_entries = ep->e_sibling; 31810314Smckusick } else { 31910314Smckusick for (np = np->e_entries; np != NIL; np = np->e_sibling) { 32010314Smckusick if (np->e_sibling == ep) { 32110314Smckusick np->e_sibling = ep->e_sibling; 32210314Smckusick break; 32310314Smckusick } 32410314Smckusick } 32510314Smckusick if (np == NIL) 32610314Smckusick badentry(ep, "cannot find entry in parent list"); 32710314Smckusick } 32810314Smckusick } 32910314Smckusick 33010314Smckusick /* 33111646Smckusick * Table of unused string entries, sorted by length. 33211646Smckusick * 33311646Smckusick * Entries are allocated in STRTBLINCR sized pieces so that names 33411646Smckusick * of similar lengths can use the same entry. The value of STRTBLINCR 33511646Smckusick * is chosen so that every entry has at least enough space to hold 33611646Smckusick * a "struct strtbl" header. Thus every entry can be linked onto an 33711646Smckusick * apprpriate free list. 33811646Smckusick * 33911646Smckusick * NB. The macro "allocsize" below assumes that "struct strhdr" 34011646Smckusick * has a size that is a power of two. 34110314Smckusick */ 34211646Smckusick struct strhdr { 34311646Smckusick struct strhdr *next; 34411646Smckusick }; 34511646Smckusick 34611646Smckusick #define STRTBLINCR (sizeof(struct strhdr)) 34711646Smckusick #define allocsize(size) (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1)) 34811646Smckusick 34911646Smckusick static struct strhdr strtblhdr[allocsize(MAXNAMLEN) / STRTBLINCR]; 35011646Smckusick 35111646Smckusick /* 35211646Smckusick * Allocate space for a name. It first looks to see if it already 35311646Smckusick * has an appropriate sized entry, and if not allocates a new one. 35411646Smckusick */ 35510314Smckusick char * 35610314Smckusick savename(name) 35710314Smckusick char *name; 35810314Smckusick { 35911646Smckusick struct strhdr *np; 36010314Smckusick long len; 36111311Smckusick char *cp; 36210314Smckusick 36310314Smckusick if (name == NULL) 36410314Smckusick panic("bad name\n"); 36511646Smckusick len = strlen(name); 36611646Smckusick np = strtblhdr[len / STRTBLINCR].next; 36711646Smckusick if (np != NULL) { 36811646Smckusick strtblhdr[len / STRTBLINCR].next = np->next; 36911646Smckusick cp = (char *)np; 37011646Smckusick } else { 37111646Smckusick cp = malloc((unsigned)allocsize(len)); 37211646Smckusick if (cp == NULL) 37311646Smckusick panic("no space for string table\n"); 37411646Smckusick } 37511440Smckusick (void) strcpy(cp, name); 37611311Smckusick return (cp); 37710314Smckusick } 37810314Smckusick 37910314Smckusick /* 38011646Smckusick * Free space for a name. The resulting entry is linked onto the 38111646Smckusick * appropriate free list. 38211646Smckusick */ 38311646Smckusick freename(name) 38411646Smckusick char *name; 38511646Smckusick { 38611646Smckusick struct strhdr *tp, *np; 38711646Smckusick 38811646Smckusick tp = &strtblhdr[strlen(name) / STRTBLINCR]; 38911646Smckusick np = (struct strhdr *)name; 39011646Smckusick np->next = tp->next; 39111646Smckusick tp->next = np; 39211646Smckusick } 39311646Smckusick 39411646Smckusick /* 39511646Smckusick * Useful quantities placed at the end of a dumped symbol table. 39611646Smckusick */ 39711646Smckusick struct symtableheader { 39811646Smckusick long volno; 39911646Smckusick long stringsize; 40011646Smckusick long entrytblsize; 40111646Smckusick time_t dumptime; 40211646Smckusick time_t dumpdate; 40311646Smckusick ino_t maxino; 40418497Smckusick long ntrec; 40511646Smckusick }; 40611646Smckusick 40711646Smckusick /* 40810314Smckusick * dump a snapshot of the symbol table 40910314Smckusick */ 41010314Smckusick dumpsymtable(filename, checkpt) 41110314Smckusick char *filename; 41210314Smckusick long checkpt; 41310314Smckusick { 41411440Smckusick register struct entry *ep, *tep; 41511440Smckusick register ino_t i; 41611440Smckusick struct entry temp, *tentry; 41711440Smckusick long mynum = 1, stroff = 0; 41810314Smckusick FILE *fd; 41910314Smckusick struct symtableheader hdr; 42010314Smckusick 42110314Smckusick vprintf(stdout, "Check pointing the restore\n"); 42234268Smckusick if (Nflag) 42334268Smckusick return; 42410314Smckusick if ((fd = fopen(filename, "w")) == NULL) { 42510314Smckusick perror("fopen"); 42610314Smckusick panic("cannot create save file %s for symbol table\n", 42710314Smckusick filename); 42810314Smckusick } 42910314Smckusick clearerr(fd); 43010314Smckusick /* 43110314Smckusick * Assign indicies to each entry 43210314Smckusick * Write out the string entries 43310314Smckusick */ 43410314Smckusick for (i = ROOTINO; i < maxino; i++) { 43510314Smckusick for (ep = lookupino(i); ep != NIL; ep = ep->e_links) { 43611440Smckusick ep->e_index = mynum++; 43711734Smckusick (void) fwrite(ep->e_name, sizeof(char), 43811734Smckusick (int)allocsize(ep->e_namlen), fd); 43910314Smckusick } 44010314Smckusick } 44110314Smckusick /* 44210314Smckusick * Convert pointers to indexes, and output 44310314Smckusick */ 44411440Smckusick tep = &temp; 44511440Smckusick stroff = 0; 44610314Smckusick for (i = ROOTINO; i < maxino; i++) { 44711440Smckusick for (ep = lookupino(i); ep != NIL; ep = ep->e_links) { 44811734Smckusick bcopy((char *)ep, (char *)tep, 44911734Smckusick (long)sizeof(struct entry)); 45011440Smckusick tep->e_name = (char *)stroff; 45111646Smckusick stroff += allocsize(ep->e_namlen); 45211440Smckusick tep->e_parent = (struct entry *)ep->e_parent->e_index; 45311440Smckusick if (ep->e_links != NIL) 45411440Smckusick tep->e_links = 45511440Smckusick (struct entry *)ep->e_links->e_index; 45611440Smckusick if (ep->e_sibling != NIL) 45711440Smckusick tep->e_sibling = 45811440Smckusick (struct entry *)ep->e_sibling->e_index; 45911440Smckusick if (ep->e_entries != NIL) 46011440Smckusick tep->e_entries = 46111440Smckusick (struct entry *)ep->e_entries->e_index; 46211440Smckusick if (ep->e_next != NIL) 46311440Smckusick tep->e_next = 46411440Smckusick (struct entry *)ep->e_next->e_index; 46511734Smckusick (void) fwrite((char *)tep, sizeof(struct entry), 1, fd); 46610314Smckusick } 46710314Smckusick } 46811440Smckusick /* 46911440Smckusick * Convert entry pointers to indexes, and output 47011440Smckusick */ 47111440Smckusick for (i = 0; i < entrytblsize; i++) { 47211440Smckusick if (entry[i] == NIL) 47311440Smckusick tentry = NIL; 47411440Smckusick else 47511440Smckusick tentry = (struct entry *)entry[i]->e_index; 47611734Smckusick (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd); 47711440Smckusick } 47810314Smckusick hdr.volno = checkpt; 47910314Smckusick hdr.maxino = maxino; 48011440Smckusick hdr.entrytblsize = entrytblsize; 48111646Smckusick hdr.stringsize = stroff; 48211303Smckusick hdr.dumptime = dumptime; 48311303Smckusick hdr.dumpdate = dumpdate; 48418497Smckusick hdr.ntrec = ntrec; 48511734Smckusick (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd); 48610314Smckusick if (ferror(fd)) { 48710314Smckusick perror("fwrite"); 48810314Smckusick panic("output error to file %s writing symbol table\n", 48910314Smckusick filename); 49010314Smckusick } 49111734Smckusick (void) fclose(fd); 49210314Smckusick } 49310314Smckusick 49410314Smckusick /* 49510314Smckusick * Initialize a symbol table from a file 49610314Smckusick */ 49710314Smckusick initsymtable(filename) 49810314Smckusick char *filename; 49910314Smckusick { 50010314Smckusick char *base; 50110314Smckusick long tblsize; 50210314Smckusick register struct entry *ep; 50310314Smckusick struct entry *baseep, *lep; 50410314Smckusick struct symtableheader hdr; 50510314Smckusick struct stat stbuf; 50610314Smckusick register long i; 50710314Smckusick int fd; 50810314Smckusick 50910314Smckusick vprintf(stdout, "Initialize symbol table.\n"); 51011440Smckusick if (filename == NULL) { 51111440Smckusick entrytblsize = maxino / HASHFACTOR; 51211440Smckusick entry = (struct entry **) 51311440Smckusick calloc((unsigned)entrytblsize, sizeof(struct entry *)); 51411440Smckusick if (entry == (struct entry **)NIL) 51511440Smckusick panic("no memory for entry table\n"); 51612221Smckusick ep = addentry(".", ROOTINO, NODE); 51712221Smckusick ep->e_flags |= NEW; 51811440Smckusick return; 51911440Smckusick } 52010314Smckusick if ((fd = open(filename, 0)) < 0) { 52110314Smckusick perror("open"); 52210314Smckusick panic("cannot open symbol table file %s\n", filename); 52310314Smckusick } 52410314Smckusick if (fstat(fd, &stbuf) < 0) { 52510314Smckusick perror("stat"); 52610314Smckusick panic("cannot stat symbol table file %s\n", filename); 52710314Smckusick } 52810314Smckusick tblsize = stbuf.st_size - sizeof(struct symtableheader); 52912439Smckusick base = calloc(sizeof(char), (unsigned)tblsize); 53010314Smckusick if (base == NULL) 53110314Smckusick panic("cannot allocate space for symbol table\n"); 53210314Smckusick if (read(fd, base, (int)tblsize) < 0 || 53310314Smckusick read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) { 53410314Smckusick perror("read"); 53510314Smckusick panic("cannot read symbol table file %s\n", filename); 53610314Smckusick } 53711303Smckusick switch (command) { 53811303Smckusick case 'r': 53911303Smckusick /* 54011303Smckusick * For normal continuation, insure that we are using 54111303Smckusick * the next incremental tape 54211303Smckusick */ 54311440Smckusick if (hdr.dumpdate != dumptime) { 54411440Smckusick if (hdr.dumpdate < dumptime) 54511303Smckusick fprintf(stderr, "Incremental tape too low\n"); 54611303Smckusick else 54711303Smckusick fprintf(stderr, "Incremental tape too high\n"); 54811303Smckusick done(1); 54911303Smckusick } 55011303Smckusick break; 55111303Smckusick case 'R': 55211303Smckusick /* 55311303Smckusick * For restart, insure that we are using the same tape 55411303Smckusick */ 55511324Smckusick curfile.action = SKIP; 55611324Smckusick dumptime = hdr.dumptime; 55711324Smckusick dumpdate = hdr.dumpdate; 55818497Smckusick if (!bflag) 55918497Smckusick newtapebuf(hdr.ntrec); 56011324Smckusick getvol(hdr.volno); 56111303Smckusick break; 56211303Smckusick default: 56311303Smckusick panic("initsymtable called from command %c\n", command); 56411303Smckusick break; 56511303Smckusick } 56610314Smckusick maxino = hdr.maxino; 56711440Smckusick entrytblsize = hdr.entrytblsize; 56811440Smckusick entry = (struct entry **) 56911440Smckusick (base + tblsize - (entrytblsize * sizeof(struct entry *))); 57011440Smckusick baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry)); 57111440Smckusick lep = (struct entry *)entry; 57211440Smckusick for (i = 0; i < entrytblsize; i++) { 57310314Smckusick if (entry[i] == NIL) 57410314Smckusick continue; 57510314Smckusick entry[i] = &baseep[(long)entry[i]]; 57610314Smckusick } 57711440Smckusick for (ep = &baseep[1]; ep < lep; ep++) { 57810314Smckusick ep->e_name = base + (long)ep->e_name; 57910314Smckusick ep->e_parent = &baseep[(long)ep->e_parent]; 58011440Smckusick if (ep->e_sibling != NIL) 58111440Smckusick ep->e_sibling = &baseep[(long)ep->e_sibling]; 58211440Smckusick if (ep->e_links != NIL) 58311440Smckusick ep->e_links = &baseep[(long)ep->e_links]; 58411440Smckusick if (ep->e_entries != NIL) 58511440Smckusick ep->e_entries = &baseep[(long)ep->e_entries]; 58611440Smckusick if (ep->e_next != NIL) 58711440Smckusick ep->e_next = &baseep[(long)ep->e_next]; 58810314Smckusick } 58910314Smckusick } 590