diff options
author | Timo Teräs <timo.teras@iki.fi> | 2015-03-10 14:38:06 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2015-03-10 14:38:06 +0200 |
commit | be8e133c0b5ba0980d0debbf26b76a0b866689e7 (patch) | |
tree | e4c6a76148b78b139f6e3731b89fb73ae3a57b2a /src | |
parent | 255fd81d79c49f6e5dbdb0df371d8ec7de600917 (diff) | |
download | apk-tools-be8e133c0b5ba0980d0debbf26b76a0b866689e7.tar.gz apk-tools-be8e133c0b5ba0980d0debbf26b76a0b866689e7.tar.bz2 apk-tools-be8e133c0b5ba0980d0debbf26b76a0b866689e7.tar.xz apk-tools-be8e133c0b5ba0980d0debbf26b76a0b866689e7.zip |
extract xattrs from packages
ref #3027
Diffstat (limited to 'src')
-rw-r--r-- | src/apk_io.h | 8 | ||||
-rw-r--r-- | src/archive.c | 33 | ||||
-rw-r--r-- | src/io.c | 5 |
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]; @@ -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; |