X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Fdirs.c;h=b049f49007801c6caa8c70d755b38ecce9dbc860;hp=b2a0cc4b3a8945b90e227f7065d2da9ec32bc502;hb=cca7148b36e60b4671518602ff9a7c2d0c22a7b2;hpb=0a99352128efc4af44160eee69e8990686bf9ad5 diff --git a/restore/dirs.c b/restore/dirs.c index b2a0cc4..b049f49 100644 --- a/restore/dirs.c +++ b/restore/dirs.c @@ -2,8 +2,8 @@ * Ported to Linux's Second Extended File System as part of the * dump and restore backup suit * Remy Card , 1994-1997 - * Stelian Pop , 1999-2000 - * Stelian Pop - Alcôve , 2000 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 */ /* @@ -23,11 +23,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -46,19 +42,31 @@ #ifndef lint static const char rcsid[] = - "$Id: dirs.c,v 1.10 2000/11/10 14:42:25 stelian Exp $"; + "$Id: dirs.c,v 1.32 2005/05/02 15:10:46 stelian Exp $"; #endif /* not lint */ +#include +#include +#include #include #include #include #ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else #include +#endif #include #else /* __linux__ */ +#ifdef sunos +#include +#include +#else #include #include +#endif #endif /* __linux__ */ #include @@ -72,8 +80,12 @@ static const char rcsid[] = #ifdef __linux__ #include #else +#ifdef sunos +#include +#else #include #endif +#endif #include "pathnames.h" #include "restore.h" @@ -86,9 +98,9 @@ static const char rcsid[] = #define INOHASH(val) (val % HASHSIZE) struct inotab { struct inotab *t_next; - ino_t t_ino; - int32_t t_seekpt; - int32_t t_size; + dump_ino_t t_ino; + OFF_T t_seekpt; + OFF_T t_size; }; static struct inotab *inotab[HASHSIZE]; @@ -96,12 +108,13 @@ static struct inotab *inotab[HASHSIZE]; * Information retained about directories. */ struct modeinfo { - ino_t ino; + dump_ino_t ino; struct timeval timep[2]; mode_t mode; uid_t uid; gid_t gid; unsigned int flags; + char xattr; }; /* @@ -119,7 +132,7 @@ struct rstdirdesc { /* * Global variables for this file. */ -static long seekpt; +static OFF_T seekpt; static FILE *df, *mf; static RST_DIR *dirp; static char dirfile[MAXPATHLEN] = "#"; /* No file */ @@ -135,20 +148,26 @@ struct odirect { char d_name[ODIRSIZ]; }; -#ifdef __linux__ -static struct inotab *allocinotab __P((ino_t, struct new_bsd_inode *, long)); +#if defined(__linux__) || defined(sunos) +static struct inotab *allocinotab __P((dump_ino_t, OFF_T)); +static void savemodeinfo __P((dump_ino_t, struct new_bsd_inode *, char *)); #else -static struct inotab *allocinotab __P((ino_t, struct dinode *, long)); +static struct inotab *allocinotab __P((dump_ino_t, OFF_T)); +static void savemodeinfo __P((dump_ino_t, struct dinode *, char *)); #endif static void dcvt __P((struct odirect *, struct direct *)); static void flushent __P((void)); -static struct inotab *inotablookup __P((ino_t)); +static struct inotab *inotablookup __P((dump_ino_t)); static RST_DIR *opendirfile __P((const char *)); static void putdir __P((char *, size_t)); static void putent __P((struct direct *)); -static void rst_seekdir __P((RST_DIR *, long, long)); -static long rst_telldir __P((RST_DIR *)); -static struct direct *searchdir __P((ino_t, char *)); +static void rst_seekdir __P((RST_DIR *, OFF_T, OFF_T)); +static OFF_T rst_telldir __P((RST_DIR *)); +static struct direct *searchdir __P((dump_ino_t, char *)); + +#ifdef sunos +extern int fdsmtc; +#endif /* * Extract directory contents, building up a directory structure @@ -159,15 +178,18 @@ static struct direct *searchdir __P((ino_t, char *)); void extractdirs(int genmode) { - register int i; -#ifdef __linux__ - register struct new_bsd_inode *ip; + int i; +#if defined(__linux__) || defined(sunos) + struct new_bsd_inode ip; #else - register struct dinode *ip; + struct dinode ip; #endif struct inotab *itp; struct direct nulldir; int fd; + char xattr[XATTR_MAXSIZE]; + int xattr_found = 0; + dump_ino_t ino; Vprintf(stdout, "Extract directories from tape\n"); (void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%ld", tmpdir, @@ -175,9 +197,9 @@ extractdirs(int genmode) if (command != 'r' && command != 'R') { (void) strncat(dirfile, "-XXXXXX", sizeof(dirfile) - strlen(dirfile)); - fd = mkstemp(dirfile); + fd = MKSTEMP(dirfile); } else - fd = open(dirfile, O_RDWR|O_CREAT|O_EXCL, 0666); + fd = OPEN(dirfile, O_RDWR|O_CREAT|O_EXCL, 0666); if (fd == -1 || (df = fdopen(fd, "w")) == NULL) { if (fd != -1) close(fd); @@ -188,9 +210,9 @@ extractdirs(int genmode) if (command != 'r' && command != 'R') { (void) strncat(modefile, "-XXXXXX", sizeof(modefile) - strlen(modefile)); - fd = mkstemp(modefile); + fd = MKSTEMP(modefile); } else - fd = open(modefile, O_RDWR|O_CREAT|O_EXCL, 0666); + fd = OPEN(modefile, O_RDWR|O_CREAT|O_EXCL, 0666); if (fd == -1 || (mf = fdopen(fd, "w")) == NULL) { if (fd != -1) close(fd); @@ -206,21 +228,44 @@ extractdirs(int genmode) for (;;) { curfile.name = ""; curfile.action = USING; - ip = curfile.dip; - if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { - (void) fclose(df); + ino = curfile.ino; + if (curfile.dip == NULL || (curfile.dip->di_mode & IFMT) != IFDIR) { + if ( fclose(df) == EOF ) + err(1, "cannot write to file %s", dirfile); dirp = opendirfile(dirfile); if (dirp == NULL) warn("opendirfile"); - if (mf != NULL) - (void) fclose(mf); + if (mf != NULL && fclose(mf) == EOF ) + err(1, "cannot write to file %s", dirfile); i = dirlookup(dot); if (i == 0) panic("Root directory is not on tape\n"); return; } - itp = allocinotab(curfile.ino, ip, seekpt); + memcpy(&ip, curfile.dip, sizeof(ip)); + itp = allocinotab(ino, seekpt); getfile(putdir, xtrnull); + xattr_found = 0; + while (spcl.c_flags & DR_EXTATTRIBUTES) { + switch (spcl.c_extattributes) { + case EXT_MACOSFNDRINFO: + msg("MacOSX attributes not supported, skipping\n"); + skipfile(); + break; + case EXT_MACOSRESFORK: + msg("MacOSX attributes not supported, skipping\n"); + skipfile(); + break; + case EXT_XATTR: + if (readxattr(xattr) == GOOD) + xattr_found = 1; + break; + } + } + if (xattr_found) + savemodeinfo(ino, &ip, xattr); + else + savemodeinfo(ino, &ip, NULL); putent(&nulldir); flushent(); itp->t_size = seekpt - itp->t_seekpt; @@ -244,12 +289,12 @@ skipdirs(void) * pname and pass them off to be processed. */ void -treescan(char *pname, ino_t ino, long (*todo) __P((char *, ino_t, int))) +treescan(char *pname, dump_ino_t ino, long (*todo) __P((char *, dump_ino_t, int))) { - register struct inotab *itp; - register struct direct *dp; + struct inotab *itp; + struct direct *dp; int namelen; - long bpt; + OFF_T bpt; char locname[MAXPATHLEN + 1]; itp = inotablookup(ino); @@ -270,7 +315,7 @@ treescan(char *pname, ino_t ino, long (*todo) __P((char *, ino_t, int))) * skipping over "." and ".." */ namelen = snprintf(locname, sizeof(locname), "%s/", pname); - if (namelen >= sizeof(locname)) + if (namelen >= (int)sizeof(locname)) namelen = sizeof(locname) - 1; rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); dp = rst_readdir(dirp); /* "." */ @@ -290,7 +335,7 @@ treescan(char *pname, ino_t ino, long (*todo) __P((char *, ino_t, int))) */ while (dp != NULL) { locname[namelen] = '\0'; - if (namelen + dp->d_namlen >= sizeof(locname)) { + if (namelen + dp->d_namlen >= (int)sizeof(locname)) { fprintf(stderr, "%s%s: name exceeds %ld char\n", locname, dp->d_name, (long)sizeof(locname) - 1); } else { @@ -309,7 +354,7 @@ treescan(char *pname, ino_t ino, long (*todo) __P((char *, ino_t, int))) struct direct * pathsearch(const char *pathname) { - ino_t ino; + dump_ino_t ino; struct direct *dp; char *path, *name, buffer[MAXPATHLEN]; @@ -319,7 +364,11 @@ pathsearch(const char *pathname) while (*path == '/') path++; dp = NULL; +#ifdef __linux__ while ((name = strsep(&path, "/")) != NULL && *name /* != NULL */) { +#else + while ((name = strtok_r(NULL, "/", &path)) != NULL && *name /* != NULL */) { +#endif if ((dp = searchdir(ino, name)) == NULL) return (NULL); ino = dp->d_ino; @@ -332,10 +381,10 @@ pathsearch(const char *pathname) * Return its inode number if found, zero if it does not exist. */ static struct direct * -searchdir(ino_t inum, char *name) +searchdir(dump_ino_t inum, char *name) { - register struct direct *dp; - register struct inotab *itp; + struct direct *dp; + struct inotab *itp; int len; itp = inotablookup(inum); @@ -358,12 +407,12 @@ static void putdir(char *buf, size_t size) { struct direct cvtbuf; - register struct odirect *odp; + struct odirect *odp; struct odirect *eodp; - register struct direct *dp; + struct direct *dp; long loc, i; - if (cvtflag) { + if (cvtflag && !ufs2flag) { eodp = (struct odirect *)&buf[size]; for (odp = (struct odirect *)buf; odp < eodp; odp++) if (odp->d_ino != 0) { @@ -371,7 +420,7 @@ putdir(char *buf, size_t size) putent(&cvtbuf); } } else { - for (loc = 0; loc < size; ) { + for (loc = 0; loc < (long)size; ) { dp = (struct direct *)(buf + loc); #ifdef DIRDEBUG printf ("reclen = %d, namlen = %d, type = %d\n", @@ -387,6 +436,8 @@ putdir(char *buf, size_t size) if (!Bcvt) dp->d_namlen = dp->d_type; # endif + if (dp->d_namlen == 0 && dp->d_type != 0) + dp->d_namlen = dp->d_type; dp->d_type = DT_UNKNOWN; } #ifdef DIRDEBUG @@ -396,8 +447,11 @@ putdir(char *buf, size_t size) i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); if ((dp->d_reclen & 0x3) != 0 || dp->d_reclen > i || - dp->d_reclen < DIRSIZ(0, dp) || - dp->d_namlen > MAXNAMLEN) { + dp->d_reclen < DIRSIZ(0, dp) +#if MAXNAMLEN < 255 + || dp->d_namlen > MAXNAMLEN +#endif + ) { Vprintf(stdout, "Mangled directory: "); if ((dp->d_reclen & 0x3) != 0) Vprintf(stdout, @@ -406,10 +460,12 @@ putdir(char *buf, size_t size) Vprintf(stdout, "reclen less than DIRSIZ (%d < %d) ", dp->d_reclen, DIRSIZ(0, dp)); +#if MAXNAMLEN < 255 if (dp->d_namlen > MAXNAMLEN) Vprintf(stdout, "reclen name too big (%d > %d) ", dp->d_namlen, MAXNAMLEN); +#endif Vprintf(stdout, "\n"); loc += i; continue; @@ -425,9 +481,9 @@ putdir(char *buf, size_t size) /* * These variables are "local" to the following two functions. */ -char dirbuf[DIRBLKSIZ]; -long dirloc = 0; -long prev = 0; +static char dirbuf[DIRBLKSIZ]; +static long dirloc = 0; +static long prev = 0; /* * add a new directory entry to a file. @@ -439,7 +495,8 @@ putent(struct direct *dp) if (dirloc + dp->d_reclen > DIRBLKSIZ) { ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; - (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); + if ( fwrite(dirbuf, 1, DIRBLKSIZ, df) != DIRBLKSIZ ) + err(1,"cannot write to file %s", dirfile); dirloc = 0; } memmove(dirbuf + dirloc, dp, (size_t)dp->d_reclen); @@ -454,8 +511,11 @@ static void flushent(void) { ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; - (void) fwrite(dirbuf, (int)dirloc, 1, df); - seekpt = ftell(df); + if ( fwrite(dirbuf, (int)dirloc, 1, df) != 1 ) + err(1, "cannot write to file %s", dirfile); + seekpt = FTELL(df); + if (seekpt == -1) + err(1, "cannot write to file %s", dirfile); dirloc = 0; } @@ -479,15 +539,15 @@ dcvt(struct odirect *odp, struct direct *ndp) * the desired seek offset into it. */ static void -rst_seekdir(RST_DIR *dirp, long loc, long base) +rst_seekdir(RST_DIR *dirp, OFF_T loc, OFF_T base) { if (loc == rst_telldir(dirp)) return; loc -= base; if (loc < 0) - fprintf(stderr, "bad seek pointer to rst_seekdir %ld\n", loc); - (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), SEEK_SET); + fprintf(stderr, "bad seek pointer to rst_seekdir %lld\n", (long long int)loc); + (void) LSEEK(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), SEEK_SET); dirp->dd_loc = loc & (DIRBLKSIZ - 1); if (dirp->dd_loc != 0) dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); @@ -499,7 +559,7 @@ rst_seekdir(RST_DIR *dirp, long loc, long base) struct direct * rst_readdir(RST_DIR *dirp) { - register struct direct *dp; + struct direct *dp; for (;;) { if (dirp->dd_loc == 0) { @@ -541,7 +601,7 @@ rst_opendir(const char *name) { struct inotab *itp; RST_DIR *dirp; - ino_t ino; + dump_ino_t ino; if ((ino = dirlookup(name)) > 0 && (itp = inotablookup(ino)) != NULL) { @@ -567,11 +627,11 @@ rst_closedir(RST_DIR *dirp) /* * Simulate finding the current offset in the directory. */ -static long +static OFF_T rst_telldir(RST_DIR *dirp) { - return ((long)lseek(dirp->dd_fd, - (off_t)0, SEEK_CUR) - dirp->dd_size + dirp->dd_loc); + return ((OFF_T)LSEEK(dirp->dd_fd, + (OFF_T)0, SEEK_CUR) - dirp->dd_size + dirp->dd_loc); } /* @@ -580,10 +640,10 @@ rst_telldir(RST_DIR *dirp) static RST_DIR * opendirfile(const char *name) { - register RST_DIR *dirp; - register int fd; + RST_DIR *dirp; + int fd; - if ((fd = open(name, O_RDONLY)) == -1) + if ((fd = OPEN(name, O_RDONLY)) == -1) return (NULL); if ((dirp = malloc(sizeof(RST_DIR))) == NULL) { (void)close(fd); @@ -622,9 +682,15 @@ setdirmodes(int flags) } clearerr(mf); for (;;) { + char xattr[XATTR_MAXSIZE]; (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); if (feof(mf)) break; + if (node.xattr) { + (void) fread(xattr, 1, XATTR_MAXSIZE, mf); + if (feof(mf)) + break; + } ep = lookupino(node.ino); if (command == 'i' || command == 'x') { if (ep == NULL) @@ -633,7 +699,8 @@ setdirmodes(int flags) ep->e_flags &= ~NEW; continue; } - if (node.ino == ROOTINO && + if ((flags & FORCE) == 0 && + node.ino == ROOTINO && reply("set owner/mode for '.'") == FAIL) continue; } @@ -645,11 +712,113 @@ setdirmodes(int flags) (void) chmod(cp, node.mode); if (node.flags) #ifdef __linux__ - (void) fsetflags(cp, node.flags); + (void) lsetflags(cp, node.flags); +#else +#ifdef sunos #else (void) chflags(cp, node.flags); +#endif #endif utimes(cp, node.timep); + if (node.xattr) + xattr_extract(cp, xattr); + ep->e_flags &= ~NEW; + } + } + if (ferror(mf)) + panic("error setting directory modes\n"); + (void) fclose(mf); +} + +/* + * In restore -C mode, tests the attributes for all directories + */ +void +comparedirmodes(void) +{ + FILE *mf; + struct modeinfo node; + struct entry *ep; + char *cp; + + Vprintf(stdout, "Compare directories modes, owner, attributes.\n"); + if (modefile[0] == '#') { + panic("modefile not defined\n"); + fprintf(stderr, "directory mode, owner, and times not set\n"); + return; + } + mf = fopen(modefile, "r"); + if (mf == NULL) { + warn("fopen"); + fprintf(stderr, "cannot open mode file %s\n", modefile); + fprintf(stderr, "directory mode, owner, and times not set\n"); + return; + } + clearerr(mf); + for (;;) { + char xattr[XATTR_MAXSIZE]; + (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); + if (feof(mf)) + break; + if (node.xattr) { + (void) fread(xattr, 1, XATTR_MAXSIZE, mf); + if (feof(mf)) + break; + } + ep = lookupino(node.ino); + if (ep == NULL) { + panic("cannot find directory inode %d\n", node.ino); + } else { + cp = myname(ep); + struct STAT sb; + unsigned long newflags; + + if (LSTAT(cp, &sb) < 0) { + warn("unable to stat %s", cp); + do_compare_error; + continue; + } + + Vprintf(stdout, "comparing directory %s\n", cp); + + if (sb.st_mode != node.mode) { + fprintf(stderr, "%s: mode changed from 0%o to 0%o.\n", + cp, node.mode & 07777, sb.st_mode & 07777); + do_compare_error; + } + if (sb.st_uid != node.uid) { + fprintf(stderr, "%s: uid changed from %d to %d.\n", + cp, node.uid, sb.st_uid); + do_compare_error; + } + if (sb.st_gid != node.gid) { + fprintf(stderr, "%s: gid changed from %d to %d.\n", + cp, node.gid, sb.st_gid); + do_compare_error; + } +#ifdef __linux__ + if (lgetflags(cp, &newflags) < 0) { + if (node.flags != 0) { + warn("%s: lgetflags failed", cp); + do_compare_error; + } + } + else { + if (newflags != node.flags) { + fprintf(stderr, "%s: flags changed from 0x%08x to 0x%08lx.\n", + cp, node.flags, newflags); + do_compare_error; + } + } +#endif + if (node.xattr) { + if (xattr_compare(cp, xattr) == FAIL) + do_compare_error; + } + else { + if (xattr_compare(cp, NULL) == FAIL) + do_compare_error; + } ep->e_flags &= ~NEW; } } @@ -662,9 +831,9 @@ setdirmodes(int flags) * Generate a literal copy of a directory. */ int -genliteraldir(char *name, ino_t ino) +genliteraldir(char *name, dump_ino_t ino) { - register struct inotab *itp; + struct inotab *itp; int ofile, dp, i, size; char buf[BUFSIZ]; @@ -699,7 +868,7 @@ genliteraldir(char *name, ino_t ino) * Determine the type of an inode */ int -inodetype(ino_t ino) +inodetype(dump_ino_t ino) { struct inotab *itp; @@ -714,14 +883,13 @@ inodetype(ino_t ino) * If requested, save its pertinent mode, owner, and time info. */ static struct inotab * -#ifdef __linux__ -allocinotab(ino_t ino, struct new_bsd_inode *dip, long seekpt) +#if defined(__linux__) || defined(sunos) +allocinotab(dump_ino_t ino, OFF_T seekpt) #else -allocinotab(ino_t ino, struct dinode *dip, long seekpt) +allocinotab(dump_ino_t ino, OFF_T seekpt) #endif { - register struct inotab *itp; - struct modeinfo node; + struct inotab *itp; itp = calloc(1, sizeof(struct inotab)); if (itp == NULL) @@ -730,35 +898,50 @@ allocinotab(ino_t ino, struct dinode *dip, long seekpt) inotab[INOHASH(ino)] = itp; itp->t_ino = ino; itp->t_seekpt = seekpt; + return itp; +} + +static void +#if defined(__linux__) || defined(sunos) +savemodeinfo(dump_ino_t ino, struct new_bsd_inode *dip, char *xattr) { +#else +savemodeinfo(dump_ino_t ino, struct dinode *dip, char *xattr) { +#endif + struct modeinfo node; + if (mf == NULL) - return (itp); + return; node.ino = ino; -#ifdef __linux__ +#if defined(__linux__) || defined(sunos) node.timep[0].tv_sec = dip->di_atime.tv_sec; node.timep[0].tv_usec = dip->di_atime.tv_usec; node.timep[1].tv_sec = dip->di_mtime.tv_sec; node.timep[1].tv_usec = dip->di_mtime.tv_usec; -#else /* __linux__ */ +#else /* __linux__ || sunos */ node.timep[0].tv_sec = dip->di_atime; node.timep[0].tv_usec = dip->di_atimensec / 1000; node.timep[1].tv_sec = dip->di_mtime; node.timep[1].tv_usec = dip->di_mtimensec / 1000; -#endif /* __linux__ */ +#endif /* __linux__ || sunos */ node.mode = dip->di_mode; node.flags = dip->di_flags; node.uid = dip->di_uid; node.gid = dip->di_gid; - (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); - return (itp); + node.xattr = xattr ? 1 : 0; + if ( fwrite((char *)&node, 1, sizeof(struct modeinfo), mf) != sizeof(struct modeinfo) ) + err(1,"cannot write to file %s", modefile); + if (xattr) + if ( fwrite(xattr, 1, XATTR_MAXSIZE, mf) != XATTR_MAXSIZE) + err(1,"cannot write to file %s", modefile); } /* * Look up an inode in the table of directories */ static struct inotab * -inotablookup(ino_t ino) +inotablookup(dump_ino_t ino) { - register struct inotab *itp; + struct inotab *itp; for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) if (itp->t_ino == ino)