X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Ftape.c;h=e60921bf3b86b1afff5ce0a8666978da04fe89d7;hp=b4fa15d93c8cdc9882f6a112524253614c6ee1d2;hb=cca7148b36e60b4671518602ff9a7c2d0c22a7b2;hpb=d1925e0c515fcb4f815d75292566d600fd715ff5 diff --git a/restore/tape.c b/restore/tape.c index b4fa15d..e60921b 100644 --- a/restore/tape.c +++ b/restore/tape.c @@ -42,7 +42,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.75 2003/10/26 16:05:48 stelian Exp $"; + "$Id: tape.c,v 1.89 2005/05/02 15:10:46 stelian Exp $"; #endif /* not lint */ #include @@ -167,7 +167,10 @@ static void xtrlnkskip __P((char *, size_t)); static void xtrmap __P((char *, size_t)); static void xtrmapskip __P((char *, size_t)); static void xtrskip __P((char *, size_t)); +static void xtrxattr __P((char *, size_t)); static void setmagtapein __P((void)); +static int extractattr __P((char *)); +static void compareattr __P((char *)); #if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) static void newcomprbuf __P((int)); @@ -194,6 +197,9 @@ static void xtrcmpskip __P((char *, size_t)); static int readmapflag; static int readingmaps; /* set to 1 while reading the maps */ +static char xattrbuf[XATTR_MAXSIZE]; +static int xattrlen; + #ifdef DUMP_MACOSX static DumpFinderInfo gFndrInfo; #endif @@ -413,13 +419,19 @@ setup(void) dump_ino_t oldmaxino = maxino; maxino += (spcl.c_count * TP_BSIZE * NBBY) + 1; resizemaps(oldmaxino, maxino); + map = usedinomap; spcl.c_dinode.di_size = spcl.c_count * TP_BSIZE; getfile(xtrmap, xtrmapskip); } Dprintf(stdout, "maxino = %lu\n", (unsigned long)maxino); - if (spcl.c_type != TS_BITS) + if (spcl.c_type != TS_BITS) { + if (spcl.c_type == TS_END) { + msg("Cannot find file dump list, assuming empty tape\n"); + exit(0); + } errx(1, "Cannot find file dump list"); + } map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); if (map == (char *)NULL) errx(1, "no memory for file dump list"); @@ -834,14 +846,19 @@ extractfile(struct entry *ep, int doremove) return (GOOD); case IFDIR: + { + int ret; if (mflag) { if (ep == NULL || ep->e_flags & EXTRACT) panic("unextracted directory %s\n", name); skipfile(); return (GOOD); } - Vprintf(stdout, "extract file %s\n", name); - return (genliteraldir(name, curfile.ino)); + Vprintf(stdout, "extract dir %s\n", name); + ret = genliteraldir(name, curfile.ino); + extractattr(name); + return ret; + } case IFLNK: { @@ -867,6 +884,7 @@ extractfile(struct entry *ep, int doremove) #ifdef HAVE_LCHOWN (void) lchown(name, luid, lgid); #endif + extractattr(name); return (GOOD); } @@ -889,7 +907,7 @@ extractfile(struct entry *ep, int doremove) (void) chmod(name, mode); if (flags) #ifdef __linux__ - (void) fsetflags(name, flags); + (void) lsetflags(name, flags); #else #ifdef sunos { @@ -901,6 +919,7 @@ extractfile(struct entry *ep, int doremove) #endif #endif skipfile(); + extractattr(name); utimes(name, timep); return (GOOD); @@ -925,8 +944,8 @@ extractfile(struct entry *ep, int doremove) if (flags) #ifdef __linux__ { - warn("%s: fsetflags called on a special file", name); - (void) fsetflags(name, flags); + warn("%s: lsetflags called on a special file", name); + (void) lsetflags(name, flags); } #else #ifdef sunos @@ -942,6 +961,7 @@ extractfile(struct entry *ep, int doremove) #endif #endif skipfile(); + extractattr(name); utimes(name, timep); return (GOOD); @@ -973,7 +993,7 @@ extractfile(struct entry *ep, int doremove) (void) chmod(name, mode); if (flags) #ifdef __linux__ - (void) fsetflags(name, flags); + (void) lsetflags(name, flags); #else #ifdef sunos { @@ -984,6 +1004,7 @@ extractfile(struct entry *ep, int doremove) (void) chflags(name, flags); #endif #endif + extractattr(name); utimes(name, timep); return (GOOD); } @@ -991,6 +1012,44 @@ extractfile(struct entry *ep, int doremove) /* NOTREACHED */ } +static int +extractattr(char *path) +{ + while (spcl.c_flags & DR_EXTATTRIBUTES) { + switch (spcl.c_extattributes) { + case EXT_MACOSFNDRINFO: +#ifdef DUMP_MACOSX + (void)extractfinderinfoufs(path); +#else + msg("MacOSX not supported in this version, skipping\n"); + skipfile(); +#endif + break; + case EXT_MACOSRESFORK: +#ifdef DUMP_MACOSX + (void)extractresourceufs(path); +#else + msg("MacOSX not supported in this version, skipping\n"); + skipfile(); +#endif + break; + case EXT_XATTR: { + char xattr[XATTR_MAXSIZE]; + + if (readxattr(xattr) == GOOD) { + xattr_extract(path, xattr); + break; + } + } + default: + msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes); + skipfile(); + break; + } + } + return GOOD; +} + #ifdef DUMP_MACOSX int extractfinderinfoufs(char *name) @@ -1000,9 +1059,6 @@ extractfinderinfoufs(char *name) int flags; mode_t mode; struct timeval timep[2]; - struct entry *ep; - int sz; - attrinfo_block_t gABuf; u_int32_t uid; u_int32_t gid; char path[MAXPATHLEN], fname[MAXPATHLEN]; @@ -1157,7 +1213,7 @@ extractresourceufs(char *name) (void) fchown(ofile, uid, gid); (void) fchmod(ofile, mode); (void) close(ofile); - (void) fsetflags(oFileRsrc, flags); + (void) lsetflags(oFileRsrc, flags); utimes(oFileRsrc, timep); return (GOOD); } @@ -1165,6 +1221,29 @@ extractresourceufs(char *name) } #endif /* DUMP_MACOSX */ +int +readxattr(char *buffer) +{ + if (dflag) + msg("reading EA data for inode %lu\n", curfile.ino); + + curfile.name = "EA block"; + if (curfile.dip->di_size > XATTR_MAXSIZE) { + fprintf(stderr, "EA size too big (%ld)", (long)curfile.dip->di_size); + skipfile(); + return (FAIL); + } + + memset(xattrbuf, 0, XATTR_MAXSIZE); + xattrlen = 0; + + getfile(xtrxattr, xtrnull); + + memcpy(buffer, xattrbuf, XATTR_MAXSIZE); + + return (GOOD); +} + /* * skip over bit maps on the tape */ @@ -1187,6 +1266,17 @@ skipfile(void) getfile(xtrnull, xtrnull); } +/* + * skip over any extended attributes. + */ +void +skipxattr(void) +{ + + while (spcl.c_flags & DR_EXTATTRIBUTES) + skipfile(); +} + /* * Extract a file from the tape. * When an allocated block is found it is passed to the fill function; @@ -1286,8 +1376,6 @@ xtrfile(char *buf, size_t size) static void xtrfilefinderinfo(char *buf, size_t size) { - if (Nflag) - return; bcopy(buf, &gFndrInfo, size); } #endif /* DUMP_MACOSX */ @@ -1313,10 +1401,13 @@ xtrlnkfile(char *buf, size_t size) { pathlen += size; - if (pathlen > MAXPATHLEN) + if (pathlen > MAXPATHLEN) { + buf[size - 1] = '\0'; errx(1, "symbolic link name: %s->%s%s; too long %d", curfile.name, lnkbuf, buf, pathlen); + } (void) strcat(lnkbuf, buf); + lnkbuf[pathlen] = '\0'; } /* @@ -1420,9 +1511,20 @@ xtrcmpskip(UNUSED(char *buf), size_t size) } #endif /* COMPARE_ONTHEFLY */ +static void +xtrxattr(char *buf, size_t size) +{ + if (xattrlen + size > XATTR_MAXSIZE) { + fprintf(stderr, "EA size too big (%ld)", (long)xattrlen + size); + return; + } + memcpy(xattrbuf + xattrlen, buf, size); + xattrlen += size; +} + #if !COMPARE_ONTHEFLY static int -do_cmpfiles(int fd_tape, int fd_disk, long size) +do_cmpfiles(int fd_tape, int fd_disk, OFF_T size) { static char buf_tape[BUFSIZ]; static char buf_disk[BUFSIZ]; @@ -1464,15 +1566,15 @@ cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk) int fd_tape, fd_disk; if (STAT(tapefile, &sbuf_tape) != 0) { - panic("Can't lstat tmp file %s: %s\n", tapefile, + panic("can't lstat tmp file %s: %s\n", tapefile, strerror(errno)); do_compare_error; } if (sbuf_disk->st_size != sbuf_tape.st_size) { fprintf(stderr, - "%s: size changed from %ld to %ld.\n", - diskfile, (long)sbuf_tape.st_size, (long)sbuf_disk->st_size); + "%s: size changed from %lld to %lld.\n", + diskfile, (long long)sbuf_tape.st_size, (long long)sbuf_disk->st_size); do_compare_error; #ifdef COMPARE_FAIL_KEEP_FILE return (0); @@ -1482,12 +1584,12 @@ cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk) } if ((fd_tape = OPEN(tapefile, O_RDONLY)) < 0) { - panic("Can't open %s: %s\n", tapefile, strerror(errno)); + panic("can't open %s: %s\n", tapefile, strerror(errno)); do_compare_error; } if ((fd_disk = OPEN(diskfile, O_RDONLY)) < 0) { close(fd_tape); - panic("Can't open %s: %s\n", diskfile, strerror(errno)); + panic("can't open %s: %s\n", diskfile, strerror(errno)); do_compare_error; } @@ -1532,6 +1634,43 @@ cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk) } #endif /* !COMPARE_ONTHEFLY */ +static void +compareattr(char *name) +{ + int xattr_done = 0; + + while (spcl.c_flags & DR_EXTATTRIBUTES) { + switch (spcl.c_extattributes) { + case EXT_MACOSFNDRINFO: + msg("MacOSX not supported for comparision in this version, skipping\n"); + skipfile(); + break; + case EXT_MACOSRESFORK: + msg("MacOSX not supported for comparision in this version, skipping\n"); + skipfile(); + break; + case EXT_XATTR: { + char xattr[XATTR_MAXSIZE]; + + if (readxattr(xattr) == GOOD) { + if (xattr_compare(name, xattr) == FAIL) + do_compare_error; + xattr_done = 1; + } + else + do_compare_error; + break; + } + default: + msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes); + skipfile(); + break; + } + } + if (!xattr_done && xattr_compare(name, NULL) == FAIL) + do_compare_error; +} + #if !COMPARE_ONTHEFLY static char tmpfilename[MAXPATHLEN]; #endif @@ -1539,17 +1678,23 @@ static char tmpfilename[MAXPATHLEN]; void comparefile(char *name) { - unsigned int mode; + mode_t mode; + uid_t uid; + uid_t gid; + unsigned int flags; + unsigned long newflags; struct STAT sb; int r; #if !COMPARE_ONTHEFLY static char *tmpfile = NULL; struct STAT stemp; #endif - curfile.name = name; curfile.action = USING; mode = curfile.dip->di_mode; + flags = curfile.dip->di_flags; + uid = curfile.dip->di_uid; + gid = curfile.dip->di_gid; if ((mode & IFMT) == IFSOCK) { Vprintf(stdout, "skipped socket %s\n", name); @@ -1558,20 +1703,45 @@ comparefile(char *name) } if ((r = LSTAT(name, &sb)) != 0) { - warn("%s: does not exist (%d)", name, r); + warn("unable to stat %s", name); do_compare_error; skipfile(); return; } - Vprintf(stdout, "comparing %s (size: %ld, mode: 0%o)\n", name, - (long)sb.st_size, mode); + Vprintf(stdout, "comparing %s (size: %lld, mode: 0%o)\n", name, + (long long)sb.st_size, mode); if (sb.st_mode != mode) { fprintf(stderr, "%s: mode changed from 0%o to 0%o.\n", name, mode & 07777, sb.st_mode & 07777); do_compare_error; } + if (sb.st_uid != uid) { + fprintf(stderr, "%s: uid changed from %d to %d.\n", + name, uid, sb.st_uid); + do_compare_error; + } + if (sb.st_gid != gid) { + fprintf(stderr, "%s: gid changed from %d to %d.\n", + name, gid, sb.st_gid); + do_compare_error; + } +#ifdef __linux__ + if (lgetflags(name, &newflags) < 0) { + if (flags != 0) { + warn("%s: lgetflags failed", name); + do_compare_error; + } + } + else { + if (newflags != flags) { + fprintf(stderr, "%s: flags changed from 0x%08x to 0x%08lx.\n", + name, flags, newflags); + do_compare_error; + } + } +#endif if (spcl.c_flags & DR_METAONLY) { skipfile(); return; @@ -1587,6 +1757,7 @@ comparefile(char *name) case IFDIR: skipfile(); + compareattr(name); return; case IFLNK: { @@ -1610,7 +1781,7 @@ comparefile(char *name) return; } if ((lsize = readlink(name, lbuf, MAXPATHLEN)) < 0) { - panic("readlink of %s failed: %s", name, + panic("readlink of %s failed: %s\n", name, strerror(errno)); do_compare_error; } @@ -1622,6 +1793,7 @@ comparefile(char *name) do_compare_error; return; } + compareattr(name); return; } @@ -1639,19 +1811,20 @@ comparefile(char *name) fprintf(stderr, "%s: device changed from %d,%d to %d,%d.\n", name, - ((int)curfile.dip->di_rdev >> 8) & 0xff, - (int)curfile.dip->di_rdev & 0xff, - ((int)sb.st_rdev >> 8) & 0xff, - (int)sb.st_rdev & 0xff); + major(curfile.dip->di_rdev), + minor(curfile.dip->di_rdev), + major(sb.st_rdev), + minor(sb.st_rdev)); do_compare_error; } skipfile(); + compareattr(name); return; case IFREG: #if COMPARE_ONTHEFLY if ((ifile = OPEN(name, O_RDONLY)) < 0) { - panic("Can't open %s: %s\n", name, strerror(errno)); + warn("can't open %s", name); skipfile(); do_compare_error; } @@ -1694,6 +1867,7 @@ comparefile(char *name) unlink(tmpfile); #endif #endif /* COMPARE_ONTHEFLY */ + compareattr(name); return; } /* NOTREACHED */ @@ -2059,9 +2233,6 @@ decompress_tapebuf(struct tapebuf *tpbin, int readsize) /* zflag gets set in setup() from the dump header */ int cresult, blocklen; unsigned long worklen; -#ifdef HAVE_BZLIB - unsigned int worklen2; -#endif char *output = NULL,*reason = NULL, *lengtherr = NULL; /* build a length error message */ @@ -2108,7 +2279,7 @@ decompress_tapebuf(struct tapebuf *tpbin, int readsize) #ifndef HAVE_BZLIB errx(1,"This restore version doesn't support bzlib decompression"); #else - worklen2 = worklen; + unsigned int worklen2 = worklen; cresult = BZ2_bzBuffToBuffDecompress( comprbuf, &worklen2, tpbin->buf, blocklen, 0, 0); @@ -2141,8 +2312,10 @@ decompress_tapebuf(struct tapebuf *tpbin, int readsize) #ifndef HAVE_LZO errx(1,"This restore version doesn't support lzo decompression"); #else + lzo_uint worklen2 = worklen; cresult = lzo1x_decompress(tpbin->buf, blocklen, - comprbuf, (lzo_uintp) &worklen,NULL); + comprbuf, &worklen2, NULL); + worklen = worklen2; output = comprbuf; switch (cresult) { case LZO_E_OK: @@ -2172,7 +2345,7 @@ decompress_tapebuf(struct tapebuf *tpbin, int readsize) } if (reason) { if (lengtherr) - fprintf(stderr, "%s compressed block: %d expected: %d\n", + fprintf(stderr, "%s compressed block: %d expected: %u\n", lengtherr, readsize, tpbin->length + PREFIXSIZE); fprintf(stderr, "decompression error, block %ld: %s\n", tpblksread+1, reason); @@ -2453,34 +2626,47 @@ converthead(struct s_spcl *buf) goto good; } memcpy(&u_ospcl.s_ospcl, buf, TP_BSIZE); - memset((char *)buf, 0, (long)TP_BSIZE); - buf->c_type = u_ospcl.s_ospcl.c_type; - buf->c_date = u_ospcl.s_ospcl.c_date; - buf->c_ddate = u_ospcl.s_ospcl.c_ddate; - buf->c_volume = u_ospcl.s_ospcl.c_volume; - buf->c_tapea = u_ospcl.s_ospcl.c_tapea; - buf->c_inumber = u_ospcl.s_ospcl.c_inumber; - buf->c_checksum = u_ospcl.s_ospcl.c_checksum; - buf->c_magic = u_ospcl.s_ospcl.c_magic; - buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; - buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; - buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; - buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; - buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; - buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; + if (checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) + return(FAIL); + if (u_ospcl.s_ospcl.c_magic == OFS_MAGIC) { + memset((char *)buf, 0, (long)TP_BSIZE); + buf->c_type = u_ospcl.s_ospcl.c_type; + buf->c_date = u_ospcl.s_ospcl.c_date; + buf->c_ddate = u_ospcl.s_ospcl.c_ddate; + buf->c_volume = u_ospcl.s_ospcl.c_volume; + buf->c_tapea = u_ospcl.s_ospcl.c_tapea; + buf->c_inumber = u_ospcl.s_ospcl.c_inumber; + buf->c_checksum = u_ospcl.s_ospcl.c_checksum; + buf->c_magic = u_ospcl.s_ospcl.c_magic; + buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; + buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; + buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; + buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; + buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; + buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; #if defined(__linux__) || defined(sunos) - buf->c_dinode.di_atime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_atime; - buf->c_dinode.di_mtime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_mtime; - buf->c_dinode.di_ctime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_ctime; + buf->c_dinode.di_atime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_atime; + buf->c_dinode.di_mtime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_mtime; + buf->c_dinode.di_ctime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_ctime; #else /* __linux__ || sunos */ - buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; - buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; - buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; + buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; + buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; + buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; #endif /* __linux__ || sunos */ - buf->c_count = u_ospcl.s_ospcl.c_count; - memmove(buf->c_addr, u_ospcl.s_ospcl.c_fill, (long)256); - if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || - checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) + buf->c_count = u_ospcl.s_ospcl.c_count; + memmove(buf->c_addr, u_ospcl.s_ospcl.c_fill, (long)256); + } + else if (u_ospcl.s_ospcl.c_magic == FS_UFS2_MAGIC) { + buf->c_date = (int32_t)(*(int64_t *)&u_ospcl.dummy[896]); + buf->c_ddate = (int32_t)(*(int64_t *)&u_ospcl.dummy[904]); + buf->c_tapea = (int32_t)(*(int64_t *)&u_ospcl.dummy[912]); + buf->c_firstrec = (int32_t)(*(int64_t *)&u_ospcl.dummy[920]); + buf->c_ntrec = 0; + buf->c_extattributes = 0; + buf->c_flags |= DR_NEWINODEFMT; + ufs2flag = 1; + } + else return(FAIL); buf->c_magic = NFS_MAGIC;