diff options
-rw-r--r-- | src/apk_database.h | 1 | ||||
-rw-r--r-- | src/apk_io.h | 2 | ||||
-rw-r--r-- | src/archive.c | 5 | ||||
-rw-r--r-- | src/database.c | 26 | ||||
-rw-r--r-- | src/io.c | 36 |
5 files changed, 63 insertions, 7 deletions
diff --git a/src/apk_database.h b/src/apk_database.h index 880809b..b2fa28e 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -28,6 +28,7 @@ struct apk_db_acl { mode_t mode; uid_t uid; gid_t gid; + struct apk_checksum xattr_csum; }; struct apk_db_file { diff --git a/src/apk_io.h b/src/apk_io.h index 59a5d70..ee81851 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -45,6 +45,7 @@ struct apk_file_info { time_t mtime; dev_t device; struct apk_checksum csum; + struct apk_checksum xattr_csum; struct apk_xattr_array *xattrs; }; @@ -150,6 +151,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_fileinfo_get(int atfd, const char *filename, unsigned int flags, struct apk_file_info *fi); +void apk_fileinfo_hash_xattr(struct apk_file_info *fi); void apk_fileinfo_free(struct apk_file_info *fi); typedef int apk_dir_file_cb(void *ctx, int dirfd, const char *entry); diff --git a/src/archive.c b/src/archive.c index 47b798b..3062c43 100644 --- a/src/archive.c +++ b/src/archive.c @@ -215,7 +215,10 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser, teis.csum = NULL; apk_xattr_array_resize(&entry.xattrs, 0); - if (paxlen) handle_extended_header(&entry, APK_BLOB_PTR_LEN(pax.ptr, paxlen)); + if (paxlen) { + handle_extended_header(&entry, APK_BLOB_PTR_LEN(pax.ptr, paxlen)); + apk_fileinfo_hash_xattr(&entry); + } switch (buf.typeflag) { case 'L': /* GNU long name extension */ diff --git a/src/database.c b/src/database.c index bdf6d6b..8619465 100644 --- a/src/database.c +++ b/src/database.c @@ -220,10 +220,14 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name) return pn; } -static struct apk_db_acl *apk_db_acl_atomize(mode_t mode, uid_t uid, gid_t gid) +static struct apk_db_acl *apk_db_acl_atomize(mode_t mode, uid_t uid, gid_t gid, const struct apk_checksum *xattr_csum) { struct apk_db_acl acl = { .mode = mode & 07777, .uid = uid, .gid = gid }; apk_blob_t *b; + + if (xattr_csum && xattr_csum->type != APK_CHECKSUM_NONE) + acl.xattr_csum = *xattr_csum; + b = apk_blob_atomize_dup(APK_BLOB_STRUCT(acl)); return (struct apk_db_acl *) b->ptr; } @@ -740,6 +744,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) struct apk_db_acl *acl; struct hlist_node **diri_node = NULL; struct hlist_node **file_diri_node = NULL; + struct apk_checksum xattr_csum; apk_blob_t token = APK_BLOB_STR("\n"), l; mode_t mode; uid_t uid; @@ -814,7 +819,12 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) gid = apk_blob_pull_uint(&l, 10); apk_blob_pull_char(&l, ':'); mode = apk_blob_pull_uint(&l, 8); - acl = apk_db_acl_atomize(mode, uid, gid); + if (apk_blob_pull_blob_match(&l, APK_BLOB_STR(":"))) + apk_blob_pull_csum(&l, &xattr_csum); + else + xattr_csum.type = APK_CHECKSUM_NONE; + + acl = apk_db_acl_atomize(mode, uid, gid, &xattr_csum); if (field == 'M') apk_db_diri_set(diri, acl); else @@ -877,6 +887,10 @@ static void apk_blob_push_db_acl(apk_blob_t *b, char field, struct apk_db_acl *a apk_blob_push_uint(b, acl->gid, 10); apk_blob_push_blob(b, APK_BLOB_STR(":")); apk_blob_push_uint(b, acl->mode, 8); + if (acl->xattr_csum.type != APK_CHECKSUM_NONE) { + apk_blob_push_blob(b, APK_BLOB_STR(":")); + apk_blob_push_csum(b, &acl->xattr_csum); + } apk_blob_push_blob(b, APK_BLOB_STR("\n")); } @@ -1426,8 +1440,8 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_blob_t blob; int r, fd, write_arch = FALSE; - apk_default_acl_dir = apk_db_acl_atomize(0755, 0, 0); - apk_default_acl_file = apk_db_acl_atomize(0644, 0, 0); + apk_default_acl_dir = apk_db_acl_atomize(0755, 0, 0, NULL); + apk_default_acl_file = apk_db_acl_atomize(0644, 0, 0, NULL); memset(db, 0, sizeof(*db)); if (apk_flags & APK_SIMULATE) { @@ -2346,7 +2360,7 @@ static int apk_db_install_archive_entry(void *_ctx, apk_message("%s", ae->name); /* Extract the file as name.apk-new */ - file->acl = apk_db_acl_atomize(ae->mode, ae->uid, ae->gid); + file->acl = apk_db_acl_atomize(ae->mode, ae->uid, ae->gid, &ae->xattr_csum); r = apk_archive_entry_extract(db->root_fd, ae, ".apk-new", is, extract_cb, ctx); @@ -2388,7 +2402,7 @@ static int apk_db_install_archive_entry(void *_ctx, diri = apk_db_install_directory_entry(ctx, name); apk_db_dir_prepare(db, diri->dir, ae->mode); - apk_db_diri_set(diri, apk_db_acl_atomize(ae->mode, ae->uid, ae->gid)); + apk_db_diri_set(diri, apk_db_acl_atomize(ae->mode, ae->uid, ae->gid, &ae->xattr_csum)); } ctx->installed_size += ctx->current_file_size; @@ -12,6 +12,7 @@ #include <errno.h> #include <stdio.h> #include <fcntl.h> +#include <endian.h> #include <unistd.h> #include <malloc.h> #include <dirent.h> @@ -529,6 +530,41 @@ int apk_blob_to_file(int atfd, const char *file, apk_blob_t b, unsigned int flag return r; } +static int cmp_xattr(const void *p1, const void *p2) +{ + const struct apk_xattr *d1 = p1, *d2 = p2; + return strcmp(d1->name, d2->name); +} + +static void hash_len_data(EVP_MD_CTX *ctx, uint32_t len, const void *ptr) +{ + uint32_t belen = htobe32(len); + EVP_DigestUpdate(ctx, &belen, sizeof(belen)); + EVP_DigestUpdate(ctx, ptr, len); +} + +void apk_fileinfo_hash_xattr(struct apk_file_info *fi) +{ + struct apk_xattr *xattr; + const EVP_MD *md = apk_checksum_default(); + EVP_MD_CTX mdctx; + + if (!fi->xattrs || fi->xattrs->num == 0) { + fi->xattr_csum.type = APK_CHECKSUM_NONE; + return; + } + + qsort(fi->xattrs->item, fi->xattrs->num, sizeof(fi->xattrs->item[0]), cmp_xattr); + + EVP_DigestInit(&mdctx, md); + foreach_array_item(xattr, fi->xattrs) { + hash_len_data(&mdctx, strlen(xattr->name), xattr->name); + hash_len_data(&mdctx, xattr->value.len, xattr->value.ptr); + } + fi->xattr_csum.type = EVP_MD_CTX_size(&mdctx); + EVP_DigestFinal(&mdctx, fi->xattr_csum.data, NULL); +} + int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags, struct apk_file_info *fi) { |