svn commit: r304869 - in head/contrib/libarchive: libarchive tar
Martin Matuska
mm at FreeBSD.org
Fri Aug 26 23:50:45 UTC 2016
Author: mm
Date: Fri Aug 26 23:50:44 2016
New Revision: 304869
URL: https://svnweb.freebsd.org/changeset/base/304869
Log:
MFV r304866:
Sync libarchive with vendor including security fixes
Vendor issues fixed:
Issue #731: Reject tar entries >= INT64_MAX
Issue #744 (part of Issue #743): Enforce sandbox with very long pathnames
Issue #748: Zip decompression failure with highly-compressed data
Issue #767: Buffer overflow printing a filename
Issue #770: Zip read: be more careful about extra_length
MFC after: 3 days
Modified:
head/contrib/libarchive/libarchive/archive_acl.c
head/contrib/libarchive/libarchive/archive_entry.h
head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
head/contrib/libarchive/libarchive/archive_read_support_format_tar.c
head/contrib/libarchive/libarchive/archive_read_support_format_zip.c
head/contrib/libarchive/libarchive/archive_write_disk_acl.c
head/contrib/libarchive/libarchive/archive_write_disk_posix.c
head/contrib/libarchive/libarchive/archive_write_set_format_pax.c
head/contrib/libarchive/tar/util.c
Directory Properties:
head/contrib/libarchive/ (props changed)
head/contrib/libarchive/libarchive/ (props changed)
head/contrib/libarchive/tar/ (props changed)
Modified: head/contrib/libarchive/libarchive/archive_acl.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_acl.c Fri Aug 26 22:56:23 2016 (r304868)
+++ head/contrib/libarchive/libarchive/archive_acl.c Fri Aug 26 23:50:44 2016 (r304869)
@@ -57,21 +57,27 @@ static int archive_acl_add_entry_len_l(s
size_t len, struct archive_string_conv *sc);
static int isint_w(const wchar_t *start, const wchar_t *end, int *result);
static int ismode_w(const wchar_t *start, const wchar_t *end, int *result);
+static int parse_nfs4_flags_w(const wchar_t *start, const wchar_t *end,
+ int *result);
+static int parse_nfs4_perms_w(const wchar_t *start, const wchar_t *end,
+ int *result);
static void next_field_w(const wchar_t **wp, const wchar_t **start,
const wchar_t **end, wchar_t *sep);
static int prefix_w(const wchar_t *start, const wchar_t *end,
const wchar_t *test);
-static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
- const wchar_t *wname, int perm, int id);
+static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+ int tag, const wchar_t *wname, int perm, int id);
static void append_id_w(wchar_t **wp, int id);
static int isint(const char *start, const char *end, int *result);
static int ismode(const char *start, const char *end, int *result);
+static int parse_nfs4_flags(const char *start, const char *end, int *result);
+static int parse_nfs4_perms(const char *start, const char *end, int *result);
static void next_field(const char **p, const char **start,
const char **end, char *sep);
static int prefix_c(const char *start, const char *end,
const char *test);
-static void append_entry(char **p, const char *prefix, int tag,
- const char *name, int perm, int id);
+static void append_entry(char **p, const char *prefix, int type,
+ int tag, const char *name, int perm, int id);
static void append_id(char **p, int id);
void
@@ -447,6 +453,16 @@ archive_acl_text_w(struct archive *a, st
int id, r;
wchar_t *wp;
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) &&
+ (flags & (ARCHIVE_ENTRY_ACL_TYPE_ACCESS | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))) {
+ /* cannot convert NFSv4 ACLs and POSIX1e ACLs at the same time */
+ return (NULL);
+ }
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) && (flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) {
+ /* cannot have access and default at the same time */
+ return (NULL);
+ }
+
if (acl->acl_text_w != NULL) {
free (acl->acl_text_w);
acl->acl_text_w = NULL;
@@ -462,17 +478,57 @@ archive_acl_text_w(struct archive *a, st
if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
(ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
length += 8; /* "default:" */
- length += 5; /* tag name */
+ switch (ap->tag) {
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ length += 6; /* "owner@" */
+ break;
+ }
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_USER:
+ length += 4; /* "user" */
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ length += 6; /* "group@" */
+ break;
+ }
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ length += 5; /* "group", "other" */
+ break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ length += 9; /* "everyone@" */
+ break;
+ }
length += 1; /* colon */
- r = archive_mstring_get_wcs(a, &ap->name, &wname);
- if (r == 0 && wname != NULL)
- length += wcslen(wname);
- else if (r < 0 && errno == ENOMEM)
- return (NULL);
+ if (((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) ||
+ ap->tag == ARCHIVE_ENTRY_ACL_USER ||
+ ap->tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ r = archive_mstring_get_wcs(a, &ap->name, &wname);
+ if (r == 0 && wname != NULL)
+ length += wcslen(wname);
+ else if (r < 0 && errno == ENOMEM)
+ return (NULL);
+ else
+ length += sizeof(uid_t) * 3 + 1;
+ length += 1; /* colon */
+ }
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
+ length += 14; /* rwxpdDaARWcCos */
else
- length += sizeof(uid_t) * 3 + 1;
- length ++; /* colon */
- length += 3; /* rwx */
+ length += 3; /* rwx */
+ length += 1; /* colon */
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ length += 7; /* fdinSFI */
+ length += 1; /* colon */
+ if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) != 0)
+ length += 4; /* deny */
+ else
+ length += 5; /* allow, alarm, audit */
+ length += 1; /* colon */
+ }
length += 1; /* colon */
length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
length ++; /* newline */
@@ -480,34 +536,39 @@ archive_acl_text_w(struct archive *a, st
ap = ap->next;
}
- if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
+ if (count == 0)
+ return (NULL);
+
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
length += 10; /* "user::rwx\n" */
length += 11; /* "group::rwx\n" */
length += 11; /* "other::rwx\n" */
}
- if (count == 0)
- return (NULL);
-
/* Now, allocate the string and actually populate it. */
wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t));
if (wp == NULL)
return (NULL);
count = 0;
+
if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
- acl->mode & 0700, -1);
+ append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, acl->mode & 0700, -1);
*wp++ = ',';
- append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
- acl->mode & 0070, -1);
+ append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, acl->mode & 0070, -1);
*wp++ = ',';
- append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
- acl->mode & 0007, -1);
+ append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_OTHER, NULL, acl->mode & 0007, -1);
count += 3;
+ }
+ if ((flags & (ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4)) != 0) {
ap = acl->acl_head;
while (ap != NULL) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ if ((ap->type & (ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4)) != 0) {
r = archive_mstring_get_wcs(a, &ap->name, &wname);
if (r == 0) {
*wp++ = separator;
@@ -515,8 +576,8 @@ archive_acl_text_w(struct archive *a, st
id = ap->id;
else
id = -1;
- append_entry_w(&wp, NULL, ap->tag, wname,
- ap->permset, id);
+ append_entry_w(&wp, NULL, ap->type, ap->tag,
+ wname, ap->permset, id);
count++;
} else if (r < 0 && errno == ENOMEM)
return (NULL);
@@ -525,7 +586,6 @@ archive_acl_text_w(struct archive *a, st
}
}
-
if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT)
prefix = L"default:";
@@ -543,8 +603,8 @@ archive_acl_text_w(struct archive *a, st
id = ap->id;
else
id = -1;
- append_entry_w(&wp, prefix, ap->tag,
- wname, ap->permset, id);
+ append_entry_w(&wp, prefix, ap->type,
+ ap->tag, wname, ap->permset, id);
count ++;
} else if (r < 0 && errno == ENOMEM)
return (NULL);
@@ -568,8 +628,8 @@ append_id_w(wchar_t **wp, int id)
}
static void
-append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
- const wchar_t *wname, int perm, int id)
+append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+ int tag, const wchar_t *wname, int perm, int id)
{
if (prefix != NULL) {
wcscpy(*wp, prefix);
@@ -579,6 +639,11 @@ append_entry_w(wchar_t **wp, const wchar
case ARCHIVE_ENTRY_ACL_USER_OBJ:
wname = NULL;
id = -1;
+ if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ wcscpy(*wp, L"owner@");
+ break;
+ }
+ /* FALLTHROUGH */
/* FALLTHROUGH */
case ARCHIVE_ENTRY_ACL_USER:
wcscpy(*wp, L"user");
@@ -603,18 +668,57 @@ append_entry_w(wchar_t **wp, const wchar
}
*wp += wcslen(*wp);
*(*wp)++ = L':';
- if (wname != NULL) {
- wcscpy(*wp, wname);
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0 ||
+ tag == ARCHIVE_ENTRY_ACL_USER ||
+ tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ if (wname != NULL) {
+ wcscpy(*wp, wname);
+ *wp += wcslen(*wp);
+ } else if (tag == ARCHIVE_ENTRY_ACL_USER
+ || tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ append_id_w(wp, id);
+ id = -1;
+ }
+ *(*wp)++ = L':';
+ }
+ *(*wp)++ = (perm & (ARCHIVE_ENTRY_ACL_READ |
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_LIST_DIRECTORY)) ? L'r' : L'-';
+ *(*wp)++ = (perm & (ARCHIVE_ENTRY_ACL_WRITE |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_ADD_FILE)) ? L'w' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_EXECUTE) ? L'x' : L'-';
+ if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ *(*wp)++ = (perm & (ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY)) ? L'p' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_DELETE) ? L'd' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_DELETE_CHILD) ? L'D' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES) ? L'a' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES) ? L'A' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS) ? L'R' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS) ? L'W' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_READ_ACL) ? L'c' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_WRITE_ACL) ? L'C' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_WRITE_OWNER) ? L'o' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_SYNCHRONIZE) ? L's' : L'-';
+ *(*wp)++ = L':';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT) ? L'f' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT) ? L'd' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY) ? L'i' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT) ? L'n' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS) ? L'S' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS) ? L'F' : L'-';
+ *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_INHERITED) ? L'I' : L'-';
+ *(*wp)++ = L':';
+ if (type & ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
+ wcscpy(*wp, L"allow");
+ else if (type & ARCHIVE_ENTRY_ACL_TYPE_DENY)
+ wcscpy(*wp, L"deny");
+ else if (type & ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
+ wcscpy(*wp, L"audit");
+ else if (type & ARCHIVE_ENTRY_ACL_TYPE_ALARM)
+ wcscpy(*wp, L"alarm");
*wp += wcslen(*wp);
- } else if (tag == ARCHIVE_ENTRY_ACL_USER
- || tag == ARCHIVE_ENTRY_ACL_GROUP) {
- append_id_w(wp, id);
- id = -1;
}
- *(*wp)++ = L':';
- *(*wp)++ = (perm & 0444) ? L'r' : L'-';
- *(*wp)++ = (perm & 0222) ? L'w' : L'-';
- *(*wp)++ = (perm & 0111) ? L'x' : L'-';
if (id != -1) {
*(*wp)++ = L':';
append_id_w(wp, id);
@@ -637,6 +741,16 @@ archive_acl_text_l(struct archive_acl *a
int id, r;
char *p;
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) &&
+ (flags & (ARCHIVE_ENTRY_ACL_TYPE_ACCESS | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))) {
+ /* cannot convert NFSv4 ACLs and POSIX1e ACLs at the same time */
+ return (-1);
+ }
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) && (flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) {
+ /* cannot have access and default at the same time */
+ return (-1);
+ }
+
if (acl->acl_text != NULL) {
free (acl->acl_text);
acl->acl_text = NULL;
@@ -655,63 +769,109 @@ archive_acl_text_l(struct archive_acl *a
if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
(ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
length += 8; /* "default:" */
- length += 5; /* tag name */
+ switch (ap->tag) {
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ length += 6; /* "owner@" */
+ break;
+ }
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_USER:
+ length += 4; /* "user" */
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ length += 6; /* "group@" */
+ break;
+ }
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ length += 5; /* "group", "other" */
+ break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ length += 9; /* "everyone@" */
+ break;
+ }
+
length += 1; /* colon */
- r = archive_mstring_get_mbs_l(
- &ap->name, &name, &len, sc);
- if (r != 0)
- return (-1);
- if (len > 0 && name != NULL)
- length += len;
+ if (((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) ||
+ ap->tag == ARCHIVE_ENTRY_ACL_USER ||
+ ap->tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ r = archive_mstring_get_mbs_l(
+ &ap->name, &name, &len, sc);
+ if (r != 0)
+ return (-1);
+ if (len > 0 && name != NULL)
+ length += len;
+ else
+ length += sizeof(uid_t) * 3 + 1;
+ length += 1; /* colon */
+ }
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
+ length += 14; /* rwxpdDaARWcCos */
else
- length += sizeof(uid_t) * 3 + 1;
- length ++; /* colon */
- length += 3; /* rwx */
+ length += 3; /* rwx */
length += 1; /* colon */
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ length += 7; /* fdinSFI */
+ length += 1; /* colon */
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DENY) != 0)
+ length += 4; /* deny */
+ else
+ length += 5; /* allow, alarm, audit */
+ length += 1; /* colon */
+ }
+
length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
length ++; /* newline */
}
ap = ap->next;
}
- if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
+ if (count == 0)
+ return (0);
+
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
length += 10; /* "user::rwx\n" */
length += 11; /* "group::rwx\n" */
length += 11; /* "other::rwx\n" */
}
- if (count == 0)
- return (0);
-
/* Now, allocate the string and actually populate it. */
p = acl->acl_text = (char *)malloc(length);
if (p == NULL)
return (-1);
count = 0;
if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
- acl->mode & 0700, -1);
+ append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, acl->mode & 0700, -1);
*p++ = ',';
- append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
- acl->mode & 0070, -1);
+ append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, acl->mode & 0070, -1);
*p++ = ',';
- append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
- acl->mode & 0007, -1);
+ append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_OTHER, NULL, acl->mode & 0007, -1);
count += 3;
+ }
+ if ((flags & (ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4)) != 0) {
for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) == 0)
+ if ((ap->type & (ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4)) == 0)
continue;
r = archive_mstring_get_mbs_l(
&ap->name, &name, &len, sc);
if (r != 0)
return (-1);
- *p++ = separator;
+ if (count > 0)
+ *p++ = separator;
if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
id = ap->id;
else
id = -1;
- append_entry(&p, NULL, ap->tag, name,
+ append_entry(&p, NULL, ap->type, ap->tag, name,
ap->permset, id);
count++;
}
@@ -737,7 +897,7 @@ archive_acl_text_l(struct archive_acl *a
id = ap->id;
else
id = -1;
- append_entry(&p, prefix, ap->tag,
+ append_entry(&p, prefix, ap->type, ap->tag,
name, ap->permset, id);
count ++;
}
@@ -760,8 +920,8 @@ append_id(char **p, int id)
}
static void
-append_entry(char **p, const char *prefix, int tag,
- const char *name, int perm, int id)
+append_entry(char **p, const char *prefix, int type,
+ int tag, const char *name, int perm, int id)
{
if (prefix != NULL) {
strcpy(*p, prefix);
@@ -771,6 +931,10 @@ append_entry(char **p, const char *prefi
case ARCHIVE_ENTRY_ACL_USER_OBJ:
name = NULL;
id = -1;
+ if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ strcpy(*p, "owner@");
+ break;
+ }
/* FALLTHROUGH */
case ARCHIVE_ENTRY_ACL_USER:
strcpy(*p, "user");
@@ -778,6 +942,10 @@ append_entry(char **p, const char *prefi
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
name = NULL;
id = -1;
+ if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ strcpy(*p, "group@");
+ break;
+ }
/* FALLTHROUGH */
case ARCHIVE_ENTRY_ACL_GROUP:
strcpy(*p, "group");
@@ -792,21 +960,65 @@ append_entry(char **p, const char *prefi
name = NULL;
id = -1;
break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ strcpy(*p, "everyone@");
+ name = NULL;
+ id = -1;
+ break;
}
*p += strlen(*p);
*(*p)++ = ':';
- if (name != NULL) {
- strcpy(*p, name);
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0 ||
+ tag == ARCHIVE_ENTRY_ACL_USER ||
+ tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ if (name != NULL) {
+ strcpy(*p, name);
+ *p += strlen(*p);
+ } else if (tag == ARCHIVE_ENTRY_ACL_USER
+ || tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ append_id(p, id);
+ id = -1;
+ }
+ *(*p)++ = ':';
+ }
+ *(*p)++ = (perm & (ARCHIVE_ENTRY_ACL_READ |
+ ARCHIVE_ENTRY_ACL_READ_DATA |
+ ARCHIVE_ENTRY_ACL_LIST_DIRECTORY)) ? 'r' : '-';
+ *(*p)++ = (perm & (ARCHIVE_ENTRY_ACL_WRITE |
+ ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_ADD_FILE)) ? 'w' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_EXECUTE) ? 'x' : '-';
+ if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ *(*p)++ = (perm & (ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY)) ? 'p' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_DELETE) ? 'd' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_DELETE_CHILD) ? 'D' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES) ? 'a' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES) ? 'A' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS) ? 'R' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS) ? 'W' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_READ_ACL) ? 'c' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_WRITE_ACL) ? 'C' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_WRITE_OWNER) ? 'o' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_SYNCHRONIZE) ? 's' : '-';
+ *(*p)++ = ':';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT) ? 'f' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT) ? 'd' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY) ? 'i' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT) ? 'n' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS) ? 'S' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS) ? 'F' : '-';
+ *(*p)++ = (perm & ARCHIVE_ENTRY_ACL_ENTRY_INHERITED) ? 'I' : '-';
+ *(*p)++ = ':';
+ if (type & ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
+ strcpy(*p, "allow");
+ else if (type & ARCHIVE_ENTRY_ACL_TYPE_DENY)
+ strcpy(*p, "deny");
+ else if (type & ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
+ strcpy(*p, "audit");
+ else if (type & ARCHIVE_ENTRY_ACL_TYPE_ALARM)
+ strcpy(*p, "alarm");
*p += strlen(*p);
- } else if (tag == ARCHIVE_ENTRY_ACL_USER
- || tag == ARCHIVE_ENTRY_ACL_GROUP) {
- append_id(p, id);
- id = -1;
}
- *(*p)++ = ':';
- *(*p)++ = (perm & 0444) ? 'r' : '-';
- *(*p)++ = (perm & 0222) ? 'w' : '-';
- *(*p)++ = (perm & 0111) ? 'x' : '-';
if (id != -1) {
*(*p)++ = ':';
append_id(p, id);
@@ -827,12 +1039,19 @@ archive_acl_parse_w(struct archive_acl *
struct {
const wchar_t *start;
const wchar_t *end;
- } field[4], name;
+ } field[6], name;
- int fields, n;
+ int numfields, fields, n;
int type, tag, permset, id;
+ int offset;
wchar_t sep;
+ if (default_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4)
+ numfields = 6;
+ else
+ numfields = 4;
+
+
while (text != NULL && *text != L'\0') {
/*
* Parse the fields out of the next entry,
@@ -842,7 +1061,7 @@ archive_acl_parse_w(struct archive_acl *
do {
const wchar_t *start, *end;
next_field_w(&text, &start, &end, &sep);
- if (fields < 4) {
+ if (fields < numfields) {
field[fields].start = start;
field[fields].end = end;
}
@@ -850,72 +1069,148 @@ archive_acl_parse_w(struct archive_acl *
} while (sep == L':');
/* Set remaining fields to blank. */
- for (n = fields; n < 4; ++n)
+ for (n = fields; n < numfields; ++n)
field[n].start = field[n].end = NULL;
- /* Check for a numeric ID in field 1 or 3. */
- id = -1;
- isint_w(field[1].start, field[1].end, &id);
- /* Field 3 is optional. */
- if (id == -1 && fields > 3)
- isint_w(field[3].start, field[3].end, &id);
+ if (default_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ /* POSIX.1e ACLs */
+ /* Check for a numeric ID in field 1 or 3. */
+ id = -1;
+ isint_w(field[1].start, field[1].end, &id);
+ /* Field 3 is optional. */
+ if (id == -1 && fields > 3)
+ isint_w(field[3].start, field[3].end, &id);
+
+ /*
+ * Solaris extension: "defaultuser::rwx" is the
+ * default ACL corresponding to "user::rwx", etc.
+ */
+ if (field[0].end - field[0].start > 7
+ && wmemcmp(field[0].start, L"default", 7) == 0) {
+ type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+ field[0].start += 7;
+ } else
+ type = default_type;
- /*
- * Solaris extension: "defaultuser::rwx" is the
- * default ACL corresponding to "user::rwx", etc.
- */
- if (field[0].end - field[0].start > 7
- && wmemcmp(field[0].start, L"default", 7) == 0) {
- type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
- field[0].start += 7;
- } else
- type = default_type;
-
- name.start = name.end = NULL;
- if (prefix_w(field[0].start, field[0].end, L"user")) {
- if (!ismode_w(field[2].start, field[2].end, &permset))
+ name.start = name.end = NULL;
+ if (prefix_w(field[0].start, field[0].end, L"user")) {
+ if (!ismode_w(field[2].start, field[2].end,
+ &permset))
return (ARCHIVE_WARN);
- if (id != -1 || field[1].start < field[1].end) {
- tag = ARCHIVE_ENTRY_ACL_USER;
- name = field[1];
+ if (id != -1 || field[1].start < field[1].end) {
+ tag = ARCHIVE_ENTRY_ACL_USER;
+ name = field[1];
+ } else
+ tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ } else if (prefix_w(field[0].start, field[0].end,
+ L"group")) {
+ if (!ismode_w(field[2].start, field[2].end,
+ &permset))
+ return (ARCHIVE_WARN);
+ if (id != -1 || field[1].start < field[1].end) {
+ tag = ARCHIVE_ENTRY_ACL_GROUP;
+ name = field[1];
+ } else
+ tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ } else if (prefix_w(field[0].start, field[0].end,
+ L"other")) {
+ if (fields == 2
+ && field[1].start < field[1].end
+ && ismode_w(field[1].start, field[1].end,
+ &permset)) {
+ /* This is Solaris-style "other:rwx" */
+ } else if (fields == 3
+ && field[1].start == field[1].end
+ && field[2].start < field[2].end
+ && ismode_w(field[2].start, field[2].end,
+ &permset)) {
+ /* This is FreeBSD-style "other::rwx" */
+ } else
+ return (ARCHIVE_WARN);
+ tag = ARCHIVE_ENTRY_ACL_OTHER;
+ } else if (prefix_w(field[0].start, field[0].end,
+ L"mask")) {
+ if (fields == 2
+ && field[1].start < field[1].end
+ && ismode_w(field[1].start, field[1].end,
+ &permset)) {
+ /* This is Solaris-style "mask:rwx" */
+ } else if (fields == 3
+ && field[1].start == field[1].end
+ && field[2].start < field[2].end
+ && ismode_w(field[2].start, field[2].end,
+ &permset)) {
+ /* This is FreeBSD-style "mask::rwx" */
+ } else
+ return (ARCHIVE_WARN);
+ tag = ARCHIVE_ENTRY_ACL_MASK;
} else
- tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
- } else if (prefix_w(field[0].start, field[0].end, L"group")) {
- if (!ismode_w(field[2].start, field[2].end, &permset))
return (ARCHIVE_WARN);
- if (id != -1 || field[1].start < field[1].end) {
+ } else {
+ /* NFSv4 ACLs */
+ if (wcsncmp(field[0].start, L"user",
+ field[0].end - field[0].start) == 0)
+ tag = ARCHIVE_ENTRY_ACL_USER;
+ else if (wcsncmp(field[0].start, L"group",
+ field[0].end - field[0].start) == 0)
tag = ARCHIVE_ENTRY_ACL_GROUP;
- name = field[1];
- } else
+ else if (wcsncmp(field[0].start, L"owner@",
+ field[0].end - field[0].start) == 0)
+ tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ else if (wcsncmp(field[0].start, L"group@",
+ field[0].end - field[0].start) == 0)
tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- } else if (prefix_w(field[0].start, field[0].end, L"other")) {
- if (fields == 2
- && field[1].start < field[1].end
- && ismode_w(field[1].start, field[1].end, &permset)) {
- /* This is Solaris-style "other:rwx" */
- } else if (fields == 3
- && field[1].start == field[1].end
- && field[2].start < field[2].end
- && ismode_w(field[2].start, field[2].end, &permset)) {
- /* This is FreeBSD-style "other::rwx" */
- } else
+ else if (wcsncmp(field[0].start, L"everyone@",
+ field[0].end - field[0].start) == 0)
+ tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+ else {
+ /* Unknown entry */
return (ARCHIVE_WARN);
- tag = ARCHIVE_ENTRY_ACL_OTHER;
- } else if (prefix_w(field[0].start, field[0].end, L"mask")) {
- if (fields == 2
- && field[1].start < field[1].end
- && ismode_w(field[1].start, field[1].end, &permset)) {
- /* This is Solaris-style "mask:rwx" */
- } else if (fields == 3
- && field[1].start == field[1].end
- && field[2].start < field[2].end
- && ismode_w(field[2].start, field[2].end, &permset)) {
- /* This is FreeBSD-style "mask::rwx" */
+ }
+
+ permset = 0;
+ name.start = name.end = NULL;
+
+ if (tag == ARCHIVE_ENTRY_ACL_USER ||
+ tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ offset = 1;
+ name = field[1];
} else
+ offset = 0;
+
+ if (parse_nfs4_perms_w(field[1 + offset].start,
+ field[1 + offset].end, &permset) != 0) {
+ /* NFS4 perms are invalid */
+ return (ARCHIVE_WARN);
+ }
+ if (parse_nfs4_flags_w(field[2 + offset].start,
+ field[2 + offset].end, &permset) != 0) {
+ /* NFS4 flags are invalid */
+ return (ARCHIVE_WARN);
+ }
+ if (wcsncmp(field[3 + offset].start, L"allow",
+ field[3 + offset].end - field[3 + offset].start)
+ == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ else if (wcsncmp(field[3 + offset].start, L"deny",
+ field[3 + offset].end - field[3 + offset].start)
+ == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ else if (wcsncmp(field[3 + offset].start, L"audit",
+ field[3 + offset].end - field[3 + offset].start)
+ == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+ else if (wcsncmp(field[3 + offset].start, L"alarm",
+ field[3 + offset].end - field[3 + offset].start)
+ == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+ else {
+ /* Unknown type */
return (ARCHIVE_WARN);
- tag = ARCHIVE_ENTRY_ACL_MASK;
- } else
- return (ARCHIVE_WARN);
+ }
+ isint_w(field[4 + offset].start, field[4 + offset].end,
+ &id);
+ }
/* Add entry to the internal list. */
archive_acl_add_entry_w_len(acl, type, permset,
@@ -985,6 +1280,78 @@ ismode_w(const wchar_t *start, const wch
return (1);
}
+/* Parse a wstring as a strict NFSv4 ACL permission field. */
+static int
+parse_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+ const wchar_t *p;
+ int pos;
+ const wchar_t *letter = L"rwxpdDaARWcCos";
+ const int perms[14] = {
+ ARCHIVE_ENTRY_ACL_READ_DATA,
+ ARCHIVE_ENTRY_ACL_WRITE_DATA,
+ ARCHIVE_ENTRY_ACL_EXECUTE,
+ ARCHIVE_ENTRY_ACL_APPEND_DATA,
+ ARCHIVE_ENTRY_ACL_DELETE,
+ ARCHIVE_ENTRY_ACL_DELETE_CHILD,
+ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
+ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
+ ARCHIVE_ENTRY_ACL_READ_ACL,
+ ARCHIVE_ENTRY_ACL_WRITE_ACL,
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER,
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE
+ };
+
+ if (start >= end)
+ return (0);
+ p = start;
+ pos = 0;
+ while (p < end && pos < 14) {
+ if (*p == letter[pos])
+ *permset |= perms[pos];
+ else if (*p != '-')
+ return (-1);
+ p = p + sizeof(wchar_t);
+ pos++;
+ }
+ return (0);
+}
+
+/* Parse a string as a strict NFSv4 ACL flags field. */
+static int
+parse_nfs4_flags_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+ const wchar_t *p;
+ int pos;
+ const wchar_t *letter = L"fdinSFI";
+ const int perms[7] = {
+ ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT,
+ ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
+ ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
+ ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
+ ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS,
+ ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS,
+ ARCHIVE_ENTRY_ACL_ENTRY_INHERITED
+ };
+
+ if (start >= end)
+ return (0);
+ p = start;
+ pos = 0;
+ while (p < end && pos < 7) {
+ if (*p == letter[pos])
+ *permset |= perms[pos];
+ else if (*p != '-')
+ return (-1);
+ p = p + sizeof(wchar_t);
+ pos++;
+ }
+ return (0);
+}
+
+
/*
* Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated
* to point to just after the separator. *start points to the first
@@ -1057,12 +1424,18 @@ archive_acl_parse_l(struct archive_acl *
struct {
const char *start;
const char *end;
- } field[4], name;
+ } field[6], name;
- int fields, n, r, ret = ARCHIVE_OK;
+ int numfields, fields, n, r, ret = ARCHIVE_OK;
int type, tag, permset, id;
+ int offset;
char sep;
+ if (default_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4)
+ numfields = 6;
+ else
+ numfields = 4;
+
while (text != NULL && *text != '\0') {
/*
* Parse the fields out of the next entry,
@@ -1072,7 +1445,7 @@ archive_acl_parse_l(struct archive_acl *
do {
const char *start, *end;
next_field(&text, &start, &end, &sep);
- if (fields < 4) {
+ if (fields < numfields) {
field[fields].start = start;
field[fields].end = end;
}
@@ -1080,72 +1453,148 @@ archive_acl_parse_l(struct archive_acl *
} while (sep == ':');
/* Set remaining fields to blank. */
- for (n = fields; n < 4; ++n)
+ for (n = fields; n < numfields; ++n)
field[n].start = field[n].end = NULL;
- /* Check for a numeric ID in field 1 or 3. */
- id = -1;
- isint(field[1].start, field[1].end, &id);
- /* Field 3 is optional. */
- if (id == -1 && fields > 3)
- isint(field[3].start, field[3].end, &id);
+ if (default_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ /* POSIX.1e ACLs */
+ /* Check for a numeric ID in field 1 or 3. */
+ id = -1;
+ isint(field[1].start, field[1].end, &id);
+ /* Field 3 is optional. */
+ if (id == -1 && fields > 3)
+ isint(field[3].start, field[3].end, &id);
+
+ /*
+ * Solaris extension: "defaultuser::rwx" is the
+ * default ACL corresponding to "user::rwx", etc.
+ */
+ if (field[0].end - field[0].start > 7
+ && memcmp(field[0].start, "default", 7) == 0) {
+ type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+ field[0].start += 7;
+ } else
+ type = default_type;
- /*
- * Solaris extension: "defaultuser::rwx" is the
- * default ACL corresponding to "user::rwx", etc.
- */
- if (field[0].end - field[0].start > 7
- && memcmp(field[0].start, "default", 7) == 0) {
- type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
- field[0].start += 7;
- } else
- type = default_type;
-
- name.start = name.end = NULL;
- if (prefix_c(field[0].start, field[0].end, "user")) {
- if (!ismode(field[2].start, field[2].end, &permset))
+ name.start = name.end = NULL;
+ if (prefix_c(field[0].start, field[0].end, "user")) {
+ if (!ismode(field[2].start, field[2].end,
+ &permset))
+ return (ARCHIVE_WARN);
+ if (id != -1 || field[1].start < field[1].end) {
+ tag = ARCHIVE_ENTRY_ACL_USER;
+ name = field[1];
+ } else
+ tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ } else if (prefix_c(field[0].start, field[0].end,
+ "group")) {
+ if (!ismode(field[2].start, field[2].end,
+ &permset))
+ return (ARCHIVE_WARN);
+ if (id != -1 || field[1].start < field[1].end) {
+ tag = ARCHIVE_ENTRY_ACL_GROUP;
+ name = field[1];
+ } else
+ tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ } else if (prefix_c(field[0].start, field[0].end,
+ "other")) {
+ if (fields == 2
+ && field[1].start < field[1].end
+ && ismode(field[1].start, field[1].end,
+ &permset)) {
+ /* This is Solaris-style "other:rwx" */
+ } else if (fields == 3
+ && field[1].start == field[1].end
+ && field[2].start < field[2].end
+ && ismode(field[2].start, field[2].end,
+ &permset)) {
+ /* This is FreeBSD-style "other::rwx" */
+ } else
+ return (ARCHIVE_WARN);
+ tag = ARCHIVE_ENTRY_ACL_OTHER;
+ } else if (prefix_c(field[0].start, field[0].end,
+ "mask")) {
+ if (fields == 2
+ && field[1].start < field[1].end
+ && ismode(field[1].start, field[1].end,
+ &permset)) {
+ /* This is Solaris-style "mask:rwx" */
+ } else if (fields == 3
+ && field[1].start == field[1].end
+ && field[2].start < field[2].end
+ && ismode(field[2].start, field[2].end,
+ &permset)) {
+ /* This is FreeBSD-style "mask::rwx" */
+ } else
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list