aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libarchive/libarchive/archive_write_disk_posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libarchive/libarchive/archive_write_disk_posix.c')
-rw-r--r--contrib/libarchive/libarchive/archive_write_disk_posix.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/contrib/libarchive/libarchive/archive_write_disk_posix.c b/contrib/libarchive/libarchive/archive_write_disk_posix.c
index 327b695a0620..91e9b6b59005 100644
--- a/contrib/libarchive/libarchive/archive_write_disk_posix.c
+++ b/contrib/libarchive/libarchive/archive_write_disk_posix.c
@@ -546,6 +546,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
struct fixup_entry *fe;
+ const char *linkname;
int ret, r;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -591,6 +592,17 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
return (ret);
/*
+ * Check if we have a hardlink that points to itself.
+ */
+ linkname = archive_entry_hardlink(a->entry);
+ if (linkname != NULL && strcmp(a->name, linkname) == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Skipping hardlink pointing to itself: %s",
+ a->name);
+ return (ARCHIVE_WARN);
+ }
+
+ /*
* Query the umask so we get predictable mode settings.
* This gets done on every call to _write_header in case the
* user edits their umask during the extraction for some
@@ -4386,10 +4398,19 @@ set_xattrs(struct archive_write_disk *a)
ssize_t e;
int namespace;
+ namespace = EXTATTR_NAMESPACE_USER;
+
if (strncmp(name, "user.", 5) == 0) {
/* "user." attributes go to user namespace */
name += 5;
namespace = EXTATTR_NAMESPACE_USER;
+ } else if (strncmp(name, "system.", 7) == 0) {
+ name += 7;
+ namespace = EXTATTR_NAMESPACE_SYSTEM;
+ if (!strcmp(name, "nfs4.acl") ||
+ !strcmp(name, "posix1e.acl_access") ||
+ !strcmp(name, "posix1e.acl_default"))
+ continue;
} else {
/* Other namespaces are unsupported */
archive_strcat(&errlist, name);
@@ -4400,8 +4421,29 @@ set_xattrs(struct archive_write_disk *a)
}
if (a->fd >= 0) {
+ /*
+ * On FreeBSD, extattr_set_fd does not
+ * return the same as
+ * extattr_set_file. It returns zero
+ * on success, non-zero on failure.
+ *
+ * We can detect the failure by
+ * manually setting errno prior to the
+ * call and checking after.
+ *
+ * If errno remains zero, fake the
+ * return value by setting e to size.
+ *
+ * This is a hack for now until I
+ * (Shawn Webb) get FreeBSD to fix the
+ * issue, if that's even possible.
+ */
+ errno = 0;
e = extattr_set_fd(a->fd, namespace, name,
value, size);
+ if (e == 0 && errno == 0) {
+ e = size;
+ }
} else {
e = extattr_set_link(
archive_entry_pathname(entry), namespace,