nifi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From phroc...@apache.org
Subject [35/51] [partial] nifi-minifi-cpp git commit: MINIFICPP-72: Add Tar and Zip Support for MergeContent
Date Fri, 20 Oct 2017 17:18:46 GMT
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/3781b52f/thirdparty/libarchive-3.3.2/libarchive/archive_acl.c
----------------------------------------------------------------------
diff --git a/thirdparty/libarchive-3.3.2/libarchive/archive_acl.c b/thirdparty/libarchive-3.3.2/libarchive/archive_acl.c
new file mode 100644
index 0000000..b8b6b63
--- /dev/null
+++ b/thirdparty/libarchive-3.3.2/libarchive/archive_acl.c
@@ -0,0 +1,2069 @@
+/*-
+ * 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
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_WCHAR_H
+#include <wchar.h>
+#endif
+
+#include "archive_acl_private.h"
+#include "archive_entry.h"
+#include "archive_private.h"
+
+#undef max
+#define	max(a, b)	((a)>(b)?(a):(b))
+
+#ifndef HAVE_WMEMCMP
+/* Good enough for simple equality testing, but not for sorting. */
+#define wmemcmp(a,b,i)  memcmp((a), (b), (i) * sizeof(wchar_t))
+#endif
+
+static int	acl_special(struct archive_acl *acl,
+		    int type, int permset, int tag);
+static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl,
+		    int type, int permset, int tag, int id);
+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 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 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);
+
+static const struct {
+	const int perm;
+	const char c;
+	const wchar_t wc;
+} nfsv4_acl_perm_map[] = {
+	{ ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, 'r',
+	    L'r' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_ADD_FILE, 'w',
+	    L'w' },
+	{ ARCHIVE_ENTRY_ACL_EXECUTE, 'x', L'x' },
+	{ ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
+	    'p', L'p' },
+	{ ARCHIVE_ENTRY_ACL_DELETE, 'd', L'd' },
+	{ ARCHIVE_ENTRY_ACL_DELETE_CHILD, 'D', L'D' },
+	{ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, 'a', L'a' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, 'A', L'A' },
+	{ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, 'R', L'R' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, 'W', L'W' },
+	{ ARCHIVE_ENTRY_ACL_READ_ACL, 'c', L'c' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_ACL, 'C', L'C' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_OWNER, 'o', L'o' },
+	{ ARCHIVE_ENTRY_ACL_SYNCHRONIZE, 's', L's' }
+};
+
+static const int nfsv4_acl_perm_map_size = (int)(sizeof(nfsv4_acl_perm_map) /
+    sizeof(nfsv4_acl_perm_map[0]));
+
+static const struct {
+	const int perm;
+	const char c;
+	const wchar_t wc;
+} nfsv4_acl_flag_map[] = {
+	{ ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, 'f', L'f' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 'd', L'd' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, 'i', L'i' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 'n', L'n' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 'S', L'S' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, 'F', L'F' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, 'I', L'I' }
+};
+
+static const int nfsv4_acl_flag_map_size = (int)(sizeof(nfsv4_acl_flag_map) /
+    sizeof(nfsv4_acl_flag_map[0]));
+
+void
+archive_acl_clear(struct archive_acl *acl)
+{
+	struct archive_acl_entry *ap;
+
+	while (acl->acl_head != NULL) {
+		ap = acl->acl_head->next;
+		archive_mstring_clean(&acl->acl_head->name);
+		free(acl->acl_head);
+		acl->acl_head = ap;
+	}
+	if (acl->acl_text_w != NULL) {
+		free(acl->acl_text_w);
+		acl->acl_text_w = NULL;
+	}
+	if (acl->acl_text != NULL) {
+		free(acl->acl_text);
+		acl->acl_text = NULL;
+	}
+	acl->acl_p = NULL;
+	acl->acl_types = 0;
+	acl->acl_state = 0; /* Not counting. */
+}
+
+void
+archive_acl_copy(struct archive_acl *dest, struct archive_acl *src)
+{
+	struct archive_acl_entry *ap, *ap2;
+
+	archive_acl_clear(dest);
+
+	dest->mode = src->mode;
+	ap = src->acl_head;
+	while (ap != NULL) {
+		ap2 = acl_new_entry(dest,
+		    ap->type, ap->permset, ap->tag, ap->id);
+		if (ap2 != NULL)
+			archive_mstring_copy(&ap2->name, &ap->name);
+		ap = ap->next;
+	}
+}
+
+int
+archive_acl_add_entry(struct archive_acl *acl,
+    int type, int permset, int tag, int id, const char *name)
+{
+	struct archive_acl_entry *ap;
+
+	if (acl_special(acl, type, permset, tag) == 0)
+		return ARCHIVE_OK;
+	ap = acl_new_entry(acl, type, permset, tag, id);
+	if (ap == NULL) {
+		/* XXX Error XXX */
+		return ARCHIVE_FAILED;
+	}
+	if (name != NULL  &&  *name != '\0')
+		archive_mstring_copy_mbs(&ap->name, name);
+	else
+		archive_mstring_clean(&ap->name);
+	return ARCHIVE_OK;
+}
+
+int
+archive_acl_add_entry_w_len(struct archive_acl *acl,
+    int type, int permset, int tag, int id, const wchar_t *name, size_t len)
+{
+	struct archive_acl_entry *ap;
+
+	if (acl_special(acl, type, permset, tag) == 0)
+		return ARCHIVE_OK;
+	ap = acl_new_entry(acl, type, permset, tag, id);
+	if (ap == NULL) {
+		/* XXX Error XXX */
+		return ARCHIVE_FAILED;
+	}
+	if (name != NULL  &&  *name != L'\0' && len > 0)
+		archive_mstring_copy_wcs_len(&ap->name, name, len);
+	else
+		archive_mstring_clean(&ap->name);
+	return ARCHIVE_OK;
+}
+
+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)
+{
+	struct archive_acl_entry *ap;
+	int r;
+
+	if (acl_special(acl, type, permset, tag) == 0)
+		return ARCHIVE_OK;
+	ap = acl_new_entry(acl, type, permset, tag, id);
+	if (ap == NULL) {
+		/* XXX Error XXX */
+		return ARCHIVE_FAILED;
+	}
+	if (name != NULL  &&  *name != '\0' && len > 0) {
+		r = archive_mstring_copy_mbs_len_l(&ap->name, name, len, sc);
+	} else {
+		r = 0;
+		archive_mstring_clean(&ap->name);
+	}
+	if (r == 0)
+		return (ARCHIVE_OK);
+	else if (errno == ENOMEM)
+		return (ARCHIVE_FATAL);
+	else
+		return (ARCHIVE_WARN);
+}
+
+/*
+ * If this ACL entry is part of the standard POSIX permissions set,
+ * store the permissions in the stat structure and return zero.
+ */
+static int
+acl_special(struct archive_acl *acl, int type, int permset, int tag)
+{
+	if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+	    && ((permset & ~007) == 0)) {
+		switch (tag) {
+		case ARCHIVE_ENTRY_ACL_USER_OBJ:
+			acl->mode &= ~0700;
+			acl->mode |= (permset & 7) << 6;
+			return (0);
+		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+			acl->mode &= ~0070;
+			acl->mode |= (permset & 7) << 3;
+			return (0);
+		case ARCHIVE_ENTRY_ACL_OTHER:
+			acl->mode &= ~0007;
+			acl->mode |= permset & 7;
+			return (0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Allocate and populate a new ACL entry with everything but the
+ * name.
+ */
+static struct archive_acl_entry *
+acl_new_entry(struct archive_acl *acl,
+    int type, int permset, int tag, int id)
+{
+	struct archive_acl_entry *ap, *aq;
+
+	/* Type argument must be a valid NFS4 or POSIX.1e type.
+	 * The type must agree with anything already set and
+	 * the permset must be compatible. */
+	if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+		if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+			return (NULL);
+		}
+		if (permset &
+		    ~(ARCHIVE_ENTRY_ACL_PERMS_NFS4
+			| ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4)) {
+			return (NULL);
+		}
+	} else	if (type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
+		if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
+			return (NULL);
+		}
+		if (permset & ~ARCHIVE_ENTRY_ACL_PERMS_POSIX1E) {
+			return (NULL);
+		}
+	} else {
+		return (NULL);
+	}
+
+	/* Verify the tag is valid and compatible with NFS4 or POSIX.1e. */
+	switch (tag) {
+	case ARCHIVE_ENTRY_ACL_USER:
+	case ARCHIVE_ENTRY_ACL_USER_OBJ:
+	case ARCHIVE_ENTRY_ACL_GROUP:
+	case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+		/* Tags valid in both NFS4 and POSIX.1e */
+		break;
+	case ARCHIVE_ENTRY_ACL_MASK:
+	case ARCHIVE_ENTRY_ACL_OTHER:
+		/* Tags valid only in POSIX.1e. */
+		if (type & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
+			return (NULL);
+		}
+		break;
+	case ARCHIVE_ENTRY_ACL_EVERYONE:
+		/* Tags valid only in NFS4. */
+		if (type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+			return (NULL);
+		}
+		break;
+	default:
+		/* No other values are valid. */
+		return (NULL);
+	}
+
+	if (acl->acl_text_w != NULL) {
+		free(acl->acl_text_w);
+		acl->acl_text_w = NULL;
+	}
+	if (acl->acl_text != NULL) {
+		free(acl->acl_text);
+		acl->acl_text = NULL;
+	}
+
+	/*
+	 * If there's a matching entry already in the list, overwrite it.
+	 * NFSv4 entries may be repeated and are not overwritten.
+	 *
+	 * TODO: compare names of no id is provided (needs more rework)
+	 */
+	ap = acl->acl_head;
+	aq = NULL;
+	while (ap != NULL) {
+		if (((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) &&
+		    ap->type == type && ap->tag == tag && ap->id == id) {
+			if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER &&
+			    tag != ARCHIVE_ENTRY_ACL_GROUP)) {
+				ap->permset = permset;
+				return (ap);
+			}
+		}
+		aq = ap;
+		ap = ap->next;
+	}
+
+	/* Add a new entry to the end of the list. */
+	ap = (struct archive_acl_entry *)calloc(1, sizeof(*ap));
+	if (ap == NULL)
+		return (NULL);
+	if (aq == NULL)
+		acl->acl_head = ap;
+	else
+		aq->next = ap;
+	ap->type = type;
+	ap->tag = tag;
+	ap->id = id;
+	ap->permset = permset;
+	acl->acl_types |= type;
+	return (ap);
+}
+
+/*
+ * Return a count of entries matching "want_type".
+ */
+int
+archive_acl_count(struct archive_acl *acl, int want_type)
+{
+	int count;
+	struct archive_acl_entry *ap;
+
+	count = 0;
+	ap = acl->acl_head;
+	while (ap != NULL) {
+		if ((ap->type & want_type) != 0)
+			count++;
+		ap = ap->next;
+	}
+
+	if (count > 0 && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0))
+		count += 3;
+	return (count);
+}
+
+/*
+ * 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.
+ */
+int
+archive_acl_reset(struct archive_acl *acl, int want_type)
+{
+	int count, cutoff;
+
+	count = archive_acl_count(acl, want_type);
+
+	/*
+	 * If the only entries are the three standard ones,
+	 * then don't return any ACL data.  (In this case,
+	 * client can just use chmod(2) to set permissions.)
+	 */
+	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
+		cutoff = 3;
+	else
+		cutoff = 0;
+
+	if (count > cutoff)
+		acl->acl_state = ARCHIVE_ENTRY_ACL_USER_OBJ;
+	else
+		acl->acl_state = 0;
+	acl->acl_p = acl->acl_head;
+	return (count);
+}
+
+
+/*
+ * Return the next ACL entry in the list.  Fake entries for the
+ * 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)
+{
+	*name = NULL;
+	*id = -1;
+
+	/*
+	 * The acl_state is either zero (no entries available), -1
+	 * (reading from list), or an entry type (retrieve that type
+	 * from ae_stat.aest_mode).
+	 */
+	if (acl->acl_state == 0)
+		return (ARCHIVE_WARN);
+
+	/* The first three access entries are special. */
+	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+		switch (acl->acl_state) {
+		case ARCHIVE_ENTRY_ACL_USER_OBJ:
+			*permset = (acl->mode >> 6) & 7;
+			*type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+			*tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+			acl->acl_state = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+			return (ARCHIVE_OK);
+		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+			*permset = (acl->mode >> 3) & 7;
+			*type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+			*tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+			acl->acl_state = ARCHIVE_ENTRY_ACL_OTHER;
+			return (ARCHIVE_OK);
+		case ARCHIVE_ENTRY_ACL_OTHER:
+			*permset = acl->mode & 7;
+			*type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+			*tag = ARCHIVE_ENTRY_ACL_OTHER;
+			acl->acl_state = -1;
+			acl->acl_p = acl->acl_head;
+			return (ARCHIVE_OK);
+		default:
+			break;
+		}
+	}
+
+	while (acl->acl_p != NULL && (acl->acl_p->type & want_type) == 0)
+		acl->acl_p = acl->acl_p->next;
+	if (acl->acl_p == NULL) {
+		acl->acl_state = 0;
+		*type = 0;
+		*permset = 0;
+		*tag = 0;
+		*id = -1;
+		*name = NULL;
+		return (ARCHIVE_EOF); /* End of ACL entries. */
+	}
+	*type = acl->acl_p->type;
+	*permset = acl->acl_p->permset;
+	*tag = acl->acl_p->tag;
+	*id = acl->acl_p->id;
+	if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0) {
+		if (errno == ENOMEM)
+			return (ARCHIVE_FATAL);
+		*name = NULL;
+	}
+	acl->acl_p = acl->acl_p->next;
+	return (ARCHIVE_OK);
+}
+
+/*
+ * Determine what type of ACL do we want
+ */
+static int
+archive_acl_text_want_type(struct archive_acl *acl, int flags)
+{
+	int want_type;
+
+	/* 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);
+	}
+
+	/* 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;
+	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 */
+			/* ID digit count */
+			idlen = 1;
+			tmp = ap->id;
+			while (tmp > 9) {
+				tmp = tmp / 10;
+				idlen++;
+			}
+			length += idlen;
+		}
+		length ++; /* entry separator */
+	}
+
+	/* 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);
+
+	/* 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 = ws = (wchar_t *)malloc(length * sizeof(wchar_t));
+	if (wp == NULL) {
+		if (errno == ENOMEM)
+			__archive_errx(1, "No memory");
+		return (NULL);
+	}
+	count = 0;
+
+	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++ = separator;
+		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		    ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
+		    acl->mode & 0070, -1);
+		*wp++ = separator;
+		append_entry_w(&wp, 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 & 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;
+		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);
+	}
+
+	/* 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)
+{
+	if (id < 0)
+		id = 0;
+	if (id > 9)
+		append_id_w(wp, id / 10);
+	*(*wp)++ = L"0123456789"[id % 10];
+}
+
+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)
+{
+	int i;
+
+	if (prefix != NULL) {
+		wcscpy(*wp, prefix);
+		*wp += wcslen(*wp);
+	}
+	switch (tag) {
+	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");
+		break;
+	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");
+		break;
+	case ARCHIVE_ENTRY_ACL_MASK:
+		wcscpy(*wp, L"mask");
+		wname = NULL;
+		id = -1;
+		break;
+	case ARCHIVE_ENTRY_ACL_OTHER:
+		wcscpy(*wp, L"other");
+		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 (((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 {
+		/* NFSv4 ACL perms */
+		for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
+			if (perm & nfsv4_acl_perm_map[i].perm)
+				*(*wp)++ = nfsv4_acl_perm_map[i].wc;
+			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+				*(*wp)++ = L'-';
+		}
+		*(*wp)++ = L':';
+		for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
+			if (perm & nfsv4_acl_flag_map[i].perm)
+				*(*wp)++ = nfsv4_acl_flag_map[i].wc;
+			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+				*(*wp)++ = 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);
+	}
+	if (id != -1) {
+		*(*wp)++ = L':';
+		append_id_w(wp, id);
+	}
+}
+
+/*
+ * 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;
+	ssize_t length;
+	size_t len;
+	const char *name;
+	const char *prefix;
+	char separator;
+	struct archive_acl_entry *ap;
+	int id, r, want_type;
+	char *p, *s;
+
+	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, 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 = s = (char *)malloc(length * sizeof(char));
+	if (p == NULL) {
+		if (errno == ENOMEM)
+			__archive_errx(1, "No memory");
+		return (NULL);
+	}
+	count = 0;
+
+	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++ = separator;
+		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		    ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
+		    acl->mode & 0070, -1);
+		*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 & 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;
+		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++;
+	}
+
+	/* 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
+append_id(char **p, int id)
+{
+	if (id < 0)
+		id = 0;
+	if (id > 9)
+		append_id(p, id / 10);
+	*(*p)++ = "0123456789"[id % 10];
+}
+
+static void
+append_entry(char **p, const char *prefix, int type,
+    int tag, int flags, const char *name, int perm, int id)
+{
+	int i;
+
+	if (prefix != NULL) {
+		strcpy(*p, prefix);
+		*p += strlen(*p);
+	}
+	switch (tag) {
+	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");
+		break;
+	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");
+		break;
+	case ARCHIVE_ENTRY_ACL_MASK:
+		strcpy(*p, "mask");
+		name = NULL;
+		id = -1;
+		break;
+	case ARCHIVE_ENTRY_ACL_OTHER:
+		strcpy(*p, "other");
+		name = NULL;
+		id = -1;
+		break;
+	case ARCHIVE_ENTRY_ACL_EVERYONE:
+		strcpy(*p, "everyone@");
+		name = NULL;
+		id = -1;
+		break;
+	}
+	*p += strlen(*p);
+	*(*p)++ = ':';
+	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 {
+		/* NFSv4 ACL perms */
+		for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
+			if (perm & nfsv4_acl_perm_map[i].perm)
+				*(*p)++ = nfsv4_acl_perm_map[i].c;
+			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+				*(*p)++ = '-';
+		}
+		*(*p)++ = ':';
+		for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
+			if (perm & nfsv4_acl_flag_map[i].perm)
+				*(*p)++ = nfsv4_acl_flag_map[i].c;
+			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+				*(*p)++ = '-';
+		}
+		*(*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);
+	}
+	if (id != -1) {
+		*(*p)++ = ':';
+		append_id(p, id);
+	}
+}
+
+/*
+ * 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_from_text_w(struct archive_acl *acl, const wchar_t *text,
+    int want_type)
+{
+	struct {
+		const wchar_t *start;
+		const wchar_t *end;
+	} field[6], name;
+
+	const wchar_t *s, *st;
+
+	int numfields, fields, n, r, sol, ret;
+	int type, types, tag, permset, id;
+	size_t len;
+	wchar_t sep;
+
+	ret = ARCHIVE_OK;
+	types = 0;
+
+	switch (want_type) {
+	case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
+		want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+		numfields = 5;
+		break;
+	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+		numfields = 6;
+		break;
+	default:
+		return (ARCHIVE_FATAL);
+	}
+
+	while (text != NULL && *text != L'\0') {
+		/*
+		 * Parse the fields out of the next entry,
+		 * advance 'text' to start of next entry.
+		 */
+		fields = 0;
+		do {
+			const wchar_t *start, *end;
+			next_field_w(&text, &start, &end, &sep);
+			if (fields < numfields) {
+				field[fields].start = start;
+				field[fields].end = end;
+			}
+			++fields;
+		} while (sep == L':');
+
+		/* Set remaining fields to blank. */
+		for (n = fields; n < numfields; ++n)
+			field[n].start = field[n].end = NULL;
+
+		if (field[0].start != NULL && *(field[0].start) == L'#') {
+			/* Comment, skip entry */
+			continue;
+		}
+
+		n = 0;
+		sol = 0;
+		id = -1;
+		permset = 0;
+		name.start = name.end = NULL;
+
+		if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+			/* POSIX.1e ACLs */
+			/*
+			 * Default keyword "default:user::rwx"
+			 * if found, we have one more field
+			 *
+			 * We also support old Solaris extension:
+			 * "defaultuser::rwx" is the default ACL corresponding
+			 * to "user::rwx", etc. valid only for first field
+			 */
+			s = field[0].start;
+			len = field[0].end - field[0].start;
+			if (*s == L'd' && (len == 1 || (len >= 7
+			    && wmemcmp((s + 1), L"efault", 6) == 0))) {
+				type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+				if (len > 7)
+					field[0].start += 7;
+				else
+					n = 1;
+			} else
+				type = want_type;
+
+			/* Check for a numeric ID in field n+1 or n+3. */
+			isint_w(field[n + 1].start, field[n + 1].end, &id);
+			/* Field n+3 is optional. */
+			if (id == -1 && fields > n+3)
+				isint_w(field[n + 3].start, field[n + 3].end,
+				    &id);
+
+			tag = 0;
+			s = field[n].start;
+			st = field[n].start + 1;
+			len = field[n].end - field[n].start;
+
+			switch (*s) {
+			case L'u':
+				if (len == 1 || (len == 4
+				    && wmemcmp(st, L"ser", 3) == 0))
+					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+				break;
+			case L'g':
+				if (len == 1 || (len == 5
+				    && wmemcmp(st, L"roup", 4) == 0))
+					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+				break;
+			case L'o':
+				if (len == 1 || (len == 5
+				    && wmemcmp(st, L"ther", 4) == 0))
+					tag = ARCHIVE_ENTRY_ACL_OTHER;
+				break;
+			case L'm':
+				if (len == 1 || (len == 4
+				    && wmemcmp(st, L"ask", 3) == 0))
+					tag = ARCHIVE_ENTRY_ACL_MASK;
+				break;
+			default:
+					break;
+			}
+
+			switch (tag) {
+			case ARCHIVE_ENTRY_ACL_OTHER:
+			case ARCHIVE_ENTRY_ACL_MASK:
+				if (fields == (n + 2)
+				    && field[n + 1].start < field[n + 1].end
+				    && ismode_w(field[n + 1].start,
+				    field[n + 1].end, &permset)) {
+					/* This is Solaris-style "other:rwx" */
+					sol = 1;
+				} else if (fields == (n + 3) &&
+				    field[n + 1].start < field[n + 1].end) {
+					/* Invalid mask or other field */
+					ret = ARCHIVE_WARN;
+					continue;
+				}
+				break;
+			case ARCHIVE_ENTRY_ACL_USER_OBJ:
+			case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+				if (id != -1 ||
+				    field[n + 1].start < field[n + 1].end) {
+					name = field[n + 1];
+					if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
+						tag = ARCHIVE_ENTRY_ACL_USER;
+					else
+						tag = ARCHIVE_ENTRY_ACL_GROUP;
+				}
+				break;
+			default:
+				/* Invalid tag, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+
+			/*
+			 * Without "default:" we expect mode in field 2
+			 * Exception: Solaris other and mask fields
+			 */
+			if (permset == 0 && !ismode_w(field[n + 2 - sol].start,
+			    field[n + 2 - sol].end, &permset)) {
+				/* Invalid mode, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+		} else {
+			/* NFS4 ACLs */
+			s = field[0].start;
+			len = field[0].end - field[0].start;
+			tag = 0;
+
+			switch (len) {
+			case 4:
+				if (wmemcmp(s, L"user", 4) == 0)
+					tag = ARCHIVE_ENTRY_ACL_USER;
+				break;
+			case 5:
+				if (wmemcmp(s, L"group", 5) == 0)
+					tag = ARCHIVE_ENTRY_ACL_GROUP;
+				break;
+			case 6:
+				if (wmemcmp(s, L"owner@", 6) == 0)
+					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+				else if (wmemcmp(s, L"group@", len) == 0)
+					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+				break;
+			case 9:
+				if (wmemcmp(s, L"everyone@", 9) == 0)
+					tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+			default:
+				break;
+			}
+
+			if (tag == 0) {
+				/* Invalid tag, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			} else if (tag == ARCHIVE_ENTRY_ACL_USER ||
+			    tag == ARCHIVE_ENTRY_ACL_GROUP) {
+				n = 1;
+				name = field[1];
+				isint_w(name.start, name.end, &id);
+			} else
+				n = 0;
+
+			if (!is_nfs4_perms_w(field[1 + n].start,
+			    field[1 + n].end, &permset)) {
+				/* Invalid NFSv4 perms, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			if (!is_nfs4_flags_w(field[2 + n].start,
+			    field[2 + n].end, &permset)) {
+				/* Invalid NFSv4 flags, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			s = field[3 + n].start;
+			len = field[3 + n].end - field[3 + n].start;
+			type = 0;
+			if (len == 4) {
+				if (wmemcmp(s, L"deny", 4) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+			} else if (len == 5) {
+				if (wmemcmp(s, L"allow", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+				else if (wmemcmp(s, L"audit", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+				else if (wmemcmp(s, L"alarm", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+			}
+			if (type == 0) {
+				/* Invalid entry type, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			isint_w(field[4 + n].start, field[4 + n].end, &id);
+		}
+
+		/* Add entry to the internal list. */
+		r = archive_acl_add_entry_w_len(acl, type, permset,
+		    tag, id, name.start, name.end - name.start);
+		if (r < ARCHIVE_WARN)
+			return (r);
+		if (r != ARCHIVE_OK)
+			ret = ARCHIVE_WARN;
+		types |= type;
+	}
+
+	/* Reset ACL */
+	archive_acl_reset(acl, types);
+
+	return (ret);
+}
+
+/*
+ * Parse a string to a positive decimal integer.  Returns true if
+ * the string is non-empty and consists only of decimal digits,
+ * false otherwise.
+ */
+static int
+isint_w(const wchar_t *start, const wchar_t *end, int *result)
+{
+	int n = 0;
+	if (start >= end)
+		return (0);
+	while (start < end) {
+		if (*start < '0' || *start > '9')
+			return (0);
+		if (n > (INT_MAX / 10) ||
+		    (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) {
+			n = INT_MAX;
+		} else {
+			n *= 10;
+			n += *start - '0';
+		}
+		start++;
+	}
+	*result = n;
+	return (1);
+}
+
+/*
+ * Parse a string as a mode field.  Returns true if
+ * the string is non-empty and consists only of mode characters,
+ * false otherwise.
+ */
+static int
+ismode_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+	const wchar_t *p;
+
+	if (start >= end)
+		return (0);
+	p = start;
+	*permset = 0;
+	while (p < end) {
+		switch (*p++) {
+		case L'r': case L'R':
+			*permset |= ARCHIVE_ENTRY_ACL_READ;
+			break;
+		case L'w': case L'W':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE;
+			break;
+		case L'x': case L'X':
+			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+			break;
+		case L'-':
+			break;
+		default:
+			return (0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL permission field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * permission characters, false otherwise
+ */
+static int
+is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+	const wchar_t *p = start;
+
+	while (p < end) {
+		switch (*p++) {
+		case L'r':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
+			break;
+		case L'w':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
+			break;
+		case L'x':
+			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+			break;
+		case L'p':
+			*permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
+			break;
+		case L'D':
+			*permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
+			break;
+		case L'd':
+			*permset |= ARCHIVE_ENTRY_ACL_DELETE;
+			break;
+		case L'a':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
+			break;
+		case L'A':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
+			break;
+		case L'R':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
+			break;
+		case L'W':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
+			break;
+		case L'c':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
+			break;
+		case L'C':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
+			break;
+		case L'o':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+			break;
+		case L's':
+			*permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+			break;
+		case L'-':
+			break;
+		default:
+			return(0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL flags field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * flag characters, false otherwise
+ */
+static int
+is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+	const wchar_t *p = start;
+
+	while (p < end) {
+		switch(*p++) {
+		case L'f':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
+			break;
+		case L'd':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
+			break;
+		case L'i':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
+			break;
+		case L'n':
+			*permset |=
+			    ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
+			break;
+		case L'S':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
+			break;
+		case L'F':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
+			break;
+		case L'I':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
+			break;
+		case L'-':
+			break;
+		default:
+			return (0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]".  *wp is updated
+ * to point to just after the separator.  *start points to the first
+ * character of the matched text and *end just after the last
+ * character of the matched identifier.  In particular *end - *start
+ * is the length of the field body, not including leading or trailing
+ * whitespace.
+ */
+static void
+next_field_w(const wchar_t **wp, const wchar_t **start,
+    const wchar_t **end, wchar_t *sep)
+{
+	/* Skip leading whitespace to find start of field. */
+	while (**wp == L' ' || **wp == L'\t' || **wp == L'\n') {
+		(*wp)++;
+	}
+	*start = *wp;
+
+	/* Scan for the separator. */
+	while (**wp != L'\0' && **wp != L',' && **wp != L':' &&
+	    **wp != L'\n') {
+		(*wp)++;
+	}
+	*sep = **wp;
+
+	/* Trim trailing whitespace to locate end of field. */
+	*end = *wp - 1;
+	while (**end == L' ' || **end == L'\t' || **end == L'\n') {
+		(*end)--;
+	}
+	(*end)++;
+
+	/* Adjust scanner location. */
+	if (**wp != L'\0')
+		(*wp)++;
+}
+
+/*
+ * Parse an 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_from_text_l(struct archive_acl *acl, const char *text,
+    int want_type, struct archive_string_conv *sc)
+{
+	struct {
+		const char *start;
+		const char *end;
+	} field[6], name;
+
+	const char *s, *st;
+	int numfields, fields, n, r, sol, ret;
+	int type, types, tag, permset, id;
+	size_t len;
+	char sep;
+
+	switch (want_type) {
+	case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
+		want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+		numfields = 5;
+		break;
+	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+		numfields = 6;
+		break;
+	default:
+		return (ARCHIVE_FATAL);
+	}
+
+	ret = ARCHIVE_OK;
+	types = 0;
+
+	while (text != NULL  &&  *text != '\0') {
+		/*
+		 * Parse the fields out of the next entry,
+		 * advance 'text' to start of next entry.
+		 */
+		fields = 0;
+		do {
+			const char *start, *end;
+			next_field(&text, &start, &end, &sep);
+			if (fields < numfields) {
+				field[fields].start = start;
+				field[fields].end = end;
+			}
+			++fields;
+		} while (sep == ':');
+
+		/* Set remaining fields to blank. */
+		for (n = fields; n < numfields; ++n)
+			field[n].start = field[n].end = NULL;
+
+		if (field[0].start != NULL && *(field[0].start) == '#') {
+			/* Comment, skip entry */
+			continue;
+		}
+
+		n = 0;
+		sol = 0;
+		id = -1;
+		permset = 0;
+		name.start = name.end = NULL;
+
+		if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+			/* POSIX.1e ACLs */
+			/*
+			 * Default keyword "default:user::rwx"
+			 * if found, we have one more field
+			 *
+			 * We also support old Solaris extension:
+			 * "defaultuser::rwx" is the default ACL corresponding
+			 * to "user::rwx", etc. valid only for first field
+			 */
+			s = field[0].start;
+			len = field[0].end - field[0].start;
+			if (*s == 'd' && (len == 1 || (len >= 7
+			    && memcmp((s + 1), "efault", 6) == 0))) {
+				type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+				if (len > 7)
+					field[0].start += 7;
+				else
+					n = 1;
+			} else
+				type = want_type;
+
+			/* Check for a numeric ID in field n+1 or n+3. */
+			isint(field[n + 1].start, field[n + 1].end, &id);
+			/* Field n+3 is optional. */
+			if (id == -1 && fields > (n + 3))
+				isint(field[n + 3].start, field[n + 3].end,
+				    &id);
+
+			tag = 0;
+			s = field[n].start;
+			st = field[n].start + 1;
+			len = field[n].end - field[n].start;
+
+			switch (*s) {
+			case 'u':
+				if (len == 1 || (len == 4
+				    && memcmp(st, "ser", 3) == 0))
+					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+				break;
+			case 'g':
+				if (len == 1 || (len == 5
+				    && memcmp(st, "roup", 4) == 0))
+					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+				break;
+			case 'o':
+				if (len == 1 || (len == 5
+				    && memcmp(st, "ther", 4) == 0))
+					tag = ARCHIVE_ENTRY_ACL_OTHER;
+				break;
+			case 'm':
+				if (len == 1 || (len == 4
+				    && memcmp(st, "ask", 3) == 0))
+					tag = ARCHIVE_ENTRY_ACL_MASK;
+				break;
+			default:
+					break;
+			}
+
+			switch (tag) {
+			case ARCHIVE_ENTRY_ACL_OTHER:
+			case ARCHIVE_ENTRY_ACL_MASK:
+				if (fields == (n + 2)
+				    && field[n + 1].start < field[n + 1].end
+				    && ismode(field[n + 1].start,
+				    field[n + 1].end, &permset)) {
+					/* This is Solaris-style "other:rwx" */
+					sol = 1;
+				} else if (fields == (n + 3) &&
+				    field[n + 1].start < field[n + 1].end) {
+					/* Invalid mask or other field */
+					ret = ARCHIVE_WARN;
+					continue;
+				}
+				break;
+			case ARCHIVE_ENTRY_ACL_USER_OBJ:
+			case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+				if (id != -1 ||
+				    field[n + 1].start < field[n + 1].end) {
+					name = field[n + 1];
+					if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
+						tag = ARCHIVE_ENTRY_ACL_USER;
+					else
+						tag = ARCHIVE_ENTRY_ACL_GROUP;
+				}
+				break;
+			default:
+				/* Invalid tag, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+
+			/*
+			 * Without "default:" we expect mode in field 3
+			 * Exception: Solaris other and mask fields
+			 */
+			if (permset == 0 && !ismode(field[n + 2 - sol].start,
+			    field[n + 2 - sol].end, &permset)) {
+				/* Invalid mode, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+		} else {
+			/* NFS4 ACLs */
+			s = field[0].start;
+			len = field[0].end - field[0].start;
+			tag = 0;
+
+			switch (len) {
+			case 4:
+				if (memcmp(s, "user", 4) == 0)
+					tag = ARCHIVE_ENTRY_ACL_USER;
+				break;
+			case 5:
+				if (memcmp(s, "group", 5) == 0)
+					tag = ARCHIVE_ENTRY_ACL_GROUP;
+				break;
+			case 6:
+				if (memcmp(s, "owner@", 6) == 0)
+					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+				else if (memcmp(s, "group@", 6) == 0)
+					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+				break;
+			case 9:
+				if (memcmp(s, "everyone@", 9) == 0)
+					tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+				break;
+			default:
+				break;
+			}
+
+			if (tag == 0) {
+				/* Invalid tag, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			} else if (tag == ARCHIVE_ENTRY_ACL_USER ||
+			    tag == ARCHIVE_ENTRY_ACL_GROUP) {
+				n = 1;
+				name = field[1];
+				isint(name.start, name.end, &id);
+			} else
+				n = 0;
+
+			if (!is_nfs4_perms(field[1 + n].start,
+			    field[1 + n].end, &permset)) {
+				/* Invalid NFSv4 perms, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			if (!is_nfs4_flags(field[2 + n].start,
+			    field[2 + n].end, &permset)) {
+				/* Invalid NFSv4 flags, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			s = field[3 + n].start;
+			len = field[3 + n].end - field[3 + n].start;
+			type = 0;
+			if (len == 4) {
+				if (memcmp(s, "deny", 4) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+			} else if (len == 5) {
+				if (memcmp(s, "allow", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+				else if (memcmp(s, "audit", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+				else if (memcmp(s, "alarm", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+			}
+			if (type == 0) {
+				/* Invalid entry type, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			isint(field[4 + n].start, field[4 + n].end,
+			    &id);
+		}
+
+		/* Add entry to the internal list. */
+		r = archive_acl_add_entry_len_l(acl, type, permset,
+		    tag, id, name.start, name.end - name.start, sc);
+		if (r < ARCHIVE_WARN)
+			return (r);
+		if (r != ARCHIVE_OK)
+			ret = ARCHIVE_WARN;
+		types |= type;
+	}
+
+	/* Reset ACL */
+	archive_acl_reset(acl, types);
+
+	return (ret);
+}
+
+/*
+ * Parse a string to a positive decimal integer.  Returns true if
+ * the string is non-empty and consists only of decimal digits,
+ * false otherwise.
+ */
+static int
+isint(const char *start, const char *end, int *result)
+{
+	int n = 0;
+	if (start >= end)
+		return (0);
+	while (start < end) {
+		if (*start < '0' || *start > '9')
+			return (0);
+		if (n > (INT_MAX / 10) ||
+		    (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) {
+			n = INT_MAX;
+		} else {
+			n *= 10;
+			n += *start - '0';
+		}
+		start++;
+	}
+	*result = n;
+	return (1);
+}
+
+/*
+ * Parse a string as a mode field.  Returns true if
+ * the string is non-empty and consists only of mode characters,
+ * false otherwise.
+ */
+static int
+ismode(const char *start, const char *end, int *permset)
+{
+	const char *p;
+
+	if (start >= end)
+		return (0);
+	p = start;
+	*permset = 0;
+	while (p < end) {
+		switch (*p++) {
+		case 'r': case 'R':
+			*permset |= ARCHIVE_ENTRY_ACL_READ;
+			break;
+		case 'w': case 'W':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE;
+			break;
+		case 'x': case 'X':
+			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+			break;
+		case '-':
+			break;
+		default:
+			return (0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL permission field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * permission characters, false otherwise
+ */
+static int
+is_nfs4_perms(const char *start, const char *end, int *permset)
+{
+	const char *p = start;
+
+	while (p < end) {
+		switch (*p++) {
+		case 'r':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
+			break;
+		case 'w':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
+			break;
+		case 'x':
+			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+			break;
+		case 'p':
+			*permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
+			break;
+		case 'D':
+			*permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
+			break;
+		case 'd':
+			*permset |= ARCHIVE_ENTRY_ACL_DELETE;
+			break;
+		case 'a':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
+			break;
+		case 'A':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
+			break;
+		case 'R':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
+			break;
+		case 'W':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
+			break;
+		case 'c':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
+			break;
+		case 'C':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
+			break;
+		case 'o':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+			break;
+		case 's':
+			*permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+			break;
+		case '-':
+			break;
+		default:
+			return(0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL flags field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * flag characters, false otherwise
+ */
+static int
+is_nfs4_flags(const char *start, const char *end, int *permset)
+{
+	const char *p = start;
+
+	while (p < end) {
+		switch(*p++) {
+		case 'f':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
+			break;
+		case 'd':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
+			break;
+		case 'i':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
+			break;
+		case 'n':
+			*permset |=
+			    ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
+			break;
+		case 'S':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
+			break;
+		case 'F':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
+			break;
+		case 'I':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
+			break;
+		case '-':
+			break;
+		default:
+			return (0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]".  *wp is updated
+ * to point to just after the separator.  *start points to the first
+ * character of the matched text and *end just after the last
+ * character of the matched identifier.  In particular *end - *start
+ * is the length of the field body, not including leading or trailing
+ * whitespace.
+ */
+static void
+next_field(const char **p, const char **start,
+    const char **end, char *sep)
+{
+	/* Skip leading whitespace to find start of field. */
+	while (**p == ' ' || **p == '\t' || **p == '\n') {
+		(*p)++;
+	}
+	*start = *p;
+
+	/* Scan for the separator. */
+	while (**p != '\0' && **p != ',' && **p != ':' && **p != '\n') {
+		(*p)++;
+	}
+	*sep = **p;
+
+	/* Trim trailing whitespace to locate end of field. */
+	*end = *p - 1;
+	while (**end == ' ' || **end == '\t' || **end == '\n') {
+		(*end)--;
+	}
+	(*end)++;
+
+	/* Adjust scanner location. */
+	if (**p != '\0')
+		(*p)++;
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/3781b52f/thirdparty/libarchive-3.3.2/libarchive/archive_acl_private.h
----------------------------------------------------------------------
diff --git a/thirdparty/libarchive-3.3.2/libarchive/archive_acl_private.h b/thirdparty/libarchive-3.3.2/libarchive/archive_acl_private.h
new file mode 100644
index 0000000..ef0b023
--- /dev/null
+++ b/thirdparty/libarchive-3.3.2/libarchive/archive_acl_private.h
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifndef ARCHIVE_ACL_PRIVATE_H_INCLUDED
+#define	ARCHIVE_ACL_PRIVATE_H_INCLUDED
+
+#include "archive_string.h"
+
+struct archive_acl_entry {
+	struct archive_acl_entry *next;
+	int	type;			/* E.g., access or default */
+	int	tag;			/* E.g., user/group/other/mask */
+	int	permset;		/* r/w/x bits */
+	int	id;			/* uid/gid for user/group */
+	struct archive_mstring name;		/* uname/gname */
+};
+
+struct archive_acl {
+	mode_t		mode;
+	struct archive_acl_entry	*acl_head;
+	struct archive_acl_entry	*acl_p;
+	int		 acl_state;	/* See acl_next for details. */
+	wchar_t		*acl_text_w;
+	char		*acl_text;
+	int		 acl_types;
+};
+
+void archive_acl_clear(struct archive_acl *);
+void archive_acl_copy(struct archive_acl *, struct archive_acl *);
+int archive_acl_count(struct archive_acl *, int);
+int archive_acl_types(struct archive_acl *);
+int archive_acl_reset(struct archive_acl *, int);
+int archive_acl_next(struct archive *, struct archive_acl *, int,
+    int *, int *, int *, int *, const char **);
+
+int archive_acl_add_entry(struct archive_acl *, int, int, int, int, const char *);
+int archive_acl_add_entry_w_len(struct archive_acl *,
+    int, int, int, int, const wchar_t *, size_t);
+int archive_acl_add_entry_len(struct archive_acl *,
+    int, int, int, int, const char *, size_t);
+
+wchar_t *archive_acl_to_text_w(struct archive_acl *, ssize_t *, int,
+    struct archive *);
+char *archive_acl_to_text_l(struct archive_acl *, ssize_t *, int,
+    struct archive_string_conv *);
+
+/*
+ * ACL text parser.
+ */
+int archive_acl_from_text_w(struct archive_acl *, const wchar_t * /* wtext */,
+    int /* type */);
+int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
+    int /* type */, struct archive_string_conv *);
+
+#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/3781b52f/thirdparty/libarchive-3.3.2/libarchive/archive_check_magic.c
----------------------------------------------------------------------
diff --git a/thirdparty/libarchive-3.3.2/libarchive/archive_check_magic.c b/thirdparty/libarchive-3.3.2/libarchive/archive_check_magic.c
new file mode 100644
index 0000000..288ce23
--- /dev/null
+++ b/thirdparty/libarchive-3.3.2/libarchive/archive_check_magic.c
@@ -0,0 +1,175 @@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_check_magic.c 201089 2009-12-28 02:20:23Z kientzle $");
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <windows.h>
+#include <winbase.h>
+#endif
+
+#include "archive_private.h"
+
+static void
+errmsg(const char *m)
+{
+	size_t s = strlen(m);
+	ssize_t written;
+
+	while (s > 0) {
+		written = write(2, m, strlen(m));
+		if (written <= 0)
+			return;
+		m += written;
+		s -= written;
+	}
+}
+
+static __LA_DEAD void
+diediedie(void)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
+	/* Cause a breakpoint exception  */
+	DebugBreak();
+#endif
+	abort();        /* Terminate the program abnormally. */
+}
+
+static const char *
+state_name(unsigned s)
+{
+	switch (s) {
+	case ARCHIVE_STATE_NEW:		return ("new");
+	case ARCHIVE_STATE_HEADER:	return ("header");
+	case ARCHIVE_STATE_DATA:	return ("data");
+	case ARCHIVE_STATE_EOF:		return ("eof");
+	case ARCHIVE_STATE_CLOSED:	return ("closed");
+	case ARCHIVE_STATE_FATAL:	return ("fatal");
+	default:			return ("??");
+	}
+}
+
+static const char *
+archive_handle_type_name(unsigned m)
+{
+	switch (m) {
+	case ARCHIVE_WRITE_MAGIC:	return ("archive_write");
+	case ARCHIVE_READ_MAGIC:	return ("archive_read");
+	case ARCHIVE_WRITE_DISK_MAGIC:	return ("archive_write_disk");
+	case ARCHIVE_READ_DISK_MAGIC:	return ("archive_read_disk");
+	case ARCHIVE_MATCH_MAGIC:	return ("archive_match");
+	default:			return NULL;
+	}
+}
+
+
+static char *
+write_all_states(char *buff, unsigned int states)
+{
+	unsigned int lowbit;
+
+	buff[0] = '\0';
+
+	/* A trick for computing the lowest set bit. */
+	while ((lowbit = states & (1 + ~states)) != 0) {
+		states &= ~lowbit;		/* Clear the low bit. */
+		strcat(buff, state_name(lowbit));
+		if (states != 0)
+			strcat(buff, "/");
+	}
+	return buff;
+}
+
+/*
+ * Check magic value and current state.
+ *   Magic value mismatches are fatal and result in calls to abort().
+ *   State mismatches return ARCHIVE_FATAL.
+ *   Otherwise, returns ARCHIVE_OK.
+ *
+ * This is designed to catch serious programming errors that violate
+ * the libarchive API.
+ */
+int
+__archive_check_magic(struct archive *a, unsigned int magic,
+    unsigned int state, const char *function)
+{
+	char states1[64];
+	char states2[64];
+	const char *handle_type;
+
+	/*
+	 * If this isn't some form of archive handle,
+	 * then the library user has screwed up so bad that
+	 * we don't even have a reliable way to report an error.
+	 */
+	handle_type = archive_handle_type_name(a->magic);
+
+	if (!handle_type) {
+		errmsg("PROGRAMMER ERROR: Function ");
+		errmsg(function);
+		errmsg(" invoked with invalid archive handle.\n");
+		diediedie();
+	}
+
+	if (a->magic != magic) {
+		archive_set_error(a, -1,
+		    "PROGRAMMER ERROR: Function '%s' invoked"
+		    " on '%s' archive object, which is not supported.",
+		    function,
+		    handle_type);
+		a->state = ARCHIVE_STATE_FATAL;
+		return (ARCHIVE_FATAL);
+	}
+
+	if ((a->state & state) == 0) {
+		/* If we're already FATAL, don't overwrite the error. */
+		if (a->state != ARCHIVE_STATE_FATAL)
+			archive_set_error(a, -1,
+			    "INTERNAL ERROR: Function '%s' invoked with"
+			    " archive structure in state '%s',"
+			    " should be in state '%s'",
+			    function,
+			    write_all_states(states1, a->state),
+			    write_all_states(states2, state));
+		a->state = ARCHIVE_STATE_FATAL;
+		return (ARCHIVE_FATAL);
+	}
+	return ARCHIVE_OK;
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/3781b52f/thirdparty/libarchive-3.3.2/libarchive/archive_cmdline.c
----------------------------------------------------------------------
diff --git a/thirdparty/libarchive-3.3.2/libarchive/archive_cmdline.c b/thirdparty/libarchive-3.3.2/libarchive/archive_cmdline.c
new file mode 100644
index 0000000..7d3bac5
--- /dev/null
+++ b/thirdparty/libarchive-3.3.2/libarchive/archive_cmdline.c
@@ -0,0 +1,227 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif
+
+#include "archive.h"
+#include "archive_cmdline_private.h"
+#include "archive_string.h"
+
+static int cmdline_set_path(struct archive_cmdline *, const char *);
+static int cmdline_add_arg(struct archive_cmdline *, const char *);
+
+static ssize_t
+extract_quotation(struct archive_string *as, const char *p)
+{
+	const char *s;
+
+	for (s = p + 1; *s;) {
+		if (*s == '\\') {
+			if (s[1] != '\0') {
+				archive_strappend_char(as, s[1]);
+				s += 2;
+			} else
+				s++;
+		} else if (*s == '"')
+			break;
+		else {
+			archive_strappend_char(as, s[0]);
+			s++;
+		}
+	}
+	if (*s != '"')
+		return (ARCHIVE_FAILED);/* Invalid sequence. */
+	return ((ssize_t)(s + 1 - p));
+}
+
+static ssize_t
+get_argument(struct archive_string *as, const char *p)
+{
+	const char *s = p;
+
+	archive_string_empty(as);
+
+	/* Skip beginning space characters. */
+	while (*s != '\0' && *s == ' ')
+		s++;
+	/* Copy non-space characters. */
+	while (*s != '\0' && *s != ' ') {
+		if (*s == '\\') {
+			if (s[1] != '\0') {
+				archive_strappend_char(as, s[1]);
+				s += 2;
+			} else {
+				s++;/* Ignore this character.*/
+				break;
+			}
+		} else if (*s == '"') {
+			ssize_t q = extract_quotation(as, s);
+			if (q < 0)
+				return (ARCHIVE_FAILED);/* Invalid sequence. */
+			s += q;
+		} else {
+			archive_strappend_char(as, s[0]);
+			s++;
+		}
+	}
+	return ((ssize_t)(s - p));
+}
+
+/*
+ * Set up command line arguments.
+ * Returns ARChIVE_OK if everything okey.
+ * Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an
+ * empty command line.
+ * Returns ARChIVE_FATAL if no memory.
+ */
+int
+__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
+{
+	struct archive_string as;
+	const char *p;
+	ssize_t al;
+	int r;
+
+	archive_string_init(&as);
+
+	/* Get first argument as a command path. */
+	al = get_argument(&as, cmd);
+	if (al < 0) {
+		r = ARCHIVE_FAILED;/* Invalid sequence. */
+		goto exit_function;
+	}
+	if (archive_strlen(&as) == 0) {
+		r = ARCHIVE_FAILED;/* An empty command path. */
+		goto exit_function;
+	}
+	r = cmdline_set_path(data, as.s);
+	if (r != ARCHIVE_OK)
+		goto exit_function;
+	p = strrchr(as.s, '/');
+	if (p == NULL)
+		p = as.s;
+	else
+		p++;
+	r = cmdline_add_arg(data, p);
+	if (r != ARCHIVE_OK)
+		goto exit_function;
+	cmd += al;
+
+	for (;;) {
+		al = get_argument(&as, cmd);
+		if (al < 0) {
+			r = ARCHIVE_FAILED;/* Invalid sequence. */
+			goto exit_function;
+		}
+		if (al == 0)
+			break;
+		cmd += al;
+		if (archive_strlen(&as) == 0 && *cmd == '\0')
+			break;
+		r = cmdline_add_arg(data, as.s);
+		if (r != ARCHIVE_OK)
+			goto exit_function;
+	}
+	r = ARCHIVE_OK;
+exit_function:
+	archive_string_free(&as);
+	return (r);
+}
+
+/*
+ * Set the program path.
+ */
+static int
+cmdline_set_path(struct archive_cmdline *data, const char *path)
+{
+	char *newptr;
+
+	newptr = realloc(data->path, strlen(path) + 1);
+	if (newptr == NULL)
+		return (ARCHIVE_FATAL);
+	data->path = newptr;
+	strcpy(data->path, path);
+	return (ARCHIVE_OK);
+}
+
+/*
+ * Add a argument for the program.
+ */
+static int
+cmdline_add_arg(struct archive_cmdline *data, const char *arg)
+{
+	char **newargv;
+
+	if (data->path == NULL)
+		return (ARCHIVE_FAILED);
+
+	newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));
+	if (newargv == NULL)
+		return (ARCHIVE_FATAL);
+	data->argv = newargv;
+	data->argv[data->argc] = strdup(arg);
+	if (data->argv[data->argc] == NULL)
+		return (ARCHIVE_FATAL);
+	/* Set the terminator of argv. */
+	data->argv[++data->argc] = NULL;
+	return (ARCHIVE_OK);
+}
+
+struct archive_cmdline *
+__archive_cmdline_allocate(void)
+{
+	return (struct archive_cmdline *)
+		calloc(1, sizeof(struct archive_cmdline));
+}
+
+/*
+ * Release the resources.
+ */
+int
+__archive_cmdline_free(struct archive_cmdline *data)
+{
+
+	if (data) {
+		free(data->path);
+		if (data->argv != NULL) {
+			int i;
+			for (i = 0; data->argv[i] != NULL; i++)
+				free(data->argv[i]);
+			free(data->argv);
+		}
+		free(data);
+	}
+	return (ARCHIVE_OK);
+}
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/3781b52f/thirdparty/libarchive-3.3.2/libarchive/archive_cmdline_private.h
----------------------------------------------------------------------
diff --git a/thirdparty/libarchive-3.3.2/libarchive/archive_cmdline_private.h b/thirdparty/libarchive-3.3.2/libarchive/archive_cmdline_private.h
new file mode 100644
index 0000000..4e409e8
--- /dev/null
+++ b/thirdparty/libarchive-3.3.2/libarchive/archive_cmdline_private.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __LIBARCHIVE_BUILD
+#ifndef __LIBARCHIVE_TEST
+#error This header is only to be used internally to libarchive.
+#endif
+#endif
+
+#ifndef ARCHIVE_CMDLINE_PRIVATE_H
+#define ARCHIVE_CMDLINE_PRIVATE_H
+
+struct archive_cmdline {
+        char            *path;
+        char            **argv;
+        int              argc;
+};
+
+struct archive_cmdline *__archive_cmdline_allocate(void);
+int __archive_cmdline_parse(struct archive_cmdline *, const char *);
+int __archive_cmdline_free(struct archive_cmdline *);
+
+#endif

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/3781b52f/thirdparty/libarchive-3.3.2/libarchive/archive_crc32.h
----------------------------------------------------------------------
diff --git a/thirdparty/libarchive-3.3.2/libarchive/archive_crc32.h b/thirdparty/libarchive-3.3.2/libarchive/archive_crc32.h
new file mode 100644
index 0000000..cd633af
--- /dev/null
+++ b/thirdparty/libarchive-3.3.2/libarchive/archive_crc32.h
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2009 Joerg  Sonnenberger
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: head/lib/libarchive/archive_crc32.h 201102 2009-12-28 03:11:36Z kientzle $
+ */
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+/*
+ * When zlib is unavailable, we should still be able to validate
+ * uncompressed zip archives.  That requires us to be able to compute
+ * the CRC32 check value.  This is a drop-in compatible replacement
+ * for crc32() from zlib.  It's slower than the zlib implementation,
+ * but still pretty fast: This runs about 300MB/s on my 3GHz P4
+ * compared to about 800MB/s for the zlib implementation.
+ */
+static unsigned long
+crc32(unsigned long crc, const void *_p, size_t len)
+{
+	unsigned long crc2, b, i;
+	const unsigned char *p = _p;
+	static volatile int crc_tbl_inited = 0;
+	static unsigned long crc_tbl[256];
+
+	if (!crc_tbl_inited) {
+		for (b = 0; b < 256; ++b) {
+			crc2 = b;
+			for (i = 8; i > 0; --i) {
+				if (crc2 & 1)
+					crc2 = (crc2 >> 1) ^ 0xedb88320UL;
+				else    
+					crc2 = (crc2 >> 1);
+			}
+			crc_tbl[b] = crc2;
+		}
+		crc_tbl_inited = 1;
+	}
+
+	crc = crc ^ 0xffffffffUL;
+	/* A use of this loop is about 20% - 30% faster than
+	 * no use version in any optimization option of gcc.  */
+	for (;len >= 8; len -= 8) {
+		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+	}
+	while (len--)
+		crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+	return (crc ^ 0xffffffffUL);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/3781b52f/thirdparty/libarchive-3.3.2/libarchive/archive_cryptor.c
----------------------------------------------------------------------
diff --git a/thirdparty/libarchive-3.3.2/libarchive/archive_cryptor.c b/thirdparty/libarchive-3.3.2/libarchive/archive_cryptor.c
new file mode 100644
index 0000000..ced52fd
--- /dev/null
+++ b/thirdparty/libarchive-3.3.2/libarchive/archive_cryptor.c
@@ -0,0 +1,450 @@
+/*-
+* Copyright (c) 2014 Michihiro NAKAJIMA
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "archive_platform.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include "archive.h"
+#include "archive_cryptor_private.h"
+
+/*
+ * On systems that do not support any recognized crypto libraries,
+ * this file will normally define no usable symbols.
+ *
+ * But some compilers and linkers choke on empty object files, so
+ * define a public symbol that will always exist.  This could
+ * be removed someday if this file gains another always-present
+ * symbol definition.
+ */
+int __libarchive_cryptor_build_hack(void) {
+	return 0;
+}
+
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
+
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+    size_t salt_len, unsigned rounds, uint8_t *derived_key,
+    size_t derived_key_len)
+{
+	CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pw,
+	    pw_len, salt, salt_len, kCCPRFHmacAlgSHA1, rounds,
+	    derived_key, derived_key_len);
+	return 0;
+}
+
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+#ifdef _MSC_VER
+#pragma comment(lib, "Bcrypt.lib")
+#endif
+
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+	size_t salt_len, unsigned rounds, uint8_t *derived_key,
+	size_t derived_key_len)
+{
+	NTSTATUS status;
+	BCRYPT_ALG_HANDLE hAlg;
+
+	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
+		MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
+	if (!BCRYPT_SUCCESS(status))
+		return -1;
+
+	status = BCryptDeriveKeyPBKDF2(hAlg,
+		(PUCHAR)(uintptr_t)pw, (ULONG)pw_len,
+		(PUCHAR)(uintptr_t)salt, (ULONG)salt_len, rounds,
+		(PUCHAR)derived_key, (ULONG)derived_key_len, 0);
+
+	BCryptCloseAlgorithmProvider(hAlg, 0);
+
+	return (BCRYPT_SUCCESS(status)) ? 0: -1;
+}
+
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_PBKDF2_H)
+
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+    size_t salt_len, unsigned rounds, uint8_t *derived_key,
+    size_t derived_key_len) {
+	pbkdf2_hmac_sha1((unsigned)pw_len, (const uint8_t *)pw, rounds,
+	    salt_len, salt, derived_key_len, derived_key);
+	return 0;
+}
+
+#elif defined(HAVE_LIBCRYPTO) && defined(HAVE_PKCS5_PBKDF2_HMAC_SHA1)
+
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+    size_t salt_len, unsigned rounds, uint8_t *derived_key,
+    size_t derived_key_len) {
+
+	PKCS5_PBKDF2_HMAC_SHA1(pw, pw_len, salt, salt_len, rounds,
+	    derived_key_len, derived_key);
+	return 0;
+}
+
+#else
+
+/* Stub */
+static int
+pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
+    size_t salt_len, unsigned rounds, uint8_t *derived_key,
+    size_t derived_key_len) {
+	(void)pw; /* UNUSED */
+	(void)pw_len; /* UNUSED */
+	(void)salt; /* UNUSED */
+	(void)salt_len; /* UNUSED */
+	(void)rounds; /* UNUSED */
+	(void)derived_key; /* UNUSED */
+	(void)derived_key_len; /* UNUSED */
+	return -1; /* UNSUPPORTED */
+}
+
+#endif
+
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
+#  define kCCAlgorithmAES kCCAlgorithmAES128
+# endif
+
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+	CCCryptorStatus r;
+
+	ctx->key_len = key_len;
+	memcpy(ctx->key, key, key_len);
+	memset(ctx->nonce, 0, sizeof(ctx->nonce));
+	ctx->encr_pos = AES_BLOCK_SIZE;
+	r = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES,
+	    ccNoPadding, NULL, key, key_len, NULL, 0, 0, 0, &ctx->ctx);
+	return (r == kCCSuccess)? 0: -1;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+	CCCryptorRef ref = ctx->ctx;
+	CCCryptorStatus r;
+
+	r = CCCryptorReset(ref, NULL);
+	if (r != kCCSuccess)
+		return -1;
+	r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
+	    AES_BLOCK_SIZE, NULL);
+	return (r == kCCSuccess)? 0: -1;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+	memset(ctx->key, 0, ctx->key_len);
+	memset(ctx->nonce, 0, sizeof(ctx->nonce));
+	return 0;
+}
+
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+	BCRYPT_ALG_HANDLE hAlg;
+	BCRYPT_KEY_HANDLE hKey;
+	DWORD keyObj_len, aes_key_len;
+	PBYTE keyObj;
+	ULONG result;
+	NTSTATUS status;
+	BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
+
+	ctx->hAlg = NULL;
+	ctx->hKey = NULL;
+	ctx->keyObj = NULL;
+	switch (key_len) {
+	case 16: aes_key_len = 128; break;
+	case 24: aes_key_len = 192; break;
+	case 32: aes_key_len = 256; break;
+	default: return -1;
+	}
+	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM,
+		MS_PRIMITIVE_PROVIDER, 0);
+	if (!BCRYPT_SUCCESS(status))
+		return -1;
+	status = BCryptGetProperty(hAlg, BCRYPT_KEY_LENGTHS, (PUCHAR)&key_lengths,
+		sizeof(key_lengths), &result, 0);
+	if (!BCRYPT_SUCCESS(status)) {
+		BCryptCloseAlgorithmProvider(hAlg, 0);
+		return -1;
+	}
+	if (key_lengths.dwMinLength > aes_key_len
+		|| key_lengths.dwMaxLength < aes_key_len) {
+		BCryptCloseAlgorithmProvider(hAlg, 0);
+		return -1;
+	}
+	status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObj_len,
+		sizeof(keyObj_len), &result, 0);
+	if (!BCRYPT_SUCCESS(status)) {
+		BCryptCloseAlgorithmProvider(hAlg, 0);
+		return -1;
+	}
+	keyObj = (PBYTE)HeapAlloc(GetProcessHeap(), 0, keyObj_len);
+	if (keyObj == NULL) {
+		BCryptCloseAlgorithmProvider(hAlg, 0);
+		return -1;
+	}
+	status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE,
+		(PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
+	if (!BCRYPT_SUCCESS(status)) {
+		BCryptCloseAlgorithmProvider(hAlg, 0);
+		HeapFree(GetProcessHeap(), 0, keyObj);
+		return -1;
+	}
+	status = BCryptGenerateSymmetricKey(hAlg, &hKey,
+		keyObj, keyObj_len,
+		(PUCHAR)(uintptr_t)key, (ULONG)key_len, 0);
+	if (!BCRYPT_SUCCESS(status)) {
+		BCryptCloseAlgorithmProvider(hAlg, 0);
+		HeapFree(GetProcessHeap(), 0, keyObj);
+		return -1;
+	}
+
+	ctx->hAlg = hAlg;
+	ctx->hKey = hKey;
+	ctx->keyObj = keyObj;
+	ctx->keyObj_len = keyObj_len;
+	ctx->encr_pos = AES_BLOCK_SIZE;
+
+	return 0;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+	NTSTATUS status;
+	ULONG result;
+
+	status = BCryptEncrypt(ctx->hKey, (PUCHAR)ctx->nonce, AES_BLOCK_SIZE,
+		NULL, NULL, 0, (PUCHAR)ctx->encr_buf, AES_BLOCK_SIZE,
+		&result, 0);
+	return BCRYPT_SUCCESS(status) ? 0 : -1;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+
+	if (ctx->hAlg != NULL) {
+		BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+		ctx->hAlg = NULL;
+		BCryptDestroyKey(ctx->hKey);
+		ctx->hKey = NULL;
+		HeapFree(GetProcessHeap(), 0, ctx->keyObj);
+		ctx->keyObj = NULL;
+	}
+	memset(ctx, 0, sizeof(*ctx));
+	return 0;
+}
+
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
+
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+	ctx->key_len = key_len;
+	memcpy(ctx->key, key, key_len);
+	memset(ctx->nonce, 0, sizeof(ctx->nonce));
+	ctx->encr_pos = AES_BLOCK_SIZE;
+	memset(&ctx->ctx, 0, sizeof(ctx->ctx));
+	return 0;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+	aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key);
+	aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce);
+	return 0;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+	memset(ctx, 0, sizeof(*ctx));
+	return 0;
+}
+
+#elif defined(HAVE_LIBCRYPTO)
+
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+	if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL)
+		return -1;
+
+	switch (key_len) {
+	case 16: ctx->type = EVP_aes_128_ecb(); break;
+	case 24: ctx->type = EVP_aes_192_ecb(); break;
+	case 32: ctx->type = EVP_aes_256_ecb(); break;
+	default: ctx->type = NULL; return -1;
+	}
+
+	ctx->key_len = key_len;
+	memcpy(ctx->key, key, key_len);
+	memset(ctx->nonce, 0, sizeof(ctx->nonce));
+	ctx->encr_pos = AES_BLOCK_SIZE;
+	EVP_CIPHER_CTX_init(ctx->ctx);
+	return 0;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+	int outl = 0;
+	int r;
+
+	r = EVP_EncryptInit_ex(ctx->ctx, ctx->type, NULL, ctx->key, NULL);
+	if (r == 0)
+		return -1;
+	r = EVP_EncryptUpdate(ctx->ctx, ctx->encr_buf, &outl, ctx->nonce,
+	    AES_BLOCK_SIZE);
+	if (r == 0 || outl != AES_BLOCK_SIZE)
+		return -1;
+	return 0;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+	EVP_CIPHER_CTX_free(ctx->ctx);
+	memset(ctx->key, 0, ctx->key_len);
+	memset(ctx->nonce, 0, sizeof(ctx->nonce));
+	return 0;
+}
+
+#else
+
+#define ARCHIVE_CRYPTOR_STUB
+/* Stub */
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+	(void)ctx; /* UNUSED */
+	(void)key; /* UNUSED */
+	(void)key_len; /* UNUSED */
+	return -1;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+	(void)ctx; /* UNUSED */
+	return -1;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+	(void)ctx; /* UNUSED */
+	return 0;
+}
+
+#endif
+
+#ifdef ARCHIVE_CRYPTOR_STUB
+static int
+aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
+    size_t in_len, uint8_t * const out, size_t *out_len)
+{
+	(void)ctx; /* UNUSED */
+	(void)in; /* UNUSED */
+	(void)in_len; /* UNUSED */
+	(void)out; /* UNUSED */
+	(void)out_len; /* UNUSED */
+	aes_ctr_encrypt_counter(ctx); /* UNUSED */ /* Fix unused function warning */
+	return -1;
+}
+
+#else
+static void
+aes_ctr_increase_counter(archive_crypto_ctx *ctx)
+{
+	uint8_t *const nonce = ctx->nonce;
+	int j;
+
+	for (j = 0; j < 8; j++) {
+		if (++nonce[j])
+			break;
+	}
+}
+
+static int
+aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
+    size_t in_len, uint8_t * const out, size_t *out_len)
+{
+	uint8_t *const ebuf = ctx->encr_buf;
+	unsigned pos = ctx->encr_pos;
+	unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len);
+	unsigned i;
+
+	for (i = 0; i < max; ) {
+		if (pos == AES_BLOCK_SIZE) {
+			aes_ctr_increase_counter(ctx);
+			if (aes_ctr_encrypt_counter(ctx) != 0)
+				return -1;
+			while (max -i >= AES_BLOCK_SIZE) {
+				for (pos = 0; pos < AES_BLOCK_SIZE; pos++)
+					out[i+pos] = in[i+pos] ^ ebuf[pos];
+				i += AES_BLOCK_SIZE;
+				aes_ctr_increase_counter(ctx);
+				if (aes_ctr_encrypt_counter(ctx) != 0)
+					return -1;
+			}
+			pos = 0;
+			if (i >= max)
+				break;
+		}
+		out[i] = in[i] ^ ebuf[pos++];
+		i++;
+	}
+	ctx->encr_pos = pos;
+	*out_len = i;
+
+	return 0;
+}
+#endif /* ARCHIVE_CRYPTOR_STUB */
+
+
+const struct archive_cryptor __archive_cryptor =
+{
+  &pbkdf2_sha1,
+  &aes_ctr_init,
+  &aes_ctr_update,
+  &aes_ctr_release,
+  &aes_ctr_init,
+  &aes_ctr_update,
+  &aes_ctr_release,
+};


Mime
View raw message