121165Sdist /* 221165Sdist * Copyright (c) 1983 Regents of the University of California. 321165Sdist * All rights reserved. The Berkeley software License Agreement 421165Sdist * specifies the terms and conditions for redistribution. 521165Sdist */ 621165Sdist 711127Smckusick #ifndef lint 8*26941Ssklower static char sccsid[] = "@(#)dirs.c 5.3 (Berkeley) 03/26/86"; 921165Sdist #endif not lint 1011127Smckusick 1111127Smckusick #include "restore.h" 1223545Smckusick #include <protocols/dumprestore.h> 1311309Smckusick #include <sys/file.h> 1411127Smckusick 1511992Smckusick /* 1611992Smckusick * Symbol table of directories read from tape. 1711992Smckusick */ 1811127Smckusick #define HASHSIZE 1000 1911127Smckusick #define INOHASH(val) (val % HASHSIZE) 2011127Smckusick struct inotab { 2111127Smckusick struct inotab *t_next; 2211127Smckusick ino_t t_ino; 2311127Smckusick daddr_t t_seekpt; 2411127Smckusick long t_size; 2511309Smckusick }; 2611309Smckusick static struct inotab *inotab[HASHSIZE]; 2711309Smckusick extern struct inotab *inotablookup(); 2811322Smckusick extern struct inotab *allocinotab(); 2911127Smckusick 3011992Smckusick /* 3111992Smckusick * Information retained about directories. 3211992Smckusick */ 3311127Smckusick struct modeinfo { 3411127Smckusick ino_t ino; 3511127Smckusick time_t timep[2]; 3611127Smckusick short mode; 3711127Smckusick short uid; 3811127Smckusick short gid; 3911127Smckusick }; 4011127Smckusick 4111992Smckusick /* 4211992Smckusick * Global variables for this file. 4311992Smckusick */ 4411309Smckusick static daddr_t seekpt; 4511309Smckusick static FILE *df, *mf; 4611309Smckusick static DIR *dirp; 4711992Smckusick static char dirfile[32] = "#"; /* No file */ 4811992Smckusick static char modefile[32] = "#"; /* No file */ 4911309Smckusick extern ino_t search(); 5012556Smckusick struct direct *rst_readdir(); 5112556Smckusick extern void rst_seekdir(); 5211127Smckusick 5311992Smckusick /* 5411992Smckusick * Format of old style directories. 5511992Smckusick */ 5611127Smckusick #define ODIRSIZ 14 5711127Smckusick struct odirect { 5811127Smckusick u_short d_ino; 5911127Smckusick char d_name[ODIRSIZ]; 6011127Smckusick }; 6111127Smckusick 6211127Smckusick /* 6311127Smckusick * Extract directory contents, building up a directory structure 6411127Smckusick * on disk for extraction by name. 6511992Smckusick * If genmode is requested, save mode, owner, and times for all 6611127Smckusick * directories on the tape. 6711127Smckusick */ 6811992Smckusick extractdirs(genmode) 6911992Smckusick int genmode; 7011127Smckusick { 7111127Smckusick register int i; 7211127Smckusick register struct dinode *ip; 7311322Smckusick struct inotab *itp; 7411127Smckusick struct direct nulldir; 7511127Smckusick int putdir(), null(); 7611127Smckusick 7711127Smckusick vprintf(stdout, "Extract directories from tape\n"); 7811992Smckusick (void) sprintf(dirfile, "/tmp/rstdir%d", dumpdate); 7911127Smckusick df = fopen(dirfile, "w"); 8011127Smckusick if (df == 0) { 8111127Smckusick fprintf(stderr, 8215779Smckusick "restore: %s - cannot create directory temporary\n", 8311127Smckusick dirfile); 8411127Smckusick perror("fopen"); 8511127Smckusick done(1); 8611127Smckusick } 8711992Smckusick if (genmode != 0) { 8811992Smckusick (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate); 8911127Smckusick mf = fopen(modefile, "w"); 9011309Smckusick if (mf == 0) { 9111127Smckusick fprintf(stderr, 9215779Smckusick "restore: %s - cannot create modefile \n", 9311127Smckusick modefile); 9411127Smckusick perror("fopen"); 9511127Smckusick done(1); 9611127Smckusick } 9711127Smckusick } 9811322Smckusick nulldir.d_ino = 0; 9911127Smckusick nulldir.d_namlen = 1; 10012453Smckusick (void) strcpy(nulldir.d_name, "/"); 10111127Smckusick nulldir.d_reclen = DIRSIZ(&nulldir); 10211127Smckusick for (;;) { 10311127Smckusick curfile.name = "<directory file - name unknown>"; 10411127Smckusick curfile.action = USING; 10511127Smckusick ip = curfile.dip; 10617948Smckusick if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { 10711732Smckusick (void) fclose(df); 10811127Smckusick dirp = opendir(dirfile); 10911127Smckusick if (dirp == NULL) 11011127Smckusick perror("opendir"); 11111127Smckusick if (mf != NULL) 11211732Smckusick (void) fclose(mf); 11311992Smckusick i = dirlookup("."); 11411992Smckusick if (i == 0) 11511421Smckusick panic("Root directory is not on tape\n"); 11611127Smckusick return; 11711127Smckusick } 11811322Smckusick itp = allocinotab(curfile.ino, ip, seekpt); 11911127Smckusick getfile(putdir, null); 12011127Smckusick putent(&nulldir); 12111127Smckusick flushent(); 12211322Smckusick itp->t_size = seekpt - itp->t_seekpt; 12311127Smckusick } 12411127Smckusick } 12511127Smckusick 12611127Smckusick /* 12711322Smckusick * skip over all the directories on the tape 12811322Smckusick */ 12911322Smckusick skipdirs() 13011322Smckusick { 13111322Smckusick 13211322Smckusick while ((curfile.dip->di_mode & IFMT) == IFDIR) { 13311322Smckusick skipfile(); 13411322Smckusick } 13511322Smckusick } 13611322Smckusick 13711322Smckusick /* 13811127Smckusick * Recursively find names and inumbers of all files in subtree 13911127Smckusick * pname and pass them off to be processed. 14011127Smckusick */ 14111127Smckusick treescan(pname, ino, todo) 14211127Smckusick char *pname; 14311127Smckusick ino_t ino; 14411744Smckusick long (*todo)(); 14511127Smckusick { 14611127Smckusick register struct inotab *itp; 14712453Smckusick register struct direct *dp; 14812453Smckusick register struct entry *np; 14911127Smckusick int namelen; 15011127Smckusick daddr_t bpt; 15111644Smckusick char locname[MAXPATHLEN + 1]; 15211127Smckusick 15311127Smckusick itp = inotablookup(ino); 15411127Smckusick if (itp == NULL) { 15511127Smckusick /* 15611127Smckusick * Pname is name of a simple file or an unchanged directory. 15711127Smckusick */ 15811744Smckusick (void) (*todo)(pname, ino, LEAF); 15911127Smckusick return; 16011127Smckusick } 16111127Smckusick /* 16211127Smckusick * Pname is a dumped directory name. 16311127Smckusick */ 16411744Smckusick if ((*todo)(pname, ino, NODE) == FAIL) 16511744Smckusick return; 16611127Smckusick /* 16711127Smckusick * begin search through the directory 16811127Smckusick * skipping over "." and ".." 16911127Smckusick */ 17011992Smckusick (void) strncpy(locname, pname, MAXPATHLEN); 17111992Smckusick (void) strncat(locname, "/", MAXPATHLEN); 17211127Smckusick namelen = strlen(locname); 17312556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 17412556Smckusick dp = rst_readdir(dirp); /* "." */ 17512453Smckusick if (dp != NULL && strcmp(dp->d_name, ".") == 0) { 17612556Smckusick dp = rst_readdir(dirp); /* ".." */ 17712453Smckusick } else { 17812453Smckusick np = lookupino(ino); 17912453Smckusick if (np == NULL) 18012453Smckusick panic("corrupted symbol table\n"); 18112453Smckusick fprintf(stderr, ". missing from directory %s\n", myname(np)); 18212453Smckusick } 18312453Smckusick if (dp != NULL && strcmp(dp->d_name, "..") == 0) { 18412556Smckusick dp = rst_readdir(dirp); /* first real entry */ 18512453Smckusick } else { 18612453Smckusick np = lookupino(ino); 18712453Smckusick if (np == NULL) 18812453Smckusick panic("corrupted symbol table\n"); 18912453Smckusick fprintf(stderr, ".. missing from directory %s\n", myname(np)); 19012453Smckusick } 19111127Smckusick bpt = telldir(dirp); 19211127Smckusick /* 19312453Smckusick * a zero inode signals end of directory 19411127Smckusick */ 19512453Smckusick while (dp != NULL && dp->d_ino != 0) { 19611127Smckusick locname[namelen] = '\0'; 19711644Smckusick if (namelen + dp->d_namlen >= MAXPATHLEN) { 19811127Smckusick fprintf(stderr, "%s%s: name exceeds %d char\n", 19911644Smckusick locname, dp->d_name, MAXPATHLEN); 20011127Smckusick } else { 20111992Smckusick (void) strncat(locname, dp->d_name, (int)dp->d_namlen); 20211127Smckusick treescan(locname, dp->d_ino, todo); 20312556Smckusick rst_seekdir(dirp, bpt, itp->t_seekpt); 20411127Smckusick } 20512556Smckusick dp = rst_readdir(dirp); 20611127Smckusick bpt = telldir(dirp); 20711127Smckusick } 20811127Smckusick if (dp == NULL) 20911127Smckusick fprintf(stderr, "corrupted directory: %s.\n", locname); 21011127Smckusick } 21111127Smckusick 21211127Smckusick /* 21311127Smckusick * Search the directory tree rooted at inode ROOTINO 21411127Smckusick * for the path pointed at by n 21511127Smckusick */ 21611127Smckusick ino_t 21711127Smckusick psearch(n) 21811127Smckusick char *n; 21911127Smckusick { 22011127Smckusick register char *cp, *cp1; 22111127Smckusick ino_t ino; 22211127Smckusick char c; 22311127Smckusick 22411127Smckusick ino = ROOTINO; 22511127Smckusick if (*(cp = n) == '/') 22611127Smckusick cp++; 22711127Smckusick next: 22811127Smckusick cp1 = cp + 1; 22911127Smckusick while (*cp1 != '/' && *cp1) 23011127Smckusick cp1++; 23111127Smckusick c = *cp1; 23211127Smckusick *cp1 = 0; 23311127Smckusick ino = search(ino, cp); 23411127Smckusick if (ino == 0) { 23511127Smckusick *cp1 = c; 23611127Smckusick return(0); 23711127Smckusick } 23811127Smckusick *cp1 = c; 23911127Smckusick if (c == '/') { 24011127Smckusick cp = cp1+1; 24111127Smckusick goto next; 24211127Smckusick } 24311127Smckusick return(ino); 24411127Smckusick } 24511127Smckusick 24611127Smckusick /* 24711127Smckusick * search the directory inode ino 24811127Smckusick * looking for entry cp 24911127Smckusick */ 25011127Smckusick ino_t 25111127Smckusick search(inum, cp) 25211127Smckusick ino_t inum; 25311127Smckusick char *cp; 25411127Smckusick { 25511127Smckusick register struct direct *dp; 25611127Smckusick register struct inotab *itp; 25711127Smckusick int len; 25811127Smckusick 25911127Smckusick itp = inotablookup(inum); 26011127Smckusick if (itp == NULL) 26111127Smckusick return(0); 26212556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 26311127Smckusick len = strlen(cp); 26411127Smckusick do { 26512556Smckusick dp = rst_readdir(dirp); 26612453Smckusick if (dp == NULL || dp->d_ino == 0) 26712453Smckusick return (0); 26811992Smckusick } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len) != 0); 26911127Smckusick return(dp->d_ino); 27011127Smckusick } 27111127Smckusick 27211127Smckusick /* 27311127Smckusick * Put the directory entries in the directory file 27411127Smckusick */ 27511127Smckusick putdir(buf, size) 27611127Smckusick char *buf; 27711127Smckusick int size; 27811127Smckusick { 27911127Smckusick struct direct cvtbuf; 28011127Smckusick register struct odirect *odp; 28111127Smckusick struct odirect *eodp; 28211127Smckusick register struct direct *dp; 28311127Smckusick long loc, i; 284*26941Ssklower extern int Bcvt; 28511127Smckusick 28611127Smckusick if (cvtflag) { 28711127Smckusick eodp = (struct odirect *)&buf[size]; 28811127Smckusick for (odp = (struct odirect *)buf; odp < eodp; odp++) 28911127Smckusick if (odp->d_ino != 0) { 29011127Smckusick dcvt(odp, &cvtbuf); 29111127Smckusick putent(&cvtbuf); 29211127Smckusick } 29311127Smckusick } else { 29411127Smckusick for (loc = 0; loc < size; ) { 29511127Smckusick dp = (struct direct *)(buf + loc); 296*26941Ssklower if (Bcvt) { 297*26941Ssklower swabst("l2s", (char *) dp); 298*26941Ssklower } 29911127Smckusick i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 30011127Smckusick if (dp->d_reclen == 0 || dp->d_reclen > i) { 30111127Smckusick loc += i; 30211127Smckusick continue; 30311127Smckusick } 30411127Smckusick loc += dp->d_reclen; 30511127Smckusick if (dp->d_ino != 0) { 30611127Smckusick putent(dp); 30711127Smckusick } 30811127Smckusick } 30911127Smckusick } 31011127Smckusick } 31111127Smckusick 31211127Smckusick /* 31311127Smckusick * These variables are "local" to the following two functions. 31411127Smckusick */ 31511127Smckusick char dirbuf[DIRBLKSIZ]; 31611127Smckusick long dirloc = 0; 31711127Smckusick long prev = 0; 31811127Smckusick 31911127Smckusick /* 32011127Smckusick * add a new directory entry to a file. 32111127Smckusick */ 32211127Smckusick putent(dp) 32311127Smckusick struct direct *dp; 32411127Smckusick { 32511322Smckusick dp->d_reclen = DIRSIZ(dp); 32611127Smckusick if (dirloc + dp->d_reclen > DIRBLKSIZ) { 32711127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = 32811127Smckusick DIRBLKSIZ - prev; 32911732Smckusick (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); 33011127Smckusick dirloc = 0; 33111127Smckusick } 33211127Smckusick bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 33311127Smckusick prev = dirloc; 33411127Smckusick dirloc += dp->d_reclen; 33511127Smckusick } 33611127Smckusick 33711127Smckusick /* 33811127Smckusick * flush out a directory that is finished. 33911127Smckusick */ 34011127Smckusick flushent() 34111127Smckusick { 34211127Smckusick 34311127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 34411732Smckusick (void) fwrite(dirbuf, (int)dirloc, 1, df); 34511127Smckusick seekpt = ftell(df); 34611127Smckusick dirloc = 0; 34711127Smckusick } 34811127Smckusick 34911127Smckusick dcvt(odp, ndp) 35011127Smckusick register struct odirect *odp; 35111127Smckusick register struct direct *ndp; 35211127Smckusick { 35311127Smckusick 35411127Smckusick bzero((char *)ndp, (long)(sizeof *ndp)); 35511127Smckusick ndp->d_ino = odp->d_ino; 35611992Smckusick (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 35711127Smckusick ndp->d_namlen = strlen(ndp->d_name); 35811127Smckusick ndp->d_reclen = DIRSIZ(ndp); 35911127Smckusick } 36011127Smckusick 36111127Smckusick /* 36211127Smckusick * Seek to an entry in a directory. 36312556Smckusick * Only values returned by ``telldir'' should be passed to rst_seekdir. 36411732Smckusick * This routine handles many directories in a single file. 36511732Smckusick * It takes the base of the directory in the file, plus 36611732Smckusick * the desired seek offset into it. 36711127Smckusick */ 36811127Smckusick void 36912556Smckusick rst_seekdir(dirp, loc, base) 37011127Smckusick register DIR *dirp; 37111127Smckusick daddr_t loc, base; 37211127Smckusick { 37311127Smckusick 37411127Smckusick if (loc == telldir(dirp)) 37511127Smckusick return; 37611127Smckusick loc -= base; 37711127Smckusick if (loc < 0) 37812556Smckusick fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); 37911127Smckusick (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); 38011127Smckusick dirp->dd_loc = loc & (DIRBLKSIZ - 1); 38111127Smckusick if (dirp->dd_loc != 0) 38211127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 38311127Smckusick } 38411127Smckusick 38511127Smckusick /* 38611127Smckusick * get next entry in a directory. 38711127Smckusick */ 38811127Smckusick struct direct * 38912556Smckusick rst_readdir(dirp) 39011127Smckusick register DIR *dirp; 39111127Smckusick { 39211127Smckusick register struct direct *dp; 39311127Smckusick 39411127Smckusick for (;;) { 39511127Smckusick if (dirp->dd_loc == 0) { 39611127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 39711127Smckusick DIRBLKSIZ); 39812453Smckusick if (dirp->dd_size <= 0) { 39912453Smckusick dprintf(stderr, "error reading directory\n"); 40011127Smckusick return NULL; 40112453Smckusick } 40211127Smckusick } 40311127Smckusick if (dirp->dd_loc >= dirp->dd_size) { 40411127Smckusick dirp->dd_loc = 0; 40511127Smckusick continue; 40611127Smckusick } 40711127Smckusick dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 40811127Smckusick if (dp->d_reclen == 0 || 40912453Smckusick dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { 41012453Smckusick dprintf(stderr, "corrupted directory: bad reclen %d\n", 41112453Smckusick dp->d_reclen); 41211127Smckusick return NULL; 41312453Smckusick } 41411127Smckusick dirp->dd_loc += dp->d_reclen; 41512453Smckusick if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) 41612453Smckusick continue; 41712556Smckusick if (dp->d_ino >= maxino) { 41812453Smckusick dprintf(stderr, "corrupted directory: bad inum %d\n", 41912453Smckusick dp->d_ino); 42012453Smckusick continue; 42112453Smckusick } 42211127Smckusick return (dp); 42311127Smckusick } 42411127Smckusick } 42511127Smckusick 42611127Smckusick /* 42717753Smckusick * Simulate the opening of a directory 42817753Smckusick */ 42917753Smckusick DIR * 43017753Smckusick rst_opendir(name) 43117753Smckusick char *name; 43217753Smckusick { 43317753Smckusick struct inotab *itp; 43417753Smckusick ino_t ino; 43517753Smckusick 43617753Smckusick if ((ino = dirlookup(name)) > 0 && 43717753Smckusick (itp = inotablookup(ino)) != NULL) { 43817753Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 43917753Smckusick return (dirp); 44017753Smckusick } 44117753Smckusick return (0); 44217753Smckusick } 44317753Smckusick 44417753Smckusick /* 44511127Smckusick * Set the mode, owner, and times for all new or changed directories 44611127Smckusick */ 44711992Smckusick setdirmodes() 44811127Smckusick { 44911127Smckusick FILE *mf; 45011127Smckusick struct modeinfo node; 45111127Smckusick struct entry *ep; 45211127Smckusick char *cp; 45311127Smckusick 45411127Smckusick vprintf(stdout, "Set directory mode, owner, and times.\n"); 45515779Smckusick (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate); 45611127Smckusick mf = fopen(modefile, "r"); 45711127Smckusick if (mf == NULL) { 45811127Smckusick perror("fopen"); 45915779Smckusick fprintf(stderr, "cannot open mode file %s\n", modefile); 46015779Smckusick fprintf(stderr, "directory mode, owner, and times not set\n"); 46115779Smckusick return; 46211127Smckusick } 46311127Smckusick clearerr(mf); 46411309Smckusick for (;;) { 46511732Smckusick (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); 46611309Smckusick if (feof(mf)) 46711309Smckusick break; 46811127Smckusick ep = lookupino(node.ino); 46914453Smckusick if (command == 'i' || command == 'x') { 47014453Smckusick if (ep == NIL) 47111309Smckusick continue; 47218008Smckusick if (ep->e_flags & EXISTED) { 47318008Smckusick ep->e_flags &= ~NEW; 47418008Smckusick continue; 47518008Smckusick } 47614453Smckusick if (node.ino == ROOTINO && 47714453Smckusick reply("set owner/mode for '.'") == FAIL) 47814453Smckusick continue; 47914453Smckusick } 48014453Smckusick if (ep == NIL) 48111127Smckusick panic("cannot find directory inode %d\n", node.ino); 48211127Smckusick cp = myname(ep); 48311732Smckusick (void) chown(cp, node.uid, node.gid); 48411732Smckusick (void) chmod(cp, node.mode); 48511127Smckusick utime(cp, node.timep); 48611992Smckusick ep->e_flags &= ~NEW; 48711127Smckusick } 48811127Smckusick if (ferror(mf)) 48911127Smckusick panic("error setting directory modes\n"); 49011732Smckusick (void) fclose(mf); 49111127Smckusick } 49211127Smckusick 49311127Smckusick /* 49411127Smckusick * Generate a literal copy of a directory. 49511127Smckusick */ 49611127Smckusick genliteraldir(name, ino) 49711127Smckusick char *name; 49811127Smckusick ino_t ino; 49911127Smckusick { 50011127Smckusick register struct inotab *itp; 50111127Smckusick int ofile, dp, i, size; 50211127Smckusick char buf[BUFSIZ]; 50311127Smckusick 50411127Smckusick itp = inotablookup(ino); 50511127Smckusick if (itp == NULL) 50611322Smckusick panic("Cannot find directory inode %d named %s\n", ino, name); 50712893Ssam if ((ofile = creat(name, 0666)) < 0) { 50812556Smckusick fprintf(stderr, "%s: ", name); 50912556Smckusick (void) fflush(stderr); 51012556Smckusick perror("cannot create file"); 51111127Smckusick return (FAIL); 51211127Smckusick } 51312556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 51411127Smckusick dp = dup(dirp->dd_fd); 51511127Smckusick for (i = itp->t_size; i > 0; i -= BUFSIZ) { 51611127Smckusick size = i < BUFSIZ ? i : BUFSIZ; 51711127Smckusick if (read(dp, buf, (int) size) == -1) { 51811127Smckusick fprintf(stderr, 51911127Smckusick "write error extracting inode %d, name %s\n", 52011127Smckusick curfile.ino, curfile.name); 52111127Smckusick perror("read"); 52211127Smckusick done(1); 52311127Smckusick } 52411127Smckusick if (write(ofile, buf, (int) size) == -1) { 52511127Smckusick fprintf(stderr, 52611127Smckusick "write error extracting inode %d, name %s\n", 52711127Smckusick curfile.ino, curfile.name); 52811127Smckusick perror("write"); 52911127Smckusick done(1); 53011127Smckusick } 53111127Smckusick } 53211732Smckusick (void) close(dp); 53311732Smckusick (void) close(ofile); 53411127Smckusick return (GOOD); 53511127Smckusick } 53611127Smckusick 53711127Smckusick /* 53811992Smckusick * Determine the type of an inode 53911992Smckusick */ 54011992Smckusick inodetype(ino) 54111992Smckusick ino_t ino; 54211992Smckusick { 54311992Smckusick struct inotab *itp; 54411992Smckusick 54511992Smckusick itp = inotablookup(ino); 54611992Smckusick if (itp == NULL) 54711992Smckusick return (LEAF); 54811992Smckusick return (NODE); 54911992Smckusick } 55011992Smckusick 55111992Smckusick /* 55211127Smckusick * Allocate and initialize a directory inode entry. 55311127Smckusick * If requested, save its pertinent mode, owner, and time info. 55411127Smckusick */ 55511322Smckusick struct inotab * 55611127Smckusick allocinotab(ino, dip, seekpt) 55711127Smckusick ino_t ino; 55811127Smckusick struct dinode *dip; 55911127Smckusick daddr_t seekpt; 56011127Smckusick { 56111127Smckusick register struct inotab *itp; 56211127Smckusick struct modeinfo node; 56311127Smckusick 56411127Smckusick itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 56513859Smckusick if (itp == 0) 56613859Smckusick panic("no memory directory table\n"); 56711127Smckusick itp->t_next = inotab[INOHASH(ino)]; 56811127Smckusick inotab[INOHASH(ino)] = itp; 56911127Smckusick itp->t_ino = ino; 57011127Smckusick itp->t_seekpt = seekpt; 57111127Smckusick if (mf == NULL) 57211322Smckusick return(itp); 57311127Smckusick node.ino = ino; 57411127Smckusick node.timep[0] = dip->di_atime; 57511127Smckusick node.timep[1] = dip->di_mtime; 57611127Smckusick node.mode = dip->di_mode; 57711127Smckusick node.uid = dip->di_uid; 57811127Smckusick node.gid = dip->di_gid; 57911732Smckusick (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); 58011322Smckusick return(itp); 58111127Smckusick } 58211127Smckusick 58311127Smckusick /* 58411127Smckusick * Look up an inode in the table of directories 58511127Smckusick */ 58611127Smckusick struct inotab * 58711127Smckusick inotablookup(ino) 58811127Smckusick ino_t ino; 58911127Smckusick { 59011127Smckusick register struct inotab *itp; 59111127Smckusick 59211127Smckusick for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) 59311127Smckusick if (itp->t_ino == ino) 59411127Smckusick return(itp); 59511127Smckusick return ((struct inotab *)0); 59611127Smckusick } 59711127Smckusick 59811127Smckusick /* 59911127Smckusick * Clean up and exit 60011127Smckusick */ 60111127Smckusick done(exitcode) 60211127Smckusick int exitcode; 60311127Smckusick { 60411127Smckusick 60511127Smckusick closemt(); 60611992Smckusick if (modefile[0] != '#') 60711992Smckusick (void) unlink(modefile); 60811992Smckusick if (dirfile[0] != '#') 60911992Smckusick (void) unlink(dirfile); 61011127Smckusick exit(exitcode); 61111127Smckusick } 612