diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tar/bsdtar_platform.h | 14 | ||||
-rw-r--r-- | usr.bin/tar/write.c | 57 |
2 files changed, 63 insertions, 8 deletions
diff --git a/usr.bin/tar/bsdtar_platform.h b/usr.bin/tar/bsdtar_platform.h index fbabedb..1c5a930 100644 --- a/usr.bin/tar/bsdtar_platform.h +++ b/usr.bin/tar/bsdtar_platform.h @@ -41,6 +41,7 @@ #include <paths.h> /* For _PATH_DEFTAPE */ #define HAVE_CHFLAGS 1 +#define ARCHIVE_STAT_MTIME_NANOS(st) (st)->st_mtimespec.tv_nsec #if __FreeBSD__ > 4 #define HAVE_GETOPT_LONG 1 @@ -70,6 +71,7 @@ /* Linux */ #ifdef LINUX +#define _FILE_OFFSET_BITS 64 /* For a 64-bit off_t */ #include <stdint.h> /* for uintmax_t */ #define BSDTAR_FILESIZE_TYPE uintmax_t #define BSDTAR_FILESIZE_PRINTF "%ju" @@ -78,9 +80,15 @@ #define _GNU_SOURCE #define _PATH_DEFTAPE "/dev/st0" #define HAVE_GETOPT_LONG 1 -#define st_atimespec st_atim -#define st_mtimespec st_mtim -#define st_ctimespec st_ctim + +#ifdef HAVE_STRUCT_STAT_TIMESPEC +/* Fetch the nanosecond portion of the timestamp from a struct stat pointer. */ +#define ARCHIVE_STAT_MTIME_NANOS(pstat) (pstat)->st_mtim.tv_nsec +#else +/* High-res timestamps aren't available, so just use stubs here. */ +#define ARCHIVE_STAT_MTIME_NANOS(pstat) 0 +#endif + #endif /* diff --git a/usr.bin/tar/write.c b/usr.bin/tar/write.c index dace199..c183392 100644 --- a/usr.bin/tar/write.c +++ b/usr.bin/tar/write.c @@ -45,6 +45,10 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <string.h> #include <unistd.h> +#ifdef LINUX +#include <ext2fs/ext2_fs.h> +#include <sys/ioctl.h> +#endif #include "bsdtar.h" @@ -505,6 +509,10 @@ write_heirarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) FTSENT *ftsent; int ftsoptions; char *fts_argv[2]; +#ifdef LINUX + int fd, r; + unsigned long fflags; +#endif /* * Sigh: fts_open modifies it's first parameter, so we have to @@ -566,13 +574,27 @@ write_heirarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) } #endif +#ifdef LINUX + /* + * Linux has a nodump flag too but to read it + * we have to open() the file and do an ioctl on it... + */ + if (bsdtar->option_honor_nodump && + S_ISREG(ftsent->fts_statp->st_mode) && + ((fd = open(ftsent->fts_name, O_RDONLY|O_NONBLOCK)) >= 0) && + ((r = ioctl(fd, EXT2_IOC_GETFLAGS, &fflags)), + close(fd), r) >= 0 && + (fflags & EXT2_NODUMP_FL)) + break; +#endif + /* * In -u mode, we need to check whether this * is newer than what's already in the archive. */ if (!new_enough(bsdtar, ftsent->fts_path, ftsent->fts_statp->st_mtime, - ftsent->fts_statp->st_mtimespec.tv_nsec)) + ARCHIVE_STAT_MTIME_NANOS(ftsent->fts_statp))) break; /* * If this dir is excluded by a filename @@ -619,6 +641,21 @@ write_heirarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) (ftsent->fts_statp->st_flags & UF_NODUMP)) break; #endif + +#ifdef LINUX + /* + * Linux has a nodump flag too but to read it + * we have to open() the file and do an ioctl on it... + */ + if (bsdtar->option_honor_nodump && + S_ISREG(ftsent->fts_statp->st_mode) && + ((fd = open(ftsent->fts_name, O_RDONLY|O_NONBLOCK)) >= 0) && + ((r = ioctl(fd, EXT2_IOC_GETFLAGS, &fflags)), + close(fd), r) >= 0 && + (fflags & EXT2_NODUMP_FL)) + break; +#endif + /* * Skip this file if it's excluded by a * filename pattern. @@ -632,7 +669,7 @@ write_heirarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) */ if (!new_enough(bsdtar, ftsent->fts_path, ftsent->fts_statp->st_mtime, - ftsent->fts_statp->st_mtimespec.tv_nsec)) + ARCHIVE_STAT_MTIME_NANOS(ftsent->fts_statp))) break; if (bsdtar->option_interactive && @@ -671,7 +708,10 @@ write_entry(struct bsdtar *bsdtar, struct archive *a, struct stat *st, struct archive_entry *entry; int e; int fd; - char *fflags = NULL; +#ifdef LINUX + int r; + unsigned long stflags; +#endif static char linkbuffer[PATH_MAX+1]; (void)pathlen; /* UNUSED */ @@ -732,6 +772,15 @@ write_entry(struct bsdtar *bsdtar, struct archive *a, struct stat *st, archive_entry_set_fflags(entry, st->st_flags, 0); #endif +#ifdef LINUX + if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) && + ((fd = open(accpath, O_RDONLY|O_NONBLOCK)) >= 0) && + ((r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags)), close(fd), r) >= 0 && + stflags) { + archive_entry_set_fflags(entry, stflags, 0); + } +#endif + archive_entry_copy_stat(entry, st); setup_acls(bsdtar, entry, accpath); @@ -782,8 +831,6 @@ cleanup: if (bsdtar->verbose) fprintf(stderr, "\n"); - - if (fflags != NULL) free(fflags); } |