diff --git a/src/apk_fs.h b/src/apk_fs.h index 1b4a4e2..cb4e343 100644 --- a/src/apk_fs.h +++ b/src/apk_fs.h @@ -42,7 +42,7 @@ struct apk_fsdir_ops { int (*file_extract)(struct apk_ctx *, const struct apk_file_info *, struct apk_istream *, apk_progress_cb, void *, unsigned int, apk_blob_t); int (*file_control)(struct apk_fsdir *, apk_blob_t, int); - int (*file_digest)(struct apk_fsdir *, apk_blob_t, uint8_t alg, struct apk_digest *); + int (*file_info)(struct apk_fsdir *, apk_blob_t, unsigned int, struct apk_file_info *); }; #define APK_FSEXTRACTF_NO_CHOWN 0x0001 @@ -72,8 +72,8 @@ static inline int apk_fsdir_update_perms(struct apk_fsdir *fs, mode_t mode, uid_ static inline int apk_fsdir_file_control(struct apk_fsdir *fs, apk_blob_t filename, int ctrl) { return fs->ops->file_control(fs, filename, ctrl); } -static inline int apk_fsdir_file_digest(struct apk_fsdir *fs, apk_blob_t filename, uint8_t alg, struct apk_digest *dgst) { - return fs->ops->file_digest(fs, filename, alg, dgst); +static inline int apk_fsdir_file_info(struct apk_fsdir *fs, apk_blob_t filename, unsigned int flags, struct apk_file_info *fi) { + return fs->ops->file_info(fs, filename, flags, fi); } #endif diff --git a/src/database.c b/src/database.c index 027cc76..928a864 100644 --- a/src/database.c +++ b/src/database.c @@ -2757,6 +2757,18 @@ static const struct apk_extract_ops extract_installer = { .file = apk_db_install_file, }; +static int apk_db_audit_file(struct apk_fsdir *d, apk_blob_t filename, struct apk_db_file *dbf) +{ + struct apk_file_info fi; + int r; + + // Check file first + r = apk_fsdir_file_info(d, filename, APK_FI_NOFOLLOW | APK_FI_DIGEST(apk_dbf_digest(dbf)), &fi); + if (r != 0 || !dbf || dbf->csum.type == APK_CHECKSUM_NONE) return r != -ENOENT; + if (apk_digest_cmp_csum(&fi.digest, &dbf->csum) != 0) return 1; + return 0; +} + static void apk_db_purge_pkg(struct apk_database *db, struct apk_installed_package *ipkg, int is_installed) @@ -2766,7 +2778,6 @@ static void apk_db_purge_pkg(struct apk_database *db, struct apk_db_file *file; struct apk_db_file_hash_key key; struct apk_fsdir d; - struct apk_digest dgst; struct hlist_node *dc, *dn, *fc, *fn; unsigned long hash; int ctrl = is_installed ? APK_FS_CTRL_DELETE : APK_FS_CTRL_CANCEL; @@ -2785,9 +2796,7 @@ static void apk_db_purge_pkg(struct apk_database *db, if (!is_installed || (diri->dir->protect_mode == APK_PROTECT_NONE) || (db->ctx->flags & APK_PURGE) || - (file->csum.type != APK_CHECKSUM_NONE && - apk_fsdir_file_digest(&d, key.filename, apk_dbf_digest(file), &dgst) == 0 && - apk_digest_cmp_csum(&dgst, &file->csum) == 0)) + apk_db_audit_file(&d, key.filename, file) == 0) apk_fsdir_file_control(&d, key.filename, ctrl); apk_dbg2(out, DIR_FILE_FMT, DIR_FILE_PRINTF(diri->dir, file)); @@ -2813,7 +2822,6 @@ static uint8_t apk_db_migrate_files_for_priority(struct apk_database *db, struct apk_db_file_hash_key key; struct hlist_node *dc, *dn, *fc, *fn; struct apk_fsdir d; - struct apk_digest dgst; unsigned long hash; apk_blob_t dirname; int r, ctrl; @@ -2848,21 +2856,17 @@ static uint8_t apk_db_migrate_files_for_priority(struct apk_database *db, // File was from overlay, delete the package's version ctrl = APK_FS_CTRL_CANCEL; } else if (diri->dir->protect_mode != APK_PROTECT_NONE && - apk_fsdir_file_digest(&d, key.filename, apk_dbf_digest(ofile), &dgst) == 0 && - (!ofile || ofile->csum.type == APK_CHECKSUM_NONE || - apk_digest_cmp_csum(&dgst, &ofile->csum) != 0)) { + apk_db_audit_file(&d, key.filename, ofile) != 0) { // Protected directory, and a file without db entry // or with local modifications. Keep the filesystem file. // Determine if the package's file should be kept as .apk-new if ((db->ctx->flags & APK_CLEAN_PROTECTED) || - (file->csum.type != APK_CHECKSUM_NONE && - (apk_fsdir_file_digest(&d, key.filename, apk_dbf_digest(file), &dgst) == 0 && - apk_digest_cmp_csum(&dgst, &file->csum) == 0))) { + apk_db_audit_file(&d, key.filename, file) == 0) { // No .apk-new files allowed, or the file on disk has the same // hash as the file from new package. Keep the on disk one. ctrl = APK_FS_CTRL_CANCEL; } else { - // All files difference. Use the package's file as .apk-new. + // All files differ. Use the package's file as .apk-new. ctrl = APK_FS_CTRL_APKNEW; } } diff --git a/src/fs_fsys.c b/src/fs_fsys.c index b3ec1d5..c11ca50 100644 --- a/src/fs_fsys.c +++ b/src/fs_fsys.c @@ -12,6 +12,7 @@ #include "apk_fs.h" #include "apk_xattr.h" +#include "apk_database.h" // for db->atoms #define TMPNAME_MAX (PATH_MAX + 64) @@ -265,23 +266,16 @@ static int fsys_file_control(struct apk_fsdir *d, apk_blob_t filename, int ctrl) return rc; } -static int fsys_file_digest(struct apk_fsdir *d, apk_blob_t filename, uint8_t alg, struct apk_digest *dgst) +static int fsys_file_info(struct apk_fsdir *d, apk_blob_t filename, + unsigned int flags, struct apk_file_info *fi) { struct apk_ctx *ac = d->ac; - struct apk_istream *is; - apk_blob_t blob; - int n; + int n, r; n = apk_pathbuilder_pushb(&d->pb, filename); - is = apk_istream_from_file(apk_ctx_fd_dest(ac), apk_pathbuilder_cstr(&d->pb)); + r = apk_fileinfo_get(apk_ctx_fd_dest(ac), apk_pathbuilder_cstr(&d->pb), flags, fi, &ac->db->atoms); apk_pathbuilder_pop(&d->pb, n); - if (IS_ERR(is)) return PTR_ERR(is); - - apk_digest_ctx_reset(&ac->dctx, alg); - while (apk_istream_get_all(is, &blob) == 0) - apk_digest_ctx_update(&ac->dctx, blob.ptr, blob.len); - apk_digest_ctx_final(&ac->dctx, dgst); - return apk_istream_close(is); + return r; } static const struct apk_fsdir_ops fsdir_ops_fsys = { @@ -292,7 +286,7 @@ static const struct apk_fsdir_ops fsdir_ops_fsys = { .dir_update_perms = fsys_dir_update_perms, .file_extract = fsys_file_extract, .file_control = fsys_file_control, - .file_digest = fsys_file_digest, + .file_info = fsys_file_info, }; static const struct apk_fsdir_ops *apk_fsops_get(apk_blob_t dir) diff --git a/src/fs_uvol.c b/src/fs_uvol.c index 24952cf..292891e 100644 --- a/src/fs_uvol.c +++ b/src/fs_uvol.c @@ -150,7 +150,7 @@ static int uvol_file_control(struct apk_fsdir *d, apk_blob_t filename, int ctrl) } } -static int uvol_file_digest(struct apk_fsdir *d, apk_blob_t filename, uint8_t alg, struct apk_digest *dgst) +static int uvol_file_info(struct apk_fsdir *d, apk_blob_t filename, unsigned int flags, struct apk_file_info *fi) { return -APKE_UVOL_ERROR; } @@ -163,5 +163,5 @@ const struct apk_fsdir_ops fsdir_ops_uvol = { .dir_update_perms = uvol_dir_update_perms, .file_extract = uvol_file_extract, .file_control = uvol_file_control, - .file_digest = uvol_file_digest, + .file_info = uvol_file_info, };