121165Sdist /* 236105Sbostic * Copyright (c) 1983 The Regents of the University of California. 336105Sbostic * All rights reserved. 436105Sbostic * 542708Sbostic * %sccs.include.redist.c% 621165Sdist */ 721165Sdist 811127Smckusick #ifndef lint 9*50657Smckusick static char sccsid[] = "@(#)dirs.c 5.16 (Berkeley) 07/29/91"; 1036105Sbostic #endif /* not lint */ 1111127Smckusick 1211127Smckusick #include "restore.h" 1323545Smckusick #include <protocols/dumprestore.h> 1411309Smckusick #include <sys/file.h> 1540094Smckusick #include <ufs/dir.h> 1637952Sbostic #include "pathnames.h" 1711127Smckusick 1811992Smckusick /* 1911992Smckusick * Symbol table of directories read from tape. 2011992Smckusick */ 2111127Smckusick #define HASHSIZE 1000 2211127Smckusick #define INOHASH(val) (val % HASHSIZE) 2311127Smckusick struct inotab { 2411127Smckusick struct inotab *t_next; 2511127Smckusick ino_t t_ino; 2611127Smckusick daddr_t t_seekpt; 2711127Smckusick long t_size; 2811309Smckusick }; 2911309Smckusick static struct inotab *inotab[HASHSIZE]; 3011309Smckusick extern struct inotab *inotablookup(); 3111322Smckusick extern struct inotab *allocinotab(); 3211127Smckusick 3311992Smckusick /* 3411992Smckusick * Information retained about directories. 3511992Smckusick */ 3611127Smckusick struct modeinfo { 3711127Smckusick ino_t ino; 3839471Smckusick struct timeval timep[2]; 3911127Smckusick short mode; 4011127Smckusick short uid; 4111127Smckusick short gid; 4211127Smckusick }; 4311127Smckusick 4411992Smckusick /* 4540094Smckusick * Definitions for library routines operating on directories. 4640094Smckusick */ 4746564Smckusick #undef DIRBLKSIZ 4846564Smckusick #define DIRBLKSIZ 1024 49*50657Smckusick struct rstdirdesc { 5040094Smckusick int dd_fd; 5140094Smckusick long dd_loc; 5240094Smckusick long dd_size; 5340094Smckusick char dd_buf[DIRBLKSIZ]; 5440094Smckusick }; 55*50657Smckusick extern RST_DIR *opendirfile(); 5646715Storek extern off_t rst_telldir(); 5740094Smckusick extern void rst_seekdir(); 5840094Smckusick 5940094Smckusick /* 6011992Smckusick * Global variables for this file. 6111992Smckusick */ 6211309Smckusick static daddr_t seekpt; 6311309Smckusick static FILE *df, *mf; 64*50657Smckusick static RST_DIR *dirp; 6511992Smckusick static char dirfile[32] = "#"; /* No file */ 6611992Smckusick static char modefile[32] = "#"; /* No file */ 6746566Smckusick static char dot[2] = "."; /* So it can be modified */ 6811309Smckusick extern ino_t search(); 6912556Smckusick struct direct *rst_readdir(); 7012556Smckusick extern void rst_seekdir(); 7111127Smckusick 7211992Smckusick /* 7311992Smckusick * Format of old style directories. 7411992Smckusick */ 7511127Smckusick #define ODIRSIZ 14 7611127Smckusick struct odirect { 7711127Smckusick u_short d_ino; 7811127Smckusick char d_name[ODIRSIZ]; 7911127Smckusick }; 8011127Smckusick 8111127Smckusick /* 8211127Smckusick * Extract directory contents, building up a directory structure 8311127Smckusick * on disk for extraction by name. 8411992Smckusick * If genmode is requested, save mode, owner, and times for all 8511127Smckusick * directories on the tape. 8611127Smckusick */ 8711992Smckusick extractdirs(genmode) 8811992Smckusick int genmode; 8911127Smckusick { 9011127Smckusick register int i; 9111127Smckusick register struct dinode *ip; 9211322Smckusick struct inotab *itp; 9311127Smckusick struct direct nulldir; 9411127Smckusick int putdir(), null(); 9511127Smckusick 9611127Smckusick vprintf(stdout, "Extract directories from tape\n"); 9737952Sbostic (void) sprintf(dirfile, "%s/rstdir%d", _PATH_TMP, dumpdate); 9811127Smckusick df = fopen(dirfile, "w"); 9911127Smckusick if (df == 0) { 10011127Smckusick fprintf(stderr, 10115779Smckusick "restore: %s - cannot create directory temporary\n", 10211127Smckusick dirfile); 10311127Smckusick perror("fopen"); 10411127Smckusick done(1); 10511127Smckusick } 10611992Smckusick if (genmode != 0) { 10737952Sbostic (void) sprintf(modefile, "%s/rstmode%d", _PATH_TMP, dumpdate); 10811127Smckusick mf = fopen(modefile, "w"); 10911309Smckusick if (mf == 0) { 11011127Smckusick fprintf(stderr, 11115779Smckusick "restore: %s - cannot create modefile \n", 11211127Smckusick modefile); 11311127Smckusick perror("fopen"); 11411127Smckusick done(1); 11511127Smckusick } 11611127Smckusick } 11711322Smckusick nulldir.d_ino = 0; 11811127Smckusick nulldir.d_namlen = 1; 11912453Smckusick (void) strcpy(nulldir.d_name, "/"); 12011127Smckusick nulldir.d_reclen = DIRSIZ(&nulldir); 12111127Smckusick for (;;) { 12211127Smckusick curfile.name = "<directory file - name unknown>"; 12311127Smckusick curfile.action = USING; 12411127Smckusick ip = curfile.dip; 12517948Smckusick if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { 12611732Smckusick (void) fclose(df); 12740064Smckusick dirp = opendirfile(dirfile); 12811127Smckusick if (dirp == NULL) 12940064Smckusick perror("opendirfile"); 13011127Smckusick if (mf != NULL) 13111732Smckusick (void) fclose(mf); 13246566Smckusick i = dirlookup(dot); 13311992Smckusick if (i == 0) 13411421Smckusick panic("Root directory is not on tape\n"); 13511127Smckusick return; 13611127Smckusick } 13711322Smckusick itp = allocinotab(curfile.ino, ip, seekpt); 13811127Smckusick getfile(putdir, null); 13911127Smckusick putent(&nulldir); 14011127Smckusick flushent(); 14111322Smckusick itp->t_size = seekpt - itp->t_seekpt; 14211127Smckusick } 14311127Smckusick } 14411127Smckusick 14511127Smckusick /* 14611322Smckusick * skip over all the directories on the tape 14711322Smckusick */ 14811322Smckusick skipdirs() 14911322Smckusick { 15011322Smckusick 15111322Smckusick while ((curfile.dip->di_mode & IFMT) == IFDIR) { 15211322Smckusick skipfile(); 15311322Smckusick } 15411322Smckusick } 15511322Smckusick 15611322Smckusick /* 15711127Smckusick * Recursively find names and inumbers of all files in subtree 15811127Smckusick * pname and pass them off to be processed. 15911127Smckusick */ 16011127Smckusick treescan(pname, ino, todo) 16111127Smckusick char *pname; 16211127Smckusick ino_t ino; 16311744Smckusick long (*todo)(); 16411127Smckusick { 16511127Smckusick register struct inotab *itp; 16612453Smckusick register struct direct *dp; 16712453Smckusick register struct entry *np; 16811127Smckusick int namelen; 16911127Smckusick daddr_t bpt; 17011644Smckusick char locname[MAXPATHLEN + 1]; 17111127Smckusick 17211127Smckusick itp = inotablookup(ino); 17311127Smckusick if (itp == NULL) { 17411127Smckusick /* 17511127Smckusick * Pname is name of a simple file or an unchanged directory. 17611127Smckusick */ 17711744Smckusick (void) (*todo)(pname, ino, LEAF); 17811127Smckusick return; 17911127Smckusick } 18011127Smckusick /* 18111127Smckusick * Pname is a dumped directory name. 18211127Smckusick */ 18311744Smckusick if ((*todo)(pname, ino, NODE) == FAIL) 18411744Smckusick return; 18511127Smckusick /* 18611127Smckusick * begin search through the directory 18711127Smckusick * skipping over "." and ".." 18811127Smckusick */ 18911992Smckusick (void) strncpy(locname, pname, MAXPATHLEN); 19011992Smckusick (void) strncat(locname, "/", MAXPATHLEN); 19111127Smckusick namelen = strlen(locname); 19212556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 19312556Smckusick dp = rst_readdir(dirp); /* "." */ 19427263Smckusick if (dp != NULL && strcmp(dp->d_name, ".") == 0) 19512556Smckusick dp = rst_readdir(dirp); /* ".." */ 19627263Smckusick else 19727263Smckusick fprintf(stderr, "Warning: `.' missing from directory %s\n", 19827263Smckusick pname); 19927263Smckusick if (dp != NULL && strcmp(dp->d_name, "..") == 0) 20012556Smckusick dp = rst_readdir(dirp); /* first real entry */ 20127263Smckusick else 20227263Smckusick fprintf(stderr, "Warning: `..' missing from directory %s\n", 20327263Smckusick pname); 20440064Smckusick bpt = rst_telldir(dirp); 20511127Smckusick /* 20612453Smckusick * a zero inode signals end of directory 20711127Smckusick */ 20812453Smckusick while (dp != NULL && dp->d_ino != 0) { 20911127Smckusick locname[namelen] = '\0'; 21011644Smckusick if (namelen + dp->d_namlen >= MAXPATHLEN) { 21111127Smckusick fprintf(stderr, "%s%s: name exceeds %d char\n", 21211644Smckusick locname, dp->d_name, MAXPATHLEN); 21311127Smckusick } else { 21411992Smckusick (void) strncat(locname, dp->d_name, (int)dp->d_namlen); 21511127Smckusick treescan(locname, dp->d_ino, todo); 21612556Smckusick rst_seekdir(dirp, bpt, itp->t_seekpt); 21711127Smckusick } 21812556Smckusick dp = rst_readdir(dirp); 21940064Smckusick bpt = rst_telldir(dirp); 22011127Smckusick } 22111127Smckusick if (dp == NULL) 22211127Smckusick fprintf(stderr, "corrupted directory: %s.\n", locname); 22311127Smckusick } 22411127Smckusick 22511127Smckusick /* 22611127Smckusick * Search the directory tree rooted at inode ROOTINO 22711127Smckusick * for the path pointed at by n 22811127Smckusick */ 22911127Smckusick ino_t 23011127Smckusick psearch(n) 23111127Smckusick char *n; 23211127Smckusick { 23311127Smckusick register char *cp, *cp1; 23411127Smckusick ino_t ino; 23511127Smckusick char c; 23611127Smckusick 23711127Smckusick ino = ROOTINO; 23811127Smckusick if (*(cp = n) == '/') 23911127Smckusick cp++; 24011127Smckusick next: 24111127Smckusick cp1 = cp + 1; 24211127Smckusick while (*cp1 != '/' && *cp1) 24311127Smckusick cp1++; 24411127Smckusick c = *cp1; 24511127Smckusick *cp1 = 0; 24611127Smckusick ino = search(ino, cp); 24711127Smckusick if (ino == 0) { 24811127Smckusick *cp1 = c; 24911127Smckusick return(0); 25011127Smckusick } 25111127Smckusick *cp1 = c; 25211127Smckusick if (c == '/') { 25311127Smckusick cp = cp1+1; 25411127Smckusick goto next; 25511127Smckusick } 25611127Smckusick return(ino); 25711127Smckusick } 25811127Smckusick 25911127Smckusick /* 26011127Smckusick * search the directory inode ino 26111127Smckusick * looking for entry cp 26211127Smckusick */ 26311127Smckusick ino_t 26411127Smckusick search(inum, cp) 26511127Smckusick ino_t inum; 26611127Smckusick char *cp; 26711127Smckusick { 26811127Smckusick register struct direct *dp; 26911127Smckusick register struct inotab *itp; 27011127Smckusick int len; 27111127Smckusick 27211127Smckusick itp = inotablookup(inum); 27311127Smckusick if (itp == NULL) 27411127Smckusick return(0); 27512556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 27611127Smckusick len = strlen(cp); 27711127Smckusick do { 27812556Smckusick dp = rst_readdir(dirp); 27912453Smckusick if (dp == NULL || dp->d_ino == 0) 28012453Smckusick return (0); 28111992Smckusick } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len) != 0); 28211127Smckusick return(dp->d_ino); 28311127Smckusick } 28411127Smckusick 28511127Smckusick /* 28611127Smckusick * Put the directory entries in the directory file 28711127Smckusick */ 28811127Smckusick putdir(buf, size) 28911127Smckusick char *buf; 29011127Smckusick int size; 29111127Smckusick { 29211127Smckusick struct direct cvtbuf; 29311127Smckusick register struct odirect *odp; 29411127Smckusick struct odirect *eodp; 29511127Smckusick register struct direct *dp; 29611127Smckusick long loc, i; 29726941Ssklower extern int Bcvt; 29811127Smckusick 29911127Smckusick if (cvtflag) { 30011127Smckusick eodp = (struct odirect *)&buf[size]; 30111127Smckusick for (odp = (struct odirect *)buf; odp < eodp; odp++) 30211127Smckusick if (odp->d_ino != 0) { 30311127Smckusick dcvt(odp, &cvtbuf); 30411127Smckusick putent(&cvtbuf); 30511127Smckusick } 30611127Smckusick } else { 30711127Smckusick for (loc = 0; loc < size; ) { 30811127Smckusick dp = (struct direct *)(buf + loc); 30926941Ssklower if (Bcvt) { 31026941Ssklower swabst("l2s", (char *) dp); 31126941Ssklower } 31211127Smckusick i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 31346564Smckusick if ((dp->d_reclen & 0x3) != 0 || 31446564Smckusick dp->d_reclen > i || 31546564Smckusick dp->d_reclen < DIRSIZ(dp) || 31646564Smckusick dp->d_namlen > MAXNAMLEN) { 31746564Smckusick vprintf(stdout, "Mangled directory\n"); 31811127Smckusick loc += i; 31911127Smckusick continue; 32011127Smckusick } 32111127Smckusick loc += dp->d_reclen; 32211127Smckusick if (dp->d_ino != 0) { 32311127Smckusick putent(dp); 32411127Smckusick } 32511127Smckusick } 32611127Smckusick } 32711127Smckusick } 32811127Smckusick 32911127Smckusick /* 33011127Smckusick * These variables are "local" to the following two functions. 33111127Smckusick */ 33211127Smckusick char dirbuf[DIRBLKSIZ]; 33311127Smckusick long dirloc = 0; 33411127Smckusick long prev = 0; 33511127Smckusick 33611127Smckusick /* 33711127Smckusick * add a new directory entry to a file. 33811127Smckusick */ 33911127Smckusick putent(dp) 34011127Smckusick struct direct *dp; 34111127Smckusick { 34211322Smckusick dp->d_reclen = DIRSIZ(dp); 34311127Smckusick if (dirloc + dp->d_reclen > DIRBLKSIZ) { 34411127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = 34511127Smckusick DIRBLKSIZ - prev; 34611732Smckusick (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); 34711127Smckusick dirloc = 0; 34811127Smckusick } 34911127Smckusick bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 35011127Smckusick prev = dirloc; 35111127Smckusick dirloc += dp->d_reclen; 35211127Smckusick } 35311127Smckusick 35411127Smckusick /* 35511127Smckusick * flush out a directory that is finished. 35611127Smckusick */ 35711127Smckusick flushent() 35811127Smckusick { 35911127Smckusick 36011127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 36111732Smckusick (void) fwrite(dirbuf, (int)dirloc, 1, df); 36211127Smckusick seekpt = ftell(df); 36311127Smckusick dirloc = 0; 36411127Smckusick } 36511127Smckusick 36611127Smckusick dcvt(odp, ndp) 36711127Smckusick register struct odirect *odp; 36811127Smckusick register struct direct *ndp; 36911127Smckusick { 37011127Smckusick 37111127Smckusick bzero((char *)ndp, (long)(sizeof *ndp)); 37211127Smckusick ndp->d_ino = odp->d_ino; 37311992Smckusick (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 37411127Smckusick ndp->d_namlen = strlen(ndp->d_name); 37511127Smckusick ndp->d_reclen = DIRSIZ(ndp); 37611127Smckusick } 37711127Smckusick 37811127Smckusick /* 37911127Smckusick * Seek to an entry in a directory. 38040064Smckusick * Only values returned by rst_telldir should be passed to rst_seekdir. 38111732Smckusick * This routine handles many directories in a single file. 38211732Smckusick * It takes the base of the directory in the file, plus 38311732Smckusick * the desired seek offset into it. 38411127Smckusick */ 38511127Smckusick void 38612556Smckusick rst_seekdir(dirp, loc, base) 387*50657Smckusick register RST_DIR *dirp; 38811127Smckusick daddr_t loc, base; 38911127Smckusick { 39011127Smckusick 39140064Smckusick if (loc == rst_telldir(dirp)) 39211127Smckusick return; 39311127Smckusick loc -= base; 39411127Smckusick if (loc < 0) 39512556Smckusick fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); 39611127Smckusick (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); 39711127Smckusick dirp->dd_loc = loc & (DIRBLKSIZ - 1); 39811127Smckusick if (dirp->dd_loc != 0) 39911127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 40011127Smckusick } 40111127Smckusick 40211127Smckusick /* 40311127Smckusick * get next entry in a directory. 40411127Smckusick */ 40511127Smckusick struct direct * 40612556Smckusick rst_readdir(dirp) 407*50657Smckusick register RST_DIR *dirp; 40811127Smckusick { 40911127Smckusick register struct direct *dp; 41011127Smckusick 41111127Smckusick for (;;) { 41211127Smckusick if (dirp->dd_loc == 0) { 41311127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 41411127Smckusick DIRBLKSIZ); 41512453Smckusick if (dirp->dd_size <= 0) { 41612453Smckusick dprintf(stderr, "error reading directory\n"); 41711127Smckusick return NULL; 41812453Smckusick } 41911127Smckusick } 42011127Smckusick if (dirp->dd_loc >= dirp->dd_size) { 42111127Smckusick dirp->dd_loc = 0; 42211127Smckusick continue; 42311127Smckusick } 42411127Smckusick dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 42511127Smckusick if (dp->d_reclen == 0 || 42612453Smckusick dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { 42712453Smckusick dprintf(stderr, "corrupted directory: bad reclen %d\n", 42812453Smckusick dp->d_reclen); 42911127Smckusick return NULL; 43012453Smckusick } 43111127Smckusick dirp->dd_loc += dp->d_reclen; 43212453Smckusick if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) 43312453Smckusick continue; 43412556Smckusick if (dp->d_ino >= maxino) { 43512453Smckusick dprintf(stderr, "corrupted directory: bad inum %d\n", 43612453Smckusick dp->d_ino); 43712453Smckusick continue; 43812453Smckusick } 43911127Smckusick return (dp); 44011127Smckusick } 44111127Smckusick } 44211127Smckusick 44311127Smckusick /* 44417753Smckusick * Simulate the opening of a directory 44517753Smckusick */ 446*50657Smckusick RST_DIR * 44717753Smckusick rst_opendir(name) 44817753Smckusick char *name; 44917753Smckusick { 45017753Smckusick struct inotab *itp; 45117753Smckusick ino_t ino; 45217753Smckusick 45317753Smckusick if ((ino = dirlookup(name)) > 0 && 45417753Smckusick (itp = inotablookup(ino)) != NULL) { 45517753Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 45617753Smckusick return (dirp); 45717753Smckusick } 45817753Smckusick return (0); 45917753Smckusick } 46017753Smckusick 46117753Smckusick /* 46240064Smckusick * Simulate finding the current offset in the directory. 46340064Smckusick */ 46440064Smckusick off_t 46540064Smckusick rst_telldir(dirp) 466*50657Smckusick RST_DIR *dirp; 46740064Smckusick { 46840064Smckusick off_t lseek(); 46940064Smckusick 47040064Smckusick return (lseek(dirp->dd_fd, 0L, 1) - dirp->dd_size + dirp->dd_loc); 47140064Smckusick } 47240064Smckusick 47340064Smckusick /* 47440064Smckusick * Open a directory file. 47540064Smckusick */ 476*50657Smckusick RST_DIR * 47740064Smckusick opendirfile(name) 47840064Smckusick char *name; 47940064Smckusick { 480*50657Smckusick register RST_DIR *dirp; 48140064Smckusick register int fd; 48240064Smckusick 48340064Smckusick if ((fd = open(name, 0)) == -1) 48440064Smckusick return NULL; 485*50657Smckusick if ((dirp = (RST_DIR *)malloc(sizeof(RST_DIR))) == NULL) { 48640064Smckusick close (fd); 48740064Smckusick return NULL; 48840064Smckusick } 48940064Smckusick dirp->dd_fd = fd; 49040064Smckusick dirp->dd_loc = 0; 49140064Smckusick return dirp; 49240064Smckusick } 49340064Smckusick 49440064Smckusick /* 49511127Smckusick * Set the mode, owner, and times for all new or changed directories 49611127Smckusick */ 49711992Smckusick setdirmodes() 49811127Smckusick { 49911127Smckusick FILE *mf; 50011127Smckusick struct modeinfo node; 50111127Smckusick struct entry *ep; 50211127Smckusick char *cp; 50311127Smckusick 50411127Smckusick vprintf(stdout, "Set directory mode, owner, and times.\n"); 50537952Sbostic (void) sprintf(modefile, "%s/rstmode%d", _PATH_TMP, dumpdate); 50611127Smckusick mf = fopen(modefile, "r"); 50711127Smckusick if (mf == NULL) { 50811127Smckusick perror("fopen"); 50915779Smckusick fprintf(stderr, "cannot open mode file %s\n", modefile); 51015779Smckusick fprintf(stderr, "directory mode, owner, and times not set\n"); 51115779Smckusick return; 51211127Smckusick } 51311127Smckusick clearerr(mf); 51411309Smckusick for (;;) { 51511732Smckusick (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); 51611309Smckusick if (feof(mf)) 51711309Smckusick break; 51811127Smckusick ep = lookupino(node.ino); 51914453Smckusick if (command == 'i' || command == 'x') { 52014453Smckusick if (ep == NIL) 52111309Smckusick continue; 52218008Smckusick if (ep->e_flags & EXISTED) { 52318008Smckusick ep->e_flags &= ~NEW; 52418008Smckusick continue; 52518008Smckusick } 52614453Smckusick if (node.ino == ROOTINO && 52714453Smckusick reply("set owner/mode for '.'") == FAIL) 52814453Smckusick continue; 52914453Smckusick } 53042862Smckusick if (ep == NIL) { 53111127Smckusick panic("cannot find directory inode %d\n", node.ino); 53242862Smckusick } else { 53342862Smckusick cp = myname(ep); 53442862Smckusick (void) chown(cp, node.uid, node.gid); 53542862Smckusick (void) chmod(cp, node.mode); 53642862Smckusick utimes(cp, node.timep); 53742862Smckusick ep->e_flags &= ~NEW; 53842862Smckusick } 53911127Smckusick } 54011127Smckusick if (ferror(mf)) 54111127Smckusick panic("error setting directory modes\n"); 54211732Smckusick (void) fclose(mf); 54311127Smckusick } 54411127Smckusick 54511127Smckusick /* 54611127Smckusick * Generate a literal copy of a directory. 54711127Smckusick */ 54811127Smckusick genliteraldir(name, ino) 54911127Smckusick char *name; 55011127Smckusick ino_t ino; 55111127Smckusick { 55211127Smckusick register struct inotab *itp; 55311127Smckusick int ofile, dp, i, size; 55411127Smckusick char buf[BUFSIZ]; 55511127Smckusick 55611127Smckusick itp = inotablookup(ino); 55711127Smckusick if (itp == NULL) 55811322Smckusick panic("Cannot find directory inode %d named %s\n", ino, name); 55912893Ssam if ((ofile = creat(name, 0666)) < 0) { 56012556Smckusick fprintf(stderr, "%s: ", name); 56112556Smckusick (void) fflush(stderr); 56212556Smckusick perror("cannot create file"); 56311127Smckusick return (FAIL); 56411127Smckusick } 56512556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 56611127Smckusick dp = dup(dirp->dd_fd); 56711127Smckusick for (i = itp->t_size; i > 0; i -= BUFSIZ) { 56811127Smckusick size = i < BUFSIZ ? i : BUFSIZ; 56911127Smckusick if (read(dp, buf, (int) size) == -1) { 57011127Smckusick fprintf(stderr, 57111127Smckusick "write error extracting inode %d, name %s\n", 57211127Smckusick curfile.ino, curfile.name); 57311127Smckusick perror("read"); 57411127Smckusick done(1); 57511127Smckusick } 57634268Smckusick if (!Nflag && write(ofile, buf, (int) size) == -1) { 57711127Smckusick fprintf(stderr, 57811127Smckusick "write error extracting inode %d, name %s\n", 57911127Smckusick curfile.ino, curfile.name); 58011127Smckusick perror("write"); 58111127Smckusick done(1); 58211127Smckusick } 58311127Smckusick } 58411732Smckusick (void) close(dp); 58511732Smckusick (void) close(ofile); 58611127Smckusick return (GOOD); 58711127Smckusick } 58811127Smckusick 58911127Smckusick /* 59011992Smckusick * Determine the type of an inode 59111992Smckusick */ 59211992Smckusick inodetype(ino) 59311992Smckusick ino_t ino; 59411992Smckusick { 59511992Smckusick struct inotab *itp; 59611992Smckusick 59711992Smckusick itp = inotablookup(ino); 59811992Smckusick if (itp == NULL) 59911992Smckusick return (LEAF); 60011992Smckusick return (NODE); 60111992Smckusick } 60211992Smckusick 60311992Smckusick /* 60411127Smckusick * Allocate and initialize a directory inode entry. 60511127Smckusick * If requested, save its pertinent mode, owner, and time info. 60611127Smckusick */ 60711322Smckusick struct inotab * 60811127Smckusick allocinotab(ino, dip, seekpt) 60911127Smckusick ino_t ino; 61011127Smckusick struct dinode *dip; 61111127Smckusick daddr_t seekpt; 61211127Smckusick { 61311127Smckusick register struct inotab *itp; 61411127Smckusick struct modeinfo node; 61511127Smckusick 61611127Smckusick itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 61713859Smckusick if (itp == 0) 61813859Smckusick panic("no memory directory table\n"); 61911127Smckusick itp->t_next = inotab[INOHASH(ino)]; 62011127Smckusick inotab[INOHASH(ino)] = itp; 62111127Smckusick itp->t_ino = ino; 62211127Smckusick itp->t_seekpt = seekpt; 62311127Smckusick if (mf == NULL) 62411322Smckusick return(itp); 62511127Smckusick node.ino = ino; 62639471Smckusick node.timep[0].tv_sec = dip->di_atime; 62739471Smckusick node.timep[0].tv_usec = 0; 62839471Smckusick node.timep[1].tv_sec = dip->di_mtime; 62939471Smckusick node.timep[1].tv_usec = 0; 63011127Smckusick node.mode = dip->di_mode; 63111127Smckusick node.uid = dip->di_uid; 63211127Smckusick node.gid = dip->di_gid; 63311732Smckusick (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); 63411322Smckusick return(itp); 63511127Smckusick } 63611127Smckusick 63711127Smckusick /* 63811127Smckusick * Look up an inode in the table of directories 63911127Smckusick */ 64011127Smckusick struct inotab * 64111127Smckusick inotablookup(ino) 64211127Smckusick ino_t ino; 64311127Smckusick { 64411127Smckusick register struct inotab *itp; 64511127Smckusick 64611127Smckusick for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) 64711127Smckusick if (itp->t_ino == ino) 64811127Smckusick return(itp); 64911127Smckusick return ((struct inotab *)0); 65011127Smckusick } 65111127Smckusick 65211127Smckusick /* 65311127Smckusick * Clean up and exit 65411127Smckusick */ 65511127Smckusick done(exitcode) 65611127Smckusick int exitcode; 65711127Smckusick { 65811127Smckusick 65911127Smckusick closemt(); 66011992Smckusick if (modefile[0] != '#') 66111992Smckusick (void) unlink(modefile); 66211992Smckusick if (dirfile[0] != '#') 66311992Smckusick (void) unlink(dirfile); 66411127Smckusick exit(exitcode); 66511127Smckusick } 666