Date: Sat, 11 Feb 2017 00:56:19 +0000 (UTC) From: Martin Matuska <mm@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r313571 - in stable/10: . contrib/libarchive contrib/libarchive/cpio contrib/libarchive/libarchive contrib/libarchive/libarchive/test contrib/libarchive/tar contrib/libarchive/tar/test ... Message-ID: <201702110056.v1B0uJeI058384@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mm Date: Sat Feb 11 00:56:18 2017 New Revision: 313571 URL: https://svnweb.freebsd.org/changeset/base/313571 Log: MFC r310866,310868,310870,311903,313074: Sync libarchive with vendor. MFC r310866: PR #771: Add NFSv4 ACL support to pax and restricted pax NFSv4 ACL information may now be stored to and restored from tar archives. ACL must be non-trivial and supported by the underlying filesystem, e.g. natively by ZFS or by UFS with the NFSv4 ACL enable flag set. MFC r310868: PR #843: Fix memory leak of struct archive_entry in cpio/cpio.c PR #851: Spelling fixes Fix two protoypes in manual page archive_read_disk.3 MFC r310870: Use __LA_DEPRECATED macro with functions deprecated in 379867e MFC r311903: #691: Support for SCHILY.xattr extended attributes #854: Spelling fixes Multiple fixes in ACL code: - prefer acl_set_fd_np() to acl_set_fd() - if acl_set_fd_np() fails, do no fallback to acl_set_file() - do not warn if trying to write ACLs to a filesystem without ACL support - fix id handling in archive_acl_(from_to)_text*() for NFSv4 ACLs MFC r313074: - support extracting NFSv4 ACLs from Solaris tar archives - bugfixes and optimizations in the ACL code - multiple fixes in the test suite - typo and other small bugfixes Security fixes: - cab reader: endless loop when parsing MSZIP signature (OSS-Fuzz 335) - LHA reader: heap-buffer-overflow in lha_read_file_header_1() (CVE-2017-5601) - LZ4 reader: null-pointer dereference in lz4_filter_read_legacy_stream() (OSS-Fuzz 453) - mtree reader: heap-buffer-overflow in detect_form() (OSS-Fuzz 421, 443) - WARC reader: heap-buffer-overflow in xstrpisotime() (OSS-Fuzz 382, 458) Memory leak fixes: - ACL support: free memory allocated by acl_get_qualifier() - disk writer: missing free in create_filesystem_object() - file reader: fd leak (Coverity 1016755) - gnutar writer: fix free in archive_write_gnutar_header() (Coverity 101675) - iso 9660 reader: missing free in parse_file_info() (partial Coverity 1016754) - program reader: missing free in __archive_read_program() - program writer: missing free in __archive_write_program_free() - xar reader: missing free in xar_cleanup() - xar reader: missing frees in expat_xmlattr_setup() (Coverity 1229979-1229981) - xar writer: missing free in file_free() - zip reader: missing free in zip_read_local_file_header() List of all libarchive issues at OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&q=libarchive Security: CVE-2017-5601 Added: stable/10/contrib/libarchive/libarchive/test/test_acl_pax_nfs4.tar.uu - copied unchanged from r310866, head/contrib/libarchive/libarchive/test/test_acl_pax_nfs4.tar.uu stable/10/contrib/libarchive/libarchive/test/test_acl_pax_posix1e.tar.uu - copied unchanged from r310866, head/contrib/libarchive/libarchive/test/test_acl_pax_posix1e.tar.uu stable/10/contrib/libarchive/libarchive/test/test_acl_platform_nfs4.c - copied unchanged from r313074, head/contrib/libarchive/libarchive/test/test_acl_platform_nfs4.c stable/10/contrib/libarchive/libarchive/test/test_acl_platform_posix1e.c - copied unchanged from r313074, head/contrib/libarchive/libarchive/test/test_acl_platform_posix1e.c stable/10/contrib/libarchive/libarchive/test/test_acl_text.c - copied, changed from r310866, head/contrib/libarchive/libarchive/test/test_acl_text.c stable/10/contrib/libarchive/libarchive/test/test_compat_star_acl.c - copied unchanged from r310866, head/contrib/libarchive/libarchive/test/test_compat_star_acl.c stable/10/contrib/libarchive/libarchive/test/test_compat_star_acl_nfs4.tar.uu - copied unchanged from r310866, head/contrib/libarchive/libarchive/test/test_compat_star_acl_nfs4.tar.uu stable/10/contrib/libarchive/libarchive/test/test_read_pax_schily_xattr.c - copied unchanged from r311903, head/contrib/libarchive/libarchive/test/test_read_pax_schily_xattr.c stable/10/contrib/libarchive/libarchive/test/test_read_pax_schily_xattr.tar.uu - copied unchanged from r311903, head/contrib/libarchive/libarchive/test/test_read_pax_schily_xattr.tar.uu Deleted: stable/10/contrib/libarchive/libarchive/test/test_acl_freebsd_nfs4.c stable/10/contrib/libarchive/libarchive/test/test_acl_freebsd_posix1e.c stable/10/contrib/libarchive/libarchive/test/test_acl_pax.tar.uu stable/10/contrib/libarchive/libarchive/test/test_compat_star_acl_posix1e.c Modified: stable/10/ObsoleteFiles.inc stable/10/contrib/libarchive/NEWS stable/10/contrib/libarchive/cpio/cpio.c stable/10/contrib/libarchive/libarchive/archive_acl.c stable/10/contrib/libarchive/libarchive/archive_acl_private.h stable/10/contrib/libarchive/libarchive/archive_entry.c stable/10/contrib/libarchive/libarchive/archive_entry.h stable/10/contrib/libarchive/libarchive/archive_entry_acl.3 stable/10/contrib/libarchive/libarchive/archive_entry_locale.h stable/10/contrib/libarchive/libarchive/archive_entry_strmode.c stable/10/contrib/libarchive/libarchive/archive_match.c stable/10/contrib/libarchive/libarchive/archive_platform.h stable/10/contrib/libarchive/libarchive/archive_random.c stable/10/contrib/libarchive/libarchive/archive_rb.c stable/10/contrib/libarchive/libarchive/archive_read_disk.3 stable/10/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c stable/10/contrib/libarchive/libarchive/archive_read_disk_posix.c stable/10/contrib/libarchive/libarchive/archive_read_open_filename.c stable/10/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c stable/10/contrib/libarchive/libarchive/archive_read_support_filter_lzop.c stable/10/contrib/libarchive/libarchive/archive_read_support_filter_program.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_7zip.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_cab.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_cpio.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_lha.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_mtree.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_rar.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_tar.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_warc.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_xar.c stable/10/contrib/libarchive/libarchive/archive_read_support_format_zip.c stable/10/contrib/libarchive/libarchive/archive_string.c stable/10/contrib/libarchive/libarchive/archive_string.h stable/10/contrib/libarchive/libarchive/archive_string_composition.h stable/10/contrib/libarchive/libarchive/archive_write.c stable/10/contrib/libarchive/libarchive/archive_write_add_filter_program.c stable/10/contrib/libarchive/libarchive/archive_write_add_filter_xz.c stable/10/contrib/libarchive/libarchive/archive_write_disk_acl.c stable/10/contrib/libarchive/libarchive/archive_write_disk_posix.c stable/10/contrib/libarchive/libarchive/archive_write_open.3 stable/10/contrib/libarchive/libarchive/archive_write_set_format_7zip.c stable/10/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c stable/10/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c stable/10/contrib/libarchive/libarchive/archive_write_set_format_pax.c stable/10/contrib/libarchive/libarchive/archive_write_set_format_warc.c stable/10/contrib/libarchive/libarchive/archive_write_set_format_xar.c stable/10/contrib/libarchive/libarchive/archive_write_set_format_zip.c stable/10/contrib/libarchive/libarchive/libarchive-formats.5 stable/10/contrib/libarchive/libarchive/tar.5 stable/10/contrib/libarchive/libarchive/test/main.c stable/10/contrib/libarchive/libarchive/test/test.h stable/10/contrib/libarchive/libarchive/test/test_acl_nfs4.c stable/10/contrib/libarchive/libarchive/test/test_acl_pax.c stable/10/contrib/libarchive/libarchive/test/test_acl_posix1e.c stable/10/contrib/libarchive/libarchive/test/test_archive_read_add_passphrase.c stable/10/contrib/libarchive/libarchive/test/test_archive_string.c stable/10/contrib/libarchive/libarchive/test/test_compat_gtar.c stable/10/contrib/libarchive/libarchive/test/test_compat_solaris_tar_acl.c stable/10/contrib/libarchive/libarchive/test/test_compat_solaris_tar_acl.tar.uu stable/10/contrib/libarchive/libarchive/test/test_compat_uudecode.c stable/10/contrib/libarchive/libarchive/test/test_fuzz.c stable/10/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c stable/10/contrib/libarchive/libarchive/test/test_read_filter_lzop.c stable/10/contrib/libarchive/libarchive/test/test_read_filter_lzop_multiple_parts.c stable/10/contrib/libarchive/libarchive/test/test_read_format_7zip.c stable/10/contrib/libarchive/libarchive/test/test_read_format_cpio_afio.c stable/10/contrib/libarchive/libarchive/test/test_read_format_isorr_bz2.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_comment_stored.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_filename.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_mac_metadata.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_malformed.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_nested.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_padded.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_sfx.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_traditional_encryption_data.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes.c stable/10/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes_large.c stable/10/contrib/libarchive/libarchive/test/test_sparse_basic.c stable/10/contrib/libarchive/libarchive/test/test_write_disk_secure746.c stable/10/contrib/libarchive/libarchive/test/test_write_filter_lz4.c stable/10/contrib/libarchive/libarchive/test/test_write_filter_lzop.c stable/10/contrib/libarchive/libarchive/test/test_write_format_iso9660.c stable/10/contrib/libarchive/libarchive/test/test_write_format_iso9660_zisofs.c stable/10/contrib/libarchive/libarchive/test/test_write_format_zip_large.c stable/10/contrib/libarchive/libarchive/test/test_write_format_zip_zip64.c stable/10/contrib/libarchive/libarchive/xxhash.c stable/10/contrib/libarchive/tar/test/test_option_uid_uname.c stable/10/contrib/libarchive/tar/util.c stable/10/lib/libarchive/config_freebsd.h stable/10/lib/libarchive/tests/Makefile Directory Properties: stable/10/ (props changed) Modified: stable/10/ObsoleteFiles.inc ============================================================================== --- stable/10/ObsoleteFiles.inc Sat Feb 11 00:54:16 2017 (r313570) +++ stable/10/ObsoleteFiles.inc Sat Feb 11 00:56:18 2017 (r313571) @@ -38,6 +38,8 @@ # xargs -n1 | sort | uniq -d; # done +# 20170211: libarchive ACL pax test renamed to test_acl_pax_posix1e.tar.uu +OLD_FILES+=usr/tests/lib/libarchive/test_acl_pax.tar.uu # 20161229: Three files from gnop tests consolidated into one OLD_FILES+=usr/tests/sys/geom/class/nop/1_test OLD_FILES+=usr/tests/sys/geom/class/nop/2_test Modified: stable/10/contrib/libarchive/NEWS ============================================================================== --- stable/10/contrib/libarchive/NEWS Sat Feb 11 00:54:16 2017 (r313570) +++ stable/10/contrib/libarchive/NEWS Sat Feb 11 00:56:18 2017 (r313571) @@ -1,3 +1,10 @@ +Jan 29, 2017: Limited NFSv4 ACL support for Mac OS (Darwin) + +Jan 10, 2017: POSIX.1e and NFSv4 ACL support for Solaris and derivates + +Dec 27, 2016: NFSv4 ACL read and write support for pax + Deprecated functions: archive_entry_acl_text(), archive_entry_acl_text_w() + Oct 26, 2016: Remove liblzmadec support Oct 23, 2016: libarchive 3.2.2 released Modified: stable/10/contrib/libarchive/cpio/cpio.c ============================================================================== --- stable/10/contrib/libarchive/cpio/cpio.c Sat Feb 11 00:54:16 2017 (r313570) +++ stable/10/contrib/libarchive/cpio/cpio.c Sat Feb 11 00:56:18 2017 (r313571) @@ -703,6 +703,7 @@ file_to_archive(struct cpio *cpio, const lafe_warnc(0, "%s", archive_error_string(cpio->archive_read_disk)); if (r <= ARCHIVE_FAILED) { + archive_entry_free(entry); cpio->return_value = 1; return (r); } Modified: stable/10/contrib/libarchive/libarchive/archive_acl.c ============================================================================== --- stable/10/contrib/libarchive/libarchive/archive_acl.c Sat Feb 11 00:54:16 2017 (r313570) +++ stable/10/contrib/libarchive/libarchive/archive_acl.c Sat Feb 11 00:56:18 2017 (r313571) @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,23 +56,31 @@ static struct archive_acl_entry *acl_new static int archive_acl_add_entry_len_l(struct archive_acl *acl, int type, int permset, int tag, int id, const char *name, size_t len, struct archive_string_conv *sc); +static int archive_acl_text_want_type(struct archive_acl *acl, int flags); +static ssize_t archive_acl_text_len(struct archive_acl *acl, int want_type, + int flags, int wide, struct archive *a, + 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 is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, + int *result); +static int is_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, int flags, 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 is_nfs4_flags(const char *start, const char *end, + int *result); +static int is_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, int flags, const char *name, int perm, int id); static void append_id(char **p, int id); void @@ -340,6 +349,15 @@ archive_acl_count(struct archive_acl *ac } /* + * Return a bitmask of stored ACL types in an ACL list + */ +int +archive_acl_types(struct archive_acl *acl) +{ + return (acl->acl_types); +} + +/* * Prepare for reading entries from the ACL data. Returns a count * of entries matching "want_type", or zero if there are no * non-extended ACL entries of that type. @@ -375,8 +393,8 @@ archive_acl_reset(struct archive_acl *ac * standard permissions and include them in the returned list. */ int -archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int *type, - int *permset, int *tag, int *id, const char **name) +archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, + int *type, int *permset, int *tag, int *id, const char **name) { *name = NULL; *id = -1; @@ -441,130 +459,273 @@ archive_acl_next(struct archive *a, stru } /* - * Generate a text version of the ACL. The flags parameter controls - * the style of the generated ACL. + * Determine what type of ACL do we want */ -const wchar_t * -archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags) +static int +archive_acl_text_want_type(struct archive_acl *acl, int flags) { - int count; - size_t length; - const wchar_t *wname; - const wchar_t *prefix; - wchar_t separator; - struct archive_acl_entry *ap; - int id, r; - wchar_t *wp; + int want_type; - if (acl->acl_text_w != NULL) { - free (acl->acl_text_w); - acl->acl_text_w = NULL; + /* Check if ACL is NFSv4 */ + if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + /* NFSv4 should never mix with POSIX.1e */ + if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) + return (0); + else + return (ARCHIVE_ENTRY_ACL_TYPE_NFS4); } - separator = L','; + /* Now deal with POSIX.1e ACLs */ + + want_type = 0; + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) + want_type |= ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + want_type |= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + + /* By default we want both access and default ACLs */ + if (want_type == 0) + return (ARCHIVE_ENTRY_ACL_TYPE_POSIX1E); + + return (want_type); +} + +/* + * Calculate ACL text string length + */ +static ssize_t +archive_acl_text_len(struct archive_acl *acl, int want_type, int flags, + int wide, struct archive *a, struct archive_string_conv *sc) { + struct archive_acl_entry *ap; + const char *name; + const wchar_t *wname; + int count, idlen, tmp, r; + ssize_t length; + size_t len; + count = 0; length = 0; - ap = acl->acl_head; - while (ap != NULL) { - if ((ap->type & flags) != 0) { - count++; - if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) && - (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) - length += 8; /* "default:" */ - length += 5; /* tag name */ - 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); - else - length += sizeof(uid_t) * 3 + 1; - length ++; /* colon */ + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + count++; + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 + && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + length += 8; /* "default:" */ + switch (ap->tag) { + case ARCHIVE_ENTRY_ACL_USER_OBJ: + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + length += 6; /* "owner@" */ + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_USER: + case ARCHIVE_ENTRY_ACL_MASK: + length += 4; /* "user", "mask" */ + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + 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 after tag */ + if (ap->tag == ARCHIVE_ENTRY_ACL_USER || + ap->tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (wide) { + r = archive_mstring_get_wcs(a, &ap->name, + &wname); + if (r == 0 && wname != NULL) + length += wcslen(wname); + else if (r < 0 && errno == ENOMEM) + return (0); + else + length += sizeof(uid_t) * 3 + 1; + } else { + r = archive_mstring_get_mbs_l(&ap->name, &name, + &len, sc); + if (r != 0) + return (0); + if (len > 0 && name != NULL) + length += len; + else + length += sizeof(uid_t) * 3 + 1; + } + length += 1; /* colon after user or group name */ + } else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) + length += 1; /* 2nd colon empty user,group or other */ + + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) + && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) + && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER + || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) { + /* Solaris has no colon after other: and mask: */ + length = length - 1; + } + + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* rwxpdDaARWcCos:fdinSFI:deny */ + length += 27; + if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0) + length += 1; /* allow, alarm, audit */ + } else length += 3; /* rwx */ + + if ((ap->tag == ARCHIVE_ENTRY_ACL_USER || + ap->tag == ARCHIVE_ENTRY_ACL_GROUP) && + (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) { length += 1; /* colon */ - length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1; - length ++; /* newline */ + /* ID digit count */ + idlen = 1; + tmp = ap->id; + while (tmp > 9) { + tmp = tmp / 10; + idlen++; + } + length += idlen; } - ap = ap->next; + length ++; /* entry separator */ } - if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) { - length += 10; /* "user::rwx\n" */ - length += 11; /* "group::rwx\n" */ - length += 11; /* "other::rwx\n" */ - } + /* Add filemode-mapping access entries to the length */ + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) { + /* "user::rwx\ngroup::rwx\nother:rwx\n" */ + length += 31; + } else { + /* "user::rwx\ngroup::rwx\nother::rwx\n" */ + length += 32; + } + } else if (count == 0) + return (0); - if (count == 0) + /* The terminating character is included in count */ + return (length); +} + +/* + * Generate a wide text version of the ACL. The flags parameter controls + * the type and style of the generated ACL. + */ +wchar_t * +archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, + struct archive *a) +{ + int count; + ssize_t length; + size_t len; + const wchar_t *wname; + const wchar_t *prefix; + wchar_t separator; + struct archive_acl_entry *ap; + int id, r, want_type; + wchar_t *wp, *ws; + + want_type = archive_acl_text_want_type(acl, flags); + + /* Both NFSv4 and POSIX.1 types found */ + if (want_type == 0) + return (NULL); + + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) + flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; + + length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL); + + if (length == 0) return (NULL); + if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) + separator = L','; + else + separator = L'\n'; + /* Now, allocate the string and actually populate it. */ - wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t)); - if (wp == NULL) + wp = ws = (wchar_t *)malloc(length * sizeof(wchar_t)); + if (wp == NULL) { + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); + } count = 0; - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, + + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *wp++ = ','; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, + *wp++ = separator; + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *wp++ = ','; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL, + *wp++ = separator; + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); count += 3; - - ap = acl->acl_head; - while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - r = archive_mstring_get_wcs(a, &ap->name, &wname); - if (r == 0) { - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, NULL, ap->tag, wname, - ap->permset, id); - count++; - } else if (r < 0 && errno == ENOMEM) - return (NULL); - } - ap = ap->next; - } } - - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT && + (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) prefix = L"default:"; else prefix = NULL; - ap = acl->acl_head; - count = 0; - while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - r = archive_mstring_get_wcs(a, &ap->name, &wname); - if (r == 0) { - if (count > 0) - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, prefix, ap->tag, - wname, ap->permset, id); - count ++; - } else if (r < 0 && errno == ENOMEM) - return (NULL); - } - ap = ap->next; - } + r = archive_mstring_get_wcs(a, &ap->name, &wname); + if (r == 0) { + if (count > 0) + *wp++ = separator; + if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + id = ap->id; + else + id = -1; + append_entry_w(&wp, prefix, ap->type, ap->tag, flags, + wname, ap->permset, id); + count++; + } else if (r < 0 && errno == ENOMEM) + return (NULL); } - return (acl->acl_text_w); -} + /* Add terminating character */ + *wp++ = L'\0'; + + len = wcslen(ws); + if ((ssize_t)len > (length - 1)) + __archive_errx(1, "Buffer overrun"); + + if (text_len != NULL) + *text_len = len; + + return (ws); +} static void append_id_w(wchar_t **wp, int id) @@ -577,8 +738,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, int flags, const wchar_t *wname, int perm, int id) { if (prefix != NULL) { wcscpy(*wp, prefix); @@ -588,6 +749,10 @@ 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) != 0) { + wcscpy(*wp, L"owner@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: wcscpy(*wp, L"user"); @@ -595,6 +760,10 @@ append_entry_w(wchar_t **wp, const wchar case ARCHIVE_ENTRY_ACL_GROUP_OBJ: wname = NULL; id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + wcscpy(*wp, L"group@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: wcscpy(*wp, L"group"); @@ -609,154 +778,210 @@ append_entry_w(wchar_t **wp, const wchar wname = NULL; id = -1; break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + wcscpy(*wp, L"everyone@"); + wname = NULL; + id = -1; + break; } *wp += wcslen(*wp); *(*wp)++ = L':'; - if (wname != NULL) { - wcscpy(*wp, wname); + if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 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); + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) + id = -1; + } + /* Solaris style has no second colon after other and mask */ + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) + || (tag != ARCHIVE_ENTRY_ACL_OTHER + && tag != ARCHIVE_ENTRY_ACL_MASK)) + *(*wp)++ = L':'; + } + if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* POSIX.1e ACL perms */ + *(*wp)++ = (perm & 0444) ? L'r' : L'-'; + *(*wp)++ = (perm & 0222) ? L'w' : L'-'; + *(*wp)++ = (perm & 0111) ? L'x' : L'-'; + } else { + /* NFS4 ACL perms */ + *(*wp)++ = (perm & (ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_LIST_DIRECTORY)) ? L'r' : L'-'; + *(*wp)++ = (perm & (ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_ADD_FILE)) ? L'w' : L'-'; + *(*wp)++ = (perm & ARCHIVE_ENTRY_ACL_EXECUTE) ? L'x' : L'-'; + *(*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':'; + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + wcscpy(*wp, L"allow"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + wcscpy(*wp, L"deny"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + wcscpy(*wp, L"audit"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + wcscpy(*wp, L"alarm"); + break; + default: + break; + } *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); } - **wp = L'\0'; } -int -archive_acl_text_l(struct archive_acl *acl, int flags, - const char **acl_text, size_t *acl_text_len, +/* + * Generate a text version of the ACL. The flags parameter controls + * the type and style of the generated ACL. + */ +char * +archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, struct archive_string_conv *sc) { int count; - size_t length; + ssize_t length; + size_t len; const char *name; const char *prefix; char separator; struct archive_acl_entry *ap; - size_t len; - int id, r; - char *p; + int id, r, want_type; + char *p, *s; - if (acl->acl_text != NULL) { - free (acl->acl_text); - acl->acl_text = NULL; - } + want_type = archive_acl_text_want_type(acl, flags); - *acl_text = NULL; - if (acl_text_len != NULL) - *acl_text_len = 0; - separator = ','; - count = 0; - length = 0; - ap = acl->acl_head; - while (ap != NULL) { - if ((ap->type & flags) != 0) { - count++; - if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) && - (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) - length += 8; /* "default:" */ - length += 5; /* tag name */ - 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; - else - length += sizeof(uid_t) * 3 + 1; - length ++; /* colon */ - length += 3; /* rwx */ - length += 1; /* colon */ - length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1; - length ++; /* newline */ - } - ap = ap->next; - } + /* Both NFSv4 and POSIX.1 types found */ + if (want_type == 0) + return (NULL); - if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) { - length += 10; /* "user::rwx\n" */ - length += 11; /* "group::rwx\n" */ - length += 11; /* "other::rwx\n" */ - } + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) + flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; - if (count == 0) - return (0); + length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc); + + if (length == 0) + return (NULL); + + if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) + separator = ','; + else + separator = '\n'; /* Now, allocate the string and actually populate it. */ - p = acl->acl_text = (char *)malloc(length); - if (p == NULL) - return (-1); + p = s = (char *)malloc(length * sizeof(char)); + if (p == NULL) { + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); + } count = 0; - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, + + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *p++ = ','; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, + *p++ = separator; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *p++ = ','; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL, + *p++ = separator; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); count += 3; - - for (ap = acl->acl_head; ap != NULL; ap = ap->next) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) == 0) - continue; - r = archive_mstring_get_mbs_l( - &ap->name, &name, &len, sc); - if (r != 0) - return (-1); - *p++ = separator; - if (name == NULL || (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) { - id = ap->id; - } else { - id = -1; - } - append_entry(&p, NULL, ap->tag, name, - ap->permset, id); - count++; - } } - - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT && + (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) prefix = "default:"; else prefix = NULL; - count = 0; - for (ap = acl->acl_head; ap != NULL; ap = ap->next) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) == 0) - continue; - r = archive_mstring_get_mbs_l( - &ap->name, &name, &len, sc); - if (r != 0) - return (-1); - if (count > 0) - *p++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry(&p, prefix, ap->tag, - name, ap->permset, id); - count ++; + r = archive_mstring_get_mbs_l( + &ap->name, &name, &len, sc); + if (r != 0) + return (NULL); + if (count > 0) + *p++ = separator; + if (name == NULL || + (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) { + id = ap->id; + } else { + id = -1; } + append_entry(&p, prefix, ap->type, ap->tag, flags, name, + ap->permset, id); + count++; } - *acl_text = acl->acl_text; - if (acl_text_len != NULL) - *acl_text_len = strlen(acl->acl_text); - return (0); + /* Add terminating character */ + *p++ = '\0'; + + len = strlen(s); + + if ((ssize_t)len > (length - 1)) + __archive_errx(1, "Buffer overrun"); + + if (text_len != NULL) + *text_len = len; + + return (s); } static void @@ -770,8 +995,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, int flags, const char *name, int perm, int id) { if (prefix != NULL) { strcpy(*p, prefix); @@ -781,6 +1006,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) != 0) { + strcpy(*p, "owner@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: strcpy(*p, "user"); @@ -788,6 +1017,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) != 0) { + strcpy(*p, "group@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: strcpy(*p, "group"); @@ -802,48 +1035,147 @@ 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_POSIX1E) != 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); + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) + id = -1; + } + /* Solaris style has no second colon after other and mask */ + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) + || (tag != ARCHIVE_ENTRY_ACL_OTHER + && tag != ARCHIVE_ENTRY_ACL_MASK)) + *(*p)++ = ':'; + } + if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* POSIX.1e ACL perms */ + *(*p)++ = (perm & 0444) ? 'r' : '-'; + *(*p)++ = (perm & 0222) ? 'w' : '-'; + *(*p)++ = (perm & 0111) ? 'x' : '-'; + } else { + /* NFS4 ACL perms */ + *(*p)++ = (perm & (ARCHIVE_ENTRY_ACL_READ_DATA | + ARCHIVE_ENTRY_ACL_LIST_DIRECTORY)) ? 'r' : '-'; + *(*p)++ = (perm & (ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_ADD_FILE)) ? 'w' : '-'; + *(*p)++ = (perm & (ARCHIVE_ENTRY_ACL_EXECUTE)) ? 'x' : '-'; + *(*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)++ = ':'; + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + strcpy(*p, "allow"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + strcpy(*p, "deny"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + strcpy(*p, "audit"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + strcpy(*p, "alarm"); + break; + } *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); } - **p = '\0'; } /* - * Parse a textual ACL. This automatically recognizes and supports - * extensions described above. The 'type' argument is used to - * indicate the type that should be used for any entries not - * explicitly marked as "default:". + * Parse a wide ACL text string. + * + * The want_type argument may be one of the following: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT + * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL + * + * POSIX.1e ACL entries prefixed with "default:" are treated as + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4 */ int -archive_acl_parse_w(struct archive_acl *acl, - const wchar_t *text, int default_type) +archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, + int want_type) { struct { const wchar_t *start; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201702110056.v1B0uJeI058384>