summaryrefslogtreecommitdiffstats
path: root/usr.bin/tar
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2006-03-21 17:03:51 +0000
committerkientzle <kientzle@FreeBSD.org>2006-03-21 17:03:51 +0000
commit2276f34c5fe887ff9ffe16296b723f9b16881154 (patch)
tree95e77682c7792281c3e4dd227adcb76fd79264d6 /usr.bin/tar
parent537ab73b2f9d8cc3e849014fd44738b6a48f6c99 (diff)
downloadFreeBSD-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/tar')
-rw-r--r--usr.bin/tar/Makefile2
-rw-r--r--usr.bin/tar/bsdtar.c3
-rw-r--r--usr.bin/tar/bsdtar.h2
-rw-r--r--usr.bin/tar/bsdtar_platform.h10
-rw-r--r--usr.bin/tar/getdate.y4
-rw-r--r--usr.bin/tar/read.c2
-rw-r--r--usr.bin/tar/tree.c2
-rw-r--r--usr.bin/tar/util.c1
-rw-r--r--usr.bin/tar/write.c137
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);
OpenPOWER on IntegriCloud