diff options
author | Timo Teras <timo.teras@iki.fi> | 2009-01-14 19:48:30 +0200 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2009-01-14 19:48:30 +0200 |
commit | 2cfde12c8933c166feda81e52d6c091d2c7c5748 (patch) | |
tree | 3b302be3033c567f6e275131cc628720699c7e08 /src | |
parent | 15b547c55b2045e68f9f48f7d929d47b300dc3a9 (diff) | |
download | aports-2cfde12c8933c166feda81e52d6c091d2c7c5748.tar.bz2 aports-2cfde12c8933c166feda81e52d6c091d2c7c5748.tar.xz |
audit: new command to check changed files
Currently only implement --backup to get list of (config) files in
protected directories to backup.
This also fixes a database corruption bug in database.c.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 1 | ||||
-rw-r--r-- | src/apk_database.h | 6 | ||||
-rw-r--r-- | src/audit.c | 146 | ||||
-rw-r--r-- | src/database.c | 40 |
4 files changed, 178 insertions, 15 deletions
diff --git a/src/Makefile b/src/Makefile index 745e1da4da..e6bf9adb17 100644 --- a/src/Makefile +++ b/src/Makefile @@ -26,6 +26,7 @@ apk_OBJS = \ ver.o \ index.o \ info.o \ + audit.o \ apk.o ALL_OBJS = $(apk_OBJS) diff --git a/src/apk_database.h b/src/apk_database.h index 14df1a23e8..0bbca9aa63 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -95,7 +95,11 @@ typedef union apk_database_or_void { struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name); struct apk_name *apk_db_query_name(struct apk_database *db, apk_blob_t name); -void apk_name_free(struct apk_name *pkgname); +struct apk_db_dir *apk_db_dir_query(struct apk_database *db, + apk_blob_t name); +struct apk_db_file *apk_db_file_query(struct apk_database *db, + apk_blob_t dir, + apk_blob_t name); int apk_db_create(const char *root); int apk_db_open(struct apk_database *db, const char *root); diff --git a/src/audit.c b/src/audit.c new file mode 100644 index 0000000000..f04b14afeb --- /dev/null +++ b/src/audit.c @@ -0,0 +1,146 @@ +/* audit.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org> + * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi> + * 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. + */ + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <dirent.h> +#include <sys/stat.h> +#include "apk_applet.h" +#include "apk_database.h" + +struct audit_ctx { + int (*action)(struct apk_database *db); +}; + +static int audit_directory(apk_hash_item item, void *ctx) +{ + struct apk_db_dir *dbd = (struct apk_db_dir *) item; + struct apk_db_file *dbf; + struct apk_database *db = (struct apk_database *) ctx; + struct dirent *de; + struct stat st; + struct apk_bstream *bs; + char tmp[512], reason; + DIR *dir; + apk_blob_t bdir = APK_BLOB_STR(dbd->dirname); + csum_t csum; + + if (!(dbd->flags & APK_DBDIRF_PROTECTED)) + return 0; + + dir = opendir(dbd->dirname); + if (dir == NULL) + return 0; + + while ((de = readdir(dir)) != NULL) { + if (strcmp(de->d_name, ".") == 0 || + strcmp(de->d_name, "..") == 0) + continue; + + snprintf(tmp, sizeof(tmp), "%s/%s", + dbd->dirname, de->d_name); + + if (stat(tmp, &st) < 0) + continue; + + if (S_ISDIR(st.st_mode)) { + if (apk_db_dir_query(db, APK_BLOB_STR(tmp)) != NULL) + continue; + + reason = 'D'; + } else { + dbf = apk_db_file_query(db, bdir, APK_BLOB_STR(de->d_name)); + if (dbf != NULL) { + bs = apk_bstream_from_file(tmp); + if (bs == NULL) + continue; + + bs->close(bs, csum, NULL); + + if (apk_blob_compare(APK_BLOB_BUF(csum), + APK_BLOB_BUF(dbf->csum)) == 0) + continue; + + reason = 'M'; + } else { + reason = 'F'; + } + } + if (apk_quiet) + printf("%s\n", tmp); + else + printf("%c %s\n", reason, tmp); + } + + closedir(dir); + return 0; +} + +static int audit_backup(struct apk_database *db) +{ + fchdir(db->root_fd); + return apk_hash_foreach(&db->installed.dirs, audit_directory, db); +} + +static int audit_parse(void *ctx, int optch, int optindex, const char *optarg) +{ + struct audit_ctx *actx = (struct audit_ctx *) ctx; + + switch (optch) { + case 0x10000: + actx->action = audit_backup; + break; + default: + return -1; + } + return 0; +} + +static int audit_main(void *ctx, int argc, char **argv) +{ + struct audit_ctx *actx = (struct audit_ctx *) ctx; + struct apk_database db; + int r; + + if (actx->action == NULL) { + apk_error("No audit action requested"); + return 2; + } + + r = apk_db_open(&db, apk_root); + if (r != 0) { + apk_error("APK database not present"); + return 1; + } + + r = actx->action(&db); + + apk_db_close(&db); + return r; +} + +static struct option audit_options[] = { + { "backup", no_argument, NULL, 0x10000 }, +}; + +static struct apk_applet apk_audit = { + .name = "audit", + .usage = "--backup", + .context_size = sizeof(struct audit_ctx), + .num_options = ARRAY_SIZE(audit_options), + .options = audit_options, + .parse = audit_parse, + .main = audit_main, +}; + +APK_DEFINE_APPLET(apk_audit); + diff --git a/src/database.c b/src/database.c index a84154fbc1..36492a4064 100644 --- a/src/database.c +++ b/src/database.c @@ -45,12 +45,19 @@ static apk_blob_t pkg_name_get_key(apk_hash_item item) return APK_BLOB_STR(((struct apk_name *) item)->name); } +static void pkg_name_free(struct apk_name *name) +{ + free(name->name); + free(name->pkgs); + free(name); +} + static const struct apk_hash_ops pkg_name_hash_ops = { .node_offset = offsetof(struct apk_name, hash_node), .get_key = pkg_name_get_key, .hash_key = apk_blob_hash, .compare = apk_blob_compare, - .delete_item = (apk_hash_delete_f) apk_name_free, + .delete_item = (apk_hash_delete_f) pkg_name_free, }; static apk_blob_t pkg_info_get_key(apk_hash_item item) @@ -151,13 +158,6 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name) return pn; } -void apk_name_free(struct apk_name *name) -{ - free(name->name); - free(name->pkgs); - free(name); -} - static void apk_db_dir_unref(struct apk_database *db, struct apk_db_dir *dir) { dir->refs--; @@ -176,8 +176,8 @@ static struct apk_db_dir *apk_db_dir_ref(struct apk_db_dir *dir) return dir; } -static struct apk_db_dir *apk_db_dir_query(struct apk_database *db, - apk_blob_t name) +struct apk_db_dir *apk_db_dir_query(struct apk_database *db, + apk_blob_t name) { return (struct apk_db_dir *) apk_hash_get(&db->installed.dirs, name); } @@ -271,6 +271,21 @@ static void apk_db_diri_free(struct apk_database *db, free(diri); } +struct apk_db_file *apk_db_file_query(struct apk_database *db, + apk_blob_t dir, + apk_blob_t name) +{ + struct apk_db_file_hash_key key; + + key = (struct apk_db_file_hash_key) { + .dirname = dir, + .filename = name, + }; + + return (struct apk_db_file *) apk_hash_get(&db->installed.files, + APK_BLOB_BUF(&key)); +} + static struct apk_db_file *apk_db_file_get(struct apk_database *db, struct apk_db_dir_instance *diri, apk_blob_t name) @@ -925,10 +940,6 @@ static int apk_db_install_archive_entry(void *_ctx, if (bfile.len > 6 && memcmp(bfile.ptr, ".keep_", 6) == 0) return 0; - r = strlen(diri->dir->dirname); - r = strlen(bdir.ptr); - r = 0; - /* Make sure the file is part of the cached directory tree */ if (diri == NULL || strncmp(diri->dir->dirname, bdir.ptr, bdir.len) != 0 || @@ -946,6 +957,7 @@ static int apk_db_install_archive_entry(void *_ctx, return -1; } ctx->diri = diri; + ctx->file_diri_node = NULL; } file = apk_db_file_get(db, diri, bfile); |