X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Fdirs.c;h=26c637bffb69bebb46a58df6bf5c0869d6da8bc9;hp=3a8a94d4fd0dfc1a15016ac9f7b339eb7fbe5077;hb=f30c53e5aacd10d449f01703b31a927c8a7a3134;hpb=cc7747ebe3cb5b31e059155a8bb1ee4cecc67236 diff --git a/restore/dirs.c b/restore/dirs.c index 3a8a94d..26c637b 100644 --- a/restore/dirs.c +++ b/restore/dirs.c @@ -42,7 +42,7 @@ #ifndef lint static const char rcsid[] = - "$Id: dirs.c,v 1.26 2004/04/13 13:04:33 stelian Exp $"; + "$Id: dirs.c,v 1.31 2005/01/24 10:32:14 stelian Exp $"; #endif /* not lint */ #include @@ -148,9 +148,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 *)); #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 *)); #endif static void dcvt __P((struct odirect *, struct direct *)); static void flushent __P((void)); @@ -177,13 +179,14 @@ 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; + dump_ino_t ino; Vprintf(stdout, "Extract directories from tape\n"); (void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%ld", tmpdir, @@ -222,8 +225,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 +239,26 @@ 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); + 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: + msg("EA/ACLs attributes not supported, skipping\n"); + skipfile(); + break; + } + } + savemodeinfo(ino, &ip); putent(&nulldir); flushent(); itp->t_size = seekpt - itp->t_seekpt; @@ -419,8 +440,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, @@ -429,10 +453,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; @@ -513,7 +539,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) @@ -673,7 +699,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 @@ -689,6 +715,89 @@ setdirmodes(int flags) (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 (;;) { + (void) fread((char *)&node, 1, sizeof(struct modeinfo), 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 + ep->e_flags &= ~NEW; + } + } + if (ferror(mf)) + panic("error setting directory modes\n"); + (void) fclose(mf); +} + /* * Generate a literal copy of a directory. */ @@ -746,13 +855,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) @@ -761,8 +869,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) { +#else +savemodeinfo(dump_ino_t ino, struct dinode *dip) { +#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; @@ -781,7 +900,6 @@ allocinotab(dump_ino_t ino, struct dinode *dip, OFF_T seekpt) node.gid = dip->di_gid; if ( fwrite((char *)&node, 1, sizeof(struct modeinfo), mf) != sizeof(struct modeinfo) ) err(1,"cannot write to file %s", modefile); - return (itp); } /*