121165Sdist /* 2*36105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*36105Sbostic * All rights reserved. 4*36105Sbostic * 5*36105Sbostic * Redistribution and use in source and binary forms are permitted 6*36105Sbostic * provided that the above copyright notice and this paragraph are 7*36105Sbostic * duplicated in all such forms and that any documentation, 8*36105Sbostic * advertising materials, and other materials related to such 9*36105Sbostic * distribution and use acknowledge that the software was developed 10*36105Sbostic * by the University of California, Berkeley. The name of the 11*36105Sbostic * University may not be used to endorse or promote products derived 12*36105Sbostic * from this software without specific prior written permission. 13*36105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*36105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*36105Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621165Sdist */ 1721165Sdist 1811127Smckusick #ifndef lint 19*36105Sbostic static char sccsid[] = "@(#)dirs.c 5.6 (Berkeley) 10/24/88"; 20*36105Sbostic #endif /* not lint */ 2111127Smckusick 2211127Smckusick #include "restore.h" 2323545Smckusick #include <protocols/dumprestore.h> 2411309Smckusick #include <sys/file.h> 2511127Smckusick 2611992Smckusick /* 2711992Smckusick * Symbol table of directories read from tape. 2811992Smckusick */ 2911127Smckusick #define HASHSIZE 1000 3011127Smckusick #define INOHASH(val) (val % HASHSIZE) 3111127Smckusick struct inotab { 3211127Smckusick struct inotab *t_next; 3311127Smckusick ino_t t_ino; 3411127Smckusick daddr_t t_seekpt; 3511127Smckusick long t_size; 3611309Smckusick }; 3711309Smckusick static struct inotab *inotab[HASHSIZE]; 3811309Smckusick extern struct inotab *inotablookup(); 3911322Smckusick extern struct inotab *allocinotab(); 4011127Smckusick 4111992Smckusick /* 4211992Smckusick * Information retained about directories. 4311992Smckusick */ 4411127Smckusick struct modeinfo { 4511127Smckusick ino_t ino; 4611127Smckusick time_t timep[2]; 4711127Smckusick short mode; 4811127Smckusick short uid; 4911127Smckusick short gid; 5011127Smckusick }; 5111127Smckusick 5211992Smckusick /* 5311992Smckusick * Global variables for this file. 5411992Smckusick */ 5511309Smckusick static daddr_t seekpt; 5611309Smckusick static FILE *df, *mf; 5711309Smckusick static DIR *dirp; 5811992Smckusick static char dirfile[32] = "#"; /* No file */ 5911992Smckusick static char modefile[32] = "#"; /* No file */ 6011309Smckusick extern ino_t search(); 6112556Smckusick struct direct *rst_readdir(); 6212556Smckusick extern void rst_seekdir(); 6311127Smckusick 6411992Smckusick /* 6511992Smckusick * Format of old style directories. 6611992Smckusick */ 6711127Smckusick #define ODIRSIZ 14 6811127Smckusick struct odirect { 6911127Smckusick u_short d_ino; 7011127Smckusick char d_name[ODIRSIZ]; 7111127Smckusick }; 7211127Smckusick 7311127Smckusick /* 7411127Smckusick * Extract directory contents, building up a directory structure 7511127Smckusick * on disk for extraction by name. 7611992Smckusick * If genmode is requested, save mode, owner, and times for all 7711127Smckusick * directories on the tape. 7811127Smckusick */ 7911992Smckusick extractdirs(genmode) 8011992Smckusick int genmode; 8111127Smckusick { 8211127Smckusick register int i; 8311127Smckusick register struct dinode *ip; 8411322Smckusick struct inotab *itp; 8511127Smckusick struct direct nulldir; 8611127Smckusick int putdir(), null(); 8711127Smckusick 8811127Smckusick vprintf(stdout, "Extract directories from tape\n"); 8911992Smckusick (void) sprintf(dirfile, "/tmp/rstdir%d", dumpdate); 9011127Smckusick df = fopen(dirfile, "w"); 9111127Smckusick if (df == 0) { 9211127Smckusick fprintf(stderr, 9315779Smckusick "restore: %s - cannot create directory temporary\n", 9411127Smckusick dirfile); 9511127Smckusick perror("fopen"); 9611127Smckusick done(1); 9711127Smckusick } 9811992Smckusick if (genmode != 0) { 9911992Smckusick (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate); 10011127Smckusick mf = fopen(modefile, "w"); 10111309Smckusick if (mf == 0) { 10211127Smckusick fprintf(stderr, 10315779Smckusick "restore: %s - cannot create modefile \n", 10411127Smckusick modefile); 10511127Smckusick perror("fopen"); 10611127Smckusick done(1); 10711127Smckusick } 10811127Smckusick } 10911322Smckusick nulldir.d_ino = 0; 11011127Smckusick nulldir.d_namlen = 1; 11112453Smckusick (void) strcpy(nulldir.d_name, "/"); 11211127Smckusick nulldir.d_reclen = DIRSIZ(&nulldir); 11311127Smckusick for (;;) { 11411127Smckusick curfile.name = "<directory file - name unknown>"; 11511127Smckusick curfile.action = USING; 11611127Smckusick ip = curfile.dip; 11717948Smckusick if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { 11811732Smckusick (void) fclose(df); 11911127Smckusick dirp = opendir(dirfile); 12011127Smckusick if (dirp == NULL) 12111127Smckusick perror("opendir"); 12211127Smckusick if (mf != NULL) 12311732Smckusick (void) fclose(mf); 12411992Smckusick i = dirlookup("."); 12511992Smckusick if (i == 0) 12611421Smckusick panic("Root directory is not on tape\n"); 12711127Smckusick return; 12811127Smckusick } 12911322Smckusick itp = allocinotab(curfile.ino, ip, seekpt); 13011127Smckusick getfile(putdir, null); 13111127Smckusick putent(&nulldir); 13211127Smckusick flushent(); 13311322Smckusick itp->t_size = seekpt - itp->t_seekpt; 13411127Smckusick } 13511127Smckusick } 13611127Smckusick 13711127Smckusick /* 13811322Smckusick * skip over all the directories on the tape 13911322Smckusick */ 14011322Smckusick skipdirs() 14111322Smckusick { 14211322Smckusick 14311322Smckusick while ((curfile.dip->di_mode & IFMT) == IFDIR) { 14411322Smckusick skipfile(); 14511322Smckusick } 14611322Smckusick } 14711322Smckusick 14811322Smckusick /* 14911127Smckusick * Recursively find names and inumbers of all files in subtree 15011127Smckusick * pname and pass them off to be processed. 15111127Smckusick */ 15211127Smckusick treescan(pname, ino, todo) 15311127Smckusick char *pname; 15411127Smckusick ino_t ino; 15511744Smckusick long (*todo)(); 15611127Smckusick { 15711127Smckusick register struct inotab *itp; 15812453Smckusick register struct direct *dp; 15912453Smckusick register struct entry *np; 16011127Smckusick int namelen; 16111127Smckusick daddr_t bpt; 16211644Smckusick char locname[MAXPATHLEN + 1]; 16311127Smckusick 16411127Smckusick itp = inotablookup(ino); 16511127Smckusick if (itp == NULL) { 16611127Smckusick /* 16711127Smckusick * Pname is name of a simple file or an unchanged directory. 16811127Smckusick */ 16911744Smckusick (void) (*todo)(pname, ino, LEAF); 17011127Smckusick return; 17111127Smckusick } 17211127Smckusick /* 17311127Smckusick * Pname is a dumped directory name. 17411127Smckusick */ 17511744Smckusick if ((*todo)(pname, ino, NODE) == FAIL) 17611744Smckusick return; 17711127Smckusick /* 17811127Smckusick * begin search through the directory 17911127Smckusick * skipping over "." and ".." 18011127Smckusick */ 18111992Smckusick (void) strncpy(locname, pname, MAXPATHLEN); 18211992Smckusick (void) strncat(locname, "/", MAXPATHLEN); 18311127Smckusick namelen = strlen(locname); 18412556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 18512556Smckusick dp = rst_readdir(dirp); /* "." */ 18627263Smckusick if (dp != NULL && strcmp(dp->d_name, ".") == 0) 18712556Smckusick dp = rst_readdir(dirp); /* ".." */ 18827263Smckusick else 18927263Smckusick fprintf(stderr, "Warning: `.' missing from directory %s\n", 19027263Smckusick pname); 19127263Smckusick if (dp != NULL && strcmp(dp->d_name, "..") == 0) 19212556Smckusick dp = rst_readdir(dirp); /* first real entry */ 19327263Smckusick else 19427263Smckusick fprintf(stderr, "Warning: `..' missing from directory %s\n", 19527263Smckusick pname); 19611127Smckusick bpt = telldir(dirp); 19711127Smckusick /* 19812453Smckusick * a zero inode signals end of directory 19911127Smckusick */ 20012453Smckusick while (dp != NULL && dp->d_ino != 0) { 20111127Smckusick locname[namelen] = '\0'; 20211644Smckusick if (namelen + dp->d_namlen >= MAXPATHLEN) { 20311127Smckusick fprintf(stderr, "%s%s: name exceeds %d char\n", 20411644Smckusick locname, dp->d_name, MAXPATHLEN); 20511127Smckusick } else { 20611992Smckusick (void) strncat(locname, dp->d_name, (int)dp->d_namlen); 20711127Smckusick treescan(locname, dp->d_ino, todo); 20812556Smckusick rst_seekdir(dirp, bpt, itp->t_seekpt); 20911127Smckusick } 21012556Smckusick dp = rst_readdir(dirp); 21111127Smckusick bpt = telldir(dirp); 21211127Smckusick } 21311127Smckusick if (dp == NULL) 21411127Smckusick fprintf(stderr, "corrupted directory: %s.\n", locname); 21511127Smckusick } 21611127Smckusick 21711127Smckusick /* 21811127Smckusick * Search the directory tree rooted at inode ROOTINO 21911127Smckusick * for the path pointed at by n 22011127Smckusick */ 22111127Smckusick ino_t 22211127Smckusick psearch(n) 22311127Smckusick char *n; 22411127Smckusick { 22511127Smckusick register char *cp, *cp1; 22611127Smckusick ino_t ino; 22711127Smckusick char c; 22811127Smckusick 22911127Smckusick ino = ROOTINO; 23011127Smckusick if (*(cp = n) == '/') 23111127Smckusick cp++; 23211127Smckusick next: 23311127Smckusick cp1 = cp + 1; 23411127Smckusick while (*cp1 != '/' && *cp1) 23511127Smckusick cp1++; 23611127Smckusick c = *cp1; 23711127Smckusick *cp1 = 0; 23811127Smckusick ino = search(ino, cp); 23911127Smckusick if (ino == 0) { 24011127Smckusick *cp1 = c; 24111127Smckusick return(0); 24211127Smckusick } 24311127Smckusick *cp1 = c; 24411127Smckusick if (c == '/') { 24511127Smckusick cp = cp1+1; 24611127Smckusick goto next; 24711127Smckusick } 24811127Smckusick return(ino); 24911127Smckusick } 25011127Smckusick 25111127Smckusick /* 25211127Smckusick * search the directory inode ino 25311127Smckusick * looking for entry cp 25411127Smckusick */ 25511127Smckusick ino_t 25611127Smckusick search(inum, cp) 25711127Smckusick ino_t inum; 25811127Smckusick char *cp; 25911127Smckusick { 26011127Smckusick register struct direct *dp; 26111127Smckusick register struct inotab *itp; 26211127Smckusick int len; 26311127Smckusick 26411127Smckusick itp = inotablookup(inum); 26511127Smckusick if (itp == NULL) 26611127Smckusick return(0); 26712556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 26811127Smckusick len = strlen(cp); 26911127Smckusick do { 27012556Smckusick dp = rst_readdir(dirp); 27112453Smckusick if (dp == NULL || dp->d_ino == 0) 27212453Smckusick return (0); 27311992Smckusick } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len) != 0); 27411127Smckusick return(dp->d_ino); 27511127Smckusick } 27611127Smckusick 27711127Smckusick /* 27811127Smckusick * Put the directory entries in the directory file 27911127Smckusick */ 28011127Smckusick putdir(buf, size) 28111127Smckusick char *buf; 28211127Smckusick int size; 28311127Smckusick { 28411127Smckusick struct direct cvtbuf; 28511127Smckusick register struct odirect *odp; 28611127Smckusick struct odirect *eodp; 28711127Smckusick register struct direct *dp; 28811127Smckusick long loc, i; 28926941Ssklower extern int Bcvt; 29011127Smckusick 29111127Smckusick if (cvtflag) { 29211127Smckusick eodp = (struct odirect *)&buf[size]; 29311127Smckusick for (odp = (struct odirect *)buf; odp < eodp; odp++) 29411127Smckusick if (odp->d_ino != 0) { 29511127Smckusick dcvt(odp, &cvtbuf); 29611127Smckusick putent(&cvtbuf); 29711127Smckusick } 29811127Smckusick } else { 29911127Smckusick for (loc = 0; loc < size; ) { 30011127Smckusick dp = (struct direct *)(buf + loc); 30126941Ssklower if (Bcvt) { 30226941Ssklower swabst("l2s", (char *) dp); 30326941Ssklower } 30411127Smckusick i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 30511127Smckusick if (dp->d_reclen == 0 || dp->d_reclen > i) { 30611127Smckusick loc += i; 30711127Smckusick continue; 30811127Smckusick } 30911127Smckusick loc += dp->d_reclen; 31011127Smckusick if (dp->d_ino != 0) { 31111127Smckusick putent(dp); 31211127Smckusick } 31311127Smckusick } 31411127Smckusick } 31511127Smckusick } 31611127Smckusick 31711127Smckusick /* 31811127Smckusick * These variables are "local" to the following two functions. 31911127Smckusick */ 32011127Smckusick char dirbuf[DIRBLKSIZ]; 32111127Smckusick long dirloc = 0; 32211127Smckusick long prev = 0; 32311127Smckusick 32411127Smckusick /* 32511127Smckusick * add a new directory entry to a file. 32611127Smckusick */ 32711127Smckusick putent(dp) 32811127Smckusick struct direct *dp; 32911127Smckusick { 33011322Smckusick dp->d_reclen = DIRSIZ(dp); 33111127Smckusick if (dirloc + dp->d_reclen > DIRBLKSIZ) { 33211127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = 33311127Smckusick DIRBLKSIZ - prev; 33411732Smckusick (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); 33511127Smckusick dirloc = 0; 33611127Smckusick } 33711127Smckusick bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 33811127Smckusick prev = dirloc; 33911127Smckusick dirloc += dp->d_reclen; 34011127Smckusick } 34111127Smckusick 34211127Smckusick /* 34311127Smckusick * flush out a directory that is finished. 34411127Smckusick */ 34511127Smckusick flushent() 34611127Smckusick { 34711127Smckusick 34811127Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 34911732Smckusick (void) fwrite(dirbuf, (int)dirloc, 1, df); 35011127Smckusick seekpt = ftell(df); 35111127Smckusick dirloc = 0; 35211127Smckusick } 35311127Smckusick 35411127Smckusick dcvt(odp, ndp) 35511127Smckusick register struct odirect *odp; 35611127Smckusick register struct direct *ndp; 35711127Smckusick { 35811127Smckusick 35911127Smckusick bzero((char *)ndp, (long)(sizeof *ndp)); 36011127Smckusick ndp->d_ino = odp->d_ino; 36111992Smckusick (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 36211127Smckusick ndp->d_namlen = strlen(ndp->d_name); 36311127Smckusick ndp->d_reclen = DIRSIZ(ndp); 36411127Smckusick } 36511127Smckusick 36611127Smckusick /* 36711127Smckusick * Seek to an entry in a directory. 36812556Smckusick * Only values returned by ``telldir'' should be passed to rst_seekdir. 36911732Smckusick * This routine handles many directories in a single file. 37011732Smckusick * It takes the base of the directory in the file, plus 37111732Smckusick * the desired seek offset into it. 37211127Smckusick */ 37311127Smckusick void 37412556Smckusick rst_seekdir(dirp, loc, base) 37511127Smckusick register DIR *dirp; 37611127Smckusick daddr_t loc, base; 37711127Smckusick { 37811127Smckusick 37911127Smckusick if (loc == telldir(dirp)) 38011127Smckusick return; 38111127Smckusick loc -= base; 38211127Smckusick if (loc < 0) 38312556Smckusick fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); 38411127Smckusick (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); 38511127Smckusick dirp->dd_loc = loc & (DIRBLKSIZ - 1); 38611127Smckusick if (dirp->dd_loc != 0) 38711127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 38811127Smckusick } 38911127Smckusick 39011127Smckusick /* 39111127Smckusick * get next entry in a directory. 39211127Smckusick */ 39311127Smckusick struct direct * 39412556Smckusick rst_readdir(dirp) 39511127Smckusick register DIR *dirp; 39611127Smckusick { 39711127Smckusick register struct direct *dp; 39811127Smckusick 39911127Smckusick for (;;) { 40011127Smckusick if (dirp->dd_loc == 0) { 40111127Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 40211127Smckusick DIRBLKSIZ); 40312453Smckusick if (dirp->dd_size <= 0) { 40412453Smckusick dprintf(stderr, "error reading directory\n"); 40511127Smckusick return NULL; 40612453Smckusick } 40711127Smckusick } 40811127Smckusick if (dirp->dd_loc >= dirp->dd_size) { 40911127Smckusick dirp->dd_loc = 0; 41011127Smckusick continue; 41111127Smckusick } 41211127Smckusick dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 41311127Smckusick if (dp->d_reclen == 0 || 41412453Smckusick dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { 41512453Smckusick dprintf(stderr, "corrupted directory: bad reclen %d\n", 41612453Smckusick dp->d_reclen); 41711127Smckusick return NULL; 41812453Smckusick } 41911127Smckusick dirp->dd_loc += dp->d_reclen; 42012453Smckusick if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) 42112453Smckusick continue; 42212556Smckusick if (dp->d_ino >= maxino) { 42312453Smckusick dprintf(stderr, "corrupted directory: bad inum %d\n", 42412453Smckusick dp->d_ino); 42512453Smckusick continue; 42612453Smckusick } 42711127Smckusick return (dp); 42811127Smckusick } 42911127Smckusick } 43011127Smckusick 43111127Smckusick /* 43217753Smckusick * Simulate the opening of a directory 43317753Smckusick */ 43417753Smckusick DIR * 43517753Smckusick rst_opendir(name) 43617753Smckusick char *name; 43717753Smckusick { 43817753Smckusick struct inotab *itp; 43917753Smckusick ino_t ino; 44017753Smckusick 44117753Smckusick if ((ino = dirlookup(name)) > 0 && 44217753Smckusick (itp = inotablookup(ino)) != NULL) { 44317753Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 44417753Smckusick return (dirp); 44517753Smckusick } 44617753Smckusick return (0); 44717753Smckusick } 44817753Smckusick 44917753Smckusick /* 45011127Smckusick * Set the mode, owner, and times for all new or changed directories 45111127Smckusick */ 45211992Smckusick setdirmodes() 45311127Smckusick { 45411127Smckusick FILE *mf; 45511127Smckusick struct modeinfo node; 45611127Smckusick struct entry *ep; 45711127Smckusick char *cp; 45811127Smckusick 45911127Smckusick vprintf(stdout, "Set directory mode, owner, and times.\n"); 46015779Smckusick (void) sprintf(modefile, "/tmp/rstmode%d", dumpdate); 46111127Smckusick mf = fopen(modefile, "r"); 46211127Smckusick if (mf == NULL) { 46311127Smckusick perror("fopen"); 46415779Smckusick fprintf(stderr, "cannot open mode file %s\n", modefile); 46515779Smckusick fprintf(stderr, "directory mode, owner, and times not set\n"); 46615779Smckusick return; 46711127Smckusick } 46811127Smckusick clearerr(mf); 46911309Smckusick for (;;) { 47011732Smckusick (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); 47111309Smckusick if (feof(mf)) 47211309Smckusick break; 47311127Smckusick ep = lookupino(node.ino); 47414453Smckusick if (command == 'i' || command == 'x') { 47514453Smckusick if (ep == NIL) 47611309Smckusick continue; 47718008Smckusick if (ep->e_flags & EXISTED) { 47818008Smckusick ep->e_flags &= ~NEW; 47918008Smckusick continue; 48018008Smckusick } 48114453Smckusick if (node.ino == ROOTINO && 48214453Smckusick reply("set owner/mode for '.'") == FAIL) 48314453Smckusick continue; 48414453Smckusick } 48514453Smckusick if (ep == NIL) 48611127Smckusick panic("cannot find directory inode %d\n", node.ino); 48711127Smckusick cp = myname(ep); 48811732Smckusick (void) chown(cp, node.uid, node.gid); 48911732Smckusick (void) chmod(cp, node.mode); 49011127Smckusick utime(cp, node.timep); 49111992Smckusick ep->e_flags &= ~NEW; 49211127Smckusick } 49311127Smckusick if (ferror(mf)) 49411127Smckusick panic("error setting directory modes\n"); 49511732Smckusick (void) fclose(mf); 49611127Smckusick } 49711127Smckusick 49811127Smckusick /* 49911127Smckusick * Generate a literal copy of a directory. 50011127Smckusick */ 50111127Smckusick genliteraldir(name, ino) 50211127Smckusick char *name; 50311127Smckusick ino_t ino; 50411127Smckusick { 50511127Smckusick register struct inotab *itp; 50611127Smckusick int ofile, dp, i, size; 50711127Smckusick char buf[BUFSIZ]; 50811127Smckusick 50911127Smckusick itp = inotablookup(ino); 51011127Smckusick if (itp == NULL) 51111322Smckusick panic("Cannot find directory inode %d named %s\n", ino, name); 51212893Ssam if ((ofile = creat(name, 0666)) < 0) { 51312556Smckusick fprintf(stderr, "%s: ", name); 51412556Smckusick (void) fflush(stderr); 51512556Smckusick perror("cannot create file"); 51611127Smckusick return (FAIL); 51711127Smckusick } 51812556Smckusick rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 51911127Smckusick dp = dup(dirp->dd_fd); 52011127Smckusick for (i = itp->t_size; i > 0; i -= BUFSIZ) { 52111127Smckusick size = i < BUFSIZ ? i : BUFSIZ; 52211127Smckusick if (read(dp, buf, (int) size) == -1) { 52311127Smckusick fprintf(stderr, 52411127Smckusick "write error extracting inode %d, name %s\n", 52511127Smckusick curfile.ino, curfile.name); 52611127Smckusick perror("read"); 52711127Smckusick done(1); 52811127Smckusick } 52934268Smckusick if (!Nflag && write(ofile, buf, (int) size) == -1) { 53011127Smckusick fprintf(stderr, 53111127Smckusick "write error extracting inode %d, name %s\n", 53211127Smckusick curfile.ino, curfile.name); 53311127Smckusick perror("write"); 53411127Smckusick done(1); 53511127Smckusick } 53611127Smckusick } 53711732Smckusick (void) close(dp); 53811732Smckusick (void) close(ofile); 53911127Smckusick return (GOOD); 54011127Smckusick } 54111127Smckusick 54211127Smckusick /* 54311992Smckusick * Determine the type of an inode 54411992Smckusick */ 54511992Smckusick inodetype(ino) 54611992Smckusick ino_t ino; 54711992Smckusick { 54811992Smckusick struct inotab *itp; 54911992Smckusick 55011992Smckusick itp = inotablookup(ino); 55111992Smckusick if (itp == NULL) 55211992Smckusick return (LEAF); 55311992Smckusick return (NODE); 55411992Smckusick } 55511992Smckusick 55611992Smckusick /* 55711127Smckusick * Allocate and initialize a directory inode entry. 55811127Smckusick * If requested, save its pertinent mode, owner, and time info. 55911127Smckusick */ 56011322Smckusick struct inotab * 56111127Smckusick allocinotab(ino, dip, seekpt) 56211127Smckusick ino_t ino; 56311127Smckusick struct dinode *dip; 56411127Smckusick daddr_t seekpt; 56511127Smckusick { 56611127Smckusick register struct inotab *itp; 56711127Smckusick struct modeinfo node; 56811127Smckusick 56911127Smckusick itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 57013859Smckusick if (itp == 0) 57113859Smckusick panic("no memory directory table\n"); 57211127Smckusick itp->t_next = inotab[INOHASH(ino)]; 57311127Smckusick inotab[INOHASH(ino)] = itp; 57411127Smckusick itp->t_ino = ino; 57511127Smckusick itp->t_seekpt = seekpt; 57611127Smckusick if (mf == NULL) 57711322Smckusick return(itp); 57811127Smckusick node.ino = ino; 57911127Smckusick node.timep[0] = dip->di_atime; 58011127Smckusick node.timep[1] = dip->di_mtime; 58111127Smckusick node.mode = dip->di_mode; 58211127Smckusick node.uid = dip->di_uid; 58311127Smckusick node.gid = dip->di_gid; 58411732Smckusick (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); 58511322Smckusick return(itp); 58611127Smckusick } 58711127Smckusick 58811127Smckusick /* 58911127Smckusick * Look up an inode in the table of directories 59011127Smckusick */ 59111127Smckusick struct inotab * 59211127Smckusick inotablookup(ino) 59311127Smckusick ino_t ino; 59411127Smckusick { 59511127Smckusick register struct inotab *itp; 59611127Smckusick 59711127Smckusick for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) 59811127Smckusick if (itp->t_ino == ino) 59911127Smckusick return(itp); 60011127Smckusick return ((struct inotab *)0); 60111127Smckusick } 60211127Smckusick 60311127Smckusick /* 60411127Smckusick * Clean up and exit 60511127Smckusick */ 60611127Smckusick done(exitcode) 60711127Smckusick int exitcode; 60811127Smckusick { 60911127Smckusick 61011127Smckusick closemt(); 61111992Smckusick if (modefile[0] != '#') 61211992Smckusick (void) unlink(modefile); 61311992Smckusick if (dirfile[0] != '#') 61411992Smckusick (void) unlink(dirfile); 61511127Smckusick exit(exitcode); 61611127Smckusick } 617