X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Fdirs.c;h=b049f49007801c6caa8c70d755b38ecce9dbc860;hp=49d50529b689a3c1720dd739caedc6dafdd2ea00;hb=cca7148b36e60b4671518602ff9a7c2d0c22a7b2;hpb=814574507fef62cfe83f6d1c579aa4b6736443a2 diff --git a/restore/dirs.c b/restore/dirs.c index 49d5052..b049f49 100644 --- a/restore/dirs.c +++ b/restore/dirs.c @@ -42,7 +42,7 @@ #ifndef lint static const char rcsid[] = - "$Id: dirs.c,v 1.27 2004/04/21 09:15:22 stelian Exp $"; + "$Id: dirs.c,v 1.32 2005/05/02 15:10:46 stelian Exp $"; #endif /* not lint */ #include @@ -114,6 +114,7 @@ struct modeinfo { uid_t uid; gid_t gid; unsigned int flags; + char xattr; }; /* @@ -148,9 +149,11 @@ struct odirect { }; #if defined(__linux__) || defined(sunos) -static struct inotab *allocinotab __P((dump_ino_t, struct new_bsd_inode *, OFF_T)); +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((dump_ino_t, struct dinode *, OFF_T)); +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)); @@ -177,13 +180,16 @@ extractdirs(int genmode) { int i; #if defined(__linux__) || defined(sunos) - struct new_bsd_inode *ip; + struct new_bsd_inode ip; #else - 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, @@ -222,8 +228,8 @@ extractdirs(int genmode) for (;;) { curfile.name = ""; curfile.action = USING; - ip = curfile.dip; - if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { + 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); @@ -236,8 +242,30 @@ extractdirs(int genmode) 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; @@ -518,7 +546,7 @@ rst_seekdir(RST_DIR *dirp, OFF_T loc, OFF_T base) return; loc -= base; if (loc < 0) - fprintf(stderr, "bad seek pointer to rst_seekdir %lld\n", loc); + 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) @@ -654,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) @@ -678,7 +712,7 @@ 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 @@ -686,6 +720,105 @@ setdirmodes(int 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; } } @@ -751,13 +884,12 @@ inodetype(dump_ino_t ino) */ static struct inotab * #if defined(__linux__) || defined(sunos) -allocinotab(dump_ino_t ino, struct new_bsd_inode *dip, OFF_T seekpt) +allocinotab(dump_ino_t ino, OFF_T seekpt) #else -allocinotab(dump_ino_t ino, struct dinode *dip, OFF_T seekpt) +allocinotab(dump_ino_t ino, OFF_T seekpt) #endif { struct inotab *itp; - struct modeinfo node; itp = calloc(1, sizeof(struct inotab)); if (itp == NULL) @@ -766,8 +898,19 @@ allocinotab(dump_ino_t ino, struct dinode *dip, OFF_T 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; #if defined(__linux__) || defined(sunos) node.timep[0].tv_sec = dip->di_atime.tv_sec; @@ -784,9 +927,12 @@ allocinotab(dump_ino_t ino, struct dinode *dip, OFF_T seekpt) node.flags = dip->di_flags; node.uid = dip->di_uid; node.gid = dip->di_gid; + 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); - return (itp); + if (xattr) + if ( fwrite(xattr, 1, XATTR_MAXSIZE, mf) != XATTR_MAXSIZE) + err(1,"cannot write to file %s", modefile); } /*