symtab.c revision 40668
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1983, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 3537906Scharnier#if 0 3623685Speterstatic char sccsid[] = "@(#)symtab.c 8.3 (Berkeley) 4/28/95"; 3737906Scharnier#endif 3837906Scharnierstatic const char rcsid[] = 3940668Sdima "$Id: symtab.c,v 1.5 1998/07/28 06:20:13 charnier Exp $"; 401558Srgrimes#endif /* not lint */ 411558Srgrimes 421558Srgrimes/* 431558Srgrimes * These routines maintain the symbol table which tracks the state 441558Srgrimes * of the file system being restored. They provide lookup by either 451558Srgrimes * name or inode number. They also provide for creation, deletion, 461558Srgrimes * and renaming of entries. Because of the dynamic nature of pathnames, 471558Srgrimes * names should not be saved, but always constructed just before they 481558Srgrimes * are needed, by calling "myname". 491558Srgrimes */ 501558Srgrimes 511558Srgrimes#include <sys/param.h> 521558Srgrimes#include <sys/stat.h> 531558Srgrimes 541558Srgrimes#include <ufs/ufs/dinode.h> 551558Srgrimes 561558Srgrimes#include <errno.h> 571558Srgrimes#include <fcntl.h> 581558Srgrimes#include <stdio.h> 591558Srgrimes#include <stdlib.h> 601558Srgrimes#include <string.h> 611558Srgrimes#include <unistd.h> 621558Srgrimes 631558Srgrimes#include "restore.h" 641558Srgrimes#include "extern.h" 651558Srgrimes 661558Srgrimes/* 671558Srgrimes * The following variables define the inode symbol table. 681558Srgrimes * The primary hash table is dynamically allocated based on 691558Srgrimes * the number of inodes in the file system (maxino), scaled by 701558Srgrimes * HASHFACTOR. The variable "entry" points to the hash table; 711558Srgrimes * the variable "entrytblsize" indicates its size (in entries). 721558Srgrimes */ 731558Srgrimes#define HASHFACTOR 5 741558Srgrimesstatic struct entry **entry; 751558Srgrimesstatic long entrytblsize; 761558Srgrimes 771558Srgrimesstatic void addino __P((ino_t, struct entry *)); 781558Srgrimesstatic struct entry *lookupparent __P((char *)); 791558Srgrimesstatic void removeentry __P((struct entry *)); 801558Srgrimes 811558Srgrimes/* 821558Srgrimes * Look up an entry by inode number 831558Srgrimes */ 841558Srgrimesstruct entry * 851558Srgrimeslookupino(inum) 861558Srgrimes ino_t inum; 871558Srgrimes{ 881558Srgrimes register struct entry *ep; 891558Srgrimes 9023685Speter if (inum < WINO || inum >= maxino) 911558Srgrimes return (NULL); 921558Srgrimes for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next) 931558Srgrimes if (ep->e_ino == inum) 941558Srgrimes return (ep); 951558Srgrimes return (NULL); 961558Srgrimes} 971558Srgrimes 981558Srgrimes/* 991558Srgrimes * Add an entry into the entry table 1001558Srgrimes */ 1011558Srgrimesstatic void 1021558Srgrimesaddino(inum, np) 1031558Srgrimes ino_t inum; 1041558Srgrimes struct entry *np; 1051558Srgrimes{ 1061558Srgrimes struct entry **epp; 1071558Srgrimes 10823685Speter if (inum < WINO || inum >= maxino) 1091558Srgrimes panic("addino: out of range %d\n", inum); 1101558Srgrimes epp = &entry[inum % entrytblsize]; 1111558Srgrimes np->e_ino = inum; 1121558Srgrimes np->e_next = *epp; 1131558Srgrimes *epp = np; 1141558Srgrimes if (dflag) 1151558Srgrimes for (np = np->e_next; np != NULL; np = np->e_next) 1161558Srgrimes if (np->e_ino == inum) 1171558Srgrimes badentry(np, "duplicate inum"); 1181558Srgrimes} 1191558Srgrimes 1201558Srgrimes/* 1211558Srgrimes * Delete an entry from the entry table 1221558Srgrimes */ 1231558Srgrimesvoid 1241558Srgrimesdeleteino(inum) 1251558Srgrimes ino_t inum; 1261558Srgrimes{ 1271558Srgrimes register struct entry *next; 1281558Srgrimes struct entry **prev; 1291558Srgrimes 13023685Speter if (inum < WINO || inum >= maxino) 1311558Srgrimes panic("deleteino: out of range %d\n", inum); 1321558Srgrimes prev = &entry[inum % entrytblsize]; 1331558Srgrimes for (next = *prev; next != NULL; next = next->e_next) { 1341558Srgrimes if (next->e_ino == inum) { 1351558Srgrimes next->e_ino = 0; 1361558Srgrimes *prev = next->e_next; 1371558Srgrimes return; 1381558Srgrimes } 1391558Srgrimes prev = &next->e_next; 1401558Srgrimes } 1411558Srgrimes panic("deleteino: %d not found\n", inum); 1421558Srgrimes} 1431558Srgrimes 1441558Srgrimes/* 1451558Srgrimes * Look up an entry by name 1461558Srgrimes */ 1471558Srgrimesstruct entry * 1481558Srgrimeslookupname(name) 1491558Srgrimes char *name; 1501558Srgrimes{ 1511558Srgrimes register struct entry *ep; 1521558Srgrimes register char *np, *cp; 1531558Srgrimes char buf[MAXPATHLEN]; 1541558Srgrimes 1551558Srgrimes cp = name; 1561558Srgrimes for (ep = lookupino(ROOTINO); ep != NULL; ep = ep->e_entries) { 15722482Seivind for (np = buf; *cp != '/' && *cp != '\0' && 15822482Seivind np < &buf[sizeof(buf)]; ) 1591558Srgrimes *np++ = *cp++; 16022482Seivind if (np == &buf[sizeof(buf)]) 16122482Seivind break; 1621558Srgrimes *np = '\0'; 1631558Srgrimes for ( ; ep != NULL; ep = ep->e_sibling) 1641558Srgrimes if (strcmp(ep->e_name, buf) == 0) 1651558Srgrimes break; 1661558Srgrimes if (ep == NULL) 1671558Srgrimes break; 1681558Srgrimes if (*cp++ == '\0') 1691558Srgrimes return (ep); 1701558Srgrimes } 1711558Srgrimes return (NULL); 1721558Srgrimes} 1731558Srgrimes 1741558Srgrimes/* 1751558Srgrimes * Look up the parent of a pathname 1761558Srgrimes */ 1771558Srgrimesstatic struct entry * 1781558Srgrimeslookupparent(name) 1791558Srgrimes char *name; 1801558Srgrimes{ 1811558Srgrimes struct entry *ep; 1821558Srgrimes char *tailindex; 1831558Srgrimes 18423685Speter tailindex = strrchr(name, '/'); 1851558Srgrimes if (tailindex == NULL) 1861558Srgrimes return (NULL); 1871558Srgrimes *tailindex = '\0'; 1881558Srgrimes ep = lookupname(name); 1891558Srgrimes *tailindex = '/'; 1901558Srgrimes if (ep == NULL) 1911558Srgrimes return (NULL); 1921558Srgrimes if (ep->e_type != NODE) 1931558Srgrimes panic("%s is not a directory\n", name); 1941558Srgrimes return (ep); 1951558Srgrimes} 1961558Srgrimes 1971558Srgrimes/* 1981558Srgrimes * Determine the current pathname of a node or leaf 1991558Srgrimes */ 2001558Srgrimeschar * 2011558Srgrimesmyname(ep) 2021558Srgrimes register struct entry *ep; 2031558Srgrimes{ 2041558Srgrimes register char *cp; 2051558Srgrimes static char namebuf[MAXPATHLEN]; 2061558Srgrimes 2071558Srgrimes for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) { 2081558Srgrimes cp -= ep->e_namlen; 20923685Speter memmove(cp, ep->e_name, (long)ep->e_namlen); 2101558Srgrimes if (ep == lookupino(ROOTINO)) 2111558Srgrimes return (cp); 2121558Srgrimes *(--cp) = '/'; 2131558Srgrimes ep = ep->e_parent; 2141558Srgrimes } 2151558Srgrimes panic("%s: pathname too long\n", cp); 2161558Srgrimes return(cp); 2171558Srgrimes} 2181558Srgrimes 2191558Srgrimes/* 22037906Scharnier * Unused symbol table entries are linked together on a free list 2211558Srgrimes * headed by the following pointer. 2221558Srgrimes */ 2231558Srgrimesstatic struct entry *freelist = NULL; 2241558Srgrimes 2251558Srgrimes/* 2261558Srgrimes * add an entry to the symbol table 2271558Srgrimes */ 2281558Srgrimesstruct entry * 2291558Srgrimesaddentry(name, inum, type) 2301558Srgrimes char *name; 2311558Srgrimes ino_t inum; 2321558Srgrimes int type; 2331558Srgrimes{ 2341558Srgrimes register struct entry *np, *ep; 2351558Srgrimes 2361558Srgrimes if (freelist != NULL) { 2371558Srgrimes np = freelist; 2381558Srgrimes freelist = np->e_next; 23923685Speter memset(np, 0, (long)sizeof(struct entry)); 2401558Srgrimes } else { 2411558Srgrimes np = (struct entry *)calloc(1, sizeof(struct entry)); 2421558Srgrimes if (np == NULL) 2431558Srgrimes panic("no memory to extend symbol table\n"); 2441558Srgrimes } 2451558Srgrimes np->e_type = type & ~LINK; 2461558Srgrimes ep = lookupparent(name); 2471558Srgrimes if (ep == NULL) { 2481558Srgrimes if (inum != ROOTINO || lookupino(ROOTINO) != NULL) 2491558Srgrimes panic("bad name to addentry %s\n", name); 2501558Srgrimes np->e_name = savename(name); 2511558Srgrimes np->e_namlen = strlen(name); 2521558Srgrimes np->e_parent = np; 2531558Srgrimes addino(ROOTINO, np); 2541558Srgrimes return (np); 2551558Srgrimes } 25623685Speter np->e_name = savename(strrchr(name, '/') + 1); 2571558Srgrimes np->e_namlen = strlen(np->e_name); 2581558Srgrimes np->e_parent = ep; 2591558Srgrimes np->e_sibling = ep->e_entries; 2601558Srgrimes ep->e_entries = np; 2611558Srgrimes if (type & LINK) { 2621558Srgrimes ep = lookupino(inum); 2631558Srgrimes if (ep == NULL) 26437906Scharnier panic("link to non-existent name\n"); 2651558Srgrimes np->e_ino = inum; 2661558Srgrimes np->e_links = ep->e_links; 2671558Srgrimes ep->e_links = np; 2681558Srgrimes } else if (inum != 0) { 2691558Srgrimes if (lookupino(inum) != NULL) 2701558Srgrimes panic("duplicate entry\n"); 2711558Srgrimes addino(inum, np); 2721558Srgrimes } 2731558Srgrimes return (np); 2741558Srgrimes} 2751558Srgrimes 2761558Srgrimes/* 2771558Srgrimes * delete an entry from the symbol table 2781558Srgrimes */ 2791558Srgrimesvoid 2801558Srgrimesfreeentry(ep) 2811558Srgrimes register struct entry *ep; 2821558Srgrimes{ 2831558Srgrimes register struct entry *np; 2841558Srgrimes ino_t inum; 2851558Srgrimes 2861558Srgrimes if (ep->e_flags != REMOVED) 2871558Srgrimes badentry(ep, "not marked REMOVED"); 2881558Srgrimes if (ep->e_type == NODE) { 2891558Srgrimes if (ep->e_links != NULL) 2901558Srgrimes badentry(ep, "freeing referenced directory"); 2911558Srgrimes if (ep->e_entries != NULL) 2921558Srgrimes badentry(ep, "freeing non-empty directory"); 2931558Srgrimes } 2941558Srgrimes if (ep->e_ino != 0) { 2951558Srgrimes np = lookupino(ep->e_ino); 2961558Srgrimes if (np == NULL) 2971558Srgrimes badentry(ep, "lookupino failed"); 2981558Srgrimes if (np == ep) { 2991558Srgrimes inum = ep->e_ino; 3001558Srgrimes deleteino(inum); 3011558Srgrimes if (ep->e_links != NULL) 3021558Srgrimes addino(inum, ep->e_links); 3031558Srgrimes } else { 3041558Srgrimes for (; np != NULL; np = np->e_links) { 3051558Srgrimes if (np->e_links == ep) { 3061558Srgrimes np->e_links = ep->e_links; 3071558Srgrimes break; 3081558Srgrimes } 3091558Srgrimes } 3101558Srgrimes if (np == NULL) 3111558Srgrimes badentry(ep, "link not found"); 3121558Srgrimes } 3131558Srgrimes } 3141558Srgrimes removeentry(ep); 3151558Srgrimes freename(ep->e_name); 3161558Srgrimes ep->e_next = freelist; 3171558Srgrimes freelist = ep; 3181558Srgrimes} 3191558Srgrimes 3201558Srgrimes/* 3211558Srgrimes * Relocate an entry in the tree structure 3221558Srgrimes */ 3231558Srgrimesvoid 3241558Srgrimesmoveentry(ep, newname) 3251558Srgrimes register struct entry *ep; 3261558Srgrimes char *newname; 3271558Srgrimes{ 3281558Srgrimes struct entry *np; 3291558Srgrimes char *cp; 3301558Srgrimes 3311558Srgrimes np = lookupparent(newname); 3321558Srgrimes if (np == NULL) 3331558Srgrimes badentry(ep, "cannot move ROOT"); 3341558Srgrimes if (np != ep->e_parent) { 3351558Srgrimes removeentry(ep); 3361558Srgrimes ep->e_parent = np; 3371558Srgrimes ep->e_sibling = np->e_entries; 3381558Srgrimes np->e_entries = ep; 3391558Srgrimes } 34023685Speter cp = strrchr(newname, '/') + 1; 3411558Srgrimes freename(ep->e_name); 3421558Srgrimes ep->e_name = savename(cp); 3431558Srgrimes ep->e_namlen = strlen(cp); 3441558Srgrimes if (strcmp(gentempname(ep), ep->e_name) == 0) 3451558Srgrimes ep->e_flags |= TMPNAME; 3461558Srgrimes else 3471558Srgrimes ep->e_flags &= ~TMPNAME; 3481558Srgrimes} 3491558Srgrimes 3501558Srgrimes/* 3511558Srgrimes * Remove an entry in the tree structure 3521558Srgrimes */ 3531558Srgrimesstatic void 3541558Srgrimesremoveentry(ep) 3551558Srgrimes register struct entry *ep; 3561558Srgrimes{ 3571558Srgrimes register struct entry *np; 3581558Srgrimes 3591558Srgrimes np = ep->e_parent; 3601558Srgrimes if (np->e_entries == ep) { 3611558Srgrimes np->e_entries = ep->e_sibling; 3621558Srgrimes } else { 3631558Srgrimes for (np = np->e_entries; np != NULL; np = np->e_sibling) { 3641558Srgrimes if (np->e_sibling == ep) { 3651558Srgrimes np->e_sibling = ep->e_sibling; 3661558Srgrimes break; 3671558Srgrimes } 3681558Srgrimes } 3691558Srgrimes if (np == NULL) 3701558Srgrimes badentry(ep, "cannot find entry in parent list"); 3711558Srgrimes } 3721558Srgrimes} 3731558Srgrimes 3741558Srgrimes/* 3751558Srgrimes * Table of unused string entries, sorted by length. 3768871Srgrimes * 3771558Srgrimes * Entries are allocated in STRTBLINCR sized pieces so that names 3781558Srgrimes * of similar lengths can use the same entry. The value of STRTBLINCR 3791558Srgrimes * is chosen so that every entry has at least enough space to hold 3801558Srgrimes * a "struct strtbl" header. Thus every entry can be linked onto an 38137906Scharnier * appropriate free list. 3821558Srgrimes * 3831558Srgrimes * NB. The macro "allocsize" below assumes that "struct strhdr" 3841558Srgrimes * has a size that is a power of two. 3851558Srgrimes */ 3861558Srgrimesstruct strhdr { 3871558Srgrimes struct strhdr *next; 3881558Srgrimes}; 3891558Srgrimes 3901558Srgrimes#define STRTBLINCR (sizeof(struct strhdr)) 3911558Srgrimes#define allocsize(size) (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1)) 3921558Srgrimes 3931558Srgrimesstatic struct strhdr strtblhdr[allocsize(NAME_MAX) / STRTBLINCR]; 3941558Srgrimes 3951558Srgrimes/* 3961558Srgrimes * Allocate space for a name. It first looks to see if it already 3971558Srgrimes * has an appropriate sized entry, and if not allocates a new one. 3981558Srgrimes */ 3991558Srgrimeschar * 4001558Srgrimessavename(name) 4011558Srgrimes char *name; 4021558Srgrimes{ 4031558Srgrimes struct strhdr *np; 4041558Srgrimes long len; 4051558Srgrimes char *cp; 4061558Srgrimes 4071558Srgrimes if (name == NULL) 4081558Srgrimes panic("bad name\n"); 4091558Srgrimes len = strlen(name); 4101558Srgrimes np = strtblhdr[len / STRTBLINCR].next; 4111558Srgrimes if (np != NULL) { 4121558Srgrimes strtblhdr[len / STRTBLINCR].next = np->next; 4131558Srgrimes cp = (char *)np; 4141558Srgrimes } else { 4151558Srgrimes cp = malloc((unsigned)allocsize(len)); 4161558Srgrimes if (cp == NULL) 4171558Srgrimes panic("no space for string table\n"); 4181558Srgrimes } 4191558Srgrimes (void) strcpy(cp, name); 4201558Srgrimes return (cp); 4211558Srgrimes} 4221558Srgrimes 4231558Srgrimes/* 4241558Srgrimes * Free space for a name. The resulting entry is linked onto the 4251558Srgrimes * appropriate free list. 4261558Srgrimes */ 4271558Srgrimesvoid 4281558Srgrimesfreename(name) 4291558Srgrimes char *name; 4301558Srgrimes{ 4311558Srgrimes struct strhdr *tp, *np; 4328871Srgrimes 4331558Srgrimes tp = &strtblhdr[strlen(name) / STRTBLINCR]; 4341558Srgrimes np = (struct strhdr *)name; 4351558Srgrimes np->next = tp->next; 4361558Srgrimes tp->next = np; 4371558Srgrimes} 4381558Srgrimes 4391558Srgrimes/* 4401558Srgrimes * Useful quantities placed at the end of a dumped symbol table. 4411558Srgrimes */ 4421558Srgrimesstruct symtableheader { 44340668Sdima int32_t volno; 44440668Sdima int32_t stringsize; 44540668Sdima int32_t entrytblsize; 4461558Srgrimes time_t dumptime; 4471558Srgrimes time_t dumpdate; 4481558Srgrimes ino_t maxino; 44940668Sdima int32_t ntrec; 4501558Srgrimes}; 4511558Srgrimes 4521558Srgrimes/* 4531558Srgrimes * dump a snapshot of the symbol table 4541558Srgrimes */ 4551558Srgrimesvoid 4561558Srgrimesdumpsymtable(filename, checkpt) 4571558Srgrimes char *filename; 4581558Srgrimes long checkpt; 4591558Srgrimes{ 4601558Srgrimes register struct entry *ep, *tep; 4611558Srgrimes register ino_t i; 4621558Srgrimes struct entry temp, *tentry; 4631558Srgrimes long mynum = 1, stroff = 0; 4641558Srgrimes FILE *fd; 4651558Srgrimes struct symtableheader hdr; 4661558Srgrimes 4671558Srgrimes vprintf(stdout, "Check pointing the restore\n"); 4681558Srgrimes if (Nflag) 4691558Srgrimes return; 4701558Srgrimes if ((fd = fopen(filename, "w")) == NULL) { 4711558Srgrimes fprintf(stderr, "fopen: %s\n", strerror(errno)); 4721558Srgrimes panic("cannot create save file %s for symbol table\n", 4731558Srgrimes filename); 4741558Srgrimes } 4751558Srgrimes clearerr(fd); 4761558Srgrimes /* 47737906Scharnier * Assign indices to each entry 4781558Srgrimes * Write out the string entries 4791558Srgrimes */ 48023685Speter for (i = WINO; i <= maxino; i++) { 4811558Srgrimes for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { 4821558Srgrimes ep->e_index = mynum++; 4831558Srgrimes (void) fwrite(ep->e_name, sizeof(char), 4841558Srgrimes (int)allocsize(ep->e_namlen), fd); 4851558Srgrimes } 4861558Srgrimes } 4871558Srgrimes /* 4881558Srgrimes * Convert pointers to indexes, and output 4891558Srgrimes */ 4901558Srgrimes tep = &temp; 4911558Srgrimes stroff = 0; 49223685Speter for (i = WINO; i <= maxino; i++) { 4931558Srgrimes for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { 49423685Speter memmove(tep, ep, (long)sizeof(struct entry)); 4951558Srgrimes tep->e_name = (char *)stroff; 4961558Srgrimes stroff += allocsize(ep->e_namlen); 4971558Srgrimes tep->e_parent = (struct entry *)ep->e_parent->e_index; 4981558Srgrimes if (ep->e_links != NULL) 4991558Srgrimes tep->e_links = 5001558Srgrimes (struct entry *)ep->e_links->e_index; 5011558Srgrimes if (ep->e_sibling != NULL) 5021558Srgrimes tep->e_sibling = 5031558Srgrimes (struct entry *)ep->e_sibling->e_index; 5041558Srgrimes if (ep->e_entries != NULL) 5051558Srgrimes tep->e_entries = 5061558Srgrimes (struct entry *)ep->e_entries->e_index; 5071558Srgrimes if (ep->e_next != NULL) 5081558Srgrimes tep->e_next = 5091558Srgrimes (struct entry *)ep->e_next->e_index; 5101558Srgrimes (void) fwrite((char *)tep, sizeof(struct entry), 1, fd); 5111558Srgrimes } 5121558Srgrimes } 5131558Srgrimes /* 5141558Srgrimes * Convert entry pointers to indexes, and output 5151558Srgrimes */ 5161558Srgrimes for (i = 0; i < entrytblsize; i++) { 5171558Srgrimes if (entry[i] == NULL) 5181558Srgrimes tentry = NULL; 5191558Srgrimes else 5201558Srgrimes tentry = (struct entry *)entry[i]->e_index; 5211558Srgrimes (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd); 5221558Srgrimes } 5231558Srgrimes hdr.volno = checkpt; 5241558Srgrimes hdr.maxino = maxino; 5251558Srgrimes hdr.entrytblsize = entrytblsize; 5261558Srgrimes hdr.stringsize = stroff; 5271558Srgrimes hdr.dumptime = dumptime; 5281558Srgrimes hdr.dumpdate = dumpdate; 5291558Srgrimes hdr.ntrec = ntrec; 5301558Srgrimes (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd); 5311558Srgrimes if (ferror(fd)) { 5321558Srgrimes fprintf(stderr, "fwrite: %s\n", strerror(errno)); 5331558Srgrimes panic("output error to file %s writing symbol table\n", 5341558Srgrimes filename); 5351558Srgrimes } 5361558Srgrimes (void) fclose(fd); 5371558Srgrimes} 5381558Srgrimes 5391558Srgrimes/* 5401558Srgrimes * Initialize a symbol table from a file 5411558Srgrimes */ 5421558Srgrimesvoid 5431558Srgrimesinitsymtable(filename) 5441558Srgrimes char *filename; 5451558Srgrimes{ 5461558Srgrimes char *base; 5471558Srgrimes long tblsize; 5481558Srgrimes register struct entry *ep; 5491558Srgrimes struct entry *baseep, *lep; 5501558Srgrimes struct symtableheader hdr; 5511558Srgrimes struct stat stbuf; 5521558Srgrimes register long i; 5531558Srgrimes int fd; 5541558Srgrimes 5551558Srgrimes vprintf(stdout, "Initialize symbol table.\n"); 5561558Srgrimes if (filename == NULL) { 5571558Srgrimes entrytblsize = maxino / HASHFACTOR; 5581558Srgrimes entry = (struct entry **) 5591558Srgrimes calloc((unsigned)entrytblsize, sizeof(struct entry *)); 5601558Srgrimes if (entry == (struct entry **)NULL) 5611558Srgrimes panic("no memory for entry table\n"); 5621558Srgrimes ep = addentry(".", ROOTINO, NODE); 5631558Srgrimes ep->e_flags |= NEW; 5641558Srgrimes return; 5651558Srgrimes } 5661558Srgrimes if ((fd = open(filename, O_RDONLY, 0)) < 0) { 5671558Srgrimes fprintf(stderr, "open: %s\n", strerror(errno)); 5681558Srgrimes panic("cannot open symbol table file %s\n", filename); 5691558Srgrimes } 5701558Srgrimes if (fstat(fd, &stbuf) < 0) { 5711558Srgrimes fprintf(stderr, "stat: %s\n", strerror(errno)); 5721558Srgrimes panic("cannot stat symbol table file %s\n", filename); 5731558Srgrimes } 5741558Srgrimes tblsize = stbuf.st_size - sizeof(struct symtableheader); 5751558Srgrimes base = calloc(sizeof(char), (unsigned)tblsize); 5761558Srgrimes if (base == NULL) 5771558Srgrimes panic("cannot allocate space for symbol table\n"); 5781558Srgrimes if (read(fd, base, (int)tblsize) < 0 || 5791558Srgrimes read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) { 5801558Srgrimes fprintf(stderr, "read: %s\n", strerror(errno)); 5811558Srgrimes panic("cannot read symbol table file %s\n", filename); 5821558Srgrimes } 5831558Srgrimes switch (command) { 5841558Srgrimes case 'r': 5851558Srgrimes /* 5861558Srgrimes * For normal continuation, insure that we are using 5871558Srgrimes * the next incremental tape 5881558Srgrimes */ 5891558Srgrimes if (hdr.dumpdate != dumptime) { 5901558Srgrimes if (hdr.dumpdate < dumptime) 5911558Srgrimes fprintf(stderr, "Incremental tape too low\n"); 5921558Srgrimes else 5931558Srgrimes fprintf(stderr, "Incremental tape too high\n"); 5941558Srgrimes done(1); 5951558Srgrimes } 5961558Srgrimes break; 5971558Srgrimes case 'R': 5981558Srgrimes /* 5991558Srgrimes * For restart, insure that we are using the same tape 6001558Srgrimes */ 6011558Srgrimes curfile.action = SKIP; 6021558Srgrimes dumptime = hdr.dumptime; 6031558Srgrimes dumpdate = hdr.dumpdate; 6041558Srgrimes if (!bflag) 6051558Srgrimes newtapebuf(hdr.ntrec); 6061558Srgrimes getvol(hdr.volno); 6071558Srgrimes break; 6081558Srgrimes default: 6091558Srgrimes panic("initsymtable called from command %c\n", command); 6101558Srgrimes break; 6111558Srgrimes } 6121558Srgrimes maxino = hdr.maxino; 6131558Srgrimes entrytblsize = hdr.entrytblsize; 6141558Srgrimes entry = (struct entry **) 6151558Srgrimes (base + tblsize - (entrytblsize * sizeof(struct entry *))); 6161558Srgrimes baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry)); 6171558Srgrimes lep = (struct entry *)entry; 6181558Srgrimes for (i = 0; i < entrytblsize; i++) { 6191558Srgrimes if (entry[i] == NULL) 6201558Srgrimes continue; 6211558Srgrimes entry[i] = &baseep[(long)entry[i]]; 6221558Srgrimes } 6231558Srgrimes for (ep = &baseep[1]; ep < lep; ep++) { 6241558Srgrimes ep->e_name = base + (long)ep->e_name; 6251558Srgrimes ep->e_parent = &baseep[(long)ep->e_parent]; 6261558Srgrimes if (ep->e_sibling != NULL) 6271558Srgrimes ep->e_sibling = &baseep[(long)ep->e_sibling]; 6281558Srgrimes if (ep->e_links != NULL) 6291558Srgrimes ep->e_links = &baseep[(long)ep->e_links]; 6301558Srgrimes if (ep->e_entries != NULL) 6311558Srgrimes ep->e_entries = &baseep[(long)ep->e_entries]; 6321558Srgrimes if (ep->e_next != NULL) 6331558Srgrimes ep->e_next = &baseep[(long)ep->e_next]; 6341558Srgrimes } 6351558Srgrimes} 636