summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2015-03-10 14:38:06 +0200
committerTimo Teräs <timo.teras@iki.fi>2015-03-10 14:38:06 +0200
commitbe8e133c0b5ba0980d0debbf26b76a0b866689e7 (patch)
treee4c6a76148b78b139f6e3731b89fb73ae3a57b2a
parent255fd81d79c49f6e5dbdb0df371d8ec7de600917 (diff)
downloadapk-tools-be8e133c0b5ba0980d0debbf26b76a0b866689e7.tar.bz2
apk-tools-be8e133c0b5ba0980d0debbf26b76a0b866689e7.tar.xz
extract xattrs from packages
ref #3027
-rw-r--r--src/apk_io.h8
-rw-r--r--src/archive.c33
-rw-r--r--src/io.c5
3 files changed, 46 insertions, 0 deletions
diff --git a/src/apk_io.h b/src/apk_io.h
index 2e1c319..3e5e63f 100644
--- a/src/apk_io.h
+++ b/src/apk_io.h
@@ -27,6 +27,12 @@ struct apk_id_cache {
struct apk_hash gid_cache;
};
+struct apk_xattr {
+ const char *name;
+ apk_blob_t value;
+};
+APK_ARRAY(apk_xattr_array, struct apk_xattr);
+
struct apk_file_info {
char *name;
char *link_target;
@@ -39,6 +45,7 @@ struct apk_file_info {
time_t mtime;
dev_t device;
struct apk_checksum csum;
+ struct apk_xattr_array *xattrs;
};
struct apk_istream {
@@ -143,6 +150,7 @@ int apk_blob_to_file(int atfd, const char *file, apk_blob_t b, unsigned int flag
#define APK_FI_NOFOLLOW 0x80000000
int apk_file_get_info(int atfd, const char *filename, unsigned int flags,
struct apk_file_info *fi);
+void apk_file_info_free(struct apk_file_info *fi);
typedef int apk_dir_file_cb(void *ctx, int dirfd, const char *entry);
int apk_dir_foreach_file(int dirfd, apk_dir_file_cb cb, void *ctx);
diff --git a/src/archive.c b/src/archive.c
index 6a0774b..279ccb9 100644
--- a/src/archive.c
+++ b/src/archive.c
@@ -20,6 +20,7 @@
#include <sysexits.h>
#include <sys/wait.h>
#include <sys/stat.h>
+#include <sys/xattr.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
@@ -148,6 +149,12 @@ static void handle_extended_header(struct apk_file_info *fi, apk_blob_t hdr)
fi->name = value.ptr;
} else if (apk_blob_compare(name, APK_BLOB_STR("linkpath")) == 0) {
fi->link_target = value.ptr;
+ } else if (apk_blob_pull_blob_match(&name, APK_BLOB_STR("SCHILY.xattr."))) {
+ name.ptr[name.len] = 0;
+ *apk_xattr_array_add(&fi->xattrs) = (struct apk_xattr) {
+ .name = name.ptr,
+ .value = value,
+ };
} else if (apk_blob_pull_blob_match(&name, APK_BLOB_STR("APK-TOOLS.checksum."))) {
int type = APK_CHECKSUM_NONE;
if (apk_blob_compare(name, APK_BLOB_STR("SHA1")) == 0)
@@ -201,10 +208,12 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
.gname = buf.gname,
.device = makedev(GET_OCTAL(buf.devmajor),
GET_OCTAL(buf.devminor)),
+ .xattrs = entry.xattrs,
};
buf.mode[0] = 0; /* to nul terminate 100-byte buf.name */
buf.magic[0] = 0; /* to nul terminate 100-byte buf.linkname */
teis.csum = NULL;
+ apk_xattr_array_resize(&entry.xattrs, 0);
if (paxlen) handle_extended_header(&entry, APK_BLOB_PTR_LEN(pax.ptr, paxlen));
@@ -305,6 +314,7 @@ err:
EVP_MD_CTX_cleanup(&teis.mdctx);
free(pax.ptr);
free(longname.ptr);
+ apk_file_info_free(&entry);
return r;
err_nomem:
@@ -382,6 +392,7 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
const char *suffix, struct apk_istream *is,
apk_progress_cb cb, void *cb_ctx)
{
+ struct apk_xattr *xattr;
char *fn = ae->name;
int fd, r = -1, atflags = 0;
@@ -454,6 +465,28 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
}
}
+ /* extract xattrs */
+ if (ae->xattrs && ae->xattrs->num) {
+ r = 0;
+ fd = openat(atfd, fn, O_RDWR);
+ if (fd >= 0) {
+ foreach_array_item(xattr, ae->xattrs) {
+ if (fsetxattr(fd, xattr->name, xattr->value.ptr, xattr->value.len, 0) < 0) {
+ r = errno;
+ break;
+ }
+ }
+ close(fd);
+ } else {
+ r = errno;
+ }
+ if (r < 0) {
+ apk_error("Failed to set xattrs on %s: %s",
+ fn, strerror(r));
+ return -r;
+ }
+ }
+
if (!S_ISLNK(ae->mode)) {
/* preserve modification time */
struct timespec times[2];
diff --git a/src/io.c b/src/io.c
index 6821c54..84ecdb4 100644
--- a/src/io.c
+++ b/src/io.c
@@ -586,6 +586,11 @@ int apk_file_get_info(int atfd, const char *filename, unsigned int flags,
return 0;
}
+void apk_file_info_free(struct apk_file_info *fi)
+{
+ apk_xattr_array_free(&fi->xattrs);
+}
+
int apk_dir_foreach_file(int dirfd, apk_dir_file_cb cb, void *ctx)
{
struct dirent *de;