diff options
author | kientzle <kientzle@FreeBSD.org> | 2006-03-21 17:03:51 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2006-03-21 17:03:51 +0000 |
commit | 2276f34c5fe887ff9ffe16296b723f9b16881154 (patch) | |
tree | 95e77682c7792281c3e4dd227adcb76fd79264d6 /usr.bin | |
parent | 537ab73b2f9d8cc3e849014fd44738b6a48f6c99 (diff) | |
download | FreeBSD-src-2276f34c5fe887ff9ffe16296b723f9b16881154.zip FreeBSD-src-2276f34c5fe887ff9ffe16296b723f9b16881154.tar.gz |
Extended attribute support on write for Linux; FreeBSD hooks are
forthcoming. This commit also has a number of style(9) fixes and
minor corrections so the code works better with the build system being
used for non-FreeBSD builds.
Many thanks to: Jaakko Heinonen, who proposed a mechanism for extended
attribute support and implemented both the machine-independent portion
and the Linux-specific portion.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tar/Makefile | 2 | ||||
-rw-r--r-- | usr.bin/tar/bsdtar.c | 3 | ||||
-rw-r--r-- | usr.bin/tar/bsdtar.h | 2 | ||||
-rw-r--r-- | usr.bin/tar/bsdtar_platform.h | 10 | ||||
-rw-r--r-- | usr.bin/tar/getdate.y | 4 | ||||
-rw-r--r-- | usr.bin/tar/read.c | 2 | ||||
-rw-r--r-- | usr.bin/tar/tree.c | 2 | ||||
-rw-r--r-- | usr.bin/tar/util.c | 1 | ||||
-rw-r--r-- | usr.bin/tar/write.c | 137 |
9 files changed, 140 insertions, 23 deletions
diff --git a/usr.bin/tar/Makefile b/usr.bin/tar/Makefile index c854bd0..e3ccef0 100644 --- a/usr.bin/tar/Makefile +++ b/usr.bin/tar/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= bsdtar -VERSION= 1.2.41 +VERSION= 1.2.51 SRCS= bsdtar.c getdate.y matching.c read.c tree.c util.c write.c WARNS?= 5 DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ} diff --git a/usr.bin/tar/bsdtar.c b/usr.bin/tar/bsdtar.c index a63ee6f..07a923b 100644 --- a/usr.bin/tar/bsdtar.c +++ b/usr.bin/tar/bsdtar.c @@ -29,8 +29,6 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/stat.h> -#include <archive.h> -#include <archive_entry.h> #include <errno.h> #include <fcntl.h> #ifdef HAVE_GETOPT_LONG @@ -410,6 +408,7 @@ main(int argc, char **argv) case 'p': /* GNU tar, star */ bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; + bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; break; case 'r': /* SUSv2 */ diff --git a/usr.bin/tar/bsdtar.h b/usr.bin/tar/bsdtar.h index 5c37a71..0da306c 100644 --- a/usr.bin/tar/bsdtar.h +++ b/usr.bin/tar/bsdtar.h @@ -29,7 +29,7 @@ * $FreeBSD$ */ -#include <archive.h> +#include "bsdtar_platform.h" #include <stdio.h> #define DEFAULT_BYTES_PER_BLOCK (20*512) diff --git a/usr.bin/tar/bsdtar_platform.h b/usr.bin/tar/bsdtar_platform.h index e74e25a..f8b3d2c 100644 --- a/usr.bin/tar/bsdtar_platform.h +++ b/usr.bin/tar/bsdtar_platform.h @@ -112,8 +112,14 @@ #define __FBSDID(a) /* null */ #endif -#ifndef HAVE_LIBARCHIVE -#error Configuration error: did not find libarchive. +#ifdef HAVE_LIBARCHIVE +/* If we're using the platform libarchive, include system headers. */ +#include <archive.h> +#include <archive_entry.h> +#else +/* Otherwise, include user headers. */ +#include "archive.h" +#include "archive_entry.h" #endif /* diff --git a/usr.bin/tar/getdate.y b/usr.bin/tar/getdate.y index e6ca781..b40058c 100644 --- a/usr.bin/tar/getdate.y +++ b/usr.bin/tar/getdate.y @@ -23,8 +23,10 @@ /* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */ /* SUPPRESS 288 on yyerrlab *//* Label unused */ -#include "bsdtar_platform.h" +#ifdef __FreeBSD__ +#include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#endif #include <ctype.h> #include <stdio.h> diff --git a/usr.bin/tar/read.c b/usr.bin/tar/read.c index 681308d..ea677fe 100644 --- a/usr.bin/tar/read.c +++ b/usr.bin/tar/read.c @@ -31,8 +31,6 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/stat.h> -#include <archive.h> -#include <archive_entry.h> #include <errno.h> #include <grp.h> #include <limits.h> diff --git a/usr.bin/tar/tree.c b/usr.bin/tar/tree.c index 944a787..6ecb5de 100644 --- a/usr.bin/tar/tree.c +++ b/usr.bin/tar/tree.c @@ -130,7 +130,7 @@ tree_dump(struct tree *t, FILE *out) fprintf(out, "\tpwd: "); fflush(stdout); system("pwd"); fprintf(out, "\taccess: %s\n", t->basename); fprintf(out, "\tstack:\n"); - for(te = t->stack; te != NULL; te = te->next) { + for (te = t->stack; te != NULL; te = te->next) { fprintf(out, "\t\tte->name: %s%s%s\n", te->name, te->flags & needsPreVisit ? "" : " *", t->current == te ? " (current)" : ""); diff --git a/usr.bin/tar/util.c b/usr.bin/tar/util.c index 69cc671..2b7e9a7 100644 --- a/usr.bin/tar/util.c +++ b/usr.bin/tar/util.c @@ -29,7 +29,6 @@ __FBSDID("$FreeBSD$"); #include <sys/stat.h> #include <sys/types.h> /* Linux doesn't define mode_t, etc. in sys/stat.h. */ -#include <archive_entry.h> #include <ctype.h> #include <errno.h> #include <stdarg.h> diff --git a/usr.bin/tar/write.c b/usr.bin/tar/write.c index 8ce18a7..3f08eb0 100644 --- a/usr.bin/tar/write.c +++ b/usr.bin/tar/write.c @@ -32,8 +32,9 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_POSIX_ACL #include <sys/acl.h> #endif -#include <archive.h> -#include <archive_entry.h> +#ifdef HAVE_ATTR_XATTR_H +#include <attr/xattr.h> +#endif #include <errno.h> #include <fcntl.h> #include <fnmatch.h> @@ -119,6 +120,8 @@ static int new_enough(struct bsdtar *, const char *path, const struct stat *); static void setup_acls(struct bsdtar *, struct archive_entry *, const char *path); +static void setup_xattrs(struct bsdtar *, struct archive_entry *, + const char *path); static void test_for_append(struct bsdtar *); static void write_archive(struct archive *, struct bsdtar *); static void write_entry(struct bsdtar *, struct archive *, @@ -444,10 +447,11 @@ archive_names_from_file_helper(struct bsdtar *bsdtar, const char *line) } /* - * Copy from specified archive to current archive. - * Returns non-zero on fatal error (i.e., output errors). Errors - * reading the input archive set bsdtar->return_value, but this - * function will still return zero. + * Copy from specified archive to current archive. Returns non-zero + * for write errors (which force us to terminate the entire archiving + * operation). If there are errors reading the input archive, we set + * bsdtar->return_value but return zero, so the overall archiving + * operation will complete and return non-zero. */ static int append_archive(struct bsdtar *bsdtar, struct archive *a, const char *filename) @@ -509,7 +513,8 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, const char *filename) bsdtar->return_value = 1; } - return (0); /* TODO: Return non-zero on error */ + /* Note: If we got here, we saw no write errors, so return success. */ + return (0); } /* @@ -741,6 +746,7 @@ write_entry(struct bsdtar *bsdtar, struct archive *a, const struct stat *st, archive_entry_copy_stat(entry, st); setup_acls(bsdtar, entry, accpath); + setup_xattrs(bsdtar, entry, accpath); /* * If it's a regular file (and non-zero in size) make sure we @@ -991,11 +997,11 @@ lookup_hardlink(struct bsdtar *bsdtar, struct archive_entry *entry, } #ifdef HAVE_POSIX_ACL -void setup_acl(struct bsdtar *bsdtar, +static void setup_acl(struct bsdtar *bsdtar, struct archive_entry *entry, const char *accpath, int acl_type, int archive_entry_acl_type); -void +static void setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry, const char *accpath) { @@ -1009,7 +1015,7 @@ setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry, ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); } -void +static void setup_acl(struct bsdtar *bsdtar, struct archive_entry *entry, const char *accpath, int acl_type, int archive_entry_acl_type) { @@ -1073,7 +1079,7 @@ setup_acl(struct bsdtar *bsdtar, struct archive_entry *entry, } } #else -void +static void setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry, const char *accpath) { @@ -1083,13 +1089,120 @@ setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry, } #endif +#if HAVE_LISTXATTR && HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR + +static void +setup_xattr(struct bsdtar *bsdtar, struct archive_entry *entry, + const char *accpath, const char *name) +{ + size_t size; + void *value = NULL; + char symlink_mode = bsdtar->symlink_mode; + + if (symlink_mode == 'H') + size = getxattr(accpath, name, NULL, 0); + else + size = lgetxattr(accpath, name, NULL, 0); + + if (size == -1) { + bsdtar_warnc(bsdtar, errno, "Couldn't get extended attribute"); + return; + } + + if (size > 0 && (value = malloc(size)) == NULL) { + bsdtar_errc(bsdtar, 1, errno, "Out of memory"); + return; + } + + if (symlink_mode == 'H') + size = getxattr(accpath, name, value, size); + else + size = lgetxattr(accpath, name, value, size); + + if (size == -1) { + bsdtar_warnc(bsdtar, errno, "Couldn't get extended attribute"); + return; + } + + archive_entry_xattr_add_entry(entry, name, value, size); + + free(value); +} + +/* + * Linux extended attribute support + */ +static void +setup_xattrs(struct bsdtar *bsdtar, struct archive_entry *entry, + const char *accpath) +{ + char *list, *p; + size_t list_size; + char symlink_mode = bsdtar->symlink_mode; + + if (symlink_mode == 'H') + list_size = listxattr(accpath, NULL, 0); + else + list_size = llistxattr(accpath, NULL, 0); + + if (list_size == -1) { + bsdtar_warnc(bsdtar, errno, + "Couldn't list extended attributes"); + return; + } else if (list_size == 0) + return; + + if ((list = malloc(list_size)) == NULL) { + bsdtar_errc(bsdtar, 1, errno, "Out of memory"); + return; + } + + if (symlink_mode == 'H') + list_size = listxattr(accpath, list, list_size); + else + list_size = llistxattr(accpath, list, list_size); + + if (list_size == -1) { + bsdtar_warnc(bsdtar, errno, + "Couldn't list extended attributes"); + free(list); + return; + } + + for (p = list; (p - list) < list_size; p += strlen(p) + 1) { + if (strncmp(p, "system.", 7) == 0 || + strncmp(p, "xfsroot.", 8) == 0) + continue; + + setup_xattr(bsdtar, entry, accpath, p); + } + + free(list); +} + +#else + +/* + * Generic (stub) extended attribute support. + */ +static void +setup_xattrs(struct bsdtar *bsdtar, struct archive_entry *entry, + const char *accpath) +{ + (void)bsdtar; /* UNUSED */ + (void)entry; /* UNUSED */ + (void)accpath; /* UNUSED */ +} + +#endif + static void free_cache(struct name_cache *cache) { size_t i; if (cache != NULL) { - for(i = 0; i < cache->size; i++) { + for (i = 0; i < cache->size; i++) { if (cache->cache[i].name != NULL && cache->cache[i].name != NO_NAME) free((void *)(uintptr_t)cache->cache[i].name); |