return r;
}
+int pakfire_file_write_fcaps(struct pakfire_file* file, struct vfs_cap_data* cap_data) {
+ cap_flag_value_t cap_permitted;
+ cap_flag_value_t cap_inheritable;
+ cap_flag_value_t cap_effective;
+ int r;
+
+ // This should not be called when we have no caps
+ if (!file->caps) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ uint32_t magic = VFS_CAP_REVISION_2;
+
+ for (unsigned int cap = 0; cap_valid(cap); cap++) {
+ // Find the index where to find this cap
+ int index = CAP_TO_INDEX(cap);
+ int mask = CAP_TO_MASK(cap);
+
+ // Fetch CAP_PERMITTED
+ r = cap_get_flag(file->caps, cap, CAP_PERMITTED, &cap_permitted);
+ if (r) {
+ ERROR(file->pakfire, "Could not fetch capability %d: %m\n", cap);
+ goto ERROR;
+ }
+
+ // Fetch CAP_INHERITABLE
+ r = cap_get_flag(file->caps, cap, CAP_INHERITABLE, &cap_inheritable);
+ if (r) {
+ ERROR(file->pakfire, "Could not fetch capability %d: %m\n", cap);
+ goto ERROR;
+ }
+
+ // Fetch CAP_EFFECTIVE
+ r = cap_get_flag(file->caps, cap, CAP_EFFECTIVE, &cap_effective);
+ if (r) {
+ ERROR(file->pakfire, "Could not fetch capability %d: %m\n", cap);
+ goto ERROR;
+ }
+
+ // Store CAP_PERMITTED
+ if (cap_permitted)
+ cap_data->data[index].permitted |= htole32(mask);
+
+ // Store CAP_INHERITED
+ if (cap_inheritable)
+ cap_data->data[index].inheritable |= htole32(mask);
+
+ // Set EFFECTIVE flag if CAP_EFFECTIVE is set
+ if (cap_effective)
+ magic |= VFS_CAP_FLAGS_EFFECTIVE;
+ }
+
+ // Store the magic value
+ cap_data->magic_etc = htole32(magic);
+
+ERROR:
+ return r;
+}
+
static int pakfire_file_from_archive_entry(struct pakfire_file* file, struct archive_entry* entry) {
char* buffer = NULL;
const char* path = NULL;
}
struct archive_entry* pakfire_file_archive_entry(struct pakfire_file* file, int digest_types) {
+ struct vfs_cap_data cap_data = {};
const char* path = NULL;
int r;
archive_entry_xattr_add_entry(entry, "PAKFIRE.digests.sha2_256",
file->digests.sha2_256, sizeof(file->digests.sha2_256));
+ // Capabilities
+ if (file->caps) {
+ r = pakfire_file_write_fcaps(file, &cap_data);
+ if (r) {
+ ERROR(file->pakfire, "Could not export capabilities: %m\n");
+ goto ERROR;
+ }
+
+ // Store capabilities in archive entry
+ archive_entry_xattr_add_entry(entry,
+ "security.capability", &cap_data, sizeof(cap_data));
+ }
+
return entry;
ERROR:
return 0;
}
+PAKFIRE_EXPORT int pakfire_file_has_caps(struct pakfire_file* file) {
+ if (file->caps)
+ return 1;
+
+ return 0;
+}
+
+PAKFIRE_EXPORT char* pakfire_file_get_caps(struct pakfire_file* file) {
+ char* copy = NULL;
+ char* text = NULL;
+ ssize_t length = 0;
+
+ if (file->caps) {
+ text = cap_to_text(file->caps, &length);
+ if (!text) {
+ ERROR(file->pakfire, "Could not export capabilities: %m\n");
+ goto ERROR;
+ }
+
+ // libcap is being weird and uses its own allocator so we have to copy the string
+ copy = strndup(text, length);
+ if (!copy)
+ goto ERROR;
+ }
+
+ERROR:
+ if (text)
+ cap_free(text);
+
+ return copy;
+}
+
static int pakfire_file_levels(struct pakfire_file* file) {
if (!*file->path)
return 0;