121169Sdist /* 221169Sdist * Copyright (c) 1983 Regents of the University of California. 321169Sdist * All rights reserved. The Berkeley software License Agreement 421169Sdist * specifies the terms and conditions for redistribution. 521169Sdist */ 621169Sdist 710314Smckusick #ifndef lint 8*34268Smckusick static char sccsid[] = "@(#)symtab.c 5.2 (Berkeley) 05/13/88"; 921169Sdist #endif not lint 1010314Smckusick 1111646Smckusick /* 1211646Smckusick * These routines maintain the symbol table which tracks the state 1311646Smckusick * of the file system being restored. They provide lookup by either 1411646Smckusick * name or inode number. They also provide for creation, deletion, 1511646Smckusick * and renaming of entries. Because of the dynamic nature of pathnames, 1611646Smckusick * names should not be saved, but always constructed just before they 1711646Smckusick * are needed, by calling "myname". 1811646Smckusick */ 1911646Smckusick 2010314Smckusick #include "restore.h" 2110314Smckusick #include <sys/stat.h> 2210314Smckusick 2311646Smckusick /* 2411646Smckusick * The following variables define the inode symbol table. 2511646Smckusick * The primary hash table is dynamically allocated based on 2611646Smckusick * the number of inodes in the file system (maxino), scaled by 2711646Smckusick * HASHFACTOR. The variable "entry" points to the hash table; 2811646Smckusick * the variable "entrytblsize" indicates its size (in entries). 2911646Smckusick */ 3011646Smckusick #define HASHFACTOR 5 3111440Smckusick static struct entry **entry; 3211440Smckusick static long entrytblsize; 3310314Smckusick 3410314Smckusick /* 3510314Smckusick * Look up an entry by inode number 3610314Smckusick */ 3710314Smckusick struct entry * 3810314Smckusick lookupino(inum) 3910314Smckusick ino_t inum; 4010314Smckusick { 4111440Smckusick register struct entry *ep; 4210314Smckusick 4311440Smckusick if (inum < ROOTINO || inum >= maxino) 4411440Smckusick return (NIL); 4511440Smckusick for (ep = entry[inum % entrytblsize]; ep != NIL; ep = ep->e_next) 4611440Smckusick if (ep->e_ino == inum) 4711440Smckusick return (ep); 4811440Smckusick return (NIL); 4910314Smckusick } 5010314Smckusick 5110314Smckusick /* 5210314Smckusick * Add an entry into the entry table 5310314Smckusick */ 5410314Smckusick addino(inum, np) 5511440Smckusick ino_t inum; 5610314Smckusick struct entry *np; 5710314Smckusick { 5811440Smckusick struct entry **epp; 5910314Smckusick 6011440Smckusick if (inum < ROOTINO || inum >= maxino) 6111440Smckusick panic("addino: out of range %d\n", inum); 6211440Smckusick epp = &entry[inum % entrytblsize]; 6311440Smckusick np->e_ino = inum; 6411440Smckusick np->e_next = *epp; 6511440Smckusick *epp = np; 6611440Smckusick if (dflag) 6711440Smckusick for (np = np->e_next; np != NIL; np = np->e_next) 6811440Smckusick if (np->e_ino == inum) 6911440Smckusick badentry(np, "duplicate inum"); 7010314Smckusick } 7110314Smckusick 7210314Smckusick /* 7310314Smckusick * Delete an entry from the entry table 7410314Smckusick */ 7510314Smckusick deleteino(inum) 7611440Smckusick ino_t inum; 7710314Smckusick { 7811440Smckusick register struct entry *next; 7911440Smckusick struct entry **prev; 8010314Smckusick 8111440Smckusick if (inum < ROOTINO || inum >= maxino) 8211440Smckusick panic("deleteino: out of range %d\n", inum); 8311440Smckusick prev = &entry[inum % entrytblsize]; 8411440Smckusick for (next = *prev; next != NIL; next = next->e_next) { 8511440Smckusick if (next->e_ino == inum) { 8611440Smckusick next->e_ino = 0; 8711440Smckusick *prev = next->e_next; 8811440Smckusick return; 8911440Smckusick } 9011440Smckusick prev = &next->e_next; 9111440Smckusick } 9211440Smckusick panic("deleteino: %d not found\n", inum); 9310314Smckusick } 9410314Smckusick 9510314Smckusick /* 9610314Smckusick * Look up an entry by name 9710314Smckusick */ 9810314Smckusick struct entry * 9910314Smckusick lookupname(name) 10010314Smckusick char *name; 10110314Smckusick { 10210314Smckusick register struct entry *ep; 10310314Smckusick register char *np, *cp; 10411646Smckusick char buf[MAXPATHLEN]; 10510314Smckusick 10610314Smckusick cp = name; 10710314Smckusick for (ep = lookupino(ROOTINO); ep != NIL; ep = ep->e_entries) { 10810314Smckusick for (np = buf; *cp != '/' && *cp != '\0'; ) 10910314Smckusick *np++ = *cp++; 11010314Smckusick *np = '\0'; 11110314Smckusick for ( ; ep != NIL; ep = ep->e_sibling) 11210314Smckusick if (strcmp(ep->e_name, buf) == 0) 11310314Smckusick break; 11410314Smckusick if (ep == NIL) 11510314Smckusick break; 11611311Smckusick if (*cp++ == '\0') 11710314Smckusick return (ep); 11810314Smckusick } 11911311Smckusick return (NIL); 12010314Smckusick } 12110314Smckusick 12210314Smckusick /* 12310314Smckusick * Look up the parent of a pathname 12410314Smckusick */ 12510314Smckusick struct entry * 12610314Smckusick lookupparent(name) 12710314Smckusick char *name; 12810314Smckusick { 12910314Smckusick struct entry *ep; 13010314Smckusick char *tailindex; 13110314Smckusick 13210314Smckusick tailindex = rindex(name, '/'); 13310314Smckusick if (tailindex == 0) 13410314Smckusick return (NIL); 13510314Smckusick *tailindex = '\0'; 13610314Smckusick ep = lookupname(name); 13711311Smckusick *tailindex = '/'; 13810314Smckusick if (ep == NIL) 13910314Smckusick return (NIL); 14010314Smckusick if (ep->e_type != NODE) 14110314Smckusick panic("%s is not a directory\n", name); 14210314Smckusick return (ep); 14310314Smckusick } 14410314Smckusick 14510314Smckusick /* 14610314Smckusick * Determine the current pathname of a node or leaf 14710314Smckusick */ 14810314Smckusick char * 14910314Smckusick myname(ep) 15010314Smckusick register struct entry *ep; 15110314Smckusick { 15210314Smckusick register char *cp; 15311646Smckusick static char namebuf[MAXPATHLEN]; 15410314Smckusick 15511646Smckusick for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) { 15610314Smckusick cp -= ep->e_namlen; 15710314Smckusick bcopy(ep->e_name, cp, (long)ep->e_namlen); 15810314Smckusick if (ep == lookupino(ROOTINO)) 15910314Smckusick return (cp); 16010314Smckusick *(--cp) = '/'; 16110314Smckusick ep = ep->e_parent; 16210314Smckusick } 16310314Smckusick panic("%s: pathname too long\n", cp); 16410314Smckusick return(cp); 16510314Smckusick } 16610314Smckusick 16710314Smckusick /* 16811646Smckusick * Unused symbol table entries are linked together on a freelist 16911646Smckusick * headed by the following pointer. 17011646Smckusick */ 17111646Smckusick static struct entry *freelist = NIL; 17211646Smckusick 17311646Smckusick /* 17410314Smckusick * add an entry to the symbol table 17510314Smckusick */ 17610314Smckusick struct entry * 17710314Smckusick addentry(name, inum, type) 17810314Smckusick char *name; 17910314Smckusick ino_t inum; 18010314Smckusick int type; 18110314Smckusick { 18210314Smckusick register struct entry *np, *ep; 18310314Smckusick 18410314Smckusick if (freelist != NIL) { 18510314Smckusick np = freelist; 18611440Smckusick freelist = np->e_next; 18710314Smckusick bzero((char *)np, (long)sizeof(struct entry)); 18810314Smckusick } else { 18910314Smckusick np = (struct entry *)calloc(1, sizeof(struct entry)); 19013860Smckusick if (np == NIL) 19113860Smckusick panic("no memory to extend symbol table\n"); 19210314Smckusick } 19310314Smckusick np->e_type = type & ~LINK; 19410314Smckusick ep = lookupparent(name); 19510314Smckusick if (ep == NIL) { 19610314Smckusick if (inum != ROOTINO || lookupino(ROOTINO) != NIL) 19710314Smckusick panic("bad name to addentry %s\n", name); 19810314Smckusick np->e_name = savename(name); 19910314Smckusick np->e_namlen = strlen(name); 20010314Smckusick np->e_parent = np; 20110314Smckusick addino(ROOTINO, np); 20210314Smckusick return (np); 20310314Smckusick } 20410314Smckusick np->e_name = savename(rindex(name, '/') + 1); 20510314Smckusick np->e_namlen = strlen(np->e_name); 20610314Smckusick np->e_parent = ep; 20710314Smckusick np->e_sibling = ep->e_entries; 20810314Smckusick ep->e_entries = np; 20910314Smckusick if (type & LINK) { 21010314Smckusick ep = lookupino(inum); 21110314Smckusick if (ep == NIL) 21210314Smckusick panic("link to non-existant name\n"); 21311741Smckusick np->e_ino = inum; 21410314Smckusick np->e_links = ep->e_links; 21510314Smckusick ep->e_links = np; 21610314Smckusick } else if (inum != 0) { 21710314Smckusick if (lookupino(inum) != NIL) 21810314Smckusick panic("duplicate entry\n"); 21910314Smckusick addino(inum, np); 22010314Smckusick } 22110314Smckusick return (np); 22210314Smckusick } 22310314Smckusick 22410314Smckusick /* 22510314Smckusick * delete an entry from the symbol table 22610314Smckusick */ 22710314Smckusick freeentry(ep) 22810314Smckusick register struct entry *ep; 22910314Smckusick { 23010314Smckusick register struct entry *np; 23112456Smckusick ino_t inum; 23210314Smckusick 23310314Smckusick if (ep->e_flags != REMOVED) 23410314Smckusick badentry(ep, "not marked REMOVED"); 23511440Smckusick if (ep->e_type == NODE) { 23611440Smckusick if (ep->e_links != NIL) 23710314Smckusick badentry(ep, "freeing referenced directory"); 23810314Smckusick if (ep->e_entries != NIL) 23910314Smckusick badentry(ep, "freeing non-empty directory"); 24010314Smckusick } 24111440Smckusick if (ep->e_ino != 0) { 24211440Smckusick np = lookupino(ep->e_ino); 24311440Smckusick if (np == NIL) 24411440Smckusick badentry(ep, "lookupino failed"); 24511440Smckusick if (np == ep) { 24612456Smckusick inum = ep->e_ino; 24712456Smckusick deleteino(inum); 24811440Smckusick if (ep->e_links != NIL) 24912456Smckusick addino(inum, ep->e_links); 25011440Smckusick } else { 25111440Smckusick for (; np != NIL; np = np->e_links) { 25211440Smckusick if (np->e_links == ep) { 25311440Smckusick np->e_links = ep->e_links; 25411440Smckusick break; 25511440Smckusick } 25610314Smckusick } 25711440Smckusick if (np == NIL) 25811440Smckusick badentry(ep, "link not found"); 25910314Smckusick } 26010314Smckusick } 26110314Smckusick removeentry(ep); 26211646Smckusick freename(ep->e_name); 26311440Smckusick ep->e_next = freelist; 26410314Smckusick freelist = ep; 26510314Smckusick } 26610314Smckusick 26710314Smckusick /* 26810314Smckusick * Relocate an entry in the tree structure 26910314Smckusick */ 27010314Smckusick moveentry(ep, newname) 27110314Smckusick register struct entry *ep; 27210314Smckusick char *newname; 27310314Smckusick { 27410314Smckusick struct entry *np; 27510314Smckusick char *cp; 27610314Smckusick 27710314Smckusick np = lookupparent(newname); 27810314Smckusick if (np == NIL) 27910314Smckusick badentry(ep, "cannot move ROOT"); 28010314Smckusick if (np != ep->e_parent) { 28110314Smckusick removeentry(ep); 28210314Smckusick ep->e_parent = np; 28310314Smckusick ep->e_sibling = np->e_entries; 28410314Smckusick np->e_entries = ep; 28510314Smckusick } 28610314Smckusick cp = rindex(newname, '/') + 1; 28711646Smckusick freename(ep->e_name); 28811646Smckusick ep->e_name = savename(cp); 28911646Smckusick ep->e_namlen = strlen(cp); 29011646Smckusick if (strcmp(gentempname(ep), ep->e_name) == 0) 29110314Smckusick ep->e_flags |= TMPNAME; 29210314Smckusick else 29310314Smckusick ep->e_flags &= ~TMPNAME; 29410314Smckusick } 29510314Smckusick 29610314Smckusick /* 29710314Smckusick * Remove an entry in the tree structure 29810314Smckusick */ 29910314Smckusick removeentry(ep) 30010314Smckusick register struct entry *ep; 30110314Smckusick { 30210314Smckusick register struct entry *np; 30310314Smckusick 30410314Smckusick np = ep->e_parent; 30510314Smckusick if (np->e_entries == ep) { 30610314Smckusick np->e_entries = ep->e_sibling; 30710314Smckusick } else { 30810314Smckusick for (np = np->e_entries; np != NIL; np = np->e_sibling) { 30910314Smckusick if (np->e_sibling == ep) { 31010314Smckusick np->e_sibling = ep->e_sibling; 31110314Smckusick break; 31210314Smckusick } 31310314Smckusick } 31410314Smckusick if (np == NIL) 31510314Smckusick badentry(ep, "cannot find entry in parent list"); 31610314Smckusick } 31710314Smckusick } 31810314Smckusick 31910314Smckusick /* 32011646Smckusick * Table of unused string entries, sorted by length. 32111646Smckusick * 32211646Smckusick * Entries are allocated in STRTBLINCR sized pieces so that names 32311646Smckusick * of similar lengths can use the same entry. The value of STRTBLINCR 32411646Smckusick * is chosen so that every entry has at least enough space to hold 32511646Smckusick * a "struct strtbl" header. Thus every entry can be linked onto an 32611646Smckusick * apprpriate free list. 32711646Smckusick * 32811646Smckusick * NB. The macro "allocsize" below assumes that "struct strhdr" 32911646Smckusick * has a size that is a power of two. 33010314Smckusick */ 33111646Smckusick struct strhdr { 33211646Smckusick struct strhdr *next; 33311646Smckusick }; 33411646Smckusick 33511646Smckusick #define STRTBLINCR (sizeof(struct strhdr)) 33611646Smckusick #define allocsize(size) (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1)) 33711646Smckusick 33811646Smckusick static struct strhdr strtblhdr[allocsize(MAXNAMLEN) / STRTBLINCR]; 33911646Smckusick 34011646Smckusick /* 34111646Smckusick * Allocate space for a name. It first looks to see if it already 34211646Smckusick * has an appropriate sized entry, and if not allocates a new one. 34311646Smckusick */ 34410314Smckusick char * 34510314Smckusick savename(name) 34610314Smckusick char *name; 34710314Smckusick { 34811646Smckusick struct strhdr *np; 34910314Smckusick long len; 35011311Smckusick char *cp; 35110314Smckusick 35210314Smckusick if (name == NULL) 35310314Smckusick panic("bad name\n"); 35411646Smckusick len = strlen(name); 35511646Smckusick np = strtblhdr[len / STRTBLINCR].next; 35611646Smckusick if (np != NULL) { 35711646Smckusick strtblhdr[len / STRTBLINCR].next = np->next; 35811646Smckusick cp = (char *)np; 35911646Smckusick } else { 36011646Smckusick cp = malloc((unsigned)allocsize(len)); 36111646Smckusick if (cp == NULL) 36211646Smckusick panic("no space for string table\n"); 36311646Smckusick } 36411440Smckusick (void) strcpy(cp, name); 36511311Smckusick return (cp); 36610314Smckusick } 36710314Smckusick 36810314Smckusick /* 36911646Smckusick * Free space for a name. The resulting entry is linked onto the 37011646Smckusick * appropriate free list. 37111646Smckusick */ 37211646Smckusick freename(name) 37311646Smckusick char *name; 37411646Smckusick { 37511646Smckusick struct strhdr *tp, *np; 37611646Smckusick 37711646Smckusick tp = &strtblhdr[strlen(name) / STRTBLINCR]; 37811646Smckusick np = (struct strhdr *)name; 37911646Smckusick np->next = tp->next; 38011646Smckusick tp->next = np; 38111646Smckusick } 38211646Smckusick 38311646Smckusick /* 38411646Smckusick * Useful quantities placed at the end of a dumped symbol table. 38511646Smckusick */ 38611646Smckusick struct symtableheader { 38711646Smckusick long volno; 38811646Smckusick long stringsize; 38911646Smckusick long entrytblsize; 39011646Smckusick time_t dumptime; 39111646Smckusick time_t dumpdate; 39211646Smckusick ino_t maxino; 39318497Smckusick long ntrec; 39411646Smckusick }; 39511646Smckusick 39611646Smckusick /* 39710314Smckusick * dump a snapshot of the symbol table 39810314Smckusick */ 39910314Smckusick dumpsymtable(filename, checkpt) 40010314Smckusick char *filename; 40110314Smckusick long checkpt; 40210314Smckusick { 40311440Smckusick register struct entry *ep, *tep; 40411440Smckusick register ino_t i; 40511440Smckusick struct entry temp, *tentry; 40611440Smckusick long mynum = 1, stroff = 0; 40710314Smckusick FILE *fd; 40810314Smckusick struct symtableheader hdr; 40910314Smckusick 41010314Smckusick vprintf(stdout, "Check pointing the restore\n"); 411*34268Smckusick if (Nflag) 412*34268Smckusick return; 41310314Smckusick if ((fd = fopen(filename, "w")) == NULL) { 41410314Smckusick perror("fopen"); 41510314Smckusick panic("cannot create save file %s for symbol table\n", 41610314Smckusick filename); 41710314Smckusick } 41810314Smckusick clearerr(fd); 41910314Smckusick /* 42010314Smckusick * Assign indicies to each entry 42110314Smckusick * Write out the string entries 42210314Smckusick */ 42310314Smckusick for (i = ROOTINO; i < maxino; i++) { 42410314Smckusick for (ep = lookupino(i); ep != NIL; ep = ep->e_links) { 42511440Smckusick ep->e_index = mynum++; 42611734Smckusick (void) fwrite(ep->e_name, sizeof(char), 42711734Smckusick (int)allocsize(ep->e_namlen), fd); 42810314Smckusick } 42910314Smckusick } 43010314Smckusick /* 43110314Smckusick * Convert pointers to indexes, and output 43210314Smckusick */ 43311440Smckusick tep = &temp; 43411440Smckusick stroff = 0; 43510314Smckusick for (i = ROOTINO; i < maxino; i++) { 43611440Smckusick for (ep = lookupino(i); ep != NIL; ep = ep->e_links) { 43711734Smckusick bcopy((char *)ep, (char *)tep, 43811734Smckusick (long)sizeof(struct entry)); 43911440Smckusick tep->e_name = (char *)stroff; 44011646Smckusick stroff += allocsize(ep->e_namlen); 44111440Smckusick tep->e_parent = (struct entry *)ep->e_parent->e_index; 44211440Smckusick if (ep->e_links != NIL) 44311440Smckusick tep->e_links = 44411440Smckusick (struct entry *)ep->e_links->e_index; 44511440Smckusick if (ep->e_sibling != NIL) 44611440Smckusick tep->e_sibling = 44711440Smckusick (struct entry *)ep->e_sibling->e_index; 44811440Smckusick if (ep->e_entries != NIL) 44911440Smckusick tep->e_entries = 45011440Smckusick (struct entry *)ep->e_entries->e_index; 45111440Smckusick if (ep->e_next != NIL) 45211440Smckusick tep->e_next = 45311440Smckusick (struct entry *)ep->e_next->e_index; 45411734Smckusick (void) fwrite((char *)tep, sizeof(struct entry), 1, fd); 45510314Smckusick } 45610314Smckusick } 45711440Smckusick /* 45811440Smckusick * Convert entry pointers to indexes, and output 45911440Smckusick */ 46011440Smckusick for (i = 0; i < entrytblsize; i++) { 46111440Smckusick if (entry[i] == NIL) 46211440Smckusick tentry = NIL; 46311440Smckusick else 46411440Smckusick tentry = (struct entry *)entry[i]->e_index; 46511734Smckusick (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd); 46611440Smckusick } 46710314Smckusick hdr.volno = checkpt; 46810314Smckusick hdr.maxino = maxino; 46911440Smckusick hdr.entrytblsize = entrytblsize; 47011646Smckusick hdr.stringsize = stroff; 47111303Smckusick hdr.dumptime = dumptime; 47211303Smckusick hdr.dumpdate = dumpdate; 47318497Smckusick hdr.ntrec = ntrec; 47411734Smckusick (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd); 47510314Smckusick if (ferror(fd)) { 47610314Smckusick perror("fwrite"); 47710314Smckusick panic("output error to file %s writing symbol table\n", 47810314Smckusick filename); 47910314Smckusick } 48011734Smckusick (void) fclose(fd); 48110314Smckusick } 48210314Smckusick 48310314Smckusick /* 48410314Smckusick * Initialize a symbol table from a file 48510314Smckusick */ 48610314Smckusick initsymtable(filename) 48710314Smckusick char *filename; 48810314Smckusick { 48910314Smckusick char *base; 49010314Smckusick long tblsize; 49110314Smckusick register struct entry *ep; 49210314Smckusick struct entry *baseep, *lep; 49310314Smckusick struct symtableheader hdr; 49410314Smckusick struct stat stbuf; 49510314Smckusick register long i; 49610314Smckusick int fd; 49710314Smckusick 49810314Smckusick vprintf(stdout, "Initialize symbol table.\n"); 49911440Smckusick if (filename == NULL) { 50011440Smckusick entrytblsize = maxino / HASHFACTOR; 50111440Smckusick entry = (struct entry **) 50211440Smckusick calloc((unsigned)entrytblsize, sizeof(struct entry *)); 50311440Smckusick if (entry == (struct entry **)NIL) 50411440Smckusick panic("no memory for entry table\n"); 50512221Smckusick ep = addentry(".", ROOTINO, NODE); 50612221Smckusick ep->e_flags |= NEW; 50711440Smckusick return; 50811440Smckusick } 50910314Smckusick if ((fd = open(filename, 0)) < 0) { 51010314Smckusick perror("open"); 51110314Smckusick panic("cannot open symbol table file %s\n", filename); 51210314Smckusick } 51310314Smckusick if (fstat(fd, &stbuf) < 0) { 51410314Smckusick perror("stat"); 51510314Smckusick panic("cannot stat symbol table file %s\n", filename); 51610314Smckusick } 51710314Smckusick tblsize = stbuf.st_size - sizeof(struct symtableheader); 51812439Smckusick base = calloc(sizeof(char), (unsigned)tblsize); 51910314Smckusick if (base == NULL) 52010314Smckusick panic("cannot allocate space for symbol table\n"); 52110314Smckusick if (read(fd, base, (int)tblsize) < 0 || 52210314Smckusick read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) { 52310314Smckusick perror("read"); 52410314Smckusick panic("cannot read symbol table file %s\n", filename); 52510314Smckusick } 52611303Smckusick switch (command) { 52711303Smckusick case 'r': 52811303Smckusick /* 52911303Smckusick * For normal continuation, insure that we are using 53011303Smckusick * the next incremental tape 53111303Smckusick */ 53211440Smckusick if (hdr.dumpdate != dumptime) { 53311440Smckusick if (hdr.dumpdate < dumptime) 53411303Smckusick fprintf(stderr, "Incremental tape too low\n"); 53511303Smckusick else 53611303Smckusick fprintf(stderr, "Incremental tape too high\n"); 53711303Smckusick done(1); 53811303Smckusick } 53911303Smckusick break; 54011303Smckusick case 'R': 54111303Smckusick /* 54211303Smckusick * For restart, insure that we are using the same tape 54311303Smckusick */ 54411324Smckusick curfile.action = SKIP; 54511324Smckusick dumptime = hdr.dumptime; 54611324Smckusick dumpdate = hdr.dumpdate; 54718497Smckusick if (!bflag) 54818497Smckusick newtapebuf(hdr.ntrec); 54911324Smckusick getvol(hdr.volno); 55011303Smckusick break; 55111303Smckusick default: 55211303Smckusick panic("initsymtable called from command %c\n", command); 55311303Smckusick break; 55411303Smckusick } 55510314Smckusick maxino = hdr.maxino; 55611440Smckusick entrytblsize = hdr.entrytblsize; 55711440Smckusick entry = (struct entry **) 55811440Smckusick (base + tblsize - (entrytblsize * sizeof(struct entry *))); 55911440Smckusick baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry)); 56011440Smckusick lep = (struct entry *)entry; 56111440Smckusick for (i = 0; i < entrytblsize; i++) { 56210314Smckusick if (entry[i] == NIL) 56310314Smckusick continue; 56410314Smckusick entry[i] = &baseep[(long)entry[i]]; 56510314Smckusick } 56611440Smckusick for (ep = &baseep[1]; ep < lep; ep++) { 56710314Smckusick ep->e_name = base + (long)ep->e_name; 56810314Smckusick ep->e_parent = &baseep[(long)ep->e_parent]; 56911440Smckusick if (ep->e_sibling != NIL) 57011440Smckusick ep->e_sibling = &baseep[(long)ep->e_sibling]; 57111440Smckusick if (ep->e_links != NIL) 57211440Smckusick ep->e_links = &baseep[(long)ep->e_links]; 57311440Smckusick if (ep->e_entries != NIL) 57411440Smckusick ep->e_entries = &baseep[(long)ep->e_entries]; 57511440Smckusick if (ep->e_next != NIL) 57611440Smckusick ep->e_next = &baseep[(long)ep->e_next]; 57710314Smckusick } 57810314Smckusick } 579