db: fix change detection for symlinks
apk_fileinfo_get() special cases symlink digest calculation. Convert apk_fsdir_ops.file_digest to .file_info to fix symlink change detection. fixes #10853cute-signatures
parent
1ababaa99d
commit
c21f61ddd8
|
@ -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_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_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
|
#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) {
|
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);
|
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) {
|
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_digest(fs, filename, alg, dgst);
|
return fs->ops->file_info(fs, filename, flags, fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2757,6 +2757,18 @@ static const struct apk_extract_ops extract_installer = {
|
||||||
.file = apk_db_install_file,
|
.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,
|
static void apk_db_purge_pkg(struct apk_database *db,
|
||||||
struct apk_installed_package *ipkg,
|
struct apk_installed_package *ipkg,
|
||||||
int is_installed)
|
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 *file;
|
||||||
struct apk_db_file_hash_key key;
|
struct apk_db_file_hash_key key;
|
||||||
struct apk_fsdir d;
|
struct apk_fsdir d;
|
||||||
struct apk_digest dgst;
|
|
||||||
struct hlist_node *dc, *dn, *fc, *fn;
|
struct hlist_node *dc, *dn, *fc, *fn;
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
int ctrl = is_installed ? APK_FS_CTRL_DELETE : APK_FS_CTRL_CANCEL;
|
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 ||
|
if (!is_installed ||
|
||||||
(diri->dir->protect_mode == APK_PROTECT_NONE) ||
|
(diri->dir->protect_mode == APK_PROTECT_NONE) ||
|
||||||
(db->ctx->flags & APK_PURGE) ||
|
(db->ctx->flags & APK_PURGE) ||
|
||||||
(file->csum.type != APK_CHECKSUM_NONE &&
|
apk_db_audit_file(&d, key.filename, file) == 0)
|
||||||
apk_fsdir_file_digest(&d, key.filename, apk_dbf_digest(file), &dgst) == 0 &&
|
|
||||||
apk_digest_cmp_csum(&dgst, &file->csum) == 0))
|
|
||||||
apk_fsdir_file_control(&d, key.filename, ctrl);
|
apk_fsdir_file_control(&d, key.filename, ctrl);
|
||||||
|
|
||||||
apk_dbg2(out, DIR_FILE_FMT, DIR_FILE_PRINTF(diri->dir, file));
|
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 apk_db_file_hash_key key;
|
||||||
struct hlist_node *dc, *dn, *fc, *fn;
|
struct hlist_node *dc, *dn, *fc, *fn;
|
||||||
struct apk_fsdir d;
|
struct apk_fsdir d;
|
||||||
struct apk_digest dgst;
|
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
apk_blob_t dirname;
|
apk_blob_t dirname;
|
||||||
int r, ctrl;
|
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
|
// File was from overlay, delete the package's version
|
||||||
ctrl = APK_FS_CTRL_CANCEL;
|
ctrl = APK_FS_CTRL_CANCEL;
|
||||||
} else if (diri->dir->protect_mode != APK_PROTECT_NONE &&
|
} else if (diri->dir->protect_mode != APK_PROTECT_NONE &&
|
||||||
apk_fsdir_file_digest(&d, key.filename, apk_dbf_digest(ofile), &dgst) == 0 &&
|
apk_db_audit_file(&d, key.filename, ofile) != 0) {
|
||||||
(!ofile || ofile->csum.type == APK_CHECKSUM_NONE ||
|
|
||||||
apk_digest_cmp_csum(&dgst, &ofile->csum) != 0)) {
|
|
||||||
// Protected directory, and a file without db entry
|
// Protected directory, and a file without db entry
|
||||||
// or with local modifications. Keep the filesystem file.
|
// or with local modifications. Keep the filesystem file.
|
||||||
// Determine if the package's file should be kept as .apk-new
|
// Determine if the package's file should be kept as .apk-new
|
||||||
if ((db->ctx->flags & APK_CLEAN_PROTECTED) ||
|
if ((db->ctx->flags & APK_CLEAN_PROTECTED) ||
|
||||||
(file->csum.type != APK_CHECKSUM_NONE &&
|
apk_db_audit_file(&d, key.filename, file) == 0) {
|
||||||
(apk_fsdir_file_digest(&d, key.filename, apk_dbf_digest(file), &dgst) == 0 &&
|
|
||||||
apk_digest_cmp_csum(&dgst, &file->csum) == 0))) {
|
|
||||||
// No .apk-new files allowed, or the file on disk has the same
|
// 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.
|
// hash as the file from new package. Keep the on disk one.
|
||||||
ctrl = APK_FS_CTRL_CANCEL;
|
ctrl = APK_FS_CTRL_CANCEL;
|
||||||
} else {
|
} 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;
|
ctrl = APK_FS_CTRL_APKNEW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "apk_fs.h"
|
#include "apk_fs.h"
|
||||||
#include "apk_xattr.h"
|
#include "apk_xattr.h"
|
||||||
|
#include "apk_database.h" // for db->atoms
|
||||||
|
|
||||||
#define TMPNAME_MAX (PATH_MAX + 64)
|
#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;
|
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_ctx *ac = d->ac;
|
||||||
struct apk_istream *is;
|
int n, r;
|
||||||
apk_blob_t blob;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
n = apk_pathbuilder_pushb(&d->pb, filename);
|
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);
|
apk_pathbuilder_pop(&d->pb, n);
|
||||||
if (IS_ERR(is)) return PTR_ERR(is);
|
return r;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct apk_fsdir_ops fsdir_ops_fsys = {
|
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,
|
.dir_update_perms = fsys_dir_update_perms,
|
||||||
.file_extract = fsys_file_extract,
|
.file_extract = fsys_file_extract,
|
||||||
.file_control = fsys_file_control,
|
.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)
|
static const struct apk_fsdir_ops *apk_fsops_get(apk_blob_t dir)
|
||||||
|
|
|
@ -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;
|
return -APKE_UVOL_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -163,5 +163,5 @@ const struct apk_fsdir_ops fsdir_ops_uvol = {
|
||||||
.dir_update_perms = uvol_dir_update_perms,
|
.dir_update_perms = uvol_dir_update_perms,
|
||||||
.file_extract = uvol_file_extract,
|
.file_extract = uvol_file_extract,
|
||||||
.file_control = uvol_file_control,
|
.file_control = uvol_file_control,
|
||||||
.file_digest = uvol_file_digest,
|
.file_info = uvol_file_info,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue