+
+ val = acl_to_text (acl, &len);
+ acl_free (acl);
+
+ if (!val)
+ {
+ call_arg_warn ("acl_to_text", file_name);
+ return;
+ }
+
+ *ret_ptr = xstrdup (val);
+ *ret_len = len;
+
+ acl_free (val);
+}
+
+/* "system.posix_acl_default" */
+static void
+xattrs__acls_get_d (int parentfd, char const *file_name,
+ struct tar_stat_info *st,
+ char **ret_ptr, size_t * ret_len)
+{
+ char *val = NULL;
+ ssize_t len;
+ acl_t acl;
+
+ if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_DEFAULT)))
+ {
+ if (errno != ENOTSUP)
+ call_arg_warn ("acl_get_file_at", file_name);
+ return;
+ }
+
+ val = acl_to_text (acl, &len);
+ acl_free (acl);
+
+ if (!val)
+ {
+ call_arg_warn ("acl_to_text", file_name);
+ return;
+ }
+
+ *ret_ptr = xstrdup (val);
+ *ret_len = len;
+
+ acl_free (val);
+}
+#endif /* HAVE_POSIX_ACLS */
+
+static void
+acls_one_line (const char *prefix, char delim,
+ const char *aclstring, size_t len)
+{
+ /* support both long and short text representation of posix acls */
+ struct obstack stk;
+ int pref_len = strlen (prefix);
+ const char *oldstring = aclstring;
+ int pos = 0;
+
+ if (!aclstring || !len)
+ return;
+
+ obstack_init (&stk);
+ while (pos <= len)
+ {
+ int move = strcspn (aclstring, ",\n");
+ if (!move)
+ break;
+
+ if (oldstring != aclstring)
+ obstack_1grow (&stk, delim);
+
+ obstack_grow (&stk, prefix, pref_len);
+ obstack_grow (&stk, aclstring, move);
+
+ aclstring += move + 1;
+ }
+
+ obstack_1grow (&stk, '\0');
+
+ fprintf (stdlis, "%s", (char *) obstack_finish (&stk));
+
+ obstack_free (&stk, NULL);
+}
+
+void
+xattrs_acls_get (int parentfd, char const *file_name,
+ struct tar_stat_info *st, int fd, int xisfile)
+{
+ if (acls_option > 0)
+ {
+#ifndef HAVE_POSIX_ACLS
+ static int done = 0;
+ if (!done)
+ WARN ((0, 0, _("POSIX ACL support is not available")));
+ done = 1;
+#else
+ int err = file_has_acl_at (parentfd, file_name, &st->stat);
+ if (err == 0)
+ return;
+ if (err == -1)
+ {
+ call_arg_warn ("file_has_acl_at", file_name);
+ return;
+ }
+
+ xattrs__acls_get_a (parentfd, file_name, st,
+ &st->acls_a_ptr, &st->acls_a_len);
+ if (!xisfile)
+ xattrs__acls_get_d (parentfd, file_name, st,
+ &st->acls_d_ptr, &st->acls_d_len);
+#endif
+ }
+}
+
+void
+xattrs_acls_set (struct tar_stat_info const *st,
+ char const *file_name, char typeflag)
+{
+ if (acls_option > 0 && typeflag != SYMTYPE)
+ {
+#ifndef HAVE_POSIX_ACLS
+ static int done = 0;
+ if (!done)
+ WARN ((0, 0, _("POSIX ACL support is not available")));
+ done = 1;
+#else
+ xattrs__acls_set (st, file_name, ACL_TYPE_ACCESS,
+ st->acls_a_ptr, st->acls_a_len, false);
+ if (typeflag == DIRTYPE || typeflag == GNUTYPE_DUMPDIR)
+ xattrs__acls_set (st, file_name, ACL_TYPE_DEFAULT,
+ st->acls_d_ptr, st->acls_d_len, true);
+#endif
+ }
+}
+
+static void
+mask_map_realloc (struct xattrs_mask_map *map)
+{
+ if (map->used == map->size)
+ {
+ if (map->size == 0)
+ map->size = 4;
+ map->masks = x2nrealloc (map->masks, &map->size, sizeof (map->masks[0]));
+ }