110314Smckusick /* Copyright (c) 1983 Regents of the University of California */ 210314Smckusick 310314Smckusick #ifndef lint 4*11311Smckusick static char sccsid[] = "@(#)symtab.c 3.3 (Berkeley) 83/02/27"; 510314Smckusick #endif 610314Smckusick 710314Smckusick #include "restore.h" 810314Smckusick #include <sys/stat.h> 910314Smckusick 1010314Smckusick struct symtableheader { 1110314Smckusick long volno; 1210314Smckusick long stringsize; 1311303Smckusick time_t dumptime; 1411303Smckusick time_t dumpdate; 1510314Smckusick ino_t maxino; 1610314Smckusick }; 1710314Smckusick 1811129Smckusick struct entry *freelist = NIL; 1910314Smckusick 2011129Smckusick #ifndef lookupino 2110314Smckusick /* 2210314Smckusick * Look up an entry by inode number 2310314Smckusick */ 2410314Smckusick struct entry * 2510314Smckusick lookupino(inum) 2610314Smckusick ino_t inum; 2710314Smckusick { 2810314Smckusick 2911129Smckusick return (entry[inum]); 3010314Smckusick } 3111129Smckusick #endif lookupino 3210314Smckusick 3311129Smckusick #ifndef addino 3410314Smckusick /* 3510314Smckusick * Add an entry into the entry table 3610314Smckusick */ 3710314Smckusick addino(inum, np) 3811129Smckusick long inum; 3910314Smckusick struct entry *np; 4010314Smckusick { 4110314Smckusick 4211129Smckusick entry[inum] = np; 4310314Smckusick } 4411129Smckusick #endif addino 4510314Smckusick 4611129Smckusick #ifndef deleteino 4710314Smckusick /* 4810314Smckusick * Delete an entry from the entry table 4910314Smckusick */ 5010314Smckusick deleteino(inum) 5111129Smckusick long inum; 5210314Smckusick { 5310314Smckusick 5411129Smckusick entry[inum] = NIL; 5510314Smckusick } 5611129Smckusick #endif deleteino 5710314Smckusick 5810314Smckusick /* 5910314Smckusick * Look up an entry by name 6010314Smckusick */ 6110314Smckusick struct entry * 6210314Smckusick lookupname(name) 6310314Smckusick char *name; 6410314Smckusick { 6510314Smckusick register struct entry *ep; 6610314Smckusick register char *np, *cp; 6710314Smckusick char buf[BUFSIZ]; 6810314Smckusick 6910314Smckusick cp = name; 7010314Smckusick for (ep = lookupino(ROOTINO); ep != NIL; ep = ep->e_entries) { 7110314Smckusick for (np = buf; *cp != '/' && *cp != '\0'; ) 7210314Smckusick *np++ = *cp++; 7310314Smckusick *np = '\0'; 7410314Smckusick for ( ; ep != NIL; ep = ep->e_sibling) 7510314Smckusick if (strcmp(ep->e_name, buf) == 0) 7610314Smckusick break; 7710314Smckusick if (ep == NIL) 7810314Smckusick break; 79*11311Smckusick if (*cp++ == '\0') 8010314Smckusick return (ep); 8110314Smckusick } 82*11311Smckusick return (NIL); 8310314Smckusick } 8410314Smckusick 8510314Smckusick /* 8610314Smckusick * Look up the parent of a pathname 8710314Smckusick */ 8810314Smckusick struct entry * 8910314Smckusick lookupparent(name) 9010314Smckusick char *name; 9110314Smckusick { 9210314Smckusick struct entry *ep; 9310314Smckusick char *tailindex; 9410314Smckusick 9510314Smckusick tailindex = rindex(name, '/'); 9610314Smckusick if (tailindex == 0) 9710314Smckusick return (NIL); 9810314Smckusick *tailindex = '\0'; 9910314Smckusick ep = lookupname(name); 100*11311Smckusick *tailindex = '/'; 10110314Smckusick if (ep == NIL) 10210314Smckusick return (NIL); 10310314Smckusick if (ep->e_type != NODE) 10410314Smckusick panic("%s is not a directory\n", name); 10510314Smckusick return (ep); 10610314Smckusick } 10710314Smckusick 10810314Smckusick /* 10910314Smckusick * Determine the current pathname of a node or leaf 11010314Smckusick */ 11110314Smckusick char * 11210314Smckusick myname(ep) 11310314Smckusick register struct entry *ep; 11410314Smckusick { 11510314Smckusick register char *cp; 11610314Smckusick static char namebuf[BUFSIZ]; 11710314Smckusick 11810314Smckusick for (cp = &namebuf[BUFSIZ - 2]; cp > &namebuf[ep->e_namlen]; ) { 11910314Smckusick cp -= ep->e_namlen; 12010314Smckusick bcopy(ep->e_name, cp, (long)ep->e_namlen); 12110314Smckusick if (ep == lookupino(ROOTINO)) 12210314Smckusick return (cp); 12310314Smckusick *(--cp) = '/'; 12410314Smckusick ep = ep->e_parent; 12510314Smckusick } 12610314Smckusick panic("%s: pathname too long\n", cp); 12710314Smckusick return(cp); 12810314Smckusick } 12910314Smckusick 13010314Smckusick /* 13110314Smckusick * add an entry to the symbol table 13210314Smckusick */ 13310314Smckusick struct entry * 13410314Smckusick addentry(name, inum, type) 13510314Smckusick char *name; 13610314Smckusick ino_t inum; 13710314Smckusick int type; 13810314Smckusick { 13910314Smckusick register struct entry *np, *ep; 14010314Smckusick 14110314Smckusick if (freelist != NIL) { 14210314Smckusick np = freelist; 14310314Smckusick freelist = np->e_sibling; 14410314Smckusick bzero((char *)np, (long)sizeof(struct entry)); 14510314Smckusick } else { 14610314Smckusick np = (struct entry *)calloc(1, sizeof(struct entry)); 14710314Smckusick } 14810314Smckusick np->e_ino = inum; 14910314Smckusick np->e_type = type & ~LINK; 15010314Smckusick ep = lookupparent(name); 15110314Smckusick if (ep == NIL) { 15210314Smckusick if (inum != ROOTINO || lookupino(ROOTINO) != NIL) 15310314Smckusick panic("bad name to addentry %s\n", name); 15410314Smckusick np->e_name = savename(name); 15510314Smckusick np->e_namlen = strlen(name); 15610314Smckusick np->e_parent = np; 15710314Smckusick addino(ROOTINO, np); 15810314Smckusick return (np); 15910314Smckusick } 16010314Smckusick np->e_name = savename(rindex(name, '/') + 1); 16110314Smckusick np->e_namlen = strlen(np->e_name); 16210314Smckusick np->e_parent = ep; 16310314Smckusick np->e_sibling = ep->e_entries; 16410314Smckusick ep->e_entries = np; 16510314Smckusick if (type & LINK) { 16610314Smckusick ep = lookupino(inum); 16710314Smckusick if (ep == NIL) 16810314Smckusick panic("link to non-existant name\n"); 16910314Smckusick np->e_links = ep->e_links; 17010314Smckusick ep->e_links = np; 17110314Smckusick } else if (inum != 0) { 17210314Smckusick if (lookupino(inum) != NIL) 17310314Smckusick panic("duplicate entry\n"); 17410314Smckusick addino(inum, np); 17510314Smckusick } 17610314Smckusick return (np); 17710314Smckusick } 17810314Smckusick 17910314Smckusick /* 18010314Smckusick * delete an entry from the symbol table 18110314Smckusick */ 18210314Smckusick freeentry(ep) 18310314Smckusick register struct entry *ep; 18410314Smckusick { 18510314Smckusick register struct entry *np; 18610314Smckusick 18710314Smckusick np = lookupino(ep->e_ino); 18810314Smckusick if (np == NIL) 18910314Smckusick badentry(ep, "lookupino failed"); 19010314Smckusick if (ep->e_flags != REMOVED) 19110314Smckusick badentry(ep, "not marked REMOVED"); 19210314Smckusick if (np->e_type == NODE) { 19310314Smckusick if (np == ep && np->e_links != NIL) 19410314Smckusick badentry(ep, "freeing referenced directory"); 19510314Smckusick if (ep->e_entries != NIL) 19610314Smckusick badentry(ep, "freeing non-empty directory"); 19710314Smckusick } 19810314Smckusick if (np == ep) { 19910314Smckusick deleteino(ep->e_ino); 20010314Smckusick addino(ep->e_ino, ep->e_links); 20110314Smckusick } else { 20210314Smckusick for (; np != NIL; np = np->e_links) { 20310314Smckusick if (np->e_links == ep) { 20410314Smckusick np->e_links = ep->e_links; 20510314Smckusick break; 20610314Smckusick } 20710314Smckusick } 20810314Smckusick if (np == NIL) 20910314Smckusick badentry(ep, "link not found"); 21010314Smckusick } 21110314Smckusick removeentry(ep); 21210314Smckusick free(ep->e_name); 21311129Smckusick if (ep->e_newname != NULL) 21411129Smckusick free(ep->e_newname); 21510314Smckusick ep->e_sibling = freelist; 21610314Smckusick freelist = ep; 21710314Smckusick } 21810314Smckusick 21910314Smckusick /* 22011129Smckusick * change the number associated with an entry 22111129Smckusick */ 22211129Smckusick renumber(ep, newinum) 22311129Smckusick struct entry *ep; 22411129Smckusick ino_t newinum; 22511129Smckusick { 22611129Smckusick register struct entry *np; 22711129Smckusick 22811129Smckusick if (lookupino(newinum) != NIL) 22911129Smckusick badentry(ep, "renumber to active inum"); 23011129Smckusick np = lookupino(ep->e_ino); 23111129Smckusick if (np == NIL) 23211129Smckusick badentry(ep, "lookupino failed"); 23311129Smckusick deleteino(ep->e_ino); 23411129Smckusick addino(newinum, ep); 23511129Smckusick for (; np != NIL; np = np->e_links) 23611129Smckusick np->e_ino = newinum; 23711129Smckusick } 23811129Smckusick 23911129Smckusick /* 24010314Smckusick * Relocate an entry in the tree structure 24110314Smckusick */ 24210314Smckusick moveentry(ep, newname) 24310314Smckusick register struct entry *ep; 24410314Smckusick char *newname; 24510314Smckusick { 24610314Smckusick struct entry *np; 24710314Smckusick char *cp; 24810314Smckusick long len; 24910314Smckusick 25010314Smckusick np = lookupparent(newname); 25110314Smckusick if (np == NIL) 25210314Smckusick badentry(ep, "cannot move ROOT"); 25310314Smckusick if (np != ep->e_parent) { 25410314Smckusick removeentry(ep); 25510314Smckusick ep->e_parent = np; 25610314Smckusick ep->e_sibling = np->e_entries; 25710314Smckusick np->e_entries = ep; 25810314Smckusick } 25910314Smckusick cp = rindex(newname, '/') + 1; 26010314Smckusick len = strlen(cp); 26110314Smckusick if (ep->e_flags & TMPNAME) 26210314Smckusick ep->e_namlen--; 26310314Smckusick if (ep->e_namlen >= len) { 26410314Smckusick strcpy(ep->e_name, cp); 26510314Smckusick } else { 26610314Smckusick free(ep->e_name); 26710314Smckusick ep->e_name = savename(cp); 26810314Smckusick } 26910314Smckusick ep->e_namlen = len; 27010314Smckusick if (cp[len - 1] == TMPCHAR) 27110314Smckusick ep->e_flags |= TMPNAME; 27210314Smckusick else 27310314Smckusick ep->e_flags &= ~TMPNAME; 27410314Smckusick } 27510314Smckusick 27610314Smckusick /* 27710314Smckusick * Remove an entry in the tree structure 27810314Smckusick */ 27910314Smckusick removeentry(ep) 28010314Smckusick register struct entry *ep; 28110314Smckusick { 28210314Smckusick register struct entry *np; 28310314Smckusick 28410314Smckusick np = ep->e_parent; 28510314Smckusick if (np->e_entries == ep) { 28610314Smckusick np->e_entries = ep->e_sibling; 28710314Smckusick } else { 28810314Smckusick for (np = np->e_entries; np != NIL; np = np->e_sibling) { 28910314Smckusick if (np->e_sibling == ep) { 29010314Smckusick np->e_sibling = ep->e_sibling; 29110314Smckusick break; 29210314Smckusick } 29310314Smckusick } 29410314Smckusick if (np == NIL) 29510314Smckusick badentry(ep, "cannot find entry in parent list"); 29610314Smckusick } 29710314Smckusick } 29810314Smckusick 29910314Smckusick /* 30010314Smckusick * allocate space for a name 30110314Smckusick */ 30210314Smckusick char * 30310314Smckusick savename(name) 30410314Smckusick char *name; 30510314Smckusick { 30610314Smckusick long len; 307*11311Smckusick char *cp; 30810314Smckusick 30910314Smckusick if (name == NULL) 31010314Smckusick panic("bad name\n"); 31110314Smckusick len = strlen(name) + 2; 31210314Smckusick len = (len + 3) & ~3; 313*11311Smckusick cp = (char *)malloc((unsigned)len); 314*11311Smckusick strcpy(cp, name); 315*11311Smckusick return (cp); 31610314Smckusick } 31710314Smckusick 31810314Smckusick /* 31910314Smckusick * dump a snapshot of the symbol table 32010314Smckusick */ 32110314Smckusick dumpsymtable(filename, checkpt) 32210314Smckusick char *filename; 32310314Smckusick long checkpt; 32410314Smckusick { 32510314Smckusick register struct entry *ep; 32611129Smckusick register long i; 32710314Smckusick struct entry *next; 32810314Smckusick long mynum = 0, stroff = 0; 32910314Smckusick FILE *fd; 33010314Smckusick struct symtableheader hdr; 33110314Smckusick 33210314Smckusick vprintf(stdout, "Check pointing the restore\n"); 33310314Smckusick if ((fd = fopen(filename, "w")) == NULL) { 33410314Smckusick perror("fopen"); 33510314Smckusick panic("cannot create save file %s for symbol table\n", 33610314Smckusick filename); 33710314Smckusick } 33810314Smckusick clearerr(fd); 33910314Smckusick /* 34010314Smckusick * Assign indicies to each entry 34110314Smckusick * Write out the string entries 34210314Smckusick */ 34310314Smckusick for (i = ROOTINO; i < maxino; i++) { 34410314Smckusick for (ep = lookupino(i); ep != NIL; ep = ep->e_links) { 34511129Smckusick ep->e_newname = (char *)mynum++; 34610314Smckusick fwrite(ep->e_name, sizeof(char), (int)ep->e_namlen, fd); 34710314Smckusick ep->e_name = (char *)stroff; 34810314Smckusick stroff += ep->e_namlen; 34910314Smckusick } 35010314Smckusick } 35110314Smckusick /* 35210314Smckusick * Convert entry pointers to indexes, and output 35310314Smckusick */ 35411129Smckusick for (i = 0; i < maxino; i++) { 35510314Smckusick if (entry[i] == NIL) 35610314Smckusick continue; 35711129Smckusick entry[i] = (struct entry *)entry[i]->e_newname; 35810314Smckusick } 35911129Smckusick fwrite((char *)entry, sizeof(struct entry *), (int)maxino, fd); 36010314Smckusick /* 36110314Smckusick * Convert pointers to indexes, and output 36210314Smckusick */ 36310314Smckusick for (i = ROOTINO; i < maxino; i++) { 36410314Smckusick for (ep = lookupino(i); ep != NIL; ep = next) { 36510314Smckusick next = ep->e_links; 36611129Smckusick ep->e_parent = (struct entry *)ep->e_parent->e_newname; 36711129Smckusick ep->e_links = (struct entry *)ep->e_links->e_newname; 36811129Smckusick ep->e_sibling = 36911129Smckusick (struct entry *)ep->e_sibling->e_newname; 37011129Smckusick ep->e_entries = 37111129Smckusick (struct entry *)ep->e_entries->e_newname; 37210314Smckusick fwrite((char *)ep, sizeof(struct entry), 1, fd); 37310314Smckusick } 37410314Smckusick } 37510314Smckusick hdr.volno = checkpt; 37610314Smckusick hdr.maxino = maxino; 37710314Smckusick hdr.stringsize = stroff; 37811303Smckusick hdr.dumptime = dumptime; 37911303Smckusick hdr.dumpdate = dumpdate; 38010314Smckusick fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd); 38110314Smckusick if (ferror(fd)) { 38210314Smckusick perror("fwrite"); 38310314Smckusick panic("output error to file %s writing symbol table\n", 38410314Smckusick filename); 38510314Smckusick } 38610314Smckusick fclose(fd); 38710314Smckusick } 38810314Smckusick 38910314Smckusick /* 39010314Smckusick * Initialize a symbol table from a file 39110314Smckusick */ 39210314Smckusick initsymtable(filename) 39310314Smckusick char *filename; 39410314Smckusick { 39510314Smckusick char *base; 39610314Smckusick long tblsize; 39710314Smckusick register struct entry *ep; 39810314Smckusick struct entry *baseep, *lep; 39910314Smckusick struct symtableheader hdr; 40010314Smckusick struct stat stbuf; 40110314Smckusick register long i; 40210314Smckusick int fd; 40310314Smckusick 40410314Smckusick vprintf(stdout, "Initialize symbol table.\n"); 40510314Smckusick if ((fd = open(filename, 0)) < 0) { 40610314Smckusick perror("open"); 40710314Smckusick panic("cannot open symbol table file %s\n", filename); 40810314Smckusick } 40910314Smckusick if (fstat(fd, &stbuf) < 0) { 41010314Smckusick perror("stat"); 41110314Smckusick panic("cannot stat symbol table file %s\n", filename); 41210314Smckusick } 41310314Smckusick tblsize = stbuf.st_size - sizeof(struct symtableheader); 41411129Smckusick base = (char *)malloc((unsigned)tblsize); 41510314Smckusick if (base == NULL) 41610314Smckusick panic("cannot allocate space for symbol table\n"); 41710314Smckusick if (read(fd, base, (int)tblsize) < 0 || 41810314Smckusick read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) { 41910314Smckusick perror("read"); 42010314Smckusick panic("cannot read symbol table file %s\n", filename); 42110314Smckusick } 42211303Smckusick switch (command) { 42311303Smckusick case 'r': 42411303Smckusick /* 42511303Smckusick * For normal continuation, insure that we are using 42611303Smckusick * the next incremental tape 42711303Smckusick */ 42811303Smckusick if (hdr.dumptime != dumpdate) { 42911303Smckusick if (hdr.dumptime < dumpdate) 43011303Smckusick fprintf(stderr, "Incremental tape too low\n"); 43111303Smckusick else 43211303Smckusick fprintf(stderr, "Incremental tape too high\n"); 43311303Smckusick done(1); 43411303Smckusick } 43511303Smckusick break; 43611303Smckusick case 'R': 43711303Smckusick /* 43811303Smckusick * For restart, insure that we are using the same tape 43911303Smckusick */ 44011303Smckusick if (hdr.volno == 1) { 44111303Smckusick setup(); 44211303Smckusick if (dumptime != hdr.dumptime || 44311303Smckusick dumpdate != hdr.dumpdate) { 44411303Smckusick fprintf(stderr, "Wrong dump tape\n"); 44511303Smckusick done(1); 44611303Smckusick } 44711303Smckusick extractdirs(); 44811303Smckusick } else { 44911303Smckusick curfile.action = SKIP; 45011303Smckusick dumptime = hdr.dumptime; 45111303Smckusick dumpdate = hdr.dumpdate; 45211303Smckusick getvol(hdr.volno); 45311303Smckusick } 45411303Smckusick break; 45511303Smckusick default: 45611303Smckusick panic("initsymtable called from command %c\n", command); 45711303Smckusick break; 45811303Smckusick } 45910314Smckusick maxino = hdr.maxino; 46010314Smckusick entry = (struct entry **)(base + hdr.stringsize); 46111129Smckusick baseep = (struct entry *)(&entry[maxino]); 46210314Smckusick lep = (struct entry *)(base + tblsize); 46311129Smckusick for (i = 0; i < maxino; i++) { 46410314Smckusick if (entry[i] == NIL) 46510314Smckusick continue; 46610314Smckusick entry[i] = &baseep[(long)entry[i]]; 46710314Smckusick } 46810314Smckusick for (ep = baseep; ep < lep; ep++) { 46910314Smckusick ep->e_name = base + (long)ep->e_name; 47010314Smckusick ep->e_parent = &baseep[(long)ep->e_parent]; 47111129Smckusick ep->e_sibling = &baseep[(long)ep->e_sibling]; 47211129Smckusick ep->e_links = &baseep[(long)ep->e_links]; 47311129Smckusick ep->e_entries = &baseep[(long)ep->e_entries]; 47410314Smckusick } 47510314Smckusick } 476