121169Sdist /*
261536Sbostic * Copyright (c) 1983, 1993
361536Sbostic * The Regents of the University of California. All rights reserved.
436105Sbostic *
542709Sbostic * %sccs.include.redist.c%
621169Sdist */
721169Sdist
810314Smckusick #ifndef lint
9*69001Sbostic static char sccsid[] = "@(#)symtab.c 8.3 (Berkeley) 04/28/95";
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
2156567Sbostic #include <sys/param.h>
2210314Smckusick #include <sys/stat.h>
2310314Smckusick
2456567Sbostic #include <ufs/ufs/dinode.h>
2556567Sbostic
2656567Sbostic #include <errno.h>
2756567Sbostic #include <fcntl.h>
2856567Sbostic #include <stdio.h>
2956567Sbostic #include <stdlib.h>
3056567Sbostic #include <string.h>
3156567Sbostic #include <unistd.h>
3256567Sbostic
3356567Sbostic #include "restore.h"
3456567Sbostic #include "extern.h"
3556567Sbostic
3611646Smckusick /*
3711646Smckusick * The following variables define the inode symbol table.
3811646Smckusick * The primary hash table is dynamically allocated based on
3911646Smckusick * the number of inodes in the file system (maxino), scaled by
4011646Smckusick * HASHFACTOR. The variable "entry" points to the hash table;
4111646Smckusick * the variable "entrytblsize" indicates its size (in entries).
4211646Smckusick */
4311646Smckusick #define HASHFACTOR 5
4411440Smckusick static struct entry **entry;
4511440Smckusick static long entrytblsize;
4610314Smckusick
4756567Sbostic static void addino __P((ino_t, struct entry *));
4856567Sbostic static struct entry *lookupparent __P((char *));
4956567Sbostic static void removeentry __P((struct entry *));
5056567Sbostic
5110314Smckusick /*
5210314Smckusick * Look up an entry by inode number
5310314Smckusick */
5410314Smckusick struct entry *
lookupino(inum)5510314Smckusick lookupino(inum)
5610314Smckusick ino_t inum;
5710314Smckusick {
5811440Smckusick register struct entry *ep;
5910314Smckusick
6067777Smckusick if (inum < WINO || inum >= maxino)
6156567Sbostic return (NULL);
6256567Sbostic for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next)
6311440Smckusick if (ep->e_ino == inum)
6411440Smckusick return (ep);
6556567Sbostic return (NULL);
6610314Smckusick }
6710314Smckusick
6810314Smckusick /*
6910314Smckusick * Add an entry into the entry table
7010314Smckusick */
7156567Sbostic static void
addino(inum,np)7210314Smckusick addino(inum, np)
7311440Smckusick ino_t inum;
7410314Smckusick struct entry *np;
7510314Smckusick {
7611440Smckusick struct entry **epp;
7710314Smckusick
7867777Smckusick if (inum < WINO || inum >= maxino)
7911440Smckusick panic("addino: out of range %d\n", inum);
8011440Smckusick epp = &entry[inum % entrytblsize];
8111440Smckusick np->e_ino = inum;
8211440Smckusick np->e_next = *epp;
8311440Smckusick *epp = np;
8411440Smckusick if (dflag)
8556567Sbostic for (np = np->e_next; np != NULL; np = np->e_next)
8611440Smckusick if (np->e_ino == inum)
8711440Smckusick badentry(np, "duplicate inum");
8810314Smckusick }
8910314Smckusick
9010314Smckusick /*
9110314Smckusick * Delete an entry from the entry table
9210314Smckusick */
9356567Sbostic void
deleteino(inum)9410314Smckusick deleteino(inum)
9511440Smckusick ino_t inum;
9610314Smckusick {
9711440Smckusick register struct entry *next;
9811440Smckusick struct entry **prev;
9910314Smckusick
10067777Smckusick if (inum < WINO || inum >= maxino)
10111440Smckusick panic("deleteino: out of range %d\n", inum);
10211440Smckusick prev = &entry[inum % entrytblsize];
10356567Sbostic for (next = *prev; next != NULL; next = next->e_next) {
10411440Smckusick if (next->e_ino == inum) {
10511440Smckusick next->e_ino = 0;
10611440Smckusick *prev = next->e_next;
10711440Smckusick return;
10811440Smckusick }
10911440Smckusick prev = &next->e_next;
11011440Smckusick }
11111440Smckusick panic("deleteino: %d not found\n", inum);
11210314Smckusick }
11310314Smckusick
11410314Smckusick /*
11510314Smckusick * Look up an entry by name
11610314Smckusick */
11710314Smckusick struct entry *
lookupname(name)11810314Smckusick lookupname(name)
11910314Smckusick char *name;
12010314Smckusick {
12110314Smckusick register struct entry *ep;
12210314Smckusick register char *np, *cp;
12311646Smckusick char buf[MAXPATHLEN];
12410314Smckusick
12510314Smckusick cp = name;
12656567Sbostic for (ep = lookupino(ROOTINO); ep != NULL; ep = ep->e_entries) {
12710314Smckusick for (np = buf; *cp != '/' && *cp != '\0'; )
12810314Smckusick *np++ = *cp++;
12910314Smckusick *np = '\0';
13056567Sbostic for ( ; ep != NULL; ep = ep->e_sibling)
13110314Smckusick if (strcmp(ep->e_name, buf) == 0)
13210314Smckusick break;
13356567Sbostic if (ep == NULL)
13410314Smckusick break;
13511311Smckusick if (*cp++ == '\0')
13610314Smckusick return (ep);
13710314Smckusick }
13856567Sbostic return (NULL);
13910314Smckusick }
14010314Smckusick
14110314Smckusick /*
14210314Smckusick * Look up the parent of a pathname
14310314Smckusick */
14456567Sbostic static struct entry *
lookupparent(name)14510314Smckusick lookupparent(name)
14610314Smckusick char *name;
14710314Smckusick {
14810314Smckusick struct entry *ep;
14910314Smckusick char *tailindex;
15010314Smckusick
151*69001Sbostic tailindex = strrchr(name, '/');
15257930Sbostic if (tailindex == NULL)
15356567Sbostic return (NULL);
15410314Smckusick *tailindex = '\0';
15510314Smckusick ep = lookupname(name);
15611311Smckusick *tailindex = '/';
15756567Sbostic if (ep == NULL)
15856567Sbostic return (NULL);
15910314Smckusick if (ep->e_type != NODE)
16010314Smckusick panic("%s is not a directory\n", name);
16110314Smckusick return (ep);
16210314Smckusick }
16310314Smckusick
16410314Smckusick /*
16510314Smckusick * Determine the current pathname of a node or leaf
16610314Smckusick */
16710314Smckusick char *
myname(ep)16810314Smckusick myname(ep)
16910314Smckusick register struct entry *ep;
17010314Smckusick {
17110314Smckusick register char *cp;
17211646Smckusick static char namebuf[MAXPATHLEN];
17310314Smckusick
17411646Smckusick for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) {
17510314Smckusick cp -= ep->e_namlen;
176*69001Sbostic memmove(cp, ep->e_name, (long)ep->e_namlen);
17710314Smckusick if (ep == lookupino(ROOTINO))
17810314Smckusick return (cp);
17910314Smckusick *(--cp) = '/';
18010314Smckusick ep = ep->e_parent;
18110314Smckusick }
18210314Smckusick panic("%s: pathname too long\n", cp);
18310314Smckusick return(cp);
18410314Smckusick }
18510314Smckusick
18610314Smckusick /*
18711646Smckusick * Unused symbol table entries are linked together on a freelist
18811646Smckusick * headed by the following pointer.
18911646Smckusick */
19056567Sbostic static struct entry *freelist = NULL;
19111646Smckusick
19211646Smckusick /*
19310314Smckusick * add an entry to the symbol table
19410314Smckusick */
19510314Smckusick struct entry *
addentry(name,inum,type)19610314Smckusick addentry(name, inum, type)
19710314Smckusick char *name;
19810314Smckusick ino_t inum;
19910314Smckusick int type;
20010314Smckusick {
20110314Smckusick register struct entry *np, *ep;
20210314Smckusick
20356567Sbostic if (freelist != NULL) {
20410314Smckusick np = freelist;
20511440Smckusick freelist = np->e_next;
206*69001Sbostic memset(np, 0, (long)sizeof(struct entry));
20710314Smckusick } else {
20810314Smckusick np = (struct entry *)calloc(1, sizeof(struct entry));
20956567Sbostic if (np == NULL)
21013860Smckusick panic("no memory to extend symbol table\n");
21110314Smckusick }
21210314Smckusick np->e_type = type & ~LINK;
21310314Smckusick ep = lookupparent(name);
21456567Sbostic if (ep == NULL) {
21556567Sbostic if (inum != ROOTINO || lookupino(ROOTINO) != NULL)
21610314Smckusick panic("bad name to addentry %s\n", name);
21710314Smckusick np->e_name = savename(name);
21810314Smckusick np->e_namlen = strlen(name);
21910314Smckusick np->e_parent = np;
22010314Smckusick addino(ROOTINO, np);
22110314Smckusick return (np);
22210314Smckusick }
223*69001Sbostic np->e_name = savename(strrchr(name, '/') + 1);
22410314Smckusick np->e_namlen = strlen(np->e_name);
22510314Smckusick np->e_parent = ep;
22610314Smckusick np->e_sibling = ep->e_entries;
22710314Smckusick ep->e_entries = np;
22810314Smckusick if (type & LINK) {
22910314Smckusick ep = lookupino(inum);
23056567Sbostic if (ep == NULL)
23110314Smckusick panic("link to non-existant name\n");
23211741Smckusick np->e_ino = inum;
23310314Smckusick np->e_links = ep->e_links;
23410314Smckusick ep->e_links = np;
23510314Smckusick } else if (inum != 0) {
23656567Sbostic if (lookupino(inum) != NULL)
23710314Smckusick panic("duplicate entry\n");
23810314Smckusick addino(inum, np);
23910314Smckusick }
24010314Smckusick return (np);
24110314Smckusick }
24210314Smckusick
24310314Smckusick /*
24410314Smckusick * delete an entry from the symbol table
24510314Smckusick */
24656567Sbostic void
freeentry(ep)24710314Smckusick freeentry(ep)
24810314Smckusick register struct entry *ep;
24910314Smckusick {
25010314Smckusick register struct entry *np;
25112456Smckusick ino_t inum;
25210314Smckusick
25310314Smckusick if (ep->e_flags != REMOVED)
25410314Smckusick badentry(ep, "not marked REMOVED");
25511440Smckusick if (ep->e_type == NODE) {
25656567Sbostic if (ep->e_links != NULL)
25710314Smckusick badentry(ep, "freeing referenced directory");
25856567Sbostic if (ep->e_entries != NULL)
25910314Smckusick badentry(ep, "freeing non-empty directory");
26010314Smckusick }
26111440Smckusick if (ep->e_ino != 0) {
26211440Smckusick np = lookupino(ep->e_ino);
26356567Sbostic if (np == NULL)
26411440Smckusick badentry(ep, "lookupino failed");
26511440Smckusick if (np == ep) {
26612456Smckusick inum = ep->e_ino;
26712456Smckusick deleteino(inum);
26856567Sbostic if (ep->e_links != NULL)
26912456Smckusick addino(inum, ep->e_links);
27011440Smckusick } else {
27156567Sbostic for (; np != NULL; np = np->e_links) {
27211440Smckusick if (np->e_links == ep) {
27311440Smckusick np->e_links = ep->e_links;
27411440Smckusick break;
27511440Smckusick }
27610314Smckusick }
27756567Sbostic if (np == NULL)
27811440Smckusick badentry(ep, "link not found");
27910314Smckusick }
28010314Smckusick }
28110314Smckusick removeentry(ep);
28211646Smckusick freename(ep->e_name);
28311440Smckusick ep->e_next = freelist;
28410314Smckusick freelist = ep;
28510314Smckusick }
28610314Smckusick
28710314Smckusick /*
28810314Smckusick * Relocate an entry in the tree structure
28910314Smckusick */
29056567Sbostic void
moveentry(ep,newname)29110314Smckusick moveentry(ep, newname)
29210314Smckusick register struct entry *ep;
29310314Smckusick char *newname;
29410314Smckusick {
29510314Smckusick struct entry *np;
29610314Smckusick char *cp;
29710314Smckusick
29810314Smckusick np = lookupparent(newname);
29956567Sbostic if (np == NULL)
30010314Smckusick badentry(ep, "cannot move ROOT");
30110314Smckusick if (np != ep->e_parent) {
30210314Smckusick removeentry(ep);
30310314Smckusick ep->e_parent = np;
30410314Smckusick ep->e_sibling = np->e_entries;
30510314Smckusick np->e_entries = ep;
30610314Smckusick }
307*69001Sbostic cp = strrchr(newname, '/') + 1;
30811646Smckusick freename(ep->e_name);
30911646Smckusick ep->e_name = savename(cp);
31011646Smckusick ep->e_namlen = strlen(cp);
31111646Smckusick if (strcmp(gentempname(ep), ep->e_name) == 0)
31210314Smckusick ep->e_flags |= TMPNAME;
31310314Smckusick else
31410314Smckusick ep->e_flags &= ~TMPNAME;
31510314Smckusick }
31610314Smckusick
31710314Smckusick /*
31810314Smckusick * Remove an entry in the tree structure
31910314Smckusick */
32056567Sbostic static void
removeentry(ep)32110314Smckusick removeentry(ep)
32210314Smckusick register struct entry *ep;
32310314Smckusick {
32410314Smckusick register struct entry *np;
32510314Smckusick
32610314Smckusick np = ep->e_parent;
32710314Smckusick if (np->e_entries == ep) {
32810314Smckusick np->e_entries = ep->e_sibling;
32910314Smckusick } else {
33056567Sbostic for (np = np->e_entries; np != NULL; np = np->e_sibling) {
33110314Smckusick if (np->e_sibling == ep) {
33210314Smckusick np->e_sibling = ep->e_sibling;
33310314Smckusick break;
33410314Smckusick }
33510314Smckusick }
33656567Sbostic if (np == NULL)
33710314Smckusick badentry(ep, "cannot find entry in parent list");
33810314Smckusick }
33910314Smckusick }
34010314Smckusick
34110314Smckusick /*
34211646Smckusick * Table of unused string entries, sorted by length.
34311646Smckusick *
34411646Smckusick * Entries are allocated in STRTBLINCR sized pieces so that names
34511646Smckusick * of similar lengths can use the same entry. The value of STRTBLINCR
34611646Smckusick * is chosen so that every entry has at least enough space to hold
34711646Smckusick * a "struct strtbl" header. Thus every entry can be linked onto an
34811646Smckusick * apprpriate free list.
34911646Smckusick *
35011646Smckusick * NB. The macro "allocsize" below assumes that "struct strhdr"
35111646Smckusick * has a size that is a power of two.
35210314Smckusick */
35311646Smckusick struct strhdr {
35411646Smckusick struct strhdr *next;
35511646Smckusick };
35611646Smckusick
35711646Smckusick #define STRTBLINCR (sizeof(struct strhdr))
35811646Smckusick #define allocsize(size) (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1))
35911646Smckusick
36050658Smckusick static struct strhdr strtblhdr[allocsize(NAME_MAX) / STRTBLINCR];
36111646Smckusick
36211646Smckusick /*
36311646Smckusick * Allocate space for a name. It first looks to see if it already
36411646Smckusick * has an appropriate sized entry, and if not allocates a new one.
36511646Smckusick */
36610314Smckusick char *
savename(name)36710314Smckusick savename(name)
36810314Smckusick char *name;
36910314Smckusick {
37011646Smckusick struct strhdr *np;
37110314Smckusick long len;
37211311Smckusick char *cp;
37310314Smckusick
37410314Smckusick if (name == NULL)
37510314Smckusick panic("bad name\n");
37611646Smckusick len = strlen(name);
37711646Smckusick np = strtblhdr[len / STRTBLINCR].next;
37811646Smckusick if (np != NULL) {
37911646Smckusick strtblhdr[len / STRTBLINCR].next = np->next;
38011646Smckusick cp = (char *)np;
38111646Smckusick } else {
38211646Smckusick cp = malloc((unsigned)allocsize(len));
38311646Smckusick if (cp == NULL)
38411646Smckusick panic("no space for string table\n");
38511646Smckusick }
38611440Smckusick (void) strcpy(cp, name);
38711311Smckusick return (cp);
38810314Smckusick }
38910314Smckusick
39010314Smckusick /*
39111646Smckusick * Free space for a name. The resulting entry is linked onto the
39211646Smckusick * appropriate free list.
39311646Smckusick */
39456567Sbostic void
freename(name)39511646Smckusick freename(name)
39611646Smckusick char *name;
39711646Smckusick {
39811646Smckusick struct strhdr *tp, *np;
39911646Smckusick
40011646Smckusick tp = &strtblhdr[strlen(name) / STRTBLINCR];
40111646Smckusick np = (struct strhdr *)name;
40211646Smckusick np->next = tp->next;
40311646Smckusick tp->next = np;
40411646Smckusick }
40511646Smckusick
40611646Smckusick /*
40711646Smckusick * Useful quantities placed at the end of a dumped symbol table.
40811646Smckusick */
40911646Smckusick struct symtableheader {
41011646Smckusick long volno;
41111646Smckusick long stringsize;
41211646Smckusick long entrytblsize;
41311646Smckusick time_t dumptime;
41411646Smckusick time_t dumpdate;
41511646Smckusick ino_t maxino;
41618497Smckusick long ntrec;
41711646Smckusick };
41811646Smckusick
41911646Smckusick /*
42010314Smckusick * dump a snapshot of the symbol table
42110314Smckusick */
42256567Sbostic void
dumpsymtable(filename,checkpt)42310314Smckusick dumpsymtable(filename, checkpt)
42410314Smckusick char *filename;
42510314Smckusick long checkpt;
42610314Smckusick {
42711440Smckusick register struct entry *ep, *tep;
42811440Smckusick register ino_t i;
42911440Smckusick struct entry temp, *tentry;
43011440Smckusick long mynum = 1, stroff = 0;
43110314Smckusick FILE *fd;
43210314Smckusick struct symtableheader hdr;
43310314Smckusick
43410314Smckusick vprintf(stdout, "Check pointing the restore\n");
43534268Smckusick if (Nflag)
43634268Smckusick return;
43710314Smckusick if ((fd = fopen(filename, "w")) == NULL) {
43856567Sbostic fprintf(stderr, "fopen: %s\n", strerror(errno));
43910314Smckusick panic("cannot create save file %s for symbol table\n",
44010314Smckusick filename);
44110314Smckusick }
44210314Smckusick clearerr(fd);
44310314Smckusick /*
44410314Smckusick * Assign indicies to each entry
44510314Smckusick * Write out the string entries
44610314Smckusick */
44767777Smckusick for (i = WINO; i <= maxino; i++) {
44856567Sbostic for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
44911440Smckusick ep->e_index = mynum++;
45011734Smckusick (void) fwrite(ep->e_name, sizeof(char),
45111734Smckusick (int)allocsize(ep->e_namlen), fd);
45210314Smckusick }
45310314Smckusick }
45410314Smckusick /*
45510314Smckusick * Convert pointers to indexes, and output
45610314Smckusick */
45711440Smckusick tep = &temp;
45811440Smckusick stroff = 0;
45967777Smckusick for (i = WINO; i <= maxino; i++) {
46056567Sbostic for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
461*69001Sbostic memmove(tep, ep, (long)sizeof(struct entry));
46211440Smckusick tep->e_name = (char *)stroff;
46311646Smckusick stroff += allocsize(ep->e_namlen);
46411440Smckusick tep->e_parent = (struct entry *)ep->e_parent->e_index;
46556567Sbostic if (ep->e_links != NULL)
46611440Smckusick tep->e_links =
46711440Smckusick (struct entry *)ep->e_links->e_index;
46856567Sbostic if (ep->e_sibling != NULL)
46911440Smckusick tep->e_sibling =
47011440Smckusick (struct entry *)ep->e_sibling->e_index;
47156567Sbostic if (ep->e_entries != NULL)
47211440Smckusick tep->e_entries =
47311440Smckusick (struct entry *)ep->e_entries->e_index;
47456567Sbostic if (ep->e_next != NULL)
47511440Smckusick tep->e_next =
47611440Smckusick (struct entry *)ep->e_next->e_index;
47711734Smckusick (void) fwrite((char *)tep, sizeof(struct entry), 1, fd);
47810314Smckusick }
47910314Smckusick }
48011440Smckusick /*
48111440Smckusick * Convert entry pointers to indexes, and output
48211440Smckusick */
48311440Smckusick for (i = 0; i < entrytblsize; i++) {
48456567Sbostic if (entry[i] == NULL)
48556567Sbostic tentry = NULL;
48611440Smckusick else
48711440Smckusick tentry = (struct entry *)entry[i]->e_index;
48811734Smckusick (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd);
48911440Smckusick }
49010314Smckusick hdr.volno = checkpt;
49110314Smckusick hdr.maxino = maxino;
49211440Smckusick hdr.entrytblsize = entrytblsize;
49311646Smckusick hdr.stringsize = stroff;
49411303Smckusick hdr.dumptime = dumptime;
49511303Smckusick hdr.dumpdate = dumpdate;
49618497Smckusick hdr.ntrec = ntrec;
49711734Smckusick (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd);
49810314Smckusick if (ferror(fd)) {
49956567Sbostic fprintf(stderr, "fwrite: %s\n", strerror(errno));
50010314Smckusick panic("output error to file %s writing symbol table\n",
50110314Smckusick filename);
50210314Smckusick }
50311734Smckusick (void) fclose(fd);
50410314Smckusick }
50510314Smckusick
50610314Smckusick /*
50710314Smckusick * Initialize a symbol table from a file
50810314Smckusick */
50956567Sbostic void
initsymtable(filename)51010314Smckusick initsymtable(filename)
51110314Smckusick char *filename;
51210314Smckusick {
51310314Smckusick char *base;
51410314Smckusick long tblsize;
51510314Smckusick register struct entry *ep;
51610314Smckusick struct entry *baseep, *lep;
51710314Smckusick struct symtableheader hdr;
51810314Smckusick struct stat stbuf;
51910314Smckusick register long i;
52010314Smckusick int fd;
52110314Smckusick
52210314Smckusick vprintf(stdout, "Initialize symbol table.\n");
52311440Smckusick if (filename == NULL) {
52411440Smckusick entrytblsize = maxino / HASHFACTOR;
52511440Smckusick entry = (struct entry **)
52611440Smckusick calloc((unsigned)entrytblsize, sizeof(struct entry *));
52756567Sbostic if (entry == (struct entry **)NULL)
52811440Smckusick panic("no memory for entry table\n");
52912221Smckusick ep = addentry(".", ROOTINO, NODE);
53012221Smckusick ep->e_flags |= NEW;
53111440Smckusick return;
53211440Smckusick }
53356567Sbostic if ((fd = open(filename, O_RDONLY, 0)) < 0) {
53456567Sbostic fprintf(stderr, "open: %s\n", strerror(errno));
53510314Smckusick panic("cannot open symbol table file %s\n", filename);
53610314Smckusick }
53710314Smckusick if (fstat(fd, &stbuf) < 0) {
53856567Sbostic fprintf(stderr, "stat: %s\n", strerror(errno));
53910314Smckusick panic("cannot stat symbol table file %s\n", filename);
54010314Smckusick }
54110314Smckusick tblsize = stbuf.st_size - sizeof(struct symtableheader);
54212439Smckusick base = calloc(sizeof(char), (unsigned)tblsize);
54310314Smckusick if (base == NULL)
54410314Smckusick panic("cannot allocate space for symbol table\n");
54510314Smckusick if (read(fd, base, (int)tblsize) < 0 ||
54610314Smckusick read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) {
54756567Sbostic fprintf(stderr, "read: %s\n", strerror(errno));
54810314Smckusick panic("cannot read symbol table file %s\n", filename);
54910314Smckusick }
55011303Smckusick switch (command) {
55111303Smckusick case 'r':
55211303Smckusick /*
55311303Smckusick * For normal continuation, insure that we are using
55411303Smckusick * the next incremental tape
55511303Smckusick */
55611440Smckusick if (hdr.dumpdate != dumptime) {
55711440Smckusick if (hdr.dumpdate < dumptime)
55811303Smckusick fprintf(stderr, "Incremental tape too low\n");
55911303Smckusick else
56011303Smckusick fprintf(stderr, "Incremental tape too high\n");
56111303Smckusick done(1);
56211303Smckusick }
56311303Smckusick break;
56411303Smckusick case 'R':
56511303Smckusick /*
56611303Smckusick * For restart, insure that we are using the same tape
56711303Smckusick */
56811324Smckusick curfile.action = SKIP;
56911324Smckusick dumptime = hdr.dumptime;
57011324Smckusick dumpdate = hdr.dumpdate;
57118497Smckusick if (!bflag)
57218497Smckusick newtapebuf(hdr.ntrec);
57311324Smckusick getvol(hdr.volno);
57411303Smckusick break;
57511303Smckusick default:
57611303Smckusick panic("initsymtable called from command %c\n", command);
57711303Smckusick break;
57811303Smckusick }
57910314Smckusick maxino = hdr.maxino;
58011440Smckusick entrytblsize = hdr.entrytblsize;
58111440Smckusick entry = (struct entry **)
58211440Smckusick (base + tblsize - (entrytblsize * sizeof(struct entry *)));
58311440Smckusick baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry));
58411440Smckusick lep = (struct entry *)entry;
58511440Smckusick for (i = 0; i < entrytblsize; i++) {
58656567Sbostic if (entry[i] == NULL)
58710314Smckusick continue;
58810314Smckusick entry[i] = &baseep[(long)entry[i]];
58910314Smckusick }
59011440Smckusick for (ep = &baseep[1]; ep < lep; ep++) {
59110314Smckusick ep->e_name = base + (long)ep->e_name;
59210314Smckusick ep->e_parent = &baseep[(long)ep->e_parent];
59356567Sbostic if (ep->e_sibling != NULL)
59411440Smckusick ep->e_sibling = &baseep[(long)ep->e_sibling];
59556567Sbostic if (ep->e_links != NULL)
59611440Smckusick ep->e_links = &baseep[(long)ep->e_links];
59756567Sbostic if (ep->e_entries != NULL)
59811440Smckusick ep->e_entries = &baseep[(long)ep->e_entries];
59956567Sbostic if (ep->e_next != NULL)
60011440Smckusick ep->e_next = &baseep[(long)ep->e_next];
60110314Smckusick }
60210314Smckusick }
603