121165Sdist /* 236105Sbostic * Copyright (c) 1983 The Regents of the University of California. 336105Sbostic * All rights reserved. 436105Sbostic * 536105Sbostic * Redistribution and use in source and binary forms are permitted 636105Sbostic * provided that the above copyright notice and this paragraph are 736105Sbostic * duplicated in all such forms and that any documentation, 836105Sbostic * advertising materials, and other materials related to such 936105Sbostic * distribution and use acknowledge that the software was developed 1036105Sbostic * by the University of California, Berkeley. The name of the 1136105Sbostic * University may not be used to endorse or promote products derived 1236105Sbostic * from this software without specific prior written permission. 1336105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1436105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1536105Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621165Sdist */ 1721165Sdist 1811127Smckusick #ifndef lint 19*37952Sbostic static char sccsid[] = "@(#)dirs.c 5.7 (Berkeley) 05/11/89"; 2036105Sbostic #endif /* not lint */ 2111127Smckusick 2211127Smckusick #include "restore.h" 2323545Smckusick #include <protocols/dumprestore.h> 2411309Smckusick #include <sys/file.h> 25*37952Sbostic #include "pathnames.h" 2611127Smckusick 2711992Smckusick /* 2811992Smckusick * Symbol table of directories read from tape. 2911992Smckusick */ 3011127Smckusick #define HASHSIZE 1000 3111127Smckusick #define INOHASH(val) (val % HASHSIZE) 3211127Smckusick struct inotab { 3311127Smckusick struct inotab *t_next; 3411127Smckusick ino_t t_ino; 3511127Smckusick daddr_t t_seekpt; 3611127Smckusick long t_size; 3711309Smckusick }; 3811309Smckusick static struct inotab *inotab[HASHSIZE]; 3911309Smckusick extern struct inotab *inotablookup(); 4011322Smckusick extern struct inotab *allocinotab(); 4111127Smckusick 4211992Smckusick /* 4311992Smckusick * Information retained about directories. 4411992Smckusick */ 4511127Smckusick struct modeinfo { 4611127Smckusick ino_t ino; 4711127Smckusick time_t timep[2]; 4811127Smckusick short mode; 4911127Smckusick short uid; 5011127Smckusick short gid; 5111127Smckusick }; 5211127Smckusick 5311992Smckusick /* 5411992Smckusick * Global variables for this file. 5511992Smckusick */ 5611309Smckusick static daddr_t seekpt; 5711309Smckusick static FILE *df, *mf; 5811309Smckusick static DIR *dirp; 5911992Smckusick static char dirfile[32] = "#"; /* No file */ 6011992Smckusick static char modefile[32] = "#"; /* No file */ 6111309Smckusick extern ino_t search(); 6212556Smckusick struct direct *rst_readdir(); 6312556Smckusick extern void rst_seekdir(); 6411127Smckusick 6511992Smckusick /* 6611992Smckusick * Format of old style directories. 6711992Smckusick */ 6811127Smckusick #define ODIRSIZ 14 6911127Smckusick struct odirect { 7011127Smckusick u_short d_ino; 7111127Smckusick char d_name[ODIRSIZ]; 7211127Smckusick }; 7311127Smckusick 7411127Smckusick /* 7511127Smckusick * Extract directory contents, building up a directory structure 7611127Smckusick * on disk for extraction by name. 7711992Smckusick * If genmode is requested, save mode, owner, and times for all 7811127Smckusick * directories on the tape. 7911127Smckusick */ 8011992Smckusick extractdirs(genmode) 8111992Smckusick int genmode; 8211127Smckusick { 8311127Smckusick register int i; 8411127Smckusick register struct dinode *ip; 8511322Smckusick struct inotab *itp; 8611127Smckusick struct direct nulldir; 8711127Smckusick int putdir(), null(); 8811127Smckusick 8911127Smckusick vprintf(stdout, "Extract directories from tape\n"); 90*37952Sbostic (void) sprintf(dirfile, "%s/rstdir%d", _PATH_TMP, dumpdate); 9111127Smckusick df = fopen(dirfile, "w"); 9211127Smckusick if (df == 0) { 9311127Smckusick fprintf(stderr, 9415779Smckusick "restore: %s - cannot create directory temporary\n", 9511127Smckusick dirfile); 9611127Smckusick perror("fopen"); 9711127Smckusick done(1); 9811127Smckusick } 9911992Smckusick if (genmode != 0) { 100*37952Sbostic (void) sprintf(modefile, "%s/rstmode%d", _PATH_TMP, dumpdate); 10111127Smckusick mf = fopen(modefile, "w"); 10211309Smckusick if (mf == 0) { 10311127Smckusick fprintf(stderr, 10415779Smckusick "restore: %s - cannot create modefile \n", 10511127Smckusick modefile); 10611127Smckusick perror("fopen"); 10711127Smckusick done(1); 10811127Smckusick } 10911127Smckusick } 11011322Smckusick nulldir.d_ino = 0; 11111127Smckusick nulldir.d_namlen = 1; 11212453Smckusick (void) strcpy(nulldir.d_name, "/"); 11311127Smckusick nulldir.d_reclen = DIRSIZ(&nulldir); 11411127Smckusick for (;;) { 11511127Smckusick curfile.name = "<directory file - name unknown>"; 11611127Smckusick curfile.action = USING; 11711127Smckusick ip = curfile.dip; 11817948Smckusick if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { 11911732Smckusick (void) fclose(df); 12011127Smckusick dirp = opendir(dirfile); 12111127Smckusick if (dirp == NULL) 12211127Smckusick perror("opendir"); 12311127Smckusick if (mf != NULL) 12411732Smckusick (void) fclose(mf); 12511992Smckusick i = dirlookup("."); 12611992Smckusick if (i == 0) 12711421Smckusick panic("Root directory is not on tape\n"); 12811127Smckusick return; 12911127Smckusick } 13011322Smckusick itp = allocinotab(curfile.ino, ip, seekpt); 13111127Smckusick getfile(putdir, null); 13211127Smckusick putent(&nulldir); 13311127Smckusick flushent(); 13411322Smckusick itp->t_size = seekpt - itp->t_seekpt; 13511127Smckusick } 13611127Smckusick } 13711127Smckusick 13811127Smckusick /* 13911322Smckusick * skip over all the directories on the tape 14011322Smckusick */ 14111322Smckusick skipdirs() 14211322Smckusick { 14311322Smckusick 14411322Smckusick while ((curfile.dip->di_mode & IFMT) == IFDIR) { 14511322Smckusick skipfile(); 14611322Smckusick } 14711322Smckusick } 14811322Smckusick 14911322Smckusick /* 15011127Smckusick * Recursively find names and inumbers of all files in subtree 15111127Smckusick * pname and pass them off to be processed. 15211127Smckusick */ 15311127Smckusick treescan(pname, ino, todo) 15411127Smckusick char *pname; 15511127Smckusick ino_t ino; 15611744Smckusick long (*todo)(); 15711127Smckusick { 15811127Smckusick register struct inotab *itp; 15912453Smckusick register struct direct *dp; 16012453Smckusick register struct entry *np; 16111127Smckusick int namelen; 16211127Smckusick daddr_t bpt; 16311644Smckusick char locname[MAXPATHLEN + 1]; 16411127Smckusick 16511127Smckusick itp = inotablookup(ino); 16611127Smckusick if (itp == NULL) { 16711127Smckusick /* 16811127Smckusick * Pname is name of a simple file or an unchanged directory. 16911127Smckusick */ 17011744Smckusick (void) (*todo)(pname, ino, LEAF); 17111127Smckusick return; 17211127Smckusick } 17311127Smckusick /* 17411127Smckusick * Pname is a dumped directory name. 17511127Smckusick */ 17611744Smckusick if ((*todo)(pname, ino, NODE) == FAIL) 17711744Smckusick return; 17811127Smckusick /* 17911127Smckusick * begin search through the directory 18011127Smckusick * skipping over "." and ".." 18111127Smckusick */ 18211992Smckusick (void) strncpy(locname, pname, MAXPATHLEN); 18311992Smckusick (void) strncat(locname, "/", MAXPATHLEN); 18411127Smckusick namelen = strlen(locname); 18512556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 18612556Smckusick dp = rst_readdir(dirp); /* "." */ 18727263Smckusick if (dp != NULL && strcmp(dp->d_name, ".") == 0) 18812556Smckusick dp = rst_readdir(dirp); /* ".." */ 18927263Smckusick else 19027263Smckusick fprintf(stderr, "Warning: `.' missing from directory %s\n", 19127263Smckusick pname); 19227263Smckusick if (dp != NULL && strcmp(dp->d_name, "..") == 0) 19312556Smckusick dp = rst_readdir(dirp); /* first real entry */ 19427263Smckusick else 19527263Smckusick fprintf(stderr, "Warning: `..' missing from directory %s\n", 19627263Smckusick pname); 19711127Smckusick bpt = telldir(dirp); 19811127Smckusick /* 19912453Smckusick * a zero inode signals end of directory 20011127Smckusick */ 20112453Smckusick while (dp != NULL && dp->d_ino != 0) { 20211127Smckusick locname[namelen] = '\0'; 20311644Smckusick if (namelen + dp->d_namlen >= MAXPATHLEN) { 20411127Smckusick fprintf(stderr, "%s%s: name exceeds %d char\n", 20511644Smckusick locname, dp->d_name, MAXPATHLEN); 20611127Smckusick } else { 20711992Smckusick (void) strncat(locname, dp->d_name, (int)dp->d_namlen); 20811127Smckusick treescan(locname, dp->d_ino, todo); 20912556Smckusick rst_seekdir(dirp, bpt, itp->t_seekpt); 21011127Smckusick } 21112556Smckusick dp = rst_readdir(dirp); 21211127Smckusick bpt = telldir(dirp); 21311127Smckusick } 21411127Smckusick if (dp == NULL) 21511127Smckusick fprintf(stderr, "corrupted directory: %s.\n", locname); 21611127Smckusick } 21711127Smckusick 21811127Smckusick /* 21911127Smckusick * Search the directory tree rooted at inode ROOTINO 22011127Smckusick * for the path pointed at by n 22111127Smckusick */ 22211127Smckusick ino_t 22311127Smckusick psearch(n) 22411127Smckusick char *n; 22511127Smckusick { 22611127Smckusick register char *cp, *cp1; 22711127Smckusick ino_t ino; 22811127Smckusick char c; 22911127Smckusick 23011127Smckusick ino = ROOTINO; 23111127Smckusick if (*(cp = n) == '/') 23211127Smckusick cp++; 23311127Smckusick next: 23411127Smckusick cp1 = cp + 1; 23511127Smckusick while (*cp1 != '/' && *cp1) 23611127Smckusick cp1++; 23711127Smckusick c = *cp1; 23811127Smckusick *cp1 = 0; 23911127Smckusick ino = search(ino, cp); 24011127Smckusick if (ino == 0) { 24111127Smckusick *cp1 = c; 24211127Smckusick return(0); 24311127Smckusick } 24411127Smckusick *cp1 = c; 24511127Smckusick if (c == '/') { 24611127Smckusick cp = cp1+1; 24711127Smckusick goto next; 24811127Smckusick } 24911127Smckusick return(ino); 25011127Smckusick } 25111127Smckusick 25211127Smckusick /* 25311127Smckusick * search the directory inode ino 25411127Smckusick * looking for entry cp 25511127Smckusick */ 25611127Smckusick ino_t 25711127Smckusick search(inum, cp) 25811127Smckusick ino_t inum; 25911127Smckusick char *cp; 26011127Smckusick { 26111127Smckusick register struct direct *dp; 26211127Smckusick register struct inotab *itp; 26311127Smckusick int len; 26411127Smckusick 26511127Smckusick itp = inotablookup(inum); 26611127Smckusick if (itp == NULL) 26711127Smckusick return(0); 26812556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 26911127Smckusick len = strlen(cp); 27011127Smckusick do { 27112556Smckusick dp = rst_readdir(dirp); 27212453Smckusick if (dp == NULL || dp->d_ino == 0) 27312453Smckusick return (0); 27411992Smckusick } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len) != 0); 27511127Smckusick return(dp->d_ino); 27611127Smckusick } 27711127Smckusick 27811127Smckusick /* 27911127Smckusick * Put the directory entries in the directory file 28011127Smckusick */ 28111127Smckusick putdir(buf, size) 28211127Smckusick char *buf; 28311127Smckusick int size; 28411127Smckusick { 28511127Smckusick struct direct cvtbuf; 28611127Smckusick register struct odirect *odp; 28711127Smckusick struct odirect *eodp; 28811127Smckusick register struct direct *dp; 28911127Smckusick long loc, i; 29026941Ssklower extern int Bcvt; 29111127Smckusick 29211127Smckusick if (cvtflag) { 29311127Smckusick eodp = (struct odirect *)&buf[size]; 29411127Smckusick for (odp = (struct odirect *)buf; odp < eodp; odp++) 29511127Smckusick if (odp->d_ino != 0) { 29611127Smckusick dcvt(odp, &cvtbuf); 29711127Smckusick putent(&cvtbuf); 29811127Smckusick } 29911127Smckusick } else { 30011127Smckusick for (loc = 0; loc < size; ) { 30111127Smckusick dp = (struct direct *)(buf + loc); 30226941Ssklower if (Bcvt) { 30326941Ssklower swabst("l2s", (char *) dp); 30426941Ssklower } 30511127Smckusick i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 30611127Smckusick if (dp->d_reclen == 0 || dp->d_reclen > i) { 30711127Smckusick loc += i; 30811127Smckusick continue; 30911127Smckusick } 31011127Smckusick loc += dp->d_reclen; 31111127Smckusick if (dp->d_ino != 0) { 31211127Smckusick putent(dp); 31311127Smckusick } 31411127Smckusick } 31511127Smckusick } 31611127Smckusick } 31711127Smckusick 31811127Smckusick /* 31911127Smckusick * These variables are "local" to the following two functions. 32011127Smckusick */ 32111127Smckusick char dirbuf[DIRBLKSIZ]; 32211127Smckusick long dirloc = 0; 32311127Smckusick long prev = 0; 32411127Smckusick 32511127Smckusick /* 32611127Smckusick * add a new directory entry to a file. 32711127Smckusick */ 32811127Smckusick putent(dp) 32911127Smckusick struct direct *dp; 33011127Smckusick { 33111322Smckusick dp->d_reclen = DIRSIZ(dp); 33211127Smckusick if (dirloc + dp->d_reclen > DIRBLKSIZ) { 33311127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = 33411127Smckusick DIRBLKSIZ - prev; 33511732Smckusick (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); 33611127Smckusick dirloc = 0; 33711127Smckusick } 33811127Smckusick bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 33911127Smckusick prev = dirloc; 34011127Smckusick dirloc += dp->d_reclen; 34111127Smckusick } 34211127Smckusick 34311127Smckusick /* 34411127Smckusick * flush out a directory that is finished. 34511127Smckusick */ 34611127Smckusick flushent() 34711127Smckusick { 34811127Smckusick 34911127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 35011732Smckusick (void) fwrite(dirbuf, (int)dirloc, 1, df); 35111127Smckusick seekpt = ftell(df); 35211127Smckusick dirloc = 0; 35311127Smckusick } 35411127Smckusick 35511127Smckusick dcvt(odp, ndp) 35611127Smckusick register struct odirect *odp; 35711127Smckusick register struct direct *ndp; 35811127Smckusick { 35911127Smckusick 36011127Smckusick bzero((char *)ndp, (long)(sizeof *ndp)); 36111127Smckusick ndp->d_ino = odp->d_ino; 36211992Smckusick (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 36311127Smckusick ndp->d_namlen = strlen(ndp->d_name); 36411127Smckusick ndp->d_reclen = DIRSIZ(ndp); 36511127Smckusick } 36611127Smckusick 36711127Smckusick /* 36811127Smckusick * Seek to an entry in a directory. 36912556Smckusick * Only values returned by ``telldir'' should be passed to rst_seekdir. 37011732Smckusick * This routine handles many directories in a single file. 37111732Smckusick * It takes the base of the directory in the file, plus 37211732Smckusick * the desired seek offset into it. 37311127Smckusick */ 37411127Smckusick void 37512556Smckusick rst_seekdir(dirp, loc, base) 37611127Smckusick register DIR *dirp; 37711127Smckusick daddr_t loc, base; 37811127Smckusick { 37911127Smckusick 38011127Smckusick if (loc == telldir(dirp)) 38111127Smckusick return; 38211127Smckusick loc -= base; 38311127Smckusick if (loc < 0) 38412556Smckusick fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); 38511127Smckusick (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); 38611127Smckusick dirp->dd_loc = loc & (DIRBLKSIZ - 1); 38711127Smckusick if (dirp->dd_loc != 0) 38811127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 38911127Smckusick } 39011127Smckusick 39111127Smckusick /* 39211127Smckusick * get next entry in a directory. 39311127Smckusick */ 39411127Smckusick struct direct * 39512556Smckusick rst_readdir(dirp) 39611127Smckusick register DIR *dirp; 39711127Smckusick { 39811127Smckusick register struct direct *dp; 39911127Smckusick 40011127Smckusick for (;;) { 40111127Smckusick if (dirp->dd_loc == 0) { 40211127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 40311127Smckusick DIRBLKSIZ); 40412453Smckusick if (dirp->dd_size <= 0) { 40512453Smckusick dprintf(stderr, "error reading directory\n"); 40611127Smckusick return NULL; 40712453Smckusick } 40811127Smckusick } 40911127Smckusick if (dirp->dd_loc >= dirp->dd_size) { 41011127Smckusick dirp->dd_loc = 0; 41111127Smckusick continue; 41211127Smckusick } 41311127Smckusick dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 41411127Smckusick if (dp->d_reclen == 0 || 41512453Smckusick dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { 41612453Smckusick dprintf(stderr, "corrupted directory: bad reclen %d\n", 41712453Smckusick dp->d_reclen); 41811127Smckusick return NULL; 41912453Smckusick } 42011127Smckusick dirp->dd_loc += dp->d_reclen; 42112453Smckusick if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) 42212453Smckusick continue; 42312556Smckusick if (dp->d_ino >= maxino) { 42412453Smckusick dprintf(stderr, "corrupted directory: bad inum %d\n", 42512453Smckusick dp->d_ino); 42612453Smckusick continue; 42712453Smckusick } 42811127Smckusick return (dp); 42911127Smckusick } 43011127Smckusick } 43111127Smckusick 43211127Smckusick /* 43317753Smckusick * Simulate the opening of a directory 43417753Smckusick */ 43517753Smckusick DIR * 43617753Smckusick rst_opendir(name) 43717753Smckusick char *name; 43817753Smckusick { 43917753Smckusick struct inotab *itp; 44017753Smckusick ino_t ino; 44117753Smckusick 44217753Smckusick if ((ino = dirlookup(name)) > 0 && 44317753Smckusick (itp = inotablookup(ino)) != NULL) { 44417753Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 44517753Smckusick return (dirp); 44617753Smckusick } 44717753Smckusick return (0); 44817753Smckusick } 44917753Smckusick 45017753Smckusick /* 45111127Smckusick * Set the mode, owner, and times for all new or changed directories 45211127Smckusick */ 45311992Smckusick setdirmodes() 45411127Smckusick { 45511127Smckusick FILE *mf; 45611127Smckusick struct modeinfo node; 45711127Smckusick struct entry *ep; 45811127Smckusick char *cp; 45911127Smckusick 46011127Smckusick vprintf(stdout, "Set directory mode, owner, and times.\n"); 461*37952Sbostic (void) sprintf(modefile, "%s/rstmode%d", _PATH_TMP, dumpdate); 46211127Smckusick mf = fopen(modefile, "r"); 46311127Smckusick if (mf == NULL) { 46411127Smckusick perror("fopen"); 46515779Smckusick fprintf(stderr, "cannot open mode file %s\n", modefile); 46615779Smckusick fprintf(stderr, "directory mode, owner, and times not set\n"); 46715779Smckusick return; 46811127Smckusick } 46911127Smckusick clearerr(mf); 47011309Smckusick for (;;) { 47111732Smckusick (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); 47211309Smckusick if (feof(mf)) 47311309Smckusick break; 47411127Smckusick ep = lookupino(node.ino); 47514453Smckusick if (command == 'i' || command == 'x') { 47614453Smckusick if (ep == NIL) 47711309Smckusick continue; 47818008Smckusick if (ep->e_flags & EXISTED) { 47918008Smckusick ep->e_flags &= ~NEW; 48018008Smckusick continue; 48118008Smckusick } 48214453Smckusick if (node.ino == ROOTINO && 48314453Smckusick reply("set owner/mode for '.'") == FAIL) 48414453Smckusick continue; 48514453Smckusick } 48614453Smckusick if (ep == NIL) 48711127Smckusick panic("cannot find directory inode %d\n", node.ino); 48811127Smckusick cp = myname(ep); 48911732Smckusick (void) chown(cp, node.uid, node.gid); 49011732Smckusick (void) chmod(cp, node.mode); 49111127Smckusick utime(cp, node.timep); 49211992Smckusick ep->e_flags &= ~NEW; 49311127Smckusick } 49411127Smckusick if (ferror(mf)) 49511127Smckusick panic("error setting directory modes\n"); 49611732Smckusick (void) fclose(mf); 49711127Smckusick } 49811127Smckusick 49911127Smckusick /* 50011127Smckusick * Generate a literal copy of a directory. 50111127Smckusick */ 50211127Smckusick genliteraldir(name, ino) 50311127Smckusick char *name; 50411127Smckusick ino_t ino; 50511127Smckusick { 50611127Smckusick register struct inotab *itp; 50711127Smckusick int ofile, dp, i, size; 50811127Smckusick char buf[BUFSIZ]; 50911127Smckusick 51011127Smckusick itp = inotablookup(ino); 51111127Smckusick if (itp == NULL) 51211322Smckusick panic("Cannot find directory inode %d named %s\n", ino, name); 51312893Ssam if ((ofile = creat(name, 0666)) < 0) { 51412556Smckusick fprintf(stderr, "%s: ", name); 51512556Smckusick (void) fflush(stderr); 51612556Smckusick perror("cannot create file"); 51711127Smckusick return (FAIL); 51811127Smckusick } 51912556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 52011127Smckusick dp = dup(dirp->dd_fd); 52111127Smckusick for (i = itp->t_size; i > 0; i -= BUFSIZ) { 52211127Smckusick size = i < BUFSIZ ? i : BUFSIZ; 52311127Smckusick if (read(dp, buf, (int) size) == -1) { 52411127Smckusick fprintf(stderr, 52511127Smckusick "write error extracting inode %d, name %s\n", 52611127Smckusick curfile.ino, curfile.name); 52711127Smckusick perror("read"); 52811127Smckusick done(1); 52911127Smckusick } 53034268Smckusick if (!Nflag && write(ofile, buf, (int) size) == -1) { 53111127Smckusick fprintf(stderr, 53211127Smckusick "write error extracting inode %d, name %s\n", 53311127Smckusick curfile.ino, curfile.name); 53411127Smckusick perror("write"); 53511127Smckusick done(1); 53611127Smckusick } 53711127Smckusick } 53811732Smckusick (void) close(dp); 53911732Smckusick (void) close(ofile); 54011127Smckusick return (GOOD); 54111127Smckusick } 54211127Smckusick 54311127Smckusick /* 54411992Smckusick * Determine the type of an inode 54511992Smckusick */ 54611992Smckusick inodetype(ino) 54711992Smckusick ino_t ino; 54811992Smckusick { 54911992Smckusick struct inotab *itp; 55011992Smckusick 55111992Smckusick itp = inotablookup(ino); 55211992Smckusick if (itp == NULL) 55311992Smckusick return (LEAF); 55411992Smckusick return (NODE); 55511992Smckusick } 55611992Smckusick 55711992Smckusick /* 55811127Smckusick * Allocate and initialize a directory inode entry. 55911127Smckusick * If requested, save its pertinent mode, owner, and time info. 56011127Smckusick */ 56111322Smckusick struct inotab * 56211127Smckusick allocinotab(ino, dip, seekpt) 56311127Smckusick ino_t ino; 56411127Smckusick struct dinode *dip; 56511127Smckusick daddr_t seekpt; 56611127Smckusick { 56711127Smckusick register struct inotab *itp; 56811127Smckusick struct modeinfo node; 56911127Smckusick 57011127Smckusick itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 57113859Smckusick if (itp == 0) 57213859Smckusick panic("no memory directory table\n"); 57311127Smckusick itp->t_next = inotab[INOHASH(ino)]; 57411127Smckusick inotab[INOHASH(ino)] = itp; 57511127Smckusick itp->t_ino = ino; 57611127Smckusick itp->t_seekpt = seekpt; 57711127Smckusick if (mf == NULL) 57811322Smckusick return(itp); 57911127Smckusick node.ino = ino; 58011127Smckusick node.timep[0] = dip->di_atime; 58111127Smckusick node.timep[1] = dip->di_mtime; 58211127Smckusick node.mode = dip->di_mode; 58311127Smckusick node.uid = dip->di_uid; 58411127Smckusick node.gid = dip->di_gid; 58511732Smckusick (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); 58611322Smckusick return(itp); 58711127Smckusick } 58811127Smckusick 58911127Smckusick /* 59011127Smckusick * Look up an inode in the table of directories 59111127Smckusick */ 59211127Smckusick struct inotab * 59311127Smckusick inotablookup(ino) 59411127Smckusick ino_t ino; 59511127Smckusick { 59611127Smckusick register struct inotab *itp; 59711127Smckusick 59811127Smckusick for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) 59911127Smckusick if (itp->t_ino == ino) 60011127Smckusick return(itp); 60111127Smckusick return ((struct inotab *)0); 60211127Smckusick } 60311127Smckusick 60411127Smckusick /* 60511127Smckusick * Clean up and exit 60611127Smckusick */ 60711127Smckusick done(exitcode) 60811127Smckusick int exitcode; 60911127Smckusick { 61011127Smckusick 61111127Smckusick closemt(); 61211992Smckusick if (modefile[0] != '#') 61311992Smckusick (void) unlink(modefile); 61411992Smckusick if (dirfile[0] != '#') 61511992Smckusick (void) unlink(dirfile); 61611127Smckusick exit(exitcode); 61711127Smckusick } 618