121169Sdist /* 236105Sbostic * Copyright (c) 1983 The Regents of the University of California. 336105Sbostic * All rights reserved. 436105Sbostic * 542709Sbostic * %sccs.include.redist.c% 621169Sdist */ 721169Sdist 810314Smckusick #ifndef lint 9*50658Smckusick static char sccsid[] = "@(#)symtab.c 5.6 (Berkeley) 07/29/91"; 1036105Sbostic #endif /* not lint */ 1110314Smckusick 1211646Smckusick /* 1311646Smckusick * These routines maintain the symbol table which tracks the state 1411646Smckusick * of the file system being restored. They provide lookup by either 1511646Smckusick * name or inode number. They also provide for creation, deletion, 1611646Smckusick * and renaming of entries. Because of the dynamic nature of pathnames, 1711646Smckusick * names should not be saved, but always constructed just before they 1811646Smckusick * are needed, by calling "myname". 1911646Smckusick */ 2011646Smckusick 2110314Smckusick #include "restore.h" 2210314Smckusick #include <sys/stat.h> 2310314Smckusick 2411646Smckusick /* 2511646Smckusick * The following variables define the inode symbol table. 2611646Smckusick * The primary hash table is dynamically allocated based on 2711646Smckusick * the number of inodes in the file system (maxino), scaled by 2811646Smckusick * HASHFACTOR. The variable "entry" points to the hash table; 2911646Smckusick * the variable "entrytblsize" indicates its size (in entries). 3011646Smckusick */ 3111646Smckusick #define HASHFACTOR 5 3211440Smckusick static struct entry **entry; 3311440Smckusick static long entrytblsize; 3410314Smckusick 3510314Smckusick /* 3610314Smckusick * Look up an entry by inode number 3710314Smckusick */ 3810314Smckusick struct entry * 3910314Smckusick lookupino(inum) 4010314Smckusick ino_t inum; 4110314Smckusick { 4211440Smckusick register struct entry *ep; 4310314Smckusick 4411440Smckusick if (inum < ROOTINO || inum >= maxino) 4511440Smckusick return (NIL); 4611440Smckusick for (ep = entry[inum % entrytblsize]; ep != NIL; ep = ep->e_next) 4711440Smckusick if (ep->e_ino == inum) 4811440Smckusick return (ep); 4911440Smckusick return (NIL); 5010314Smckusick } 5110314Smckusick 5210314Smckusick /* 5310314Smckusick * Add an entry into the entry table 5410314Smckusick */ 5510314Smckusick addino(inum, np) 5611440Smckusick ino_t inum; 5710314Smckusick struct entry *np; 5810314Smckusick { 5911440Smckusick struct entry **epp; 6010314Smckusick 6111440Smckusick if (inum < ROOTINO || inum >= maxino) 6211440Smckusick panic("addino: out of range %d\n", inum); 6311440Smckusick epp = &entry[inum % entrytblsize]; 6411440Smckusick np->e_ino = inum; 6511440Smckusick np->e_next = *epp; 6611440Smckusick *epp = np; 6711440Smckusick if (dflag) 6811440Smckusick for (np = np->e_next; np != NIL; np = np->e_next) 6911440Smckusick if (np->e_ino == inum) 7011440Smckusick badentry(np, "duplicate inum"); 7110314Smckusick } 7210314Smckusick 7310314Smckusick /* 7410314Smckusick * Delete an entry from the entry table 7510314Smckusick */ 7610314Smckusick deleteino(inum) 7711440Smckusick ino_t inum; 7810314Smckusick { 7911440Smckusick register struct entry *next; 8011440Smckusick struct entry **prev; 8110314Smckusick 8211440Smckusick if (inum < ROOTINO || inum >= maxino) 8311440Smckusick panic("deleteino: out of range %d\n", inum); 8411440Smckusick prev = &entry[inum % entrytblsize]; 8511440Smckusick for (next = *prev; next != NIL; next = next->e_next) { 8611440Smckusick if (next->e_ino == inum) { 8711440Smckusick next->e_ino = 0; 8811440Smckusick *prev = next->e_next; 8911440Smckusick return; 9011440Smckusick } 9111440Smckusick prev = &next->e_next; 9211440Smckusick } 9311440Smckusick panic("deleteino: %d not found\n", inum); 9410314Smckusick } 9510314Smckusick 9610314Smckusick /* 9710314Smckusick * Look up an entry by name 9810314Smckusick */ 9910314Smckusick struct entry * 10010314Smckusick lookupname(name) 10110314Smckusick char *name; 10210314Smckusick { 10310314Smckusick register struct entry *ep; 10410314Smckusick register char *np, *cp; 10511646Smckusick char buf[MAXPATHLEN]; 10610314Smckusick 10710314Smckusick cp = name; 10810314Smckusick for (ep = lookupino(ROOTINO); ep != NIL; ep = ep->e_entries) { 10910314Smckusick for (np = buf; *cp != '/' && *cp != '\0'; ) 11010314Smckusick *np++ = *cp++; 11110314Smckusick *np = '\0'; 11210314Smckusick for ( ; ep != NIL; ep = ep->e_sibling) 11310314Smckusick if (strcmp(ep->e_name, buf) == 0) 11410314Smckusick break; 11510314Smckusick if (ep == NIL) 11610314Smckusick break; 11711311Smckusick if (*cp++ == '\0') 11810314Smckusick return (ep); 11910314Smckusick } 12011311Smckusick return (NIL); 12110314Smckusick } 12210314Smckusick 12310314Smckusick /* 12410314Smckusick * Look up the parent of a pathname 12510314Smckusick */ 12610314Smckusick struct entry * 12710314Smckusick lookupparent(name) 12810314Smckusick char *name; 12910314Smckusick { 13010314Smckusick struct entry *ep; 13110314Smckusick char *tailindex; 13210314Smckusick 13310314Smckusick tailindex = rindex(name, '/'); 13410314Smckusick if (tailindex == 0) 13510314Smckusick return (NIL); 13610314Smckusick *tailindex = '\0'; 13710314Smckusick ep = lookupname(name); 13811311Smckusick *tailindex = '/'; 13910314Smckusick if (ep == NIL) 14010314Smckusick return (NIL); 14110314Smckusick if (ep->e_type != NODE) 14210314Smckusick panic("%s is not a directory\n", name); 14310314Smckusick return (ep); 14410314Smckusick } 14510314Smckusick 14610314Smckusick /* 14710314Smckusick * Determine the current pathname of a node or leaf 14810314Smckusick */ 14910314Smckusick char * 15010314Smckusick myname(ep) 15110314Smckusick register struct entry *ep; 15210314Smckusick { 15310314Smckusick register char *cp; 15411646Smckusick static char namebuf[MAXPATHLEN]; 15510314Smckusick 15611646Smckusick for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) { 15710314Smckusick cp -= ep->e_namlen; 15810314Smckusick bcopy(ep->e_name, cp, (long)ep->e_namlen); 15910314Smckusick if (ep == lookupino(ROOTINO)) 16010314Smckusick return (cp); 16110314Smckusick *(--cp) = '/'; 16210314Smckusick ep = ep->e_parent; 16310314Smckusick } 16410314Smckusick panic("%s: pathname too long\n", cp); 16510314Smckusick return(cp); 16610314Smckusick } 16710314Smckusick 16810314Smckusick /* 16911646Smckusick * Unused symbol table entries are linked together on a freelist 17011646Smckusick * headed by the following pointer. 17111646Smckusick */ 17211646Smckusick static struct entry *freelist = NIL; 17311646Smckusick 17411646Smckusick /* 17510314Smckusick * add an entry to the symbol table 17610314Smckusick */ 17710314Smckusick struct entry * 17810314Smckusick addentry(name, inum, type) 17910314Smckusick char *name; 18010314Smckusick ino_t inum; 18110314Smckusick int type; 18210314Smckusick { 18310314Smckusick register struct entry *np, *ep; 18410314Smckusick 18510314Smckusick if (freelist != NIL) { 18610314Smckusick np = freelist; 18711440Smckusick freelist = np->e_next; 18810314Smckusick bzero((char *)np, (long)sizeof(struct entry)); 18910314Smckusick } else { 19010314Smckusick np = (struct entry *)calloc(1, sizeof(struct entry)); 19113860Smckusick if (np == NIL) 19213860Smckusick panic("no memory to extend symbol table\n"); 19310314Smckusick } 19410314Smckusick np->e_type = type & ~LINK; 19510314Smckusick ep = lookupparent(name); 19610314Smckusick if (ep == NIL) { 19710314Smckusick if (inum != ROOTINO || lookupino(ROOTINO) != NIL) 19810314Smckusick panic("bad name to addentry %s\n", name); 19910314Smckusick np->e_name = savename(name); 20010314Smckusick np->e_namlen = strlen(name); 20110314Smckusick np->e_parent = np; 20210314Smckusick addino(ROOTINO, np); 20310314Smckusick return (np); 20410314Smckusick } 20510314Smckusick np->e_name = savename(rindex(name, '/') + 1); 20610314Smckusick np->e_namlen = strlen(np->e_name); 20710314Smckusick np->e_parent = ep; 20810314Smckusick np->e_sibling = ep->e_entries; 20910314Smckusick ep->e_entries = np; 21010314Smckusick if (type & LINK) { 21110314Smckusick ep = lookupino(inum); 21210314Smckusick if (ep == NIL) 21310314Smckusick panic("link to non-existant name\n"); 21411741Smckusick np->e_ino = inum; 21510314Smckusick np->e_links = ep->e_links; 21610314Smckusick ep->e_links = np; 21710314Smckusick } else if (inum != 0) { 21810314Smckusick if (lookupino(inum) != NIL) 21910314Smckusick panic("duplicate entry\n"); 22010314Smckusick addino(inum, np); 22110314Smckusick } 22210314Smckusick return (np); 22310314Smckusick } 22410314Smckusick 22510314Smckusick /* 22610314Smckusick * delete an entry from the symbol table 22710314Smckusick */ 22810314Smckusick freeentry(ep) 22910314Smckusick register struct entry *ep; 23010314Smckusick { 23110314Smckusick register struct entry *np; 23212456Smckusick ino_t inum; 23310314Smckusick 23410314Smckusick if (ep->e_flags != REMOVED) 23510314Smckusick badentry(ep, "not marked REMOVED"); 23611440Smckusick if (ep->e_type == NODE) { 23711440Smckusick if (ep->e_links != NIL) 23810314Smckusick badentry(ep, "freeing referenced directory"); 23910314Smckusick if (ep->e_entries != NIL) 24010314Smckusick badentry(ep, "freeing non-empty directory"); 24110314Smckusick } 24211440Smckusick if (ep->e_ino != 0) { 24311440Smckusick np = lookupino(ep->e_ino); 24411440Smckusick if (np == NIL) 24511440Smckusick badentry(ep, "lookupino failed"); 24611440Smckusick if (np == ep) { 24712456Smckusick inum = ep->e_ino; 24812456Smckusick deleteino(inum); 24911440Smckusick if (ep->e_links != NIL) 25012456Smckusick addino(inum, ep->e_links); 25111440Smckusick } else { 25211440Smckusick for (; np != NIL; np = np->e_links) { 25311440Smckusick if (np->e_links == ep) { 25411440Smckusick np->e_links = ep->e_links; 25511440Smckusick break; 25611440Smckusick } 25710314Smckusick } 25811440Smckusick if (np == NIL) 25911440Smckusick badentry(ep, "link not found"); 26010314Smckusick } 26110314Smckusick } 26210314Smckusick removeentry(ep); 26311646Smckusick freename(ep->e_name); 26411440Smckusick ep->e_next = freelist; 26510314Smckusick freelist = ep; 26610314Smckusick } 26710314Smckusick 26810314Smckusick /* 26910314Smckusick * Relocate an entry in the tree structure 27010314Smckusick */ 27110314Smckusick moveentry(ep, newname) 27210314Smckusick register struct entry *ep; 27310314Smckusick char *newname; 27410314Smckusick { 27510314Smckusick struct entry *np; 27610314Smckusick char *cp; 27710314Smckusick 27810314Smckusick np = lookupparent(newname); 27910314Smckusick if (np == NIL) 28010314Smckusick badentry(ep, "cannot move ROOT"); 28110314Smckusick if (np != ep->e_parent) { 28210314Smckusick removeentry(ep); 28310314Smckusick ep->e_parent = np; 28410314Smckusick ep->e_sibling = np->e_entries; 28510314Smckusick np->e_entries = ep; 28610314Smckusick } 28710314Smckusick cp = rindex(newname, '/') + 1; 28811646Smckusick freename(ep->e_name); 28911646Smckusick ep->e_name = savename(cp); 29011646Smckusick ep->e_namlen = strlen(cp); 29111646Smckusick if (strcmp(gentempname(ep), ep->e_name) == 0) 29210314Smckusick ep->e_flags |= TMPNAME; 29310314Smckusick else 29410314Smckusick ep->e_flags &= ~TMPNAME; 29510314Smckusick } 29610314Smckusick 29710314Smckusick /* 29810314Smckusick * Remove an entry in the tree structure 29910314Smckusick */ 30010314Smckusick removeentry(ep) 30110314Smckusick register struct entry *ep; 30210314Smckusick { 30310314Smckusick register struct entry *np; 30410314Smckusick 30510314Smckusick np = ep->e_parent; 30610314Smckusick if (np->e_entries == ep) { 30710314Smckusick np->e_entries = ep->e_sibling; 30810314Smckusick } else { 30910314Smckusick for (np = np->e_entries; np != NIL; np = np->e_sibling) { 31010314Smckusick if (np->e_sibling == ep) { 31110314Smckusick np->e_sibling = ep->e_sibling; 31210314Smckusick break; 31310314Smckusick } 31410314Smckusick } 31510314Smckusick if (np == NIL) 31610314Smckusick badentry(ep, "cannot find entry in parent list"); 31710314Smckusick } 31810314Smckusick } 31910314Smckusick 32010314Smckusick /* 32111646Smckusick * Table of unused string entries, sorted by length. 32211646Smckusick * 32311646Smckusick * Entries are allocated in STRTBLINCR sized pieces so that names 32411646Smckusick * of similar lengths can use the same entry. The value of STRTBLINCR 32511646Smckusick * is chosen so that every entry has at least enough space to hold 32611646Smckusick * a "struct strtbl" header. Thus every entry can be linked onto an 32711646Smckusick * apprpriate free list. 32811646Smckusick * 32911646Smckusick * NB. The macro "allocsize" below assumes that "struct strhdr" 33011646Smckusick * has a size that is a power of two. 33110314Smckusick */ 33211646Smckusick struct strhdr { 33311646Smckusick struct strhdr *next; 33411646Smckusick }; 33511646Smckusick 33611646Smckusick #define STRTBLINCR (sizeof(struct strhdr)) 33711646Smckusick #define allocsize(size) (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1)) 33811646Smckusick 339*50658Smckusick static struct strhdr strtblhdr[allocsize(NAME_MAX) / STRTBLINCR]; 34011646Smckusick 34111646Smckusick /* 34211646Smckusick * Allocate space for a name. It first looks to see if it already 34311646Smckusick * has an appropriate sized entry, and if not allocates a new one. 34411646Smckusick */ 34510314Smckusick char * 34610314Smckusick savename(name) 34710314Smckusick char *name; 34810314Smckusick { 34911646Smckusick struct strhdr *np; 35010314Smckusick long len; 35111311Smckusick char *cp; 35210314Smckusick 35310314Smckusick if (name == NULL) 35410314Smckusick panic("bad name\n"); 35511646Smckusick len = strlen(name); 35611646Smckusick np = strtblhdr[len / STRTBLINCR].next; 35711646Smckusick if (np != NULL) { 35811646Smckusick strtblhdr[len / STRTBLINCR].next = np->next; 35911646Smckusick cp = (char *)np; 36011646Smckusick } else { 36111646Smckusick cp = malloc((unsigned)allocsize(len)); 36211646Smckusick if (cp == NULL) 36311646Smckusick panic("no space for string table\n"); 36411646Smckusick } 36511440Smckusick (void) strcpy(cp, name); 36611311Smckusick return (cp); 36710314Smckusick } 36810314Smckusick 36910314Smckusick /* 37011646Smckusick * Free space for a name. The resulting entry is linked onto the 37111646Smckusick * appropriate free list. 37211646Smckusick */ 37311646Smckusick freename(name) 37411646Smckusick char *name; 37511646Smckusick { 37611646Smckusick struct strhdr *tp, *np; 37711646Smckusick 37811646Smckusick tp = &strtblhdr[strlen(name) / STRTBLINCR]; 37911646Smckusick np = (struct strhdr *)name; 38011646Smckusick np->next = tp->next; 38111646Smckusick tp->next = np; 38211646Smckusick } 38311646Smckusick 38411646Smckusick /* 38511646Smckusick * Useful quantities placed at the end of a dumped symbol table. 38611646Smckusick */ 38711646Smckusick struct symtableheader { 38811646Smckusick long volno; 38911646Smckusick long stringsize; 39011646Smckusick long entrytblsize; 39111646Smckusick time_t dumptime; 39211646Smckusick time_t dumpdate; 39311646Smckusick ino_t maxino; 39418497Smckusick long ntrec; 39511646Smckusick }; 39611646Smckusick 39711646Smckusick /* 39810314Smckusick * dump a snapshot of the symbol table 39910314Smckusick */ 40010314Smckusick dumpsymtable(filename, checkpt) 40110314Smckusick char *filename; 40210314Smckusick long checkpt; 40310314Smckusick { 40411440Smckusick register struct entry *ep, *tep; 40511440Smckusick register ino_t i; 40611440Smckusick struct entry temp, *tentry; 40711440Smckusick long mynum = 1, stroff = 0; 40810314Smckusick FILE *fd; 40910314Smckusick struct symtableheader hdr; 41010314Smckusick 41110314Smckusick vprintf(stdout, "Check pointing the restore\n"); 41234268Smckusick if (Nflag) 41334268Smckusick return; 41410314Smckusick if ((fd = fopen(filename, "w")) == NULL) { 41510314Smckusick perror("fopen"); 41610314Smckusick panic("cannot create save file %s for symbol table\n", 41710314Smckusick filename); 41810314Smckusick } 41910314Smckusick clearerr(fd); 42010314Smckusick /* 42110314Smckusick * Assign indicies to each entry 42210314Smckusick * Write out the string entries 42310314Smckusick */ 42410314Smckusick for (i = ROOTINO; i < maxino; i++) { 42510314Smckusick for (ep = lookupino(i); ep != NIL; ep = ep->e_links) { 42611440Smckusick ep->e_index = mynum++; 42711734Smckusick (void) fwrite(ep->e_name, sizeof(char), 42811734Smckusick (int)allocsize(ep->e_namlen), fd); 42910314Smckusick } 43010314Smckusick } 43110314Smckusick /* 43210314Smckusick * Convert pointers to indexes, and output 43310314Smckusick */ 43411440Smckusick tep = &temp; 43511440Smckusick stroff = 0; 43610314Smckusick for (i = ROOTINO; i < maxino; i++) { 43711440Smckusick for (ep = lookupino(i); ep != NIL; ep = ep->e_links) { 43811734Smckusick bcopy((char *)ep, (char *)tep, 43911734Smckusick (long)sizeof(struct entry)); 44011440Smckusick tep->e_name = (char *)stroff; 44111646Smckusick stroff += allocsize(ep->e_namlen); 44211440Smckusick tep->e_parent = (struct entry *)ep->e_parent->e_index; 44311440Smckusick if (ep->e_links != NIL) 44411440Smckusick tep->e_links = 44511440Smckusick (struct entry *)ep->e_links->e_index; 44611440Smckusick if (ep->e_sibling != NIL) 44711440Smckusick tep->e_sibling = 44811440Smckusick (struct entry *)ep->e_sibling->e_index; 44911440Smckusick if (ep->e_entries != NIL) 45011440Smckusick tep->e_entries = 45111440Smckusick (struct entry *)ep->e_entries->e_index; 45211440Smckusick if (ep->e_next != NIL) 45311440Smckusick tep->e_next = 45411440Smckusick (struct entry *)ep->e_next->e_index; 45511734Smckusick (void) fwrite((char *)tep, sizeof(struct entry), 1, fd); 45610314Smckusick } 45710314Smckusick } 45811440Smckusick /* 45911440Smckusick * Convert entry pointers to indexes, and output 46011440Smckusick */ 46111440Smckusick for (i = 0; i < entrytblsize; i++) { 46211440Smckusick if (entry[i] == NIL) 46311440Smckusick tentry = NIL; 46411440Smckusick else 46511440Smckusick tentry = (struct entry *)entry[i]->e_index; 46611734Smckusick (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd); 46711440Smckusick } 46810314Smckusick hdr.volno = checkpt; 46910314Smckusick hdr.maxino = maxino; 47011440Smckusick hdr.entrytblsize = entrytblsize; 47111646Smckusick hdr.stringsize = stroff; 47211303Smckusick hdr.dumptime = dumptime; 47311303Smckusick hdr.dumpdate = dumpdate; 47418497Smckusick hdr.ntrec = ntrec; 47511734Smckusick (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd); 47610314Smckusick if (ferror(fd)) { 47710314Smckusick perror("fwrite"); 47810314Smckusick panic("output error to file %s writing symbol table\n", 47910314Smckusick filename); 48010314Smckusick } 48111734Smckusick (void) fclose(fd); 48210314Smckusick } 48310314Smckusick 48410314Smckusick /* 48510314Smckusick * Initialize a symbol table from a file 48610314Smckusick */ 48710314Smckusick initsymtable(filename) 48810314Smckusick char *filename; 48910314Smckusick { 49010314Smckusick char *base; 49110314Smckusick long tblsize; 49210314Smckusick register struct entry *ep; 49310314Smckusick struct entry *baseep, *lep; 49410314Smckusick struct symtableheader hdr; 49510314Smckusick struct stat stbuf; 49610314Smckusick register long i; 49710314Smckusick int fd; 49810314Smckusick 49910314Smckusick vprintf(stdout, "Initialize symbol table.\n"); 50011440Smckusick if (filename == NULL) { 50111440Smckusick entrytblsize = maxino / HASHFACTOR; 50211440Smckusick entry = (struct entry **) 50311440Smckusick calloc((unsigned)entrytblsize, sizeof(struct entry *)); 50411440Smckusick if (entry == (struct entry **)NIL) 50511440Smckusick panic("no memory for entry table\n"); 50612221Smckusick ep = addentry(".", ROOTINO, NODE); 50712221Smckusick ep->e_flags |= NEW; 50811440Smckusick return; 50911440Smckusick } 51010314Smckusick if ((fd = open(filename, 0)) < 0) { 51110314Smckusick perror("open"); 51210314Smckusick panic("cannot open symbol table file %s\n", filename); 51310314Smckusick } 51410314Smckusick if (fstat(fd, &stbuf) < 0) { 51510314Smckusick perror("stat"); 51610314Smckusick panic("cannot stat symbol table file %s\n", filename); 51710314Smckusick } 51810314Smckusick tblsize = stbuf.st_size - sizeof(struct symtableheader); 51912439Smckusick base = calloc(sizeof(char), (unsigned)tblsize); 52010314Smckusick if (base == NULL) 52110314Smckusick panic("cannot allocate space for symbol table\n"); 52210314Smckusick if (read(fd, base, (int)tblsize) < 0 || 52310314Smckusick read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) { 52410314Smckusick perror("read"); 52510314Smckusick panic("cannot read symbol table file %s\n", filename); 52610314Smckusick } 52711303Smckusick switch (command) { 52811303Smckusick case 'r': 52911303Smckusick /* 53011303Smckusick * For normal continuation, insure that we are using 53111303Smckusick * the next incremental tape 53211303Smckusick */ 53311440Smckusick if (hdr.dumpdate != dumptime) { 53411440Smckusick if (hdr.dumpdate < dumptime) 53511303Smckusick fprintf(stderr, "Incremental tape too low\n"); 53611303Smckusick else 53711303Smckusick fprintf(stderr, "Incremental tape too high\n"); 53811303Smckusick done(1); 53911303Smckusick } 54011303Smckusick break; 54111303Smckusick case 'R': 54211303Smckusick /* 54311303Smckusick * For restart, insure that we are using the same tape 54411303Smckusick */ 54511324Smckusick curfile.action = SKIP; 54611324Smckusick dumptime = hdr.dumptime; 54711324Smckusick dumpdate = hdr.dumpdate; 54818497Smckusick if (!bflag) 54918497Smckusick newtapebuf(hdr.ntrec); 55011324Smckusick getvol(hdr.volno); 55111303Smckusick break; 55211303Smckusick default: 55311303Smckusick panic("initsymtable called from command %c\n", command); 55411303Smckusick break; 55511303Smckusick } 55610314Smckusick maxino = hdr.maxino; 55711440Smckusick entrytblsize = hdr.entrytblsize; 55811440Smckusick entry = (struct entry **) 55911440Smckusick (base + tblsize - (entrytblsize * sizeof(struct entry *))); 56011440Smckusick baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry)); 56111440Smckusick lep = (struct entry *)entry; 56211440Smckusick for (i = 0; i < entrytblsize; i++) { 56310314Smckusick if (entry[i] == NIL) 56410314Smckusick continue; 56510314Smckusick entry[i] = &baseep[(long)entry[i]]; 56610314Smckusick } 56711440Smckusick for (ep = &baseep[1]; ep < lep; ep++) { 56810314Smckusick ep->e_name = base + (long)ep->e_name; 56910314Smckusick ep->e_parent = &baseep[(long)ep->e_parent]; 57011440Smckusick if (ep->e_sibling != NIL) 57111440Smckusick ep->e_sibling = &baseep[(long)ep->e_sibling]; 57211440Smckusick if (ep->e_links != NIL) 57311440Smckusick ep->e_links = &baseep[(long)ep->e_links]; 57411440Smckusick if (ep->e_entries != NIL) 57511440Smckusick ep->e_entries = &baseep[(long)ep->e_entries]; 57611440Smckusick if (ep->e_next != NIL) 57711440Smckusick ep->e_next = &baseep[(long)ep->e_next]; 57810314Smckusick } 57910314Smckusick } 580