111127Smckusick #ifndef lint 2*18008Smckusick static char sccsid[] = "@(#)dirs.c 3.20 (Berkeley) 85/02/18"; 311127Smckusick #endif 411127Smckusick 514563Ssam /* Copyright (c) 1983 Regents of the University of California */ 614563Ssam 711127Smckusick #include "restore.h" 811127Smckusick #include <dumprestor.h> 911309Smckusick #include <sys/file.h> 1011127Smckusick 1111992Smckusick /* 1211992Smckusick * Symbol table of directories read from tape. 1311992Smckusick */ 1411127Smckusick #define HASHSIZE 1000 1511127Smckusick #define INOHASH(val) (val % HASHSIZE) 1611127Smckusick struct inotab { 1711127Smckusick struct inotab *t_next; 1811127Smckusick ino_t t_ino; 1911127Smckusick daddr_t t_seekpt; 2011127Smckusick long t_size; 2111309Smckusick }; 2211309Smckusick static struct inotab *inotab[HASHSIZE]; 2311309Smckusick extern struct inotab *inotablookup(); 2411322Smckusick extern struct inotab *allocinotab(); 2511127Smckusick 2611992Smckusick /* 2711992Smckusick * Information retained about directories. 2811992Smckusick */ 2911127Smckusick struct modeinfo { 3011127Smckusick ino_t ino; 3111127Smckusick time_t timep[2]; 3211127Smckusick short mode; 3311127Smckusick short uid; 3411127Smckusick short gid; 3511127Smckusick }; 3611127Smckusick 3711992Smckusick /* 3811992Smckusick * Global variables for this file. 3911992Smckusick */ 4011309Smckusick static daddr_t seekpt; 4111309Smckusick static FILE *df, *mf; 4211309Smckusick static DIR *dirp; 4311992Smckusick static char dirfile[32] = "#"; /* No file */ 4411992Smckusick static char modefile[32] = "#"; /* No file */ 4511309Smckusick extern ino_t search(); 4612556Smckusick struct direct *rst_readdir(); 4712556Smckusick extern void rst_seekdir(); 4811127Smckusick 4911992Smckusick /* 5011992Smckusick * Format of old style directories. 5111992Smckusick */ 5211127Smckusick #define ODIRSIZ 14 5311127Smckusick struct odirect { 5411127Smckusick u_short d_ino; 5511127Smckusick char d_name[ODIRSIZ]; 5611127Smckusick }; 5711127Smckusick 5811127Smckusick /* 5911127Smckusick * Extract directory contents, building up a directory structure 6011127Smckusick * on disk for extraction by name. 6111992Smckusick * If genmode is requested, save mode, owner, and times for all 6211127Smckusick * directories on the tape. 6311127Smckusick */ 6411992Smckusick extractdirs(genmode) 6511992Smckusick int genmode; 6611127Smckusick { 6711127Smckusick register int i; 6811127Smckusick register struct dinode *ip; 6911322Smckusick struct inotab *itp; 7011127Smckusick struct direct nulldir; 7111127Smckusick int putdir(), null(); 7211127Smckusick 7311127Smckusick vprintf(stdout, "Extract directories from tape\n"); 7411992Smckusick (void) sprintf(dirfile, "/tmp/rstdir%d", dumpdate); 7511127Smckusick df = fopen(dirfile, "w"); 7611127Smckusick if (df == 0) { 7711127Smckusick fprintf(stderr, 7815779Smckusick "restore: %s - cannot create directory temporary\n", 7911127Smckusick dirfile); 8011127Smckusick perror("fopen"); 8111127Smckusick done(1); 8211127Smckusick } 8311992Smckusick if (genmode != 0) { 8411992Smckusick (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate); 8511127Smckusick mf = fopen(modefile, "w"); 8611309Smckusick if (mf == 0) { 8711127Smckusick fprintf(stderr, 8815779Smckusick "restore: %s - cannot create modefile \n", 8911127Smckusick modefile); 9011127Smckusick perror("fopen"); 9111127Smckusick done(1); 9211127Smckusick } 9311127Smckusick } 9411322Smckusick nulldir.d_ino = 0; 9511127Smckusick nulldir.d_namlen = 1; 9612453Smckusick (void) strcpy(nulldir.d_name, "/"); 9711127Smckusick nulldir.d_reclen = DIRSIZ(&nulldir); 9811127Smckusick for (;;) { 9911127Smckusick curfile.name = "<directory file - name unknown>"; 10011127Smckusick curfile.action = USING; 10111127Smckusick ip = curfile.dip; 10217948Smckusick if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { 10311732Smckusick (void) fclose(df); 10411127Smckusick dirp = opendir(dirfile); 10511127Smckusick if (dirp == NULL) 10611127Smckusick perror("opendir"); 10711127Smckusick if (mf != NULL) 10811732Smckusick (void) fclose(mf); 10911992Smckusick i = dirlookup("."); 11011992Smckusick if (i == 0) 11111421Smckusick panic("Root directory is not on tape\n"); 11211127Smckusick return; 11311127Smckusick } 11411322Smckusick itp = allocinotab(curfile.ino, ip, seekpt); 11511127Smckusick getfile(putdir, null); 11611127Smckusick putent(&nulldir); 11711127Smckusick flushent(); 11811322Smckusick itp->t_size = seekpt - itp->t_seekpt; 11911127Smckusick } 12011127Smckusick } 12111127Smckusick 12211127Smckusick /* 12311322Smckusick * skip over all the directories on the tape 12411322Smckusick */ 12511322Smckusick skipdirs() 12611322Smckusick { 12711322Smckusick 12811322Smckusick while ((curfile.dip->di_mode & IFMT) == IFDIR) { 12911322Smckusick skipfile(); 13011322Smckusick } 13111322Smckusick } 13211322Smckusick 13311322Smckusick /* 13411127Smckusick * Recursively find names and inumbers of all files in subtree 13511127Smckusick * pname and pass them off to be processed. 13611127Smckusick */ 13711127Smckusick treescan(pname, ino, todo) 13811127Smckusick char *pname; 13911127Smckusick ino_t ino; 14011744Smckusick long (*todo)(); 14111127Smckusick { 14211127Smckusick register struct inotab *itp; 14312453Smckusick register struct direct *dp; 14412453Smckusick register struct entry *np; 14511127Smckusick int namelen; 14611127Smckusick daddr_t bpt; 14711644Smckusick char locname[MAXPATHLEN + 1]; 14811127Smckusick 14911127Smckusick itp = inotablookup(ino); 15011127Smckusick if (itp == NULL) { 15111127Smckusick /* 15211127Smckusick * Pname is name of a simple file or an unchanged directory. 15311127Smckusick */ 15411744Smckusick (void) (*todo)(pname, ino, LEAF); 15511127Smckusick return; 15611127Smckusick } 15711127Smckusick /* 15811127Smckusick * Pname is a dumped directory name. 15911127Smckusick */ 16011744Smckusick if ((*todo)(pname, ino, NODE) == FAIL) 16111744Smckusick return; 16211127Smckusick /* 16311127Smckusick * begin search through the directory 16411127Smckusick * skipping over "." and ".." 16511127Smckusick */ 16611992Smckusick (void) strncpy(locname, pname, MAXPATHLEN); 16711992Smckusick (void) strncat(locname, "/", MAXPATHLEN); 16811127Smckusick namelen = strlen(locname); 16912556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 17012556Smckusick dp = rst_readdir(dirp); /* "." */ 17112453Smckusick if (dp != NULL && strcmp(dp->d_name, ".") == 0) { 17212556Smckusick dp = rst_readdir(dirp); /* ".." */ 17312453Smckusick } else { 17412453Smckusick np = lookupino(ino); 17512453Smckusick if (np == NULL) 17612453Smckusick panic("corrupted symbol table\n"); 17712453Smckusick fprintf(stderr, ". missing from directory %s\n", myname(np)); 17812453Smckusick } 17912453Smckusick if (dp != NULL && strcmp(dp->d_name, "..") == 0) { 18012556Smckusick dp = rst_readdir(dirp); /* first real entry */ 18112453Smckusick } else { 18212453Smckusick np = lookupino(ino); 18312453Smckusick if (np == NULL) 18412453Smckusick panic("corrupted symbol table\n"); 18512453Smckusick fprintf(stderr, ".. missing from directory %s\n", myname(np)); 18612453Smckusick } 18711127Smckusick bpt = telldir(dirp); 18811127Smckusick /* 18912453Smckusick * a zero inode signals end of directory 19011127Smckusick */ 19112453Smckusick while (dp != NULL && dp->d_ino != 0) { 19211127Smckusick locname[namelen] = '\0'; 19311644Smckusick if (namelen + dp->d_namlen >= MAXPATHLEN) { 19411127Smckusick fprintf(stderr, "%s%s: name exceeds %d char\n", 19511644Smckusick locname, dp->d_name, MAXPATHLEN); 19611127Smckusick } else { 19711992Smckusick (void) strncat(locname, dp->d_name, (int)dp->d_namlen); 19811127Smckusick treescan(locname, dp->d_ino, todo); 19912556Smckusick rst_seekdir(dirp, bpt, itp->t_seekpt); 20011127Smckusick } 20112556Smckusick dp = rst_readdir(dirp); 20211127Smckusick bpt = telldir(dirp); 20311127Smckusick } 20411127Smckusick if (dp == NULL) 20511127Smckusick fprintf(stderr, "corrupted directory: %s.\n", locname); 20611127Smckusick } 20711127Smckusick 20811127Smckusick /* 20911127Smckusick * Search the directory tree rooted at inode ROOTINO 21011127Smckusick * for the path pointed at by n 21111127Smckusick */ 21211127Smckusick ino_t 21311127Smckusick psearch(n) 21411127Smckusick char *n; 21511127Smckusick { 21611127Smckusick register char *cp, *cp1; 21711127Smckusick ino_t ino; 21811127Smckusick char c; 21911127Smckusick 22011127Smckusick ino = ROOTINO; 22111127Smckusick if (*(cp = n) == '/') 22211127Smckusick cp++; 22311127Smckusick next: 22411127Smckusick cp1 = cp + 1; 22511127Smckusick while (*cp1 != '/' && *cp1) 22611127Smckusick cp1++; 22711127Smckusick c = *cp1; 22811127Smckusick *cp1 = 0; 22911127Smckusick ino = search(ino, cp); 23011127Smckusick if (ino == 0) { 23111127Smckusick *cp1 = c; 23211127Smckusick return(0); 23311127Smckusick } 23411127Smckusick *cp1 = c; 23511127Smckusick if (c == '/') { 23611127Smckusick cp = cp1+1; 23711127Smckusick goto next; 23811127Smckusick } 23911127Smckusick return(ino); 24011127Smckusick } 24111127Smckusick 24211127Smckusick /* 24311127Smckusick * search the directory inode ino 24411127Smckusick * looking for entry cp 24511127Smckusick */ 24611127Smckusick ino_t 24711127Smckusick search(inum, cp) 24811127Smckusick ino_t inum; 24911127Smckusick char *cp; 25011127Smckusick { 25111127Smckusick register struct direct *dp; 25211127Smckusick register struct inotab *itp; 25311127Smckusick int len; 25411127Smckusick 25511127Smckusick itp = inotablookup(inum); 25611127Smckusick if (itp == NULL) 25711127Smckusick return(0); 25812556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 25911127Smckusick len = strlen(cp); 26011127Smckusick do { 26112556Smckusick dp = rst_readdir(dirp); 26212453Smckusick if (dp == NULL || dp->d_ino == 0) 26312453Smckusick return (0); 26411992Smckusick } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len) != 0); 26511127Smckusick return(dp->d_ino); 26611127Smckusick } 26711127Smckusick 26811127Smckusick /* 26911127Smckusick * Put the directory entries in the directory file 27011127Smckusick */ 27111127Smckusick putdir(buf, size) 27211127Smckusick char *buf; 27311127Smckusick int size; 27411127Smckusick { 27511127Smckusick struct direct cvtbuf; 27611127Smckusick register struct odirect *odp; 27711127Smckusick struct odirect *eodp; 27811127Smckusick register struct direct *dp; 27911127Smckusick long loc, i; 28011127Smckusick 28111127Smckusick if (cvtflag) { 28211127Smckusick eodp = (struct odirect *)&buf[size]; 28311127Smckusick for (odp = (struct odirect *)buf; odp < eodp; odp++) 28411127Smckusick if (odp->d_ino != 0) { 28511127Smckusick dcvt(odp, &cvtbuf); 28611127Smckusick putent(&cvtbuf); 28711127Smckusick } 28811127Smckusick } else { 28911127Smckusick for (loc = 0; loc < size; ) { 29011127Smckusick dp = (struct direct *)(buf + loc); 29111127Smckusick i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 29211127Smckusick if (dp->d_reclen == 0 || dp->d_reclen > i) { 29311127Smckusick loc += i; 29411127Smckusick continue; 29511127Smckusick } 29611127Smckusick loc += dp->d_reclen; 29711127Smckusick if (dp->d_ino != 0) { 29811127Smckusick putent(dp); 29911127Smckusick } 30011127Smckusick } 30111127Smckusick } 30211127Smckusick } 30311127Smckusick 30411127Smckusick /* 30511127Smckusick * These variables are "local" to the following two functions. 30611127Smckusick */ 30711127Smckusick char dirbuf[DIRBLKSIZ]; 30811127Smckusick long dirloc = 0; 30911127Smckusick long prev = 0; 31011127Smckusick 31111127Smckusick /* 31211127Smckusick * add a new directory entry to a file. 31311127Smckusick */ 31411127Smckusick putent(dp) 31511127Smckusick struct direct *dp; 31611127Smckusick { 31711322Smckusick dp->d_reclen = DIRSIZ(dp); 31811127Smckusick if (dirloc + dp->d_reclen > DIRBLKSIZ) { 31911127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = 32011127Smckusick DIRBLKSIZ - prev; 32111732Smckusick (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); 32211127Smckusick dirloc = 0; 32311127Smckusick } 32411127Smckusick bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 32511127Smckusick prev = dirloc; 32611127Smckusick dirloc += dp->d_reclen; 32711127Smckusick } 32811127Smckusick 32911127Smckusick /* 33011127Smckusick * flush out a directory that is finished. 33111127Smckusick */ 33211127Smckusick flushent() 33311127Smckusick { 33411127Smckusick 33511127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 33611732Smckusick (void) fwrite(dirbuf, (int)dirloc, 1, df); 33711127Smckusick seekpt = ftell(df); 33811127Smckusick dirloc = 0; 33911127Smckusick } 34011127Smckusick 34111127Smckusick dcvt(odp, ndp) 34211127Smckusick register struct odirect *odp; 34311127Smckusick register struct direct *ndp; 34411127Smckusick { 34511127Smckusick 34611127Smckusick bzero((char *)ndp, (long)(sizeof *ndp)); 34711127Smckusick ndp->d_ino = odp->d_ino; 34811992Smckusick (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 34911127Smckusick ndp->d_namlen = strlen(ndp->d_name); 35011127Smckusick ndp->d_reclen = DIRSIZ(ndp); 35111127Smckusick } 35211127Smckusick 35311127Smckusick /* 35411127Smckusick * Seek to an entry in a directory. 35512556Smckusick * Only values returned by ``telldir'' should be passed to rst_seekdir. 35611732Smckusick * This routine handles many directories in a single file. 35711732Smckusick * It takes the base of the directory in the file, plus 35811732Smckusick * the desired seek offset into it. 35911127Smckusick */ 36011127Smckusick void 36112556Smckusick rst_seekdir(dirp, loc, base) 36211127Smckusick register DIR *dirp; 36311127Smckusick daddr_t loc, base; 36411127Smckusick { 36511127Smckusick 36611127Smckusick if (loc == telldir(dirp)) 36711127Smckusick return; 36811127Smckusick loc -= base; 36911127Smckusick if (loc < 0) 37012556Smckusick fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); 37111127Smckusick (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); 37211127Smckusick dirp->dd_loc = loc & (DIRBLKSIZ - 1); 37311127Smckusick if (dirp->dd_loc != 0) 37411127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 37511127Smckusick } 37611127Smckusick 37711127Smckusick /* 37811127Smckusick * get next entry in a directory. 37911127Smckusick */ 38011127Smckusick struct direct * 38112556Smckusick rst_readdir(dirp) 38211127Smckusick register DIR *dirp; 38311127Smckusick { 38411127Smckusick register struct direct *dp; 38511127Smckusick 38611127Smckusick for (;;) { 38711127Smckusick if (dirp->dd_loc == 0) { 38811127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 38911127Smckusick DIRBLKSIZ); 39012453Smckusick if (dirp->dd_size <= 0) { 39112453Smckusick dprintf(stderr, "error reading directory\n"); 39211127Smckusick return NULL; 39312453Smckusick } 39411127Smckusick } 39511127Smckusick if (dirp->dd_loc >= dirp->dd_size) { 39611127Smckusick dirp->dd_loc = 0; 39711127Smckusick continue; 39811127Smckusick } 39911127Smckusick dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 40011127Smckusick if (dp->d_reclen == 0 || 40112453Smckusick dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { 40212453Smckusick dprintf(stderr, "corrupted directory: bad reclen %d\n", 40312453Smckusick dp->d_reclen); 40411127Smckusick return NULL; 40512453Smckusick } 40611127Smckusick dirp->dd_loc += dp->d_reclen; 40712453Smckusick if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) 40812453Smckusick continue; 40912556Smckusick if (dp->d_ino >= maxino) { 41012453Smckusick dprintf(stderr, "corrupted directory: bad inum %d\n", 41112453Smckusick dp->d_ino); 41212453Smckusick continue; 41312453Smckusick } 41411127Smckusick return (dp); 41511127Smckusick } 41611127Smckusick } 41711127Smckusick 41811127Smckusick /* 41917753Smckusick * Simulate the opening of a directory 42017753Smckusick */ 42117753Smckusick DIR * 42217753Smckusick rst_opendir(name) 42317753Smckusick char *name; 42417753Smckusick { 42517753Smckusick struct inotab *itp; 42617753Smckusick ino_t ino; 42717753Smckusick 42817753Smckusick if ((ino = dirlookup(name)) > 0 && 42917753Smckusick (itp = inotablookup(ino)) != NULL) { 43017753Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 43117753Smckusick return (dirp); 43217753Smckusick } 43317753Smckusick return (0); 43417753Smckusick } 43517753Smckusick 43617753Smckusick /* 43711127Smckusick * Set the mode, owner, and times for all new or changed directories 43811127Smckusick */ 43911992Smckusick setdirmodes() 44011127Smckusick { 44111127Smckusick FILE *mf; 44211127Smckusick struct modeinfo node; 44311127Smckusick struct entry *ep; 44411127Smckusick char *cp; 44511127Smckusick 44611127Smckusick vprintf(stdout, "Set directory mode, owner, and times.\n"); 44715779Smckusick (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate); 44811127Smckusick mf = fopen(modefile, "r"); 44911127Smckusick if (mf == NULL) { 45011127Smckusick perror("fopen"); 45115779Smckusick fprintf(stderr, "cannot open mode file %s\n", modefile); 45215779Smckusick fprintf(stderr, "directory mode, owner, and times not set\n"); 45315779Smckusick return; 45411127Smckusick } 45511127Smckusick clearerr(mf); 45611309Smckusick for (;;) { 45711732Smckusick (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); 45811309Smckusick if (feof(mf)) 45911309Smckusick break; 46011127Smckusick ep = lookupino(node.ino); 46114453Smckusick if (command == 'i' || command == 'x') { 46214453Smckusick if (ep == NIL) 46311309Smckusick continue; 464*18008Smckusick if (ep->e_flags & EXISTED) { 465*18008Smckusick ep->e_flags &= ~NEW; 466*18008Smckusick continue; 467*18008Smckusick } 46814453Smckusick if (node.ino == ROOTINO && 46914453Smckusick reply("set owner/mode for '.'") == FAIL) 47014453Smckusick continue; 47114453Smckusick } 47214453Smckusick if (ep == NIL) 47311127Smckusick panic("cannot find directory inode %d\n", node.ino); 47411127Smckusick cp = myname(ep); 47511732Smckusick (void) chown(cp, node.uid, node.gid); 47611732Smckusick (void) chmod(cp, node.mode); 47711127Smckusick utime(cp, node.timep); 47811992Smckusick ep->e_flags &= ~NEW; 47911127Smckusick } 48011127Smckusick if (ferror(mf)) 48111127Smckusick panic("error setting directory modes\n"); 48211732Smckusick (void) fclose(mf); 48311127Smckusick } 48411127Smckusick 48511127Smckusick /* 48611127Smckusick * Generate a literal copy of a directory. 48711127Smckusick */ 48811127Smckusick genliteraldir(name, ino) 48911127Smckusick char *name; 49011127Smckusick ino_t ino; 49111127Smckusick { 49211127Smckusick register struct inotab *itp; 49311127Smckusick int ofile, dp, i, size; 49411127Smckusick char buf[BUFSIZ]; 49511127Smckusick 49611127Smckusick itp = inotablookup(ino); 49711127Smckusick if (itp == NULL) 49811322Smckusick panic("Cannot find directory inode %d named %s\n", ino, name); 49912893Ssam if ((ofile = creat(name, 0666)) < 0) { 50012556Smckusick fprintf(stderr, "%s: ", name); 50112556Smckusick (void) fflush(stderr); 50212556Smckusick perror("cannot create file"); 50311127Smckusick return (FAIL); 50411127Smckusick } 50512556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 50611127Smckusick dp = dup(dirp->dd_fd); 50711127Smckusick for (i = itp->t_size; i > 0; i -= BUFSIZ) { 50811127Smckusick size = i < BUFSIZ ? i : BUFSIZ; 50911127Smckusick if (read(dp, buf, (int) size) == -1) { 51011127Smckusick fprintf(stderr, 51111127Smckusick "write error extracting inode %d, name %s\n", 51211127Smckusick curfile.ino, curfile.name); 51311127Smckusick perror("read"); 51411127Smckusick done(1); 51511127Smckusick } 51611127Smckusick if (write(ofile, buf, (int) size) == -1) { 51711127Smckusick fprintf(stderr, 51811127Smckusick "write error extracting inode %d, name %s\n", 51911127Smckusick curfile.ino, curfile.name); 52011127Smckusick perror("write"); 52111127Smckusick done(1); 52211127Smckusick } 52311127Smckusick } 52411732Smckusick (void) close(dp); 52511732Smckusick (void) close(ofile); 52611127Smckusick return (GOOD); 52711127Smckusick } 52811127Smckusick 52911127Smckusick /* 53011992Smckusick * Determine the type of an inode 53111992Smckusick */ 53211992Smckusick inodetype(ino) 53311992Smckusick ino_t ino; 53411992Smckusick { 53511992Smckusick struct inotab *itp; 53611992Smckusick 53711992Smckusick itp = inotablookup(ino); 53811992Smckusick if (itp == NULL) 53911992Smckusick return (LEAF); 54011992Smckusick return (NODE); 54111992Smckusick } 54211992Smckusick 54311992Smckusick /* 54411127Smckusick * Allocate and initialize a directory inode entry. 54511127Smckusick * If requested, save its pertinent mode, owner, and time info. 54611127Smckusick */ 54711322Smckusick struct inotab * 54811127Smckusick allocinotab(ino, dip, seekpt) 54911127Smckusick ino_t ino; 55011127Smckusick struct dinode *dip; 55111127Smckusick daddr_t seekpt; 55211127Smckusick { 55311127Smckusick register struct inotab *itp; 55411127Smckusick struct modeinfo node; 55511127Smckusick 55611127Smckusick itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 55713859Smckusick if (itp == 0) 55813859Smckusick panic("no memory directory table\n"); 55911127Smckusick itp->t_next = inotab[INOHASH(ino)]; 56011127Smckusick inotab[INOHASH(ino)] = itp; 56111127Smckusick itp->t_ino = ino; 56211127Smckusick itp->t_seekpt = seekpt; 56311127Smckusick if (mf == NULL) 56411322Smckusick return(itp); 56511127Smckusick node.ino = ino; 56611127Smckusick node.timep[0] = dip->di_atime; 56711127Smckusick node.timep[1] = dip->di_mtime; 56811127Smckusick node.mode = dip->di_mode; 56911127Smckusick node.uid = dip->di_uid; 57011127Smckusick node.gid = dip->di_gid; 57111732Smckusick (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); 57211322Smckusick return(itp); 57311127Smckusick } 57411127Smckusick 57511127Smckusick /* 57611127Smckusick * Look up an inode in the table of directories 57711127Smckusick */ 57811127Smckusick struct inotab * 57911127Smckusick inotablookup(ino) 58011127Smckusick ino_t ino; 58111127Smckusick { 58211127Smckusick register struct inotab *itp; 58311127Smckusick 58411127Smckusick for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) 58511127Smckusick if (itp->t_ino == ino) 58611127Smckusick return(itp); 58711127Smckusick return ((struct inotab *)0); 58811127Smckusick } 58911127Smckusick 59011127Smckusick /* 59111127Smckusick * Clean up and exit 59211127Smckusick */ 59311127Smckusick done(exitcode) 59411127Smckusick int exitcode; 59511127Smckusick { 59611127Smckusick 59711127Smckusick closemt(); 59811992Smckusick if (modefile[0] != '#') 59911992Smckusick (void) unlink(modefile); 60011992Smckusick if (dirfile[0] != '#') 60111992Smckusick (void) unlink(dirfile); 60211127Smckusick exit(exitcode); 60311127Smckusick } 604