From 981bc118f8bdf1df6c23c096a52c890a87ee3e5e Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Tue, 14 Jul 2009 19:14:05 +0300 Subject: [PATCH] db: live with sha1 and md5 this also convers scripts file to a tar archive. --- src/add.c | 3 +- src/apk.c | 2 - src/apk_archive.h | 3 +- src/apk_blob.h | 44 ++++++++++ src/apk_csum.h | 49 ----------- src/apk_database.h | 14 ++-- src/apk_io.h | 7 +- src/apk_package.h | 6 +- src/archive.c | 91 ++++++++++++++++++-- src/audit.c | 8 +- src/blob.c | 49 +++++++++++ src/cache.c | 23 ++--- src/database.c | 204 +++++++++++++++++++++++++++++++-------------- src/io.c | 14 ++-- src/package.c | 19 +++-- 15 files changed, 374 insertions(+), 162 deletions(-) delete mode 100644 src/apk_csum.h diff --git a/src/add.c b/src/add.c index b076706..180615c 100644 --- a/src/add.c +++ b/src/add.c @@ -103,7 +103,8 @@ static int add_main(void *ctx, int argc, char **argv) goto err; } virtpkg->name = apk_db_get_name(&db, APK_BLOB_STR(actx->virtpkg)); - csum_blob(APK_BLOB_STR(virtpkg->name->name), virtpkg->csum); + apk_blob_checksum(APK_BLOB_STR(virtpkg->name->name), + apk_default_checksum(), &virtpkg->csum); virtpkg->version = strdup("0"); virtpkg->description = strdup("virtual meta package"); virtdep = apk_dep_from_pkg(&db, virtpkg); diff --git a/src/apk.c b/src/apk.c index cd6cd91..ecbae72 100644 --- a/src/apk.c +++ b/src/apk.c @@ -23,9 +23,7 @@ #include "apk_defines.h" #include "apk_applet.h" #include "apk_blob.h" -#include "apk_csum.h" -csum_t bad_checksum = {0}; const char *apk_root; struct apk_repository_url apk_repository_list; int apk_verbosity = 1, apk_cwd_fd, apk_wait; diff --git a/src/apk_archive.h b/src/apk_archive.h index 4651255..d3b787d 100644 --- a/src/apk_archive.h +++ b/src/apk_archive.h @@ -4,7 +4,7 @@ * Copyright (C) 2008 Timo Teräs * All rights reserved. * - * This program is free software; you can redistribute it and/or modify it + * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. See http://www.gnu.org/ for details. */ @@ -22,6 +22,7 @@ typedef int (*apk_archive_entry_parser)(void *ctx, int apk_parse_tar(struct apk_istream *, apk_archive_entry_parser parser, void *ctx); int apk_parse_tar_gz(struct apk_bstream *, apk_archive_entry_parser parser, void *ctx); +int apk_write_tar_entry(struct apk_ostream *, const struct apk_file_info *ae, char *data); int apk_archive_entry_extract(const struct apk_file_info *ae, struct apk_istream *is, diff --git a/src/apk_blob.h b/src/apk_blob.h index 9ad79c4..170cf20 100644 --- a/src/apk_blob.h +++ b/src/apk_blob.h @@ -13,6 +13,8 @@ #define APK_BLOB_H #include +#include + #include "apk_defines.h" struct apk_blob { @@ -22,10 +24,38 @@ struct apk_blob { typedef struct apk_blob apk_blob_t; typedef int (*apk_blob_cb)(void *ctx, apk_blob_t blob); +#define APK_CHECKSUM_NONE 0 +#define APK_CHECKSUM_MD5 16 +#define APK_CHECKSUM_SHA1 20 + +/* Internal cointainer for MD5 or SHA1 */ +struct apk_checksum { + unsigned char data[20]; + unsigned char type; +}; + +static inline const EVP_MD *apk_default_checksum(void) +{ + return EVP_sha1(); +} + +static inline const EVP_MD *apk_get_digest(int type) +{ + switch (type) { + case APK_CHECKSUM_MD5: + return EVP_md5(); + case APK_CHECKSUM_SHA1: + return EVP_sha1(); + } + return EVP_md_null(); +} + #define APK_BLOB_IS_NULL(blob) ((blob).ptr == NULL) #define APK_BLOB_NULL ((apk_blob_t){0, NULL}) #define APK_BLOB_BUF(buf) ((apk_blob_t){sizeof(buf), (char *)(buf)}) +#define APK_BLOB_CSUM(csum) ((apk_blob_t){(csum).type, (char *)(csum).data}) +#define APK_BLOB_STRUCT(s) ((apk_blob_t){sizeof(s), (char*)&(s)}) #define APK_BLOB_PTR_LEN(beg,len) ((apk_blob_t){(len), (beg)}) #define APK_BLOB_PTR_PTR(beg,end) APK_BLOB_PTR_LEN((beg),(end)-(beg)+1) @@ -47,12 +77,26 @@ int apk_blob_compare(apk_blob_t a, apk_blob_t b); int apk_blob_for_each_segment(apk_blob_t blob, const char *split, apk_blob_cb cb, void *ctx); +static inline void apk_blob_checksum(apk_blob_t b, const EVP_MD *md, struct apk_checksum *csum) +{ + csum->type = EVP_MD_size(md); + EVP_Digest(b.ptr, b.len, csum->data, NULL, md, NULL); +} +static inline const int apk_checksum_compare(const struct apk_checksum *a, + const struct apk_checksum *b) +{ + return apk_blob_compare(APK_BLOB_PTR_LEN((char *) a->data, a->type), + APK_BLOB_PTR_LEN((char *) b->data, b->type)); +} + void apk_blob_push_blob(apk_blob_t *to, apk_blob_t literal); void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix); +void apk_blob_push_csum(apk_blob_t *to, struct apk_checksum *csum); void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary); void apk_blob_pull_char(apk_blob_t *b, int expected); unsigned int apk_blob_pull_uint(apk_blob_t *b, int radix); +void apk_blob_pull_csum(apk_blob_t *b, struct apk_checksum *csum); void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to); #endif diff --git a/src/apk_csum.h b/src/apk_csum.h deleted file mode 100644 index f2335d3..0000000 --- a/src/apk_csum.h +++ /dev/null @@ -1,49 +0,0 @@ -/* apk_csum.c - Alpine Package Keeper (APK) - * - * Copyright (C) 2009 Timo Teräs - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. See http://www.gnu.org/ for details. - */ - -#ifndef APK_CSUM_H -#define APK_CSUM_H - -#include - -#define MAX_CSUM_SIZE 16 /* MD5 */ - -typedef unsigned char *csum_p; -typedef unsigned char csum_t[MAX_CSUM_SIZE]; -typedef EVP_MD_CTX csum_ctx_t; - -extern csum_t bad_checksum; - -static inline void csum_init(csum_ctx_t *ctx) -{ - EVP_DigestInit(ctx, EVP_md5()); -} - -static inline void csum_process(csum_ctx_t *ctx, unsigned char *buf, size_t len) -{ - EVP_DigestUpdate(ctx, buf, len); -} - -static inline void csum_finish(csum_ctx_t *ctx, csum_p csum) -{ - EVP_DigestFinal(ctx, csum, NULL); -} - -static inline int csum_valid(csum_p csum) -{ - return memcmp(csum, bad_checksum, MAX_CSUM_SIZE); -} - -static inline void csum_blob(apk_blob_t blob, csum_p csum) -{ - EVP_Digest(blob.ptr, blob.len, csum, NULL, EVP_md5(), NULL); -} - -#endif diff --git a/src/apk_database.h b/src/apk_database.h index 4235c56..b4c3f04 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -17,7 +17,8 @@ #include "apk_archive.h" #include "apk_package.h" -#define APK_MAX_REPOS 32 +#define APK_MAX_REPOS 32 +#define APK_CACHE_CSUM_BYTES 4 extern const char * const apk_index_gz; @@ -29,8 +30,8 @@ struct apk_db_file { struct hlist_node diri_files_list; struct apk_db_dir_instance *diri; - csum_t csum; unsigned short namelen; + struct apk_checksum csum; char name[]; }; @@ -73,7 +74,7 @@ struct apk_name { struct apk_repository { char *url; - csum_t url_csum; + struct apk_checksum csum; }; struct apk_database { @@ -135,7 +136,7 @@ int apk_db_cache_active(struct apk_database *db); struct apk_package *apk_db_pkg_add_file(struct apk_database *db, const char *file); struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg); -struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum); +struct apk_package *apk_db_get_pkg(struct apk_database *db, struct apk_checksum *csum); struct apk_package *apk_db_get_file_owner(struct apk_database *db, apk_blob_t filename); int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo); @@ -143,9 +144,10 @@ int apk_db_index_write(struct apk_database *db, struct apk_ostream *os); int apk_db_add_repository(apk_database_t db, apk_blob_t repository); int apk_repository_update(struct apk_database *db, struct apk_repository *repo); -int apk_cache_download(struct apk_database *db, csum_t csum, +int apk_cache_download(struct apk_database *db, struct apk_checksum *csum, const char *url, const char *item); -int apk_cache_exists(struct apk_database *db, csum_t csum, const char *item); +int apk_cache_exists(struct apk_database *db, struct apk_checksum *csum, + const char *item); int apk_db_install_pkg(struct apk_database *db, struct apk_package *oldpkg, diff --git a/src/apk_io.h b/src/apk_io.h index 0ebf467..1fe4f2c 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -11,9 +11,10 @@ #ifndef APK_IO #define APK_IO +#include + #include "apk_defines.h" #include "apk_blob.h" -#include "apk_csum.h" struct apk_file_info { char *name; @@ -26,7 +27,7 @@ struct apk_file_info { mode_t mode; time_t mtime; dev_t device; - csum_t csum; + struct apk_checksum csum; }; struct apk_istream { @@ -83,7 +84,7 @@ size_t apk_ostream_write_string(struct apk_ostream *ostream, const char *string) apk_blob_t apk_blob_from_istream(struct apk_istream *istream, size_t size); apk_blob_t apk_blob_from_file(const char *file); -int apk_file_get_info(const char *filename, struct apk_file_info *fi); +int apk_file_get_info(const char *filename, int checksum, struct apk_file_info *fi); int apk_url_download(const char *url, const char *file); const char *apk_url_local_file(const char *url); diff --git a/src/apk_package.h b/src/apk_package.h index a6e4784..bec495b 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -4,7 +4,7 @@ * Copyright (C) 2008 Timo Teräs * All rights reserved. * - * This program is free software; you can redistribute it and/or modify it + * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. See http://www.gnu.org/ for details. */ @@ -52,7 +52,6 @@ APK_ARRAY(apk_dependency_array, struct apk_dependency); struct apk_package { apk_hash_node hash_node; - csum_t csum; unsigned repos; struct apk_name *name; char *version; @@ -60,6 +59,7 @@ struct apk_package { struct apk_dependency_array *depends; size_t installed_size, size; char *filename; + struct apk_checksum csum; /* for installed packages only */ struct list_head installed_pkgs_list; @@ -68,6 +68,8 @@ struct apk_package { }; APK_ARRAY(apk_package_array, struct apk_package *); +extern const char *apk_script_types[]; + int apk_deps_add(struct apk_dependency_array **depends, struct apk_dependency *dep); void apk_deps_del(struct apk_dependency_array **deps, diff --git a/src/archive.c b/src/archive.c index 450c956..0a53792 100644 --- a/src/archive.c +++ b/src/archive.c @@ -44,19 +44,34 @@ struct tar_header { char padding[12]; /* 500-512 */ }; -#define GET_OCTAL(s) get_octal(s, sizeof(s)) +#define GET_OCTAL(s) get_octal(s, sizeof(s)) +#define PUT_OCTAL(s,v) put_octal(s, sizeof(s), v) + static int get_octal(char *s, size_t l) { apk_blob_t b = APK_BLOB_PTR_LEN(s, l); return apk_blob_pull_uint(&b, 8); } +static void put_octal(char *s, size_t l, size_t value) +{ + char *ptr = &s[l - 1]; + + *(ptr--) = '\0'; + while (value != 0 && ptr >= s) { + *(ptr--) = '0' + (value % 8); + value /= 8; + } + while (ptr >= s) + *(ptr--) = '0'; +} + struct apk_tar_entry_istream { struct apk_istream is; struct apk_istream *tar_is; size_t bytes_left; - csum_ctx_t csum_ctx; - csum_p csum; + EVP_MD_CTX mdctx; + struct apk_checksum *csum; }; static size_t tar_entry_read(void *stream, void *ptr, size_t size) @@ -69,9 +84,11 @@ static size_t tar_entry_read(void *stream, void *ptr, size_t size) size = teis->tar_is->read(teis->tar_is, ptr, size); if (size > 0) { teis->bytes_left -= size; - csum_process(&teis->csum_ctx, ptr, size); - if (teis->bytes_left == 0) - csum_finish(&teis->csum_ctx, teis->csum); + EVP_DigestUpdate(&teis->mdctx, ptr, size); + if (teis->bytes_left == 0) { + teis->csum->type = EVP_MD_CTX_size(&teis->mdctx); + EVP_DigestFinal_ex(&teis->mdctx, teis->csum->data, NULL); + } } return size; } @@ -83,13 +100,14 @@ int apk_parse_tar(struct apk_istream *is, apk_archive_entry_parser parser, struct apk_tar_entry_istream teis = { .is.read = tar_entry_read, .tar_is = is, - .csum = entry.csum, + .csum = &entry.csum, }; struct tar_header buf; unsigned long offset = 0; int end = 0, r; size_t toskip; + EVP_MD_CTX_init(&teis.mdctx); memset(&entry, 0, sizeof(entry)); while ((r = is->read(is, &buf, 512)) == 512) { offset += 512; @@ -156,11 +174,11 @@ int apk_parse_tar(struct apk_istream *is, apk_archive_entry_parser parser, entry.name = strdup(buf.name); /* callback parser function */ - csum_init(&teis.csum_ctx); + EVP_DigestInit_ex(&teis.mdctx, apk_default_checksum(), NULL); r = parser(ctx, &entry, &teis.is); free(entry.name); if (r != 0) - return r; + goto err; entry.name = NULL; } @@ -173,12 +191,67 @@ int apk_parse_tar(struct apk_istream *is, apk_archive_entry_parser parser, if (toskip != 0) is->read(is, NULL, toskip); } + EVP_MD_CTX_cleanup(&teis.mdctx); if (r != 0) { apk_error("Bad TAR header (r=%d)", r); return -1; } + return 0; + +err: + EVP_MD_CTX_cleanup(&teis.mdctx); + return r; +} + +int apk_write_tar_entry(struct apk_ostream *os, const struct apk_file_info *ae, char *data) +{ + static char padding[512]; + struct tar_header buf; + int pad; + + memset(&buf, 0, sizeof(buf)); + if (ae != NULL) { + const unsigned char *src; + int chksum, i; + + if (S_ISREG(ae->mode)) + buf.typeflag = '0'; + else + return -1; + + strncpy(buf.name, ae->name, sizeof(buf.name)); + strncpy(buf.uname, ae->uname, sizeof(buf.uname)); + strncpy(buf.gname, ae->gname, sizeof(buf.gname)); + + PUT_OCTAL(buf.size, ae->size); + PUT_OCTAL(buf.uid, ae->uid); + PUT_OCTAL(buf.gid, ae->gid); + PUT_OCTAL(buf.mode, ae->mode & 07777); + PUT_OCTAL(buf.mtime, ae->mtime); + + /* Checksum */ + strcpy(buf.magic, "ustar "); + memset(buf.chksum, ' ', sizeof(buf.chksum)); + src = (const unsigned char *) &buf; + for (i = chksum = 0; i < sizeof(buf); i++) + chksum += src[i]; + put_octal(buf.chksum, sizeof(buf.chksum)-1, chksum); + } + + if (os->write(os, &buf, sizeof(buf)) != sizeof(buf)) + return -1; + + if (data != NULL) { + if (os->write(os, data, ae->size) != ae->size) + return -1; + pad = 512 - (ae->size & 511); + if (pad != 512 && + os->write(os, padding, pad) != pad) + return -1; + } + return 0; } diff --git a/src/audit.c b/src/audit.c index 7a34f15..2c5a17a 100644 --- a/src/audit.c +++ b/src/audit.c @@ -46,7 +46,7 @@ static int audit_directory(apk_hash_item item, void *ctx) snprintf(tmp, sizeof(tmp), "%s/%s", dbd->name, de->d_name); - if (apk_file_get_info(tmp, &fi) < 0) + if (apk_file_get_info(tmp, APK_CHECKSUM_NONE, &fi) < 0) continue; if (S_ISDIR(fi.mode)) { @@ -57,8 +57,10 @@ static int audit_directory(apk_hash_item item, void *ctx) } else { dbf = apk_db_file_query(db, bdir, APK_BLOB_STR(de->d_name)); if (dbf != NULL) { - if (apk_blob_compare(APK_BLOB_BUF(fi.csum), - APK_BLOB_BUF(dbf->csum)) == 0) + if (apk_file_get_info(tmp, dbf->csum.type, &fi) < 0) + continue; + + if (apk_checksum_compare(&fi.csum, &dbf->csum) == 0) continue; reason = 'U'; diff --git a/src/blob.c b/src/blob.c index 73d39ec..ed7f418 100644 --- a/src/blob.c +++ b/src/blob.c @@ -186,6 +186,30 @@ void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix) apk_blob_push_blob(to, APK_BLOB_PTR_PTR(ptr+1, &buf[sizeof(buf)-1])); } +static int checksum_char_to_id(char chr) +{ + switch (chr) { + case '1': return APK_CHECKSUM_SHA1; + } + return APK_CHECKSUM_NONE; +} + +void apk_blob_push_csum(apk_blob_t *to, struct apk_checksum *csum) +{ + switch (csum->type) { + case APK_CHECKSUM_MD5: + apk_blob_push_hexdump(to, APK_BLOB_CSUM(*csum)); + break; + case APK_CHECKSUM_SHA1: + apk_blob_push_blob(to, APK_BLOB_STR("X1")); + apk_blob_push_hexdump(to, APK_BLOB_CSUM(*csum)); + break; + default: + *to = APK_BLOB_NULL; + break; + } +} + void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary) { char *d; @@ -239,6 +263,31 @@ unsigned int apk_blob_pull_uint(apk_blob_t *b, int radix) return val; } +void apk_blob_pull_csum(apk_blob_t *b, struct apk_checksum *csum) +{ + if (unlikely(APK_BLOB_IS_NULL(*b))) + return; + + if (unlikely(b->len < 2)) { + *b = APK_BLOB_NULL; + return; + } + + switch (b->ptr[0]) { + case 'X': + csum->type = checksum_char_to_id(b->ptr[1]); + b->ptr += 2; + b->len -= 2; + apk_blob_pull_hexdump(b, APK_BLOB_CSUM(*csum)); + break; + default: + /* Assume MD5 for backwards compatibility */ + csum->type = APK_CHECKSUM_MD5; + apk_blob_pull_hexdump(b, APK_BLOB_CSUM(*csum)); + break; + } +} + void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to) { char *s, *d; diff --git a/src/cache.c b/src/cache.c index 423af72..a5643c4 100644 --- a/src/cache.c +++ b/src/cache.c @@ -46,13 +46,13 @@ static int cache_download(struct apk_database *db) pkg = change->newpkg; snprintf(pkgfile, sizeof(pkgfile), "%s-%s.apk", pkg->name->name, pkg->version); - if (apk_cache_exists(db, pkg->csum, pkgfile)) + if (apk_cache_exists(db, &pkg->csum, pkgfile)) continue; for (i = 0; i < db->num_repos; i++) { if (!(pkg->repos & BIT(i))) continue; - r = apk_cache_download(db, pkg->csum, db->repos[i].url, + r = apk_cache_download(db, &pkg->csum, db->repos[i].url, pkgfile); if (r != 0) return r; @@ -68,11 +68,9 @@ static int cache_clean(struct apk_database *db) { DIR *dir; struct dirent *de; - struct apk_package *pkg; - char path[256]; + char path[256], csum[APK_CACHE_CSUM_BYTES]; int delete, i; apk_blob_t b; - csum_t csum; snprintf(path, sizeof(path), "%s/%s", db->root, db->cache_dir); if (chdir(path) != 0) @@ -87,24 +85,25 @@ static int cache_clean(struct apk_database *db) continue; delete = TRUE; do { - if (strlen(de->d_name) <= sizeof(csum_t)*2+2) + if (strlen(de->d_name) <= APK_CACHE_CSUM_BYTES*2+2) break; - b = APK_BLOB_PTR_LEN(de->d_name, sizeof(csum_t) * 2); + b = APK_BLOB_PTR_LEN(de->d_name, APK_CACHE_CSUM_BYTES*2); apk_blob_pull_hexdump(&b, APK_BLOB_BUF(csum)); if (APK_BLOB_IS_NULL(b)) break; - if (de->d_name[sizeof(csum_t)*2] != '.') + if (de->d_name[APK_CACHE_CSUM_BYTES*2] != '.') break; - if (strcmp(&de->d_name[sizeof(csum_t)*2+1], + if (strcmp(&de->d_name[APK_CACHE_CSUM_BYTES*2+1], apk_index_gz) == 0) { /* Index - check for matching repository */ for (i = 0; i < db->num_repos; i++) - if (memcmp(db->repos[i].url_csum, - csum, sizeof(csum_t)) == 0) + if (memcmp(db->repos[i].csum.data, + csum, APK_CACHE_CSUM_BYTES) == 0) break; delete = (i >= db->num_repos); } else { /* Package - search for it */ +#if 0 pkg = apk_db_get_pkg(db, csum); if (pkg == NULL) break; @@ -113,6 +112,8 @@ static int cache_clean(struct apk_database *db) pkg->name->name, pkg->version); delete = strcmp(&de->d_name[sizeof(csum_t)*2+1], path); +#endif +//#warning FIXME - need to check if cache file is valid - look up using name, check csum } } while (0); diff --git a/src/database.c b/src/database.c index de03385..c80e9a9 100644 --- a/src/database.c +++ b/src/database.c @@ -36,7 +36,7 @@ struct install_ctx { int script; struct apk_db_dir_instance *diri; - csum_t data_csum; + struct apk_checksum data_csum; apk_progress_cb cb; void *cb_ctx; @@ -69,7 +69,7 @@ static const struct apk_hash_ops pkg_name_hash_ops = { static apk_blob_t pkg_info_get_key(apk_hash_item item) { - return APK_BLOB_BUF(((struct apk_package *) item)->csum); + return APK_BLOB_CSUM(((struct apk_package *) item)->csum); } static unsigned long csum_hash(apk_blob_t csum) @@ -372,7 +372,7 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package * { struct apk_package *idb; - idb = apk_hash_get(&db->available.packages, APK_BLOB_BUF(pkg->csum)); + idb = apk_hash_get(&db->available.packages, APK_BLOB_CSUM(pkg->csum)); if (idb == NULL) { idb = pkg; apk_hash_insert(&db->available.packages, pkg); @@ -473,8 +473,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) apk_error("FDB checksum entry before file entry"); return -1; } - - apk_blob_pull_hexdump(&l, APK_BLOB_BUF(file->csum)); + apk_blob_pull_csum(&l, &file->csum); break; default: apk_error("FDB entry '%c' unsupported", field); @@ -518,9 +517,9 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) hlist_for_each_entry(file, c2, &diri->owned_files, diri_files_list) { apk_blob_push_blob(&bbuf, APK_BLOB_STR("R:")); apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(file->name, file->namelen)); - if (csum_valid(file->csum)) { + if (file->csum.type != APK_CHECKSUM_NONE) { apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nZ:")); - apk_blob_push_hexdump(&bbuf, APK_BLOB_BUF(file->csum)); + apk_blob_push_csum(&bbuf, &file->csum); } apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); @@ -538,46 +537,114 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) return 0; } -struct apk_script_header { - csum_t csum; - unsigned int type; - unsigned int size; -}; - static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os) { struct apk_package *pkg; struct apk_script *script; - struct apk_script_header hdr; struct hlist_node *c2; + struct apk_file_info fi; + char filename[256]; + apk_blob_t bfn; + int r, i; list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) { hlist_for_each_entry(script, c2, &pkg->scripts, script_list) { - memcpy(hdr.csum, pkg->csum, sizeof(csum_t)); - hdr.type = script->type; - hdr.size = script->size; + fi = (struct apk_file_info) { + .name = filename, + .uname = "root", + .gname = "root", + .size = script->size, + .uid = 0, + .gid = 0, + .mode = 0755 | S_IFREG, + .mtime = time(NULL), + }; + /* The scripts db expects file names in format: + * pkg-version..action */ + bfn = APK_BLOB_BUF(filename); + apk_blob_push_blob(&bfn, APK_BLOB_STR(pkg->name->name)); + apk_blob_push_blob(&bfn, APK_BLOB_STR("-")); + apk_blob_push_blob(&bfn, APK_BLOB_STR(pkg->version)); + apk_blob_push_blob(&bfn, APK_BLOB_STR(".")); + apk_blob_push_csum(&bfn, &pkg->csum); + apk_blob_push_blob(&bfn, APK_BLOB_STR(".")); + apk_blob_push_blob(&bfn, APK_BLOB_STR(apk_script_types[script->type])); + apk_blob_push_blob(&bfn, APK_BLOB_PTR_LEN("", 1)); - if (os->write(os, &hdr, sizeof(hdr)) != sizeof(hdr)) - return -1; - - if (os->write(os, script->script, script->size) != script->size) - return -1; + r = apk_write_tar_entry(os, &fi, script->script); + if (r < 0) + return r; } } + for (i = 0; i < 2; i++) { + r = apk_write_tar_entry(os, NULL, NULL); + if (r < 0) + return r; + } + return 0; +} + +static int apk_db_scriptdb_read_v1(struct apk_database *db, struct apk_istream *is) +{ + struct apk_package *pkg; + struct { + unsigned char md5sum[16]; + unsigned int type; + unsigned int size; + } hdr; + struct apk_checksum csum; + + while (is->read(is, &hdr, sizeof(hdr)) == sizeof(hdr)) { + memcpy(csum.data, hdr.md5sum, sizeof(hdr.md5sum)); + csum.type = APK_CHECKSUM_MD5; + + pkg = apk_db_get_pkg(db, &csum); + if (pkg != NULL) + apk_pkg_add_script(pkg, is, hdr.type, hdr.size); + else + apk_istream_skip(is, hdr.size); + } + return 0; } -static int apk_db_scriptdb_read(struct apk_database *db, struct apk_istream *is) +static int apk_read_script_archive_entry(void *ctx, + const struct apk_file_info *ae, + struct apk_istream *is) { + struct apk_database *db = (struct apk_database *) ctx; struct apk_package *pkg; - struct apk_script_header hdr; + char *fncsum, *fnaction; + struct apk_checksum csum; + apk_blob_t blob; + int type; - while (is->read(is, &hdr, sizeof(hdr)) == sizeof(hdr)) { - pkg = apk_db_get_pkg(db, hdr.csum); - if (pkg != NULL) - apk_pkg_add_script(pkg, is, hdr.type, hdr.size); - } + if (!S_ISREG(ae->mode)) + return 0; + + /* The scripts db expects file names in format: + * pkgname-version..action */ + fnaction = memrchr(ae->name, '.', strlen(ae->name)); + if (fnaction == NULL || fnaction == ae->name) + return 0; + fncsum = memrchr(ae->name, '.', fnaction - ae->name - 1); + if (fncsum == NULL) + return 0; + fnaction++; + fncsum++; + + /* Parse it */ + type = apk_script_type(fnaction); + if (type == APK_SCRIPT_INVALID) + return 0; + blob = APK_BLOB_PTR_PTR(fncsum, fnaction - 2); + apk_blob_pull_csum(&blob, &csum); + + /* Attach script */ + pkg = apk_db_get_pkg(db, &csum); + if (pkg != NULL) + apk_pkg_add_script(pkg, is, type, ae->size); return 0; } @@ -619,11 +686,16 @@ static int apk_db_read_state(struct apk_database *db, int flags) } if (!(flags & APK_OPENF_NO_SCRIPTS)) { - is = apk_istream_from_file("var/lib/apk/scripts"); + is = apk_istream_from_file("var/lib/apk/scripts.tar"); if (is != NULL) { - apk_db_scriptdb_read(db, is); - is->close(is); + apk_parse_tar(is, apk_read_script_archive_entry, db); + } else { + is = apk_istream_from_file("var/lib/apk/scripts"); + if (is != NULL) + apk_db_scriptdb_read_v1(db, is); } + if (is != NULL) + is->close(is); } return 0; @@ -817,11 +889,15 @@ int apk_db_write_config(struct apk_database *db) if (rename("var/lib/apk/installed.new", "var/lib/apk/installed") < 0) return -errno; - os = apk_ostream_to_file("var/lib/apk/scripts", 0644); + os = apk_ostream_to_file("var/lib/apk/scripts.tar.new", 0644); if (os == NULL) return -1; apk_db_scriptdb_write(db, os); os->close(os); + if (rename("var/lib/apk/scripts.tar.new", "var/lib/apk/scripts.tar") < 0) + return -errno; + + unlink("var/lib/apk/scripts"); return 0; } @@ -868,10 +944,10 @@ int apk_db_cache_active(struct apk_database *db) return db->cache_dir != apk_static_cache_dir; } -struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum) +struct apk_package *apk_db_get_pkg(struct apk_database *db, + struct apk_checksum *csum) { - return apk_hash_get(&db->available.packages, - APK_BLOB_PTR_LEN((void*) sum, sizeof(csum_t))); + return apk_hash_get(&db->available.packages, APK_BLOB_CSUM(*csum)); } struct apk_package *apk_db_get_file_owner(struct apk_database *db, @@ -939,22 +1015,24 @@ int apk_db_index_write(struct apk_database *db, struct apk_ostream *os) } static void apk_db_cache_get_name(char *buf, size_t bufsz, - struct apk_database *db, csum_t csum, + struct apk_database *db, + struct apk_checksum *csum, const char *file, int temp) { - char csumstr[sizeof(csum_t)*2+1]; + char csumstr[APK_CACHE_CSUM_BYTES*2+1]; apk_blob_t bbuf = APK_BLOB_BUF(csumstr); apk_blob_push_hexdump(&bbuf, - APK_BLOB_PTR_LEN((void *)csum, sizeof(csum_t))); - apk_blob_push_blob(&bbuf, APK_BLOB_STR("")); + APK_BLOB_PTR_LEN((char *) csum->data, APK_CACHE_CSUM_BYTES)); + apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN("", 1)); snprintf(buf, bufsz, "%s/%s/%s.%s%s", db->root, db->cache_dir, csumstr, file, temp ? ".new" : ""); } static struct apk_bstream *apk_db_cache_open(struct apk_database *db, - csum_t csum, const char *file) + struct apk_checksum *csum, + const char *file) { char tmp[256]; @@ -975,7 +1053,7 @@ static struct apk_bstream *apk_repository_file_open(struct apk_repository *repo, return apk_bstream_from_url(tmp); } -int apk_cache_download(struct apk_database *db, csum_t csum, +int apk_cache_download(struct apk_database *db, struct apk_checksum *csum, const char *url, const char *item) { char tmp[256], tmp2[256]; @@ -999,7 +1077,8 @@ int apk_cache_download(struct apk_database *db, csum_t csum, return 0; } -int apk_cache_exists(struct apk_database *db, csum_t csum, const char *item) +int apk_cache_exists(struct apk_database *db, struct apk_checksum *csum, + const char *item) { char tmp[256]; @@ -1012,10 +1091,10 @@ int apk_cache_exists(struct apk_database *db, csum_t csum, const char *item) int apk_repository_update(struct apk_database *db, struct apk_repository *repo) { - if (!csum_valid(repo->url_csum)) + if (repo->csum.type == APK_CHECKSUM_NONE) return 0; - return apk_cache_download(db, repo->url_csum, repo->url, apk_index_gz); + return apk_cache_download(db, &repo->csum, repo->url, apk_index_gz); } int apk_db_add_repository(apk_database_t _db, apk_blob_t repository) @@ -1040,19 +1119,18 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t repository) }; if (apk_url_local_file(repo->url) == NULL) { - csum_blob(repository, repo->url_csum); + apk_blob_checksum(repository, apk_default_checksum(), &repo->csum); if (apk_flags & APK_UPDATE_CACHE) n = apk_repository_update(db, repo); - bs = apk_db_cache_open(db, repo->url_csum, apk_index_gz); + bs = apk_db_cache_open(db, &repo->csum, apk_index_gz); if (bs == NULL) { if (n == 1) n = apk_repository_update(db, repo); if (n < 0) return n; - bs = apk_db_cache_open(db, repo->url_csum, - apk_index_gz); + bs = apk_db_cache_open(db, &repo->csum, apk_index_gz); } } else { bs = apk_repository_file_open(repo, apk_index_gz); @@ -1203,9 +1281,8 @@ static int apk_db_install_archive_entry(void *_ctx, printf("%s\n", ae->name); if ((diri->dir->flags & APK_DBDIRF_PROTECTED) && - apk_file_get_info(ae->name, &fi) == 0 && - (memcmp(file->csum, fi.csum, sizeof(csum_t)) != 0 || - !csum_valid(file->csum))) { + apk_file_get_info(ae->name, file->csum.type, &fi) == 0 && + apk_checksum_compare(&file->csum, &fi.csum) != 0) { /* Protected file. Extract to separate place */ if (!(apk_flags & APK_CLEAN_PROTECTED)) { snprintf(alt_name, sizeof(alt_name), @@ -1213,15 +1290,18 @@ static int apk_db_install_archive_entry(void *_ctx, diri->dir->name, file->name); r = apk_archive_entry_extract(ae, is, alt_name, extract_cb, ctx); + /* remove identical apk-new */ - if (memcmp(ae->csum, fi.csum, sizeof(csum_t)) == 0) + if (ae->csum.type != fi.csum.type) + apk_file_get_info(ae->name, ae->csum.type, &fi); + if (apk_checksum_compare(&ae->csum, &fi.csum) == 0) unlink(alt_name); } } else { r = apk_archive_entry_extract(ae, is, NULL, extract_cb, ctx); } - memcpy(file->csum, ae->csum, sizeof(csum_t)); + memcpy(&file->csum, &ae->csum, sizeof(file->csum)); } else { if (apk_verbosity > 1) printf("%s\n", ae->name); @@ -1286,7 +1366,8 @@ static int apk_db_gzip_part(void *pctx, EVP_MD_CTX *mdctx, int part) EVP_DigestInit_ex(mdctx, EVP_md5(), NULL); break; case APK_MPART_END: - EVP_DigestFinal_ex(mdctx, ctx->data_csum, NULL); + ctx->data_csum.type = EVP_MD_CTX_size(mdctx); + EVP_DigestFinal_ex(mdctx, ctx->data_csum.data, NULL); break; } return 0; @@ -1320,14 +1401,15 @@ static int apk_db_unpack_pkg(struct apk_database *db, } repo = &db->repos[i]; - if (apk_db_cache_active(db) && csum_valid(repo->url_csum)) - bs = apk_db_cache_open(db, newpkg->csum, pkgname); + if (apk_db_cache_active(db) && + repo->csum.type != APK_CHECKSUM_NONE) + bs = apk_db_cache_open(db, &newpkg->csum, pkgname); if (bs == NULL) { snprintf(file, sizeof(file), "%s/%s", repo->url, pkgname); bs = apk_bstream_from_url(file); - if (csum_valid(repo->url_csum)) + if (repo->csum.type != APK_CHECKSUM_NONE) need_copy = TRUE; } } else { @@ -1337,7 +1419,7 @@ static int apk_db_unpack_pkg(struct apk_database *db, if (!apk_db_cache_active(db)) need_copy = FALSE; if (need_copy) { - apk_db_cache_get_name(file, sizeof(file), db, newpkg->csum, + apk_db_cache_get_name(file, sizeof(file), db, &newpkg->csum, pkgname, TRUE); bs = apk_bstream_tee(bs, file); } @@ -1362,7 +1444,7 @@ static int apk_db_unpack_pkg(struct apk_database *db, bs->close(bs, &length); /* Check the package checksum */ - if (memcmp(ctx.data_csum, newpkg->csum, sizeof(csum_t)) != 0) + if (apk_checksum_compare(&ctx.data_csum, &newpkg->csum) != 0) apk_warning("%s-%s: checksum does not match", newpkg->name->name, newpkg->version); @@ -1370,7 +1452,7 @@ static int apk_db_unpack_pkg(struct apk_database *db, if (length == newpkg->size) { char file2[256]; apk_db_cache_get_name(file2, sizeof(file2), db, - newpkg->csum, pkgname, FALSE); + &newpkg->csum, pkgname, FALSE); rename(file, file2); } else { unlink(file); diff --git a/src/io.c b/src/io.c index 26c0ebf..335b14d 100644 --- a/src/io.c +++ b/src/io.c @@ -440,11 +440,10 @@ err_fd: return APK_BLOB_NULL; } -int apk_file_get_info(const char *filename, struct apk_file_info *fi) +int apk_file_get_info(const char *filename, int checksum, struct apk_file_info *fi) { struct stat st; struct apk_bstream *bs; - csum_ctx_t ctx; if (stat(filename, &st) != 0) return -1; @@ -458,14 +457,19 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi) .device = st.st_dev, }; + if (checksum == APK_CHECKSUM_NONE) + return 0; + bs = apk_bstream_from_file(filename); if (bs != NULL) { + EVP_MD_CTX mdctx; apk_blob_t blob; - csum_init(&ctx); + EVP_DigestInit(&mdctx, apk_get_digest(checksum)); while (!APK_BLOB_IS_NULL(blob = bs->read(bs, APK_BLOB_NULL))) - csum_process(&ctx, (void*) blob.ptr, blob.len); - csum_finish(&ctx, fi->csum); + EVP_DigestUpdate(&mdctx, (void*) blob.ptr, blob.len); + fi->csum.type = EVP_MD_CTX_size(&mdctx); + EVP_DigestFinal(&mdctx, fi->csum.data, NULL); bs->close(bs, NULL); } diff --git a/src/package.c b/src/package.c index c6c6737..bb37317 100644 --- a/src/package.c +++ b/src/package.c @@ -230,7 +230,7 @@ int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os) return n; } -static const char *script_types[] = { +const char *apk_script_types[] = { [APK_SCRIPT_PRE_INSTALL] = "pre-install", [APK_SCRIPT_POST_INSTALL] = "post-install", [APK_SCRIPT_PRE_DEINSTALL] = "pre-deinstall", @@ -252,9 +252,9 @@ int apk_script_type(const char *name) { int i; - for (i = 0; i < ARRAY_SIZE(script_types); i++) - if (script_types[i] && - strcmp(script_types[i], name) == 0) + for (i = 0; i < ARRAY_SIZE(apk_script_types); i++) + if (apk_script_types[i] && + strcmp(apk_script_types[i], name) == 0) return i; return APK_SCRIPT_INVALID; @@ -290,7 +290,7 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, apk_deps_parse(db, &pkg->depends, value); break; case 'C': - apk_blob_pull_hexdump(&value, APK_BLOB_BUF(pkg->csum)); + apk_blob_pull_csum(&value, &pkg->csum); break; case 'S': pkg->size = apk_blob_pull_uint(&value, 10); @@ -426,7 +426,8 @@ static int apk_pkg_gzip_part(void *ctx, EVP_MD_CTX *mdctx, int part) EVP_DigestInit_ex(mdctx, EVP_md5(), NULL); break; case APK_MPART_END: - EVP_DigestFinal_ex(mdctx, ri->pkg->csum, NULL); + ri->pkg->csum.type = EVP_MD_CTX_size(mdctx); + EVP_DigestFinal_ex(mdctx, ri->pkg->csum.data, NULL); break; } return 0; @@ -572,7 +573,7 @@ int apk_pkg_run_script(struct apk_package *pkg, int root_fd, snprintf(fn, sizeof(fn), "tmp/%s-%s.%s", pkg->name->name, pkg->version, - script_types[type]); + apk_script_types[type]); fd = creat(fn, 0777); if (fd < 0) return fd; @@ -591,7 +592,7 @@ int apk_pkg_run_script(struct apk_package *pkg, int root_fd, execle(fn, "INSTALL", script_types2[type], pkg->version, "", NULL, environment); } else { - execle(fn, script_types[type], + execle(fn, apk_script_types[type], pkg->version, "", NULL, environment); } exit(1); @@ -649,7 +650,7 @@ int apk_pkg_write_index_entry(struct apk_package *info, int r; apk_blob_push_blob(&bbuf, APK_BLOB_STR("C:")); - apk_blob_push_hexdump(&bbuf, APK_BLOB_BUF(info->csum)); + apk_blob_push_csum(&bbuf, &info->csum); apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nP:")); apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->name->name)); apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nV:"));