1*734527fbSandvar /* $NetBSD: symtab.c,v 1.31 2024/02/10 08:24:50 andvar Exp $ */
20114e805Scgd
361f28255Scgd /*
4625a6892Smycroft * Copyright (c) 1983, 1993
5625a6892Smycroft * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * Redistribution and use in source and binary forms, with or without
861f28255Scgd * modification, are permitted provided that the following conditions
961f28255Scgd * are met:
1061f28255Scgd * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd * notice, this list of conditions and the following disclaimer.
1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer in the
1461f28255Scgd * documentation and/or other materials provided with the distribution.
15276d62f6Sagc * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd * may be used to endorse or promote products derived from this software
1761f28255Scgd * without specific prior written permission.
1861f28255Scgd *
1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd * SUCH DAMAGE.
3061f28255Scgd */
3161f28255Scgd
328b03c7fcSlukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
340114e805Scgd #if 0
357120b2eaSlukem static char sccsid[] = "@(#)symtab.c 8.3 (Berkeley) 4/28/95";
360114e805Scgd #else
37*734527fbSandvar __RCSID("$NetBSD: symtab.c,v 1.31 2024/02/10 08:24:50 andvar Exp $");
380114e805Scgd #endif
3961f28255Scgd #endif /* not lint */
4061f28255Scgd
4161f28255Scgd /*
4261f28255Scgd * These routines maintain the symbol table which tracks the state
4361f28255Scgd * of the file system being restored. They provide lookup by either
4461f28255Scgd * name or inode number. They also provide for creation, deletion,
4561f28255Scgd * and renaming of entries. Because of the dynamic nature of pathnames,
4661f28255Scgd * names should not be saved, but always constructed just before they
4761f28255Scgd * are needed, by calling "myname".
4861f28255Scgd */
4961f28255Scgd
503e75cabcScgd #include <sys/param.h>
5161f28255Scgd #include <sys/stat.h>
523e75cabcScgd
53625a6892Smycroft #include <ufs/ufs/dinode.h>
543e75cabcScgd
553e75cabcScgd #include <errno.h>
563e75cabcScgd #include <fcntl.h>
573e75cabcScgd #include <stdio.h>
583e75cabcScgd #include <stdlib.h>
593e75cabcScgd #include <string.h>
603e75cabcScgd #include <unistd.h>
613e75cabcScgd
623e75cabcScgd #include "restore.h"
633e75cabcScgd #include "extern.h"
6461f28255Scgd
6561f28255Scgd /*
6661f28255Scgd * The following variables define the inode symbol table.
6761f28255Scgd * The primary hash table is dynamically allocated based on
6861f28255Scgd * the number of inodes in the file system (maxino), scaled by
6961f28255Scgd * HASHFACTOR. The variable "entry" points to the hash table;
7061f28255Scgd * the variable "entrytblsize" indicates its size (in entries).
7161f28255Scgd */
7261f28255Scgd #define HASHFACTOR 5
7361f28255Scgd static struct entry **entry;
7461f28255Scgd static long entrytblsize;
7561f28255Scgd
76f224c38bSxtraeme static void addino(ino_t, struct entry *);
77cb1c4f11Schristos static struct entry *lookupparent(const char *);
78f224c38bSxtraeme static void removeentry(struct entry *);
793e75cabcScgd
8061f28255Scgd /*
8161f28255Scgd * Look up an entry by inode number
8261f28255Scgd */
8361f28255Scgd struct entry *
lookupino(ino_t inum)84f224c38bSxtraeme lookupino(ino_t inum)
8561f28255Scgd {
868c5cee23Slukem struct entry *ep;
8761f28255Scgd
88dcd34a91Sdholland if (inum < UFS_WINO || inum >= maxino)
893e75cabcScgd return (NULL);
903e75cabcScgd for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next)
9161f28255Scgd if (ep->e_ino == inum)
9261f28255Scgd return (ep);
933e75cabcScgd return (NULL);
9461f28255Scgd }
9561f28255Scgd
9661f28255Scgd /*
9761f28255Scgd * Add an entry into the entry table
9861f28255Scgd */
993e75cabcScgd static void
addino(ino_t inum,struct entry * np)100f224c38bSxtraeme addino(ino_t inum, struct entry *np)
10161f28255Scgd {
10261f28255Scgd struct entry **epp;
10361f28255Scgd
104dcd34a91Sdholland if (inum < UFS_WINO || inum >= maxino)
105e2325e1fSchristos panic("addino: out of range %ju\n", (uintmax_t)inum);
10661f28255Scgd epp = &entry[inum % entrytblsize];
10761f28255Scgd np->e_ino = inum;
10861f28255Scgd np->e_next = *epp;
10961f28255Scgd *epp = np;
11061f28255Scgd if (dflag)
1113e75cabcScgd for (np = np->e_next; np != NULL; np = np->e_next)
11261f28255Scgd if (np->e_ino == inum)
11361f28255Scgd badentry(np, "duplicate inum");
11461f28255Scgd }
11561f28255Scgd
11661f28255Scgd /*
11761f28255Scgd * Delete an entry from the entry table
11861f28255Scgd */
1193e75cabcScgd void
deleteino(ino_t inum)120f224c38bSxtraeme deleteino(ino_t inum)
12161f28255Scgd {
1228c5cee23Slukem struct entry *next;
12361f28255Scgd struct entry **prev;
12461f28255Scgd
125dcd34a91Sdholland if (inum < UFS_WINO || inum >= maxino)
126e2325e1fSchristos panic("deleteino: out of range %ju\n",
127e2325e1fSchristos (uintmax_t)inum);
12861f28255Scgd prev = &entry[inum % entrytblsize];
1293e75cabcScgd for (next = *prev; next != NULL; next = next->e_next) {
13061f28255Scgd if (next->e_ino == inum) {
13161f28255Scgd next->e_ino = 0;
13261f28255Scgd *prev = next->e_next;
13361f28255Scgd return;
13461f28255Scgd }
13561f28255Scgd prev = &next->e_next;
13661f28255Scgd }
137e2325e1fSchristos panic("deleteino: %ju not found\n", (uintmax_t)inum);
13861f28255Scgd }
13961f28255Scgd
14061f28255Scgd /*
14161f28255Scgd * Look up an entry by name
14261f28255Scgd */
14361f28255Scgd struct entry *
lookupname(const char * name)144cb1c4f11Schristos lookupname(const char *name)
14561f28255Scgd {
1468c5cee23Slukem struct entry *ep;
147cb1c4f11Schristos char *np;
148cb1c4f11Schristos const char *cp;
14961f28255Scgd char buf[MAXPATHLEN];
15061f28255Scgd
15161f28255Scgd cp = name;
152dcd34a91Sdholland for (ep = lookupino(UFS_ROOTINO); ep != NULL; ep = ep->e_entries) {
15361f28255Scgd for (np = buf; *cp != '/' && *cp != '\0'; )
15461f28255Scgd *np++ = *cp++;
15561f28255Scgd *np = '\0';
1563e75cabcScgd for ( ; ep != NULL; ep = ep->e_sibling)
15761f28255Scgd if (strcmp(ep->e_name, buf) == 0)
15861f28255Scgd break;
1593e75cabcScgd if (ep == NULL)
16061f28255Scgd break;
16161f28255Scgd if (*cp++ == '\0')
16261f28255Scgd return (ep);
16361f28255Scgd }
1643e75cabcScgd return (NULL);
16561f28255Scgd }
16661f28255Scgd
16761f28255Scgd /*
16861f28255Scgd * Look up the parent of a pathname
16961f28255Scgd */
1703e75cabcScgd static struct entry *
lookupparent(const char * name)171cb1c4f11Schristos lookupparent(const char *name)
17261f28255Scgd {
17361f28255Scgd struct entry *ep;
17461f28255Scgd char *tailindex;
17561f28255Scgd
176ea7b5d4eSmycroft tailindex = strrchr(name, '/');
177625a6892Smycroft if (tailindex == NULL)
1783e75cabcScgd return (NULL);
17961f28255Scgd *tailindex = '\0';
18061f28255Scgd ep = lookupname(name);
18161f28255Scgd *tailindex = '/';
1823e75cabcScgd if (ep == NULL)
1833e75cabcScgd return (NULL);
18461f28255Scgd if (ep->e_type != NODE)
18561f28255Scgd panic("%s is not a directory\n", name);
18661f28255Scgd return (ep);
18761f28255Scgd }
18861f28255Scgd
18961f28255Scgd /*
19061f28255Scgd * Determine the current pathname of a node or leaf
19161f28255Scgd */
19261f28255Scgd char *
myname(struct entry * ep)193f224c38bSxtraeme myname(struct entry *ep)
19461f28255Scgd {
1958c5cee23Slukem char *cp;
19661f28255Scgd static char namebuf[MAXPATHLEN];
19761f28255Scgd
19861f28255Scgd for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) {
19961f28255Scgd cp -= ep->e_namlen;
2007120b2eaSlukem memmove(cp, ep->e_name, (long)ep->e_namlen);
201dcd34a91Sdholland if (ep == lookupino(UFS_ROOTINO))
20261f28255Scgd return (cp);
20361f28255Scgd *(--cp) = '/';
20461f28255Scgd ep = ep->e_parent;
20561f28255Scgd }
20661f28255Scgd panic("%s: pathname too long\n", cp);
20761f28255Scgd return(cp);
20861f28255Scgd }
20961f28255Scgd
21061f28255Scgd /*
21161f28255Scgd * Unused symbol table entries are linked together on a freelist
21261f28255Scgd * headed by the following pointer.
21361f28255Scgd */
2143e75cabcScgd static struct entry *freelist = NULL;
21561f28255Scgd
21661f28255Scgd /*
21761f28255Scgd * add an entry to the symbol table
21861f28255Scgd */
21961f28255Scgd struct entry *
addentry(const char * name,ino_t inum,int type)220cb1c4f11Schristos addentry(const char *name, ino_t inum, int type)
22161f28255Scgd {
2228c5cee23Slukem struct entry *np, *ep;
22361f28255Scgd
22489e41284Senami if (freelist == NULL) {
22589e41284Senami np = malloc(pagesize);
22689e41284Senami if (np == NULL)
22789e41284Senami panic("no memory to extend symbol table\n");
22889e41284Senami for (ep = (struct entry *)((char *)np + pagesize) - 1;
22989e41284Senami np <= ep; np++) {
23089e41284Senami np->e_next = freelist;
23189e41284Senami freelist = np;
23289e41284Senami }
23389e41284Senami }
23461f28255Scgd np = freelist;
23561f28255Scgd freelist = np->e_next;
236dacc2a91Syamt memset(np, 0, sizeof(struct entry));
23789e41284Senami
23861f28255Scgd np->e_type = type & ~LINK;
23961f28255Scgd ep = lookupparent(name);
2403e75cabcScgd if (ep == NULL) {
241dcd34a91Sdholland if (inum != UFS_ROOTINO || lookupino(UFS_ROOTINO) != NULL)
24261f28255Scgd panic("bad name to addentry %s\n", name);
24361f28255Scgd np->e_name = savename(name);
24461f28255Scgd np->e_namlen = strlen(name);
24561f28255Scgd np->e_parent = np;
246dcd34a91Sdholland addino(UFS_ROOTINO, np);
24761f28255Scgd return (np);
24861f28255Scgd }
249ea7b5d4eSmycroft np->e_name = savename(strrchr(name, '/') + 1);
25061f28255Scgd np->e_namlen = strlen(np->e_name);
25161f28255Scgd np->e_parent = ep;
25261f28255Scgd np->e_sibling = ep->e_entries;
25361f28255Scgd ep->e_entries = np;
25461f28255Scgd if (type & LINK) {
25561f28255Scgd ep = lookupino(inum);
2563e75cabcScgd if (ep == NULL)
2573f9984fcSwiz panic("link to non-existent name\n");
25861f28255Scgd np->e_ino = inum;
25961f28255Scgd np->e_links = ep->e_links;
26061f28255Scgd ep->e_links = np;
26161f28255Scgd } else if (inum != 0) {
2623e75cabcScgd if (lookupino(inum) != NULL)
26361f28255Scgd panic("duplicate entry\n");
26461f28255Scgd addino(inum, np);
26561f28255Scgd }
26661f28255Scgd return (np);
26761f28255Scgd }
26861f28255Scgd
26961f28255Scgd /*
27061f28255Scgd * delete an entry from the symbol table
27161f28255Scgd */
2723e75cabcScgd void
freeentry(struct entry * ep)273f224c38bSxtraeme freeentry(struct entry *ep)
27461f28255Scgd {
2758c5cee23Slukem struct entry *np;
27661f28255Scgd ino_t inum;
27761f28255Scgd
27861f28255Scgd if (ep->e_flags != REMOVED)
27961f28255Scgd badentry(ep, "not marked REMOVED");
28061f28255Scgd if (ep->e_type == NODE) {
2813e75cabcScgd if (ep->e_links != NULL)
28261f28255Scgd badentry(ep, "freeing referenced directory");
2833e75cabcScgd if (ep->e_entries != NULL)
28461f28255Scgd badentry(ep, "freeing non-empty directory");
28561f28255Scgd }
28661f28255Scgd if (ep->e_ino != 0) {
28761f28255Scgd np = lookupino(ep->e_ino);
2883e75cabcScgd if (np == NULL)
28961f28255Scgd badentry(ep, "lookupino failed");
29061f28255Scgd if (np == ep) {
29161f28255Scgd inum = ep->e_ino;
29261f28255Scgd deleteino(inum);
2933e75cabcScgd if (ep->e_links != NULL)
29461f28255Scgd addino(inum, ep->e_links);
29561f28255Scgd } else {
2963e75cabcScgd for (; np != NULL; np = np->e_links) {
29761f28255Scgd if (np->e_links == ep) {
29861f28255Scgd np->e_links = ep->e_links;
29961f28255Scgd break;
30061f28255Scgd }
30161f28255Scgd }
3023e75cabcScgd if (np == NULL)
30361f28255Scgd badentry(ep, "link not found");
30461f28255Scgd }
30561f28255Scgd }
30661f28255Scgd removeentry(ep);
30761f28255Scgd freename(ep->e_name);
30861f28255Scgd ep->e_next = freelist;
30961f28255Scgd freelist = ep;
31061f28255Scgd }
31161f28255Scgd
31261f28255Scgd /*
31361f28255Scgd * Relocate an entry in the tree structure
31461f28255Scgd */
3153e75cabcScgd void
moveentry(struct entry * ep,const char * newname)31658874431Schristos moveentry(struct entry *ep, const char *newname)
31761f28255Scgd {
31861f28255Scgd struct entry *np;
31961f28255Scgd char *cp;
32061f28255Scgd
32161f28255Scgd np = lookupparent(newname);
3223e75cabcScgd if (np == NULL)
32361f28255Scgd badentry(ep, "cannot move ROOT");
32461f28255Scgd if (np != ep->e_parent) {
32561f28255Scgd removeentry(ep);
32661f28255Scgd ep->e_parent = np;
32761f28255Scgd ep->e_sibling = np->e_entries;
32861f28255Scgd np->e_entries = ep;
32961f28255Scgd }
330ea7b5d4eSmycroft cp = strrchr(newname, '/') + 1;
33161f28255Scgd freename(ep->e_name);
33261f28255Scgd ep->e_name = savename(cp);
33361f28255Scgd ep->e_namlen = strlen(cp);
33461f28255Scgd if (strcmp(gentempname(ep), ep->e_name) == 0)
33561f28255Scgd ep->e_flags |= TMPNAME;
33661f28255Scgd else
33761f28255Scgd ep->e_flags &= ~TMPNAME;
33861f28255Scgd }
33961f28255Scgd
34061f28255Scgd /*
34161f28255Scgd * Remove an entry in the tree structure
34261f28255Scgd */
3433e75cabcScgd static void
removeentry(struct entry * ep)344f224c38bSxtraeme removeentry(struct entry *ep)
34561f28255Scgd {
3468c5cee23Slukem struct entry *np;
34761f28255Scgd
34861f28255Scgd np = ep->e_parent;
34961f28255Scgd if (np->e_entries == ep) {
35061f28255Scgd np->e_entries = ep->e_sibling;
35161f28255Scgd } else {
3523e75cabcScgd for (np = np->e_entries; np != NULL; np = np->e_sibling) {
35361f28255Scgd if (np->e_sibling == ep) {
35461f28255Scgd np->e_sibling = ep->e_sibling;
35561f28255Scgd break;
35661f28255Scgd }
35761f28255Scgd }
3583e75cabcScgd if (np == NULL)
35961f28255Scgd badentry(ep, "cannot find entry in parent list");
36061f28255Scgd }
36161f28255Scgd }
36261f28255Scgd
36361f28255Scgd /*
36461f28255Scgd * Table of unused string entries, sorted by length.
36561f28255Scgd *
36661f28255Scgd * Entries are allocated in STRTBLINCR sized pieces so that names
36761f28255Scgd * of similar lengths can use the same entry. The value of STRTBLINCR
36861f28255Scgd * is chosen so that every entry has at least enough space to hold
36961f28255Scgd * a "struct strtbl" header. Thus every entry can be linked onto an
37034f6f0d4Senami * appropriate free list.
37161f28255Scgd *
37261f28255Scgd * NB. The macro "allocsize" below assumes that "struct strhdr"
37361f28255Scgd * has a size that is a power of two.
37461f28255Scgd */
37561f28255Scgd struct strhdr {
37661f28255Scgd struct strhdr *next;
37761f28255Scgd };
37861f28255Scgd
37961f28255Scgd #define STRTBLINCR (sizeof(struct strhdr))
38061f28255Scgd #define allocsize(size) (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1))
38161f28255Scgd
3823e75cabcScgd static struct strhdr strtblhdr[allocsize(NAME_MAX) / STRTBLINCR];
38361f28255Scgd
38461f28255Scgd /*
38561f28255Scgd * Allocate space for a name. It first looks to see if it already
38661f28255Scgd * has an appropriate sized entry, and if not allocates a new one.
38761f28255Scgd */
38861f28255Scgd char *
savename(const char * name)389cb1c4f11Schristos savename(const char *name)
39061f28255Scgd {
39132d43b32Senami struct strhdr *np, *tp;
39232d43b32Senami long len, siz;
39332d43b32Senami char *cp, *ep;
39461f28255Scgd
39561f28255Scgd if (name == NULL)
39661f28255Scgd panic("bad name\n");
39761f28255Scgd len = strlen(name);
39832d43b32Senami tp = &strtblhdr[len / STRTBLINCR];
39932d43b32Senami if (tp->next == NULL) {
40032d43b32Senami cp = malloc(pagesize);
40161f28255Scgd if (cp == NULL)
40261f28255Scgd panic("no space for string table\n");
40332d43b32Senami for (siz = allocsize(len), ep = (cp + pagesize) - siz;
40432d43b32Senami cp <= ep; cp += siz) {
40532d43b32Senami np = (struct strhdr *)cp;
40632d43b32Senami np->next = tp->next;
40732d43b32Senami tp->next = np;
40861f28255Scgd }
40932d43b32Senami }
41032d43b32Senami np = tp->next;
41132d43b32Senami tp->next = np->next;
41232d43b32Senami cp = (char *)np;
41361f28255Scgd (void) strcpy(cp, name);
41461f28255Scgd return (cp);
41561f28255Scgd }
41661f28255Scgd
41761f28255Scgd /*
41861f28255Scgd * Free space for a name. The resulting entry is linked onto the
41961f28255Scgd * appropriate free list.
42061f28255Scgd */
4213e75cabcScgd void
freename(char * name)422f224c38bSxtraeme freename(char *name)
42361f28255Scgd {
42461f28255Scgd struct strhdr *tp, *np;
42561f28255Scgd
42661f28255Scgd tp = &strtblhdr[strlen(name) / STRTBLINCR];
42761f28255Scgd np = (struct strhdr *)name;
42861f28255Scgd np->next = tp->next;
42961f28255Scgd tp->next = np;
43061f28255Scgd }
43161f28255Scgd
43261f28255Scgd /*
43361f28255Scgd * Useful quantities placed at the end of a dumped symbol table.
43461f28255Scgd */
43561f28255Scgd struct symtableheader {
436a0c5caa0Scgd int32_t volno;
437a0c5caa0Scgd int32_t stringsize;
438a0c5caa0Scgd int32_t entrytblsize;
43961f28255Scgd time_t dumptime;
44061f28255Scgd time_t dumpdate;
44161f28255Scgd ino_t maxino;
442a0c5caa0Scgd int32_t ntrec;
44361f28255Scgd };
44461f28255Scgd
44561f28255Scgd /*
44661f28255Scgd * dump a snapshot of the symbol table
44761f28255Scgd */
4483e75cabcScgd void
dumpsymtable(const char * filename,int32_t checkpt)449cb1c4f11Schristos dumpsymtable(const char *filename, int32_t checkpt)
45061f28255Scgd {
4518c5cee23Slukem struct entry *ep, *tep;
4528c5cee23Slukem ino_t i;
453292ab8c2Slukem long l;
45461f28255Scgd struct entry temp, *tentry;
45561f28255Scgd long mynum = 1, stroff = 0;
45661f28255Scgd FILE *fd;
45761f28255Scgd struct symtableheader hdr;
45861f28255Scgd
45961f28255Scgd vprintf(stdout, "Checkpointing the restore\n");
46061f28255Scgd if (Nflag)
46161f28255Scgd return;
46261f28255Scgd if ((fd = fopen(filename, "w")) == NULL) {
4633e75cabcScgd fprintf(stderr, "fopen: %s\n", strerror(errno));
46461f28255Scgd panic("cannot create save file %s for symbol table\n",
46561f28255Scgd filename);
46661f28255Scgd }
46761f28255Scgd clearerr(fd);
46861f28255Scgd /*
469*734527fbSandvar * Assign indices to each entry
47061f28255Scgd * Write out the string entries
47161f28255Scgd */
472dcd34a91Sdholland for (i = UFS_WINO; i <= maxino; i++) {
4733e75cabcScgd for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
47461f28255Scgd ep->e_index = mynum++;
47561f28255Scgd (void) fwrite(ep->e_name, sizeof(char),
47661f28255Scgd (int)allocsize(ep->e_namlen), fd);
47761f28255Scgd }
47861f28255Scgd }
47961f28255Scgd /*
48061f28255Scgd * Convert pointers to indexes, and output
48161f28255Scgd */
48261f28255Scgd tep = &temp;
48361f28255Scgd stroff = 0;
484dcd34a91Sdholland for (i = UFS_WINO; i <= maxino; i++) {
4853e75cabcScgd for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
4867120b2eaSlukem memmove(tep, ep, (long)sizeof(struct entry));
48761f28255Scgd tep->e_name = (char *)stroff;
48861f28255Scgd stroff += allocsize(ep->e_namlen);
48952ff5d8fSmrg tep->e_parent = (struct entry *)(long)
49052ff5d8fSmrg ep->e_parent->e_index;
4913e75cabcScgd if (ep->e_links != NULL)
49252ff5d8fSmrg tep->e_links = (struct entry *)(long)
49352ff5d8fSmrg ep->e_links->e_index;
4943e75cabcScgd if (ep->e_sibling != NULL)
49552ff5d8fSmrg tep->e_sibling = (struct entry *)(long)
49652ff5d8fSmrg ep->e_sibling->e_index;
4973e75cabcScgd if (ep->e_entries != NULL)
49852ff5d8fSmrg tep->e_entries = (struct entry *)(long)
49952ff5d8fSmrg ep->e_entries->e_index;
5003e75cabcScgd if (ep->e_next != NULL)
50152ff5d8fSmrg tep->e_next = (struct entry *)(long)
50252ff5d8fSmrg ep->e_next->e_index;
50361f28255Scgd (void) fwrite((char *)tep, sizeof(struct entry), 1, fd);
50461f28255Scgd }
50561f28255Scgd }
50661f28255Scgd /*
50761f28255Scgd * Convert entry pointers to indexes, and output
50861f28255Scgd */
509292ab8c2Slukem for (l = 0; l < entrytblsize; l++) {
510292ab8c2Slukem if (entry[l] == NULL)
5113e75cabcScgd tentry = NULL;
51261f28255Scgd else
513292ab8c2Slukem tentry = (struct entry *)(long)entry[l]->e_index;
51461f28255Scgd (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd);
51561f28255Scgd }
51661f28255Scgd hdr.volno = checkpt;
51761f28255Scgd hdr.maxino = maxino;
51861f28255Scgd hdr.entrytblsize = entrytblsize;
51961f28255Scgd hdr.stringsize = stroff;
52061f28255Scgd hdr.dumptime = dumptime;
52161f28255Scgd hdr.dumpdate = dumpdate;
52261f28255Scgd hdr.ntrec = ntrec;
52361f28255Scgd (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd);
52461f28255Scgd if (ferror(fd)) {
5253e75cabcScgd fprintf(stderr, "fwrite: %s\n", strerror(errno));
52661f28255Scgd panic("output error to file %s writing symbol table\n",
52761f28255Scgd filename);
52861f28255Scgd }
52961f28255Scgd (void) fclose(fd);
53061f28255Scgd }
53161f28255Scgd
53261f28255Scgd /*
53361f28255Scgd * Initialize a symbol table from a file
53461f28255Scgd */
5353e75cabcScgd void
initsymtable(const char * filename)536cb1c4f11Schristos initsymtable(const char *filename)
53761f28255Scgd {
53861f28255Scgd char *base;
53961f28255Scgd long tblsize;
5408c5cee23Slukem struct entry *ep;
54161f28255Scgd struct entry *baseep, *lep;
54261f28255Scgd struct symtableheader hdr;
54361f28255Scgd struct stat stbuf;
5448c5cee23Slukem long i;
54561f28255Scgd int fd;
54661f28255Scgd
54761f28255Scgd vprintf(stdout, "Initialize symbol table.\n");
54861f28255Scgd if (filename == NULL) {
54961f28255Scgd entrytblsize = maxino / HASHFACTOR;
55061f28255Scgd entry = (struct entry **)
55161f28255Scgd calloc((unsigned)entrytblsize, sizeof(struct entry *));
5522b8aaed8Splunky if (entry == NULL)
55361f28255Scgd panic("no memory for entry table\n");
554dcd34a91Sdholland ep = addentry(".", UFS_ROOTINO, NODE);
55561f28255Scgd ep->e_flags |= NEW;
55661f28255Scgd return;
55761f28255Scgd }
5583e75cabcScgd if ((fd = open(filename, O_RDONLY, 0)) < 0) {
5593e75cabcScgd fprintf(stderr, "open: %s\n", strerror(errno));
56061f28255Scgd panic("cannot open symbol table file %s\n", filename);
56161f28255Scgd }
56261f28255Scgd if (fstat(fd, &stbuf) < 0) {
5633e75cabcScgd fprintf(stderr, "stat: %s\n", strerror(errno));
56461f28255Scgd panic("cannot stat symbol table file %s\n", filename);
56561f28255Scgd }
56661f28255Scgd tblsize = stbuf.st_size - sizeof(struct symtableheader);
567dbf388bcSitojun base = calloc((unsigned)tblsize, sizeof(char));
56861f28255Scgd if (base == NULL)
56961f28255Scgd panic("cannot allocate space for symbol table\n");
57061f28255Scgd if (read(fd, base, (int)tblsize) < 0 ||
57161f28255Scgd read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) {
5723e75cabcScgd fprintf(stderr, "read: %s\n", strerror(errno));
57361f28255Scgd panic("cannot read symbol table file %s\n", filename);
57461f28255Scgd }
57580172dbfSwiz (void)close(fd);
57661f28255Scgd switch (command) {
57761f28255Scgd case 'r':
57861f28255Scgd /*
57961f28255Scgd * For normal continuation, insure that we are using
58061f28255Scgd * the next incremental tape
58161f28255Scgd */
58261f28255Scgd if (hdr.dumpdate != dumptime) {
58361f28255Scgd if (hdr.dumpdate < dumptime)
58461f28255Scgd fprintf(stderr, "Incremental tape too low\n");
58561f28255Scgd else
58661f28255Scgd fprintf(stderr, "Incremental tape too high\n");
587d8b173beSmycroft exit(1);
58861f28255Scgd }
58961f28255Scgd break;
59061f28255Scgd case 'R':
59161f28255Scgd /*
59261f28255Scgd * For restart, insure that we are using the same tape
59361f28255Scgd */
59461f28255Scgd curfile.action = SKIP;
59561f28255Scgd dumptime = hdr.dumptime;
59661f28255Scgd dumpdate = hdr.dumpdate;
59761f28255Scgd if (!bflag)
59861f28255Scgd newtapebuf(hdr.ntrec);
59961f28255Scgd getvol(hdr.volno);
60061f28255Scgd break;
60161f28255Scgd default:
60261f28255Scgd panic("initsymtable called from command %c\n", command);
60361f28255Scgd break;
60461f28255Scgd }
60561f28255Scgd maxino = hdr.maxino;
60661f28255Scgd entrytblsize = hdr.entrytblsize;
60761f28255Scgd entry = (struct entry **)
60861f28255Scgd (base + tblsize - (entrytblsize * sizeof(struct entry *)));
60961f28255Scgd baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry));
61061f28255Scgd lep = (struct entry *)entry;
61161f28255Scgd for (i = 0; i < entrytblsize; i++) {
6123e75cabcScgd if (entry[i] == NULL)
61361f28255Scgd continue;
61461f28255Scgd entry[i] = &baseep[(long)entry[i]];
61561f28255Scgd }
61661f28255Scgd for (ep = &baseep[1]; ep < lep; ep++) {
61761f28255Scgd ep->e_name = base + (long)ep->e_name;
61861f28255Scgd ep->e_parent = &baseep[(long)ep->e_parent];
6193e75cabcScgd if (ep->e_sibling != NULL)
62061f28255Scgd ep->e_sibling = &baseep[(long)ep->e_sibling];
6213e75cabcScgd if (ep->e_links != NULL)
62261f28255Scgd ep->e_links = &baseep[(long)ep->e_links];
6233e75cabcScgd if (ep->e_entries != NULL)
62461f28255Scgd ep->e_entries = &baseep[(long)ep->e_entries];
6253e75cabcScgd if (ep->e_next != NULL)
62661f28255Scgd ep->e_next = &baseep[(long)ep->e_next];
62761f28255Scgd }
62861f28255Scgd }
629