archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
    struct archive_entry *entry, int *fd)
{
	const char	*accpath;
	int		r;
#if ARCHIVE_ACL_LIBACL
	acl_t		acl;
#endif
#if ARCHIVE_ACL_LIBRICHACL
	struct richacl *richacl;
	mode_t		mode;
#endif

	accpath = NULL;
	r = ARCHIVE_OK;

	/* For default ACLs we need reachable accpath */
	if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) {
		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
		if (accpath == NULL)
			return (ARCHIVE_WARN);
	}

	archive_entry_acl_clear(entry);

#if ARCHIVE_ACL_LIBACL
	acl = NULL;
#endif
#if ARCHIVE_ACL_LIBRICHACL
	richacl = NULL;
#endif

#if ARCHIVE_ACL_LIBRICHACL
	/* Try NFSv4 ACL first. */
	if (*fd >= 0)
		richacl = richacl_get_fd(*fd);
	else if ((!a->follow_symlinks)
	    && (archive_entry_filetype(entry) == AE_IFLNK))
		/* We can't get the ACL of a symlink, so we assume it can't
		   have one */
		richacl = NULL;
	else
		richacl = richacl_get_file(accpath);

	/* Ignore "trivial" ACLs that just mirror the file mode. */
	if (richacl != NULL) {
		mode = archive_entry_mode(entry);
		if (richacl_equiv_mode(richacl, &mode) == 0) {
			richacl_free(richacl);
			richacl = NULL;
			return (ARCHIVE_OK);
		}
	}

	if (richacl != NULL) {
		r = translate_richacl(a, entry, richacl);
		richacl_free(richacl);
		richacl = NULL;

		if (r != ARCHIVE_OK) {
			archive_set_error(&a->archive, errno,
			"Couldn't translate NFSv4 ACLs");
		}

		return (r);
	}
#endif	/* ARCHIVE_ACL_LIBRICHACL */

#if ARCHIVE_ACL_LIBACL
	/* Retrieve access ACL from file. */
	if (*fd >= 0)
		acl = acl_get_fd(*fd);
	else if ((!a->follow_symlinks)
	    && (archive_entry_filetype(entry) == AE_IFLNK))
		/* We can't get the ACL of a symlink, so we assume it can't
		   have one. */
		acl = NULL;
	else
		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);

	if (acl != NULL) {
		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
		acl_free(acl);
		acl = NULL;

		if (r != ARCHIVE_OK) {
			archive_set_error(&a->archive, errno,
			    "Couldn't translate access ACLs");
			return (r);
		}
	}

	/* Only directories can have default ACLs. */
	if (S_ISDIR(archive_entry_mode(entry))) {
		acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
		if (acl != NULL) {
			r = translate_acl(a, entry, acl,
			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
			acl_free(acl);
			if (r != ARCHIVE_OK) {
				archive_set_error(&a->archive, errno,
				    "Couldn't translate default ACLs");
				return (r);
			}
		}
	}
#endif	/* ARCHIVE_ACL_LIBACL */
	return (r);
}
archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
    struct archive_entry *entry, int *fd)
{
	const char	*accpath;
	int		r;
#if ARCHIVE_ACL_LIBACL
	acl_t		acl;
#endif
#if ARCHIVE_ACL_LIBRICHACL
	struct richacl *richacl;
	mode_t		mode;
#endif

	accpath = NULL;
	r = ARCHIVE_OK;

	 
	if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) {
		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
		if (accpath == NULL)
			return (ARCHIVE_WARN);
	}

	archive_entry_acl_clear(entry);

#if ARCHIVE_ACL_LIBACL
	acl = NULL;
#endif
#if ARCHIVE_ACL_LIBRICHACL
	richacl = NULL;
#endif

#if ARCHIVE_ACL_LIBRICHACL
	 
	if (*fd >= 0)
		richacl = richacl_get_fd(*fd);
	else if ((!a->follow_symlinks)
	    && (archive_entry_filetype(entry) == AE_IFLNK))
		 
		richacl = NULL;
	else
		richacl = richacl_get_file(accpath);

	 
	if (richacl != NULL) {
		mode = archive_entry_mode(entry);
		if (richacl_equiv_mode(richacl, &mode) == 0) {
			richacl_free(richacl);
			richacl = NULL;
			return (ARCHIVE_OK);
		}
	}

	if (richacl != NULL) {
		r = translate_richacl(a, entry, richacl);
		richacl_free(richacl);
		richacl = NULL;

		if (r != ARCHIVE_OK) {
			archive_set_error(&a->archive, errno,
			"Couldn't translate NFSv4 ACLs");
		}

		return (r);
	}
#endif	 

#if ARCHIVE_ACL_LIBACL
	 
	if (*fd >= 0)
		acl = acl_get_fd(*fd);
	else if ((!a->follow_symlinks)
	    && (archive_entry_filetype(entry) == AE_IFLNK))
		 
		acl = NULL;
	else
		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);

	if (acl != NULL) {
		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
		acl_free(acl);
		acl = NULL;

		if (r != ARCHIVE_OK) {
			archive_set_error(&a->archive, errno,
			    "Couldn't translate access ACLs");
			return (r);
		}
	}

	 
	if (S_ISDIR(archive_entry_mode(entry))) {
		acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
		if (acl != NULL) {
			r = translate_acl(a, entry, acl,
			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
			acl_free(acl);
			if (r != ARCHIVE_OK) {
				archive_set_error(&a->archive, errno,
				    "Couldn't translate default ACLs");
				return (r);
			}
		}
	}
#endif	 
	return (r);
}