tar-util: several cleanups for ACL tag handling (#43684)
Prompted by 6df59b0753.
This commit is contained in:
+61
-58
@@ -206,6 +206,38 @@ static int open_inode_finalize_many(OpenInode **array, size_t *n) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
int libarchive;
|
||||
acl_tag_t libacl;
|
||||
} acl_tag_map[] = {
|
||||
{ ARCHIVE_ENTRY_ACL_USER, ACL_USER },
|
||||
{ ARCHIVE_ENTRY_ACL_GROUP, ACL_GROUP },
|
||||
{ ARCHIVE_ENTRY_ACL_USER_OBJ, ACL_USER_OBJ },
|
||||
{ ARCHIVE_ENTRY_ACL_GROUP_OBJ, ACL_GROUP_OBJ },
|
||||
{ ARCHIVE_ENTRY_ACL_MASK, ACL_MASK },
|
||||
{ ARCHIVE_ENTRY_ACL_OTHER, ACL_OTHER },
|
||||
};
|
||||
|
||||
static acl_tag_t libarchive_acl_tag_to_libacl_tag(int libarchive_tag) {
|
||||
FOREACH_ELEMENT(t, acl_tag_map)
|
||||
if (t->libarchive == libarchive_tag)
|
||||
return t->libacl;
|
||||
|
||||
return ACL_UNDEFINED_TAG;
|
||||
}
|
||||
|
||||
#if HAVE_ACL
|
||||
#define _ARCHIVE_ENTRY_ACL_UNDEFINED 0
|
||||
|
||||
static int libacl_tag_to_libarchive_acl_tag(acl_tag_t libacl_tag) {
|
||||
FOREACH_ELEMENT(t, acl_tag_map)
|
||||
if (t->libacl == libacl_tag)
|
||||
return t->libarchive;
|
||||
|
||||
return _ARCHIVE_ENTRY_ACL_UNDEFINED;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int archive_unpack_regular(
|
||||
struct archive *a,
|
||||
struct archive_entry *entry,
|
||||
@@ -541,24 +573,7 @@ static int archive_entry_read_acl(
|
||||
|
||||
assert(rtype == type);
|
||||
|
||||
static const struct {
|
||||
int libarchive;
|
||||
acl_tag_t libacl;
|
||||
} tag_map[] = {
|
||||
{ ARCHIVE_ENTRY_ACL_USER, ACL_USER },
|
||||
{ ARCHIVE_ENTRY_ACL_GROUP, ACL_GROUP },
|
||||
{ ARCHIVE_ENTRY_ACL_USER_OBJ, ACL_USER_OBJ },
|
||||
{ ARCHIVE_ENTRY_ACL_GROUP_OBJ, ACL_GROUP_OBJ },
|
||||
{ ARCHIVE_ENTRY_ACL_MASK, ACL_MASK },
|
||||
{ ARCHIVE_ENTRY_ACL_OTHER, ACL_OTHER },
|
||||
};
|
||||
|
||||
acl_tag_t ntag = ACL_UNDEFINED_TAG;
|
||||
FOREACH_ELEMENT(t, tag_map)
|
||||
if (t->libarchive == tag) {
|
||||
ntag = t->libacl;
|
||||
break;
|
||||
}
|
||||
acl_tag_t ntag = libarchive_acl_tag_to_libacl_tag(tag);
|
||||
if (ntag == ACL_UNDEFINED_TAG)
|
||||
continue;
|
||||
|
||||
@@ -1319,8 +1334,9 @@ static int archive_write_acl(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unexpected ACL type");
|
||||
|
||||
acl_entry_t e;
|
||||
r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &e);
|
||||
for (;;) {
|
||||
for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &e);
|
||||
;
|
||||
r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &e)) {
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry: %m");
|
||||
if (r == 0)
|
||||
@@ -1330,20 +1346,10 @@ static int archive_write_acl(
|
||||
if (sym_acl_get_tag_type(e, &ntag) < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry tag: %m");
|
||||
|
||||
static const int tag_map[] = {
|
||||
[ACL_USER] = ARCHIVE_ENTRY_ACL_USER,
|
||||
[ACL_GROUP] = ARCHIVE_ENTRY_ACL_GROUP,
|
||||
[ACL_USER_OBJ] = ARCHIVE_ENTRY_ACL_USER_OBJ,
|
||||
[ACL_GROUP_OBJ] = ARCHIVE_ENTRY_ACL_GROUP_OBJ,
|
||||
[ACL_MASK] = ARCHIVE_ENTRY_ACL_MASK,
|
||||
[ACL_OTHER] = ARCHIVE_ENTRY_ACL_OTHER,
|
||||
};
|
||||
assert_cc(ACL_UNDEFINED_TAG == 0); /* safety check, we assume that holes are filled with ACL_UNDEFINED_TAG */
|
||||
assert_cc(ELEMENTSOF(tag_map) <= 64); /* safety check, we assume that the tag ids are all packed and low */
|
||||
int tag = libacl_tag_to_libarchive_acl_tag(ntag);
|
||||
if (tag == _ARCHIVE_ENTRY_ACL_UNDEFINED)
|
||||
continue;
|
||||
|
||||
int tag = ntag >= 0 && ntag < (acl_tag_t) ELEMENTSOF(tag_map) ? tag_map[ntag] : ACL_UNDEFINED_TAG;
|
||||
|
||||
bool skip = false;
|
||||
id_t qualifier = UID_INVALID;
|
||||
if (IN_SET(ntag, ACL_USER, ACL_GROUP)) {
|
||||
id_t *q = sym_acl_get_qualifier(e);
|
||||
@@ -1354,37 +1360,34 @@ static int archive_write_acl(
|
||||
sym_acl_free(q);
|
||||
|
||||
/* Suppress invalid UIDs or those that shall be squashed */
|
||||
skip = !(uid_is_valid(qualifier) &&
|
||||
(!FLAGS_SET(flags, TAR_SQUASH_UIDS_ABOVE_64K) || qualifier < NSRESOURCE_UIDS_64K));
|
||||
if (!uid_is_valid(qualifier) ||
|
||||
(FLAGS_SET(flags, TAR_SQUASH_UIDS_ABOVE_64K) && qualifier >= NSRESOURCE_UIDS_64K))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
acl_permset_t p;
|
||||
if (sym_acl_get_permset(e, &p) < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry permission set: %m");
|
||||
acl_permset_t p;
|
||||
if (sym_acl_get_permset(e, &p) < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry permission set: %m");
|
||||
|
||||
int permset = 0;
|
||||
r = sym_acl_get_perm(p, ACL_READ);
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry read bit: %m");
|
||||
SET_FLAG(permset, ARCHIVE_ENTRY_ACL_READ, r);
|
||||
int permset = 0;
|
||||
r = sym_acl_get_perm(p, ACL_READ);
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry read bit: %m");
|
||||
SET_FLAG(permset, ARCHIVE_ENTRY_ACL_READ, r);
|
||||
|
||||
r = sym_acl_get_perm(p, ACL_WRITE);
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry write bit: %m");
|
||||
SET_FLAG(permset, ARCHIVE_ENTRY_ACL_WRITE, r);
|
||||
r = sym_acl_get_perm(p, ACL_WRITE);
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry write bit: %m");
|
||||
SET_FLAG(permset, ARCHIVE_ENTRY_ACL_WRITE, r);
|
||||
|
||||
r = sym_acl_get_perm(p, ACL_EXECUTE);
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry execute bit: %m");
|
||||
SET_FLAG(permset, ARCHIVE_ENTRY_ACL_EXECUTE, r);
|
||||
r = sym_acl_get_perm(p, ACL_EXECUTE);
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "Failed to get ACL entry execute bit: %m");
|
||||
SET_FLAG(permset, ARCHIVE_ENTRY_ACL_EXECUTE, r);
|
||||
|
||||
r = sym_archive_entry_acl_add_entry(entry, type, permset, tag, qualifier, /* name= */ NULL);
|
||||
if (r != ARCHIVE_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to add ACL entry.");
|
||||
}
|
||||
|
||||
r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &e);
|
||||
r = sym_archive_entry_acl_add_entry(entry, type, permset, tag, qualifier, /* name= */ NULL);
|
||||
if (r != ARCHIVE_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to add ACL entry.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user