X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Fdirs.c;h=26c637bffb69bebb46a58df6bf5c0869d6da8bc9;hp=6398f8768f399249735bb829a82aeae650b47bfb;hb=f30c53e5aacd10d449f01703b31a927c8a7a3134;hpb=a1b67fc50f87e9febfd56bd2a7089eb569b852f6 diff --git a/restore/dirs.c b/restore/dirs.c index 6398f87..26c637b 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,20 +42,31 @@ #ifndef lint static const char rcsid[] = - "$Id: dirs.c,v 1.14 2001/03/20 10:02:48 stelian Exp $"; + "$Id: dirs.c,v 1.31 2005/01/24 10:32:14 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 @@ -73,8 +80,12 @@ static const char rcsid[] = #ifdef __linux__ #include #else +#ifdef sunos +#include +#else #include #endif +#endif #include "pathnames.h" #include "restore.h" @@ -88,8 +99,8 @@ static const char rcsid[] = struct inotab { struct inotab *t_next; dump_ino_t t_ino; - int32_t t_seekpt; - int32_t t_size; + OFF_T t_seekpt; + OFF_T t_size; }; static struct inotab *inotab[HASHSIZE]; @@ -120,7 +131,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 */ @@ -136,10 +147,12 @@ struct odirect { char d_name[ODIRSIZ]; }; -#ifdef __linux__ -static struct inotab *allocinotab __P((dump_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 *)); #else -static struct inotab *allocinotab __P((dump_ino_t, struct dinode *, long)); +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)); @@ -147,10 +160,14 @@ 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 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 * on disk for extraction by name. @@ -160,15 +177,16 @@ static struct direct *searchdir __P((dump_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; + dump_ino_t ino; Vprintf(stdout, "Extract directories from tape\n"); (void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%ld", tmpdir, @@ -176,9 +194,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); @@ -189,9 +207,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); @@ -207,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); @@ -221,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; @@ -248,10 +284,10 @@ skipdirs(void) void 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); @@ -272,7 +308,7 @@ treescan(char *pname, dump_ino_t ino, long (*todo) __P((char *, dump_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); /* "." */ @@ -292,7 +328,7 @@ treescan(char *pname, dump_ino_t ino, long (*todo) __P((char *, dump_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 { @@ -321,7 +357,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; @@ -336,8 +376,8 @@ pathsearch(const char *pathname) static struct direct * 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); @@ -360,12 +400,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) { @@ -373,7 +413,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", @@ -389,6 +429,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 @@ -398,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, @@ -408,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; @@ -427,9 +474,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. @@ -459,7 +506,7 @@ flushent(void) ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; if ( fwrite(dirbuf, (int)dirloc, 1, df) != 1 ) err(1, "cannot write to file %s", dirfile); - seekpt = ftell(df); + seekpt = FTELL(df); if (seekpt == -1) err(1, "cannot write to file %s", dirfile); dirloc = 0; @@ -485,15 +532,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); @@ -505,7 +552,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) { @@ -573,11 +620,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); } /* @@ -586,10 +633,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); @@ -639,7 +686,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; } @@ -651,9 +699,12 @@ 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); ep->e_flags &= ~NEW; @@ -664,13 +715,96 @@ 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. */ int genliteraldir(char *name, dump_ino_t ino) { - register struct inotab *itp; + struct inotab *itp; int ofile, dp, i, size; char buf[BUFSIZ]; @@ -720,14 +854,13 @@ inodetype(dump_ino_t ino) * If requested, save its pertinent mode, owner, and time info. */ static struct inotab * -#ifdef __linux__ -allocinotab(dump_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(dump_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) @@ -736,27 +869,37 @@ allocinotab(dump_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) { +#else +savemodeinfo(dump_ino_t ino, struct dinode *dip) { +#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; if ( fwrite((char *)&node, 1, sizeof(struct modeinfo), mf) != sizeof(struct modeinfo) ) err(1,"cannot write to file %s", modefile); - return (itp); } /* @@ -765,7 +908,7 @@ allocinotab(dump_ino_t ino, struct dinode *dip, long seekpt) static struct inotab * 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)