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.cute-signatures
parent
15b547c55b
commit
2cfde12c89
|
@ -26,6 +26,7 @@ apk_OBJS = \
|
||||||
ver.o \
|
ver.o \
|
||||||
index.o \
|
index.o \
|
||||||
info.o \
|
info.o \
|
||||||
|
audit.o \
|
||||||
apk.o
|
apk.o
|
||||||
|
|
||||||
ALL_OBJS = $(apk_OBJS)
|
ALL_OBJS = $(apk_OBJS)
|
||||||
|
|
|
@ -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_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);
|
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_create(const char *root);
|
||||||
int apk_db_open(struct apk_database *db, const char *root);
|
int apk_db_open(struct apk_database *db, const char *root);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
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 = {
|
static const struct apk_hash_ops pkg_name_hash_ops = {
|
||||||
.node_offset = offsetof(struct apk_name, hash_node),
|
.node_offset = offsetof(struct apk_name, hash_node),
|
||||||
.get_key = pkg_name_get_key,
|
.get_key = pkg_name_get_key,
|
||||||
.hash_key = apk_blob_hash,
|
.hash_key = apk_blob_hash,
|
||||||
.compare = apk_blob_compare,
|
.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)
|
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;
|
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)
|
static void apk_db_dir_unref(struct apk_database *db, struct apk_db_dir *dir)
|
||||||
{
|
{
|
||||||
dir->refs--;
|
dir->refs--;
|
||||||
|
@ -176,7 +176,7 @@ static struct apk_db_dir *apk_db_dir_ref(struct apk_db_dir *dir)
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct apk_db_dir *apk_db_dir_query(struct apk_database *db,
|
struct apk_db_dir *apk_db_dir_query(struct apk_database *db,
|
||||||
apk_blob_t name)
|
apk_blob_t name)
|
||||||
{
|
{
|
||||||
return (struct apk_db_dir *) apk_hash_get(&db->installed.dirs, 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);
|
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,
|
static struct apk_db_file *apk_db_file_get(struct apk_database *db,
|
||||||
struct apk_db_dir_instance *diri,
|
struct apk_db_dir_instance *diri,
|
||||||
apk_blob_t name)
|
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)
|
if (bfile.len > 6 && memcmp(bfile.ptr, ".keep_", 6) == 0)
|
||||||
return 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 */
|
/* Make sure the file is part of the cached directory tree */
|
||||||
if (diri == NULL ||
|
if (diri == NULL ||
|
||||||
strncmp(diri->dir->dirname, bdir.ptr, bdir.len) != 0 ||
|
strncmp(diri->dir->dirname, bdir.ptr, bdir.len) != 0 ||
|
||||||
|
@ -946,6 +957,7 @@ static int apk_db_install_archive_entry(void *_ctx,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ctx->diri = diri;
|
ctx->diri = diri;
|
||||||
|
ctx->file_diri_node = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = apk_db_file_get(db, diri, bfile);
|
file = apk_db_file_get(db, diri, bfile);
|
||||||
|
|
Loading…
Reference in New Issue