📄 symtab.c
字号:
/* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)symtab.c 8.1 (Berkeley) 6/5/93";#endif /* not lint *//* * These routines maintain the symbol table which tracks the state * of the file system being restored. They provide lookup by either * name or inode number. They also provide for creation, deletion, * and renaming of entries. Because of the dynamic nature of pathnames, * names should not be saved, but always constructed just before they * are needed, by calling "myname". */#include <sys/param.h>#include <sys/stat.h>#include <ufs/ufs/dinode.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "restore.h"#include "extern.h"/* * The following variables define the inode symbol table. * The primary hash table is dynamically allocated based on * the number of inodes in the file system (maxino), scaled by * HASHFACTOR. The variable "entry" points to the hash table; * the variable "entrytblsize" indicates its size (in entries). */#define HASHFACTOR 5static struct entry **entry;static long entrytblsize;static void addino __P((ino_t, struct entry *));static struct entry *lookupparent __P((char *));static void removeentry __P((struct entry *));/* * Look up an entry by inode number */struct entry *lookupino(inum) ino_t inum;{ register struct entry *ep; if (inum < ROOTINO || inum >= maxino) return (NULL); for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next) if (ep->e_ino == inum) return (ep); return (NULL);}/* * Add an entry into the entry table */static voidaddino(inum, np) ino_t inum; struct entry *np;{ struct entry **epp; if (inum < ROOTINO || inum >= maxino) panic("addino: out of range %d\n", inum); epp = &entry[inum % entrytblsize]; np->e_ino = inum; np->e_next = *epp; *epp = np; if (dflag) for (np = np->e_next; np != NULL; np = np->e_next) if (np->e_ino == inum) badentry(np, "duplicate inum");}/* * Delete an entry from the entry table */voiddeleteino(inum) ino_t inum;{ register struct entry *next; struct entry **prev; if (inum < ROOTINO || inum >= maxino) panic("deleteino: out of range %d\n", inum); prev = &entry[inum % entrytblsize]; for (next = *prev; next != NULL; next = next->e_next) { if (next->e_ino == inum) { next->e_ino = 0; *prev = next->e_next; return; } prev = &next->e_next; } panic("deleteino: %d not found\n", inum);}/* * Look up an entry by name */struct entry *lookupname(name) char *name;{ register struct entry *ep; register char *np, *cp; char buf[MAXPATHLEN]; cp = name; for (ep = lookupino(ROOTINO); ep != NULL; ep = ep->e_entries) { for (np = buf; *cp != '/' && *cp != '\0'; ) *np++ = *cp++; *np = '\0'; for ( ; ep != NULL; ep = ep->e_sibling) if (strcmp(ep->e_name, buf) == 0) break; if (ep == NULL) break; if (*cp++ == '\0') return (ep); } return (NULL);}/* * Look up the parent of a pathname */static struct entry *lookupparent(name) char *name;{ struct entry *ep; char *tailindex; tailindex = rindex(name, '/'); if (tailindex == NULL) return (NULL); *tailindex = '\0'; ep = lookupname(name); *tailindex = '/'; if (ep == NULL) return (NULL); if (ep->e_type != NODE) panic("%s is not a directory\n", name); return (ep);}/* * Determine the current pathname of a node or leaf */char *myname(ep) register struct entry *ep;{ register char *cp; static char namebuf[MAXPATHLEN]; for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) { cp -= ep->e_namlen; bcopy(ep->e_name, cp, (long)ep->e_namlen); if (ep == lookupino(ROOTINO)) return (cp); *(--cp) = '/'; ep = ep->e_parent; } panic("%s: pathname too long\n", cp); return(cp);}/* * Unused symbol table entries are linked together on a freelist * headed by the following pointer. */static struct entry *freelist = NULL;/* * add an entry to the symbol table */struct entry *addentry(name, inum, type) char *name; ino_t inum; int type;{ register struct entry *np, *ep; if (freelist != NULL) { np = freelist; freelist = np->e_next; bzero((char *)np, (long)sizeof(struct entry)); } else { np = (struct entry *)calloc(1, sizeof(struct entry)); if (np == NULL) panic("no memory to extend symbol table\n"); } np->e_type = type & ~LINK; ep = lookupparent(name); if (ep == NULL) { if (inum != ROOTINO || lookupino(ROOTINO) != NULL) panic("bad name to addentry %s\n", name); np->e_name = savename(name); np->e_namlen = strlen(name); np->e_parent = np; addino(ROOTINO, np); return (np); } np->e_name = savename(rindex(name, '/') + 1); np->e_namlen = strlen(np->e_name); np->e_parent = ep; np->e_sibling = ep->e_entries; ep->e_entries = np; if (type & LINK) { ep = lookupino(inum); if (ep == NULL) panic("link to non-existant name\n"); np->e_ino = inum; np->e_links = ep->e_links; ep->e_links = np; } else if (inum != 0) { if (lookupino(inum) != NULL) panic("duplicate entry\n"); addino(inum, np); } return (np);}/* * delete an entry from the symbol table */voidfreeentry(ep) register struct entry *ep;{ register struct entry *np; ino_t inum; if (ep->e_flags != REMOVED) badentry(ep, "not marked REMOVED"); if (ep->e_type == NODE) { if (ep->e_links != NULL) badentry(ep, "freeing referenced directory"); if (ep->e_entries != NULL) badentry(ep, "freeing non-empty directory"); } if (ep->e_ino != 0) { np = lookupino(ep->e_ino); if (np == NULL) badentry(ep, "lookupino failed"); if (np == ep) { inum = ep->e_ino; deleteino(inum); if (ep->e_links != NULL) addino(inum, ep->e_links); } else { for (; np != NULL; np = np->e_links) { if (np->e_links == ep) { np->e_links = ep->e_links; break; } } if (np == NULL) badentry(ep, "link not found"); } } removeentry(ep); freename(ep->e_name); ep->e_next = freelist; freelist = ep;}/* * Relocate an entry in the tree structure */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -