diff options
author | Timo Teras <timo.teras@iki.fi> | 2008-11-14 14:26:59 +0200 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2008-11-14 14:26:59 +0200 |
commit | 8e23a2ba4eb7f6192c6bce8a6da81004803eca3f (patch) | |
tree | 1450b08f0e2818a4bc12206081b6777b3e92b7f8 /src/database.c | |
parent | 86676ac8c40a96880f323c2b1a09a5714d85705e (diff) | |
download | apk-tools-8e23a2ba4eb7f6192c6bce8a6da81004803eca3f.tar.gz apk-tools-8e23a2ba4eb7f6192c6bce8a6da81004803eca3f.tar.bz2 apk-tools-8e23a2ba4eb7f6192c6bce8a6da81004803eca3f.tar.xz apk-tools-8e23a2ba4eb7f6192c6bce8a6da81004803eca3f.zip |
db: checksum installed files, protect config files
Checksum of installed is computed on the fly when extracting them
and it'll be saved to fdb. When installing config files those are
diverted with suffix .apk-new if earlier version of same file with
local changes exist.
Diffstat (limited to 'src/database.c')
-rw-r--r-- | src/database.c | 67 |
1 files changed, 62 insertions, 5 deletions
diff --git a/src/database.c b/src/database.c index 15757ff..4ed3ece 100644 --- a/src/database.c +++ b/src/database.c @@ -12,6 +12,7 @@ #include <errno.h> #include <stdio.h> #include <fcntl.h> +#include <limits.h> #include <unistd.h> #include <malloc.h> #include <string.h> @@ -137,6 +138,7 @@ static struct apk_db_dir *apk_db_dir_get(struct apk_database *db, struct apk_db_dir *dir; apk_blob_t bparent; char *cstr; + int i; if (name.len && name.ptr[name.len-1] == '/') name.len--; @@ -154,11 +156,22 @@ static struct apk_db_dir *apk_db_dir_get(struct apk_database *db, if (name.len == 0) dir->parent = NULL; - else if (apk_blob_rsplit(name, '/', &bparent, NULL)) + else if (apk_blob_rsplit(name, '/', &bparent, NULL)) dir->parent = apk_db_dir_get(db, bparent); else dir->parent = apk_db_dir_get(db, APK_BLOB_NULL); + if (dir->parent != NULL) + dir->flags = dir->parent->flags; + + for (i = 0; i < db->protected_paths->num; i++) { + if (db->protected_paths->item[i][0] == '-' && + strcmp(&db->protected_paths->item[i][1], dir->dirname) == 0) + dir->flags &= ~APK_DBDIRF_PROTECTED; + else if (strcmp(db->protected_paths->item[i], dir->dirname) == 0) + dir->flags |= APK_DBDIRF_PROTECTED; + } + return dir; } @@ -295,6 +308,16 @@ static int apk_db_read_fdb(struct apk_database *db, int fd) file_dir_node = &file->dir_files_list.next; file_pkg_node = &file->pkg_files_list.next; break; + case 'C': + if (file == NULL) { + apk_error("FDB checksum entry before file entry"); + return -1; + } + if (apk_hexdump_parse(APK_BLOB_BUF(file->csum), l)) { + apk_error("Not a valid checksum"); + return -1; + } + break; default: apk_error("FDB entry '%c' unsupported", n); return -1; @@ -342,6 +365,12 @@ static int apk_db_write_fdb(struct apk_database *db, int fd) n += snprintf(&buf[n], sizeof(buf)-n, "F%s\n", file->filename); + if (csum_valid(file->csum)) { + n += snprintf(&buf[n], sizeof(buf)-n, "C"); + n += apk_hexdump_format(sizeof(buf)-n, &buf[n], + APK_BLOB_BUF(file->csum)); + n += snprintf(&buf[n], sizeof(buf)-n, "\n"); + } if (write(fd, buf, n) != n) return -1; @@ -418,7 +447,7 @@ int apk_db_create(const char *root) return 0; } -static int apk_db_read_config(struct apk_database *db) +static int apk_db_read_state(struct apk_database *db) { struct apk_istream *is; struct stat st; @@ -466,8 +495,18 @@ static int apk_db_read_config(struct apk_database *db) return 0; } +static int add_protected_path(void *ctx, apk_blob_t blob) +{ + struct apk_database *db = (struct apk_database *) ctx; + + *apk_string_array_add(&db->protected_paths) = apk_blob_cstr(blob); + return 0; +} + int apk_db_open(struct apk_database *db, const char *root) { + apk_blob_t dirs; + memset(db, 0, sizeof(*db)); apk_hash_init(&db->available.names, &pkg_name_hash_ops, 1000); apk_hash_init(&db->available.packages, &pkg_info_hash_ops, 4000); @@ -485,7 +524,10 @@ int apk_db_open(struct apk_database *db, const char *root) if (apk_repository != NULL) apk_db_add_repository(db, apk_repository); - return apk_db_read_config(db); + dirs = APK_BLOB_STR("etc:-etc/init.d"); + apk_blob_for_each_segment(dirs, ":", add_protected_path, db); + + return apk_db_read_state(db); } struct write_ctx { @@ -668,7 +710,7 @@ int apk_db_recalculate_and_commit(struct apk_database *db) } static int apk_db_install_archive_entry(void *_ctx, - const struct apk_archive_entry *ae, + const struct apk_file_info *ae, struct apk_istream *is) { struct install_ctx *ctx = (struct install_ctx *) _ctx; @@ -677,6 +719,8 @@ static int apk_db_install_archive_entry(void *_ctx, apk_blob_t name = APK_BLOB_STR(ae->name); struct apk_db_dir *dir; struct apk_db_file *file; + struct apk_file_info fi; + char alt_name[PATH_MAX]; const char *p; int r = 0, type = APK_SCRIPT_INVALID; @@ -740,7 +784,20 @@ static int apk_db_install_archive_entry(void *_ctx, if (strncmp(file->filename, ".keep_", 6) == 0) return 0; - r = apk_archive_entry_extract(ae, is, NULL); + if ((file->dir->flags & APK_DBDIRF_PROTECTED) && + csum_valid(file->csum) && + apk_file_get_info(ae->name, &fi) == 0 && + memcmp(file->csum, fi.csum, sizeof(csum_t)) != 0) { + /* Protected file, which is modified locally. + * Extract to separate place */ + snprintf(alt_name, sizeof(alt_name), + "%s/%s.apk-new", + dir->dirname, file->filename); + r = apk_archive_entry_extract(ae, is, alt_name); + } else { + r = apk_archive_entry_extract(ae, is, NULL); + } + memcpy(file->csum, ae->csum, sizeof(csum_t)); } else { if (name.ptr[name.len-1] == '/') name.len--; |