Manage files and directories

This commit is contained in:
Andreas Steffen
2013-06-21 23:25:21 +02:00
parent b61c78d3c2
commit 1f179c63b3
4 changed files with 213 additions and 127 deletions
+32 -5
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2011-2012 Andreas Steffen * Copyright (C) 2011-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil * HSR Hochschule fuer Technik Rapperswil
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -20,6 +20,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <syslog.h> #include <syslog.h>
#include <libgen.h>
#include <library.h> #include <library.h>
#include <utils/debug.h> #include <utils/debug.h>
@@ -81,6 +82,7 @@ static void attest_dbg(debug_t group, level_t level, char *fmt, ...)
*/ */
attest_db_t *attest; attest_db_t *attest;
/** /**
* atexit handler to close db on shutdown * atexit handler to close db on shutdown
*/ */
@@ -100,6 +102,7 @@ static void do_args(int argc, char *argv[])
OP_KEYS, OP_KEYS,
OP_COMPONENTS, OP_COMPONENTS,
OP_DEVICES, OP_DEVICES,
OP_DIRECTORIES,
OP_FILES, OP_FILES,
OP_HASHES, OP_HASHES,
OP_MEASUREMENTS, OP_MEASUREMENTS,
@@ -120,6 +123,8 @@ static void do_args(int argc, char *argv[])
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "components", no_argument, NULL, 'c' }, { "components", no_argument, NULL, 'c' },
{ "devices", no_argument, NULL, 'e' }, { "devices", no_argument, NULL, 'e' },
{ "directories", no_argument, NULL, 'd' },
{ "dirs", no_argument, NULL, 'd' },
{ "files", no_argument, NULL, 'f' }, { "files", no_argument, NULL, 'f' },
{ "keys", no_argument, NULL, 'k' }, { "keys", no_argument, NULL, 'k' },
{ "packages", no_argument, NULL, 'g' }, { "packages", no_argument, NULL, 'g' },
@@ -127,8 +132,9 @@ static void do_args(int argc, char *argv[])
{ "hashes", no_argument, NULL, 'H' }, { "hashes", no_argument, NULL, 'H' },
{ "measurements", no_argument, NULL, 'm' }, { "measurements", no_argument, NULL, 'm' },
{ "add", no_argument, NULL, 'a' }, { "add", no_argument, NULL, 'a' },
{ "delete", no_argument, NULL, 'd' }, { "delete", no_argument, NULL, 'r' },
{ "del", no_argument, NULL, 'd' }, { "del", no_argument, NULL, 'r' },
{ "remove", no_argument, NULL, 'r' },
{ "aik", required_argument, NULL, 'A' }, { "aik", required_argument, NULL, 'A' },
{ "blacklist", no_argument, NULL, 'B' }, { "blacklist", no_argument, NULL, 'B' },
{ "component", required_argument, NULL, 'C' }, { "component", required_argument, NULL, 'C' },
@@ -171,6 +177,9 @@ static void do_args(int argc, char *argv[])
case 'c': case 'c':
op = OP_COMPONENTS; op = OP_COMPONENTS;
continue; continue;
case 'd':
op = OP_DIRECTORIES;
continue;
case 'e': case 'e':
op = OP_DEVICES; op = OP_DEVICES;
continue; continue;
@@ -195,7 +204,7 @@ static void do_args(int argc, char *argv[])
case 'a': case 'a':
op = OP_ADD; op = OP_ADD;
continue; continue;
case 'd': case 'r':
op = OP_DEL; op = OP_DEL;
continue; continue;
case 'A': case 'A':
@@ -251,11 +260,26 @@ static void do_args(int argc, char *argv[])
} }
continue; continue;
case 'F': case 'F':
if (!attest->set_file(attest, optarg, op == OP_ADD)) {
char *path = strdup(optarg);
char *dir = dirname(path);
char *file = basename(optarg);
if (*dir != '.')
{
if (!attest->set_directory(attest, dir, op == OP_ADD))
{
free(path);
exit(EXIT_FAILURE);
}
}
free(path);
if (!attest->set_file(attest, file, op == OP_ADD))
{ {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
continue; continue;
}
case 'G': case 'G':
if (!attest->set_package(attest, optarg, op == OP_ADD)) if (!attest->set_package(attest, optarg, op == OP_ADD))
{ {
@@ -372,6 +396,9 @@ static void do_args(int argc, char *argv[])
case OP_DEVICES: case OP_DEVICES:
attest->list_devices(attest); attest->list_devices(attest);
break; break;
case OP_DIRECTORIES:
attest->list_directories(attest);
break;
case OP_FILES: case OP_FILES:
attest->list_files(attest); attest->list_files(attest);
break; break;
+152 -89
View File
@@ -62,11 +62,6 @@ struct private_attest_db_t {
*/ */
int did; int did;
/**
* TRUE if directory has been set
*/
bool dir_set;
/** /**
* Measurement file to be queried * Measurement file to be queried
*/ */
@@ -77,11 +72,6 @@ struct private_attest_db_t {
*/ */
int fid; int fid;
/**
* TRUE if file has been set
*/
bool file_set;
/** /**
* AIK to be queried * AIK to be queried
*/ */
@@ -304,35 +294,35 @@ METHOD(attest_db_t, set_directory, bool,
private_attest_db_t *this, char *dir, bool create) private_attest_db_t *this, char *dir, bool create)
{ {
enumerator_t *e; enumerator_t *e;
int did;
size_t len; size_t len;
if (this->dir_set) if (this->did)
{ {
printf("directory has already been set\n"); printf("directory has already been set\n");
return FALSE; return FALSE;
} }
free(this->dir);
/* remove trailing '/' character */ /* remove trailing '/' character if not root directory */
len = strlen(dir); len = strlen(dir);
if (len && dir[len-1] == '/') if (len > 1 && dir[len-1] == '/')
{ {
dir[len-1] = '\0'; dir[len-1] = '\0';
} }
this->dir = strdup(dir); this->dir = strdup(dir);
e = this->db->query(this->db, e = this->db->query(this->db,
"SELECT id FROM files WHERE type = 1 AND path = ?", "SELECT id FROM directories WHERE path = ?",
DB_TEXT, dir, DB_INT); DB_TEXT, dir, DB_INT);
if (e) if (e)
{ {
if (e->enumerate(e, &this->did)) if (e->enumerate(e, &did))
{ {
this->dir_set = TRUE; this->did = did;
} }
e->destroy(e); e->destroy(e);
} }
if (this->dir_set) if (this->did)
{ {
return TRUE; return TRUE;
} }
@@ -344,14 +334,15 @@ METHOD(attest_db_t, set_directory, bool,
} }
/* Add a new database entry */ /* Add a new database entry */
this->dir_set = this->db->execute(this->db, &this->did, if (1 == this->db->execute(this->db, &did,
"INSERT INTO files (type, path) VALUES (1, ?)", "INSERT INTO directories (path) VALUES (?)", DB_TEXT, dir))
DB_TEXT, dir) == 1; {
this->did = did;
}
printf("directory '%s' %sinserted into database\n", dir, printf("directory '%s' %sinserted into database\n", dir,
this->dir_set ? "" : "could not be "); this->did ? "" : "could not be ");
return this->dir_set; return this->did > 0;
} }
METHOD(attest_db_t, set_did, bool, METHOD(attest_db_t, set_did, bool,
@@ -360,22 +351,20 @@ METHOD(attest_db_t, set_did, bool,
enumerator_t *e; enumerator_t *e;
char *dir; char *dir;
if (this->dir_set) if (this->did)
{ {
printf("directory has already been set\n"); printf("directory has already been set\n");
return FALSE; return FALSE;
} }
this->did = did;
e = this->db->query(this->db, "SELECT path FROM files WHERE id = ?", e = this->db->query(this->db, "SELECT path FROM directories WHERE id = ?",
DB_UINT, did, DB_TEXT); DB_UINT, did, DB_TEXT);
if (e) if (e)
{ {
if (e->enumerate(e, &dir)) if (e->enumerate(e, &dir))
{ {
free(this->dir);
this->dir = strdup(dir); this->dir = strdup(dir);
this->dir_set = TRUE; this->did = did;
} }
else else
{ {
@@ -383,76 +372,88 @@ METHOD(attest_db_t, set_did, bool,
} }
e->destroy(e); e->destroy(e);
} }
return this->dir_set; return this->did > 0;
} }
METHOD(attest_db_t, set_file, bool, METHOD(attest_db_t, set_file, bool,
private_attest_db_t *this, char *file, bool create) private_attest_db_t *this, char *file, bool create)
{ {
int fid;
char *sep;
enumerator_t *e; enumerator_t *e;
char *filename;
if (this->file_set) if (this->file)
{ {
printf("file has already been set\n"); printf("file has already been set\n");
return FALSE; return FALSE;
} }
this->file = strdup(file); this->file = strdup(file);
filename = this->relative ? basename(file) : file;
e = this->db->query(this->db, "SELECT id FROM files WHERE path = ?", if (!this->did)
DB_TEXT, filename, DB_INT); {
return TRUE;
}
sep = streq(this->dir, "/") ? "" : "/";
e = this->db->query(this->db, "SELECT id FROM files "
"WHERE dir = ? AND name = ?",
DB_INT, this->did, DB_TEXT, file, DB_INT);
if (e) if (e)
{ {
if (e->enumerate(e, &this->fid)) if (e->enumerate(e, &fid))
{ {
this->file_set = TRUE; this->fid = fid;
} }
e->destroy(e); e->destroy(e);
} }
if (this->file_set) if (this->fid)
{ {
return TRUE; return TRUE;
} }
if (!create) if (!create)
{ {
printf("file '%s' not found in database\n", file); printf("file '%s%s%s' not found in database\n", this->dir, sep, file);
return FALSE; return FALSE;
} }
/* Add a new database entry */ /* Add a new database entry */
this->file_set = this->db->execute(this->db, &this->fid, if (1 == this->db->execute(this->db, &fid,
"INSERT INTO files (type, path) VALUES (0, ?)", "INSERT INTO files (dir, name) VALUES (?, ?)",
DB_TEXT, filename) == 1; DB_INT, this->did, DB_TEXT, file))
{
this->fid = fid;
}
printf("file '%s%s%s' %sinserted into database\n", this->dir, sep, file,
this->fid ? "" : "could not be ");
printf("file '%s' %sinserted into database\n", filename, return this->fid > 0;
this->file_set ? "" : "could not be ");
return this->file_set;
} }
METHOD(attest_db_t, set_fid, bool, METHOD(attest_db_t, set_fid, bool,
private_attest_db_t *this, int fid) private_attest_db_t *this, int fid)
{ {
enumerator_t *e; enumerator_t *e;
int did;
char *file; char *file;
if (this->file_set) if (this->fid)
{ {
printf("file has already been set\n"); printf("file has already been set\n");
return FALSE; return FALSE;
} }
this->fid = fid;
e = this->db->query(this->db, "SELECT path FROM files WHERE id = ?", e = this->db->query(this->db, "SELECT dir, name FROM files WHERE id = ?",
DB_UINT, fid, DB_TEXT); DB_UINT, fid, DB_INT, DB_TEXT);
if (e) if (e)
{ {
if (e->enumerate(e, &file)) if (e->enumerate(e, &did, &file))
{ {
if (did)
{
set_did(this, did);
}
this->file = strdup(file); this->file = strdup(file);
this->file_set = TRUE; this->fid = fid;
} }
else else
{ {
@@ -460,7 +461,7 @@ METHOD(attest_db_t, set_fid, bool,
} }
e->destroy(e); e->destroy(e);
} }
return this->file_set; return this->fid > 0;
} }
METHOD(attest_db_t, set_key, bool, METHOD(attest_db_t, set_key, bool,
@@ -920,53 +921,92 @@ METHOD(attest_db_t, list_files, void,
private_attest_db_t *this) private_attest_db_t *this)
{ {
enumerator_t *e; enumerator_t *e;
char *file, *file_type[] = { " ", "d", "r" }; char *dir, *file;
int fid, type, meas, meta, count = 0; int did, last_did = 0, fid, count = 0;
if (this->pid) if (this->did)
{ {
e = this->db->query(this->db, e = this->db->query(this->db,
"SELECT f.id, f.type, f.path, pf.measurement, pf.metadata " "SELECT id, name FROM files WHERE dir = ? ORDER BY name",
"FROM files AS f " DB_INT, this->did, DB_INT, DB_TEXT);
"JOIN product_file AS pf ON f.id = pf.file "
"WHERE pf.product = ? ORDER BY f.path",
DB_UINT, this->pid, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT);
if (e) if (e)
{ {
while (e->enumerate(e, &fid, &type, &file, &meas, &meta)) while (e->enumerate(e, &fid, &file))
{ {
type = (type < 0 || type > 2) ? 0 : type; printf("%4d: %s\n", fid, file);
printf("%4d: |%s%s| %s %s\n", fid, meas ? "M":" ", meta ? "T":" ",
file_type[type], file);
count++; count++;
} }
e->destroy(e); e->destroy(e);
} }
printf("%d file%s found in directory '%s'\n", count,
(count == 1) ? "" : "s", this->dir);
} }
else else
{ {
e = this->db->query(this->db, e = this->db->query(this->db,
"SELECT id, type, path FROM files " "SELECT d.id, d.path, f.id, f.name FROM files AS f "
"ORDER BY path", "JOIN directories AS d ON f.dir = d.id "
DB_INT, DB_INT, DB_TEXT); "ORDER BY d.path, f.name",
DB_INT, DB_TEXT, DB_INT, DB_TEXT);
if (e) if (e)
{ {
while (e->enumerate(e, &fid, &type, &file)) while (e->enumerate(e, &did, &dir, &fid, &file))
{ {
type = (type < 0 || type > 2) ? 0 : type; if (did != last_did)
printf("%4d: %s %s\n", fid, file_type[type], file); {
printf("%4d: %s\n", did, dir);
last_did = did;
}
printf("%4d: %s\n", fid, file);
count++; count++;
} }
e->destroy(e); e->destroy(e);
} }
printf("%d file%s found\n", count, (count == 1) ? "" : "s");
} }
}
printf("%d file%s found", count, (count == 1) ? "" : "s"); METHOD(attest_db_t, list_directories, void,
if (this->product_set) private_attest_db_t *this)
{
enumerator_t *e;
char *dir;
int did, count = 0;
if (this->file)
{ {
printf(" for product '%s'", this->product); e = this->db->query(this->db,
"SELECT d.id, d.path FROM directories AS d "
"JOIN files AS f ON f.dir = d.id WHERE f.name = ? "
"ORDER BY path", DB_TEXT, this->file, DB_INT, DB_TEXT);
if (e)
{
while (e->enumerate(e, &did, &dir))
{
printf("%4d: %s\n", did, dir);
count++;
}
e->destroy(e);
}
printf("%d director%s found containing file '%s'\n", count,
(count == 1) ? "y" : "ies", this->file);
}
else
{
e = this->db->query(this->db,
"SELECT id, path FROM directories ORDER BY path",
DB_INT, DB_TEXT);
if (e)
{
while (e->enumerate(e, &did, &dir))
{
printf("%4d: %s\n", did, dir);
count++;
}
e->destroy(e);
}
printf("%d director%s found\n", count, (count == 1) ? "y" : "ies");
} }
printf("\n");
} }
METHOD(attest_db_t, list_packages, void, METHOD(attest_db_t, list_packages, void,
@@ -1077,7 +1117,7 @@ METHOD(attest_db_t, list_products, void,
} }
printf("%d product%s found", count, (count == 1) ? "" : "s"); printf("%d product%s found", count, (count == 1) ? "" : "s");
if (this->file_set) if (this->fid)
{ {
printf(" for file '%s'", this->file); printf(" for file '%s'", this->file);
} }
@@ -1607,6 +1647,9 @@ METHOD(attest_db_t, delete, bool,
private_attest_db_t *this) private_attest_db_t *this)
{ {
bool success; bool success;
int id, count = 0;
char *name;
enumerator_t *e;
/* delete a file measurement hash for a given product */ /* delete a file measurement hash for a given product */
if (this->algo && this->pid && this->fid) if (this->algo && this->pid && this->fid)
@@ -1667,24 +1710,44 @@ METHOD(attest_db_t, delete, bool,
return success; return success;
} }
if (this->did)
{
success = this->db->execute(this->db, NULL,
"DELETE FROM files WHERE type = 1 AND id = ?",
DB_UINT, this->did) > 0;
printf("directory '%s' %sdeleted from database\n", this->dir,
success ? "" : "could not be ");
return success;
}
if (this->fid) if (this->fid)
{ {
success = this->db->execute(this->db, NULL, success = this->db->execute(this->db, NULL,
"DELETE FROM files WHERE id = ?", "DELETE FROM files WHERE id = ?",
DB_UINT, this->fid) > 0; DB_UINT, this->fid) > 0;
printf("file '%s' %sdeleted from database\n", this->file, printf("file '%s%s%s' %sdeleted from database\n", this->dir,
streq(this->dir, "/") ? "" : "/", this->file,
success ? "" : "could not be ");
return success;
}
if (this->did)
{
e = this->db->query(this->db,
"SELECT id, name FROM files WHERE dir = ? ORDER BY name",
DB_INT, this->did, DB_INT, DB_TEXT);
if (e)
{
while (e->enumerate(e, &id, &name))
{
printf("%4d: %s\n", id, name);
count++;
}
e->destroy(e);
if (count)
{
printf("%d dependent file%s found, "
"directory '%s' could not deleted\n",
count, (count == 1) ? "" : "s", this->dir);
return FALSE;
}
}
success = this->db->execute(this->db, NULL,
"DELETE FROM directories WHERE id = ?",
DB_UINT, this->did) > 0;
printf("directory '%s' %sdeleted from database\n", this->dir,
success ? "" : "could not be "); success ? "" : "could not be ");
return success; return success;
} }
@@ -1760,6 +1823,7 @@ attest_db_t *attest_db_create(char *uri)
.list_packages = _list_packages, .list_packages = _list_packages,
.list_products = _list_products, .list_products = _list_products,
.list_files = _list_files, .list_files = _list_files,
.list_directories = _list_directories,
.list_components = _list_components, .list_components = _list_components,
.list_devices = _list_devices, .list_devices = _list_devices,
.list_keys = _list_keys, .list_keys = _list_keys,
@@ -1769,7 +1833,6 @@ attest_db_t *attest_db_create(char *uri)
.delete = _delete, .delete = _delete,
.destroy = _destroy, .destroy = _destroy,
}, },
.dir = strdup(""),
.db = lib->db->create(lib->db, uri), .db = lib->db->create(lib->db, uri),
); );
@@ -192,6 +192,11 @@ struct attest_db_t {
*/ */
void (*list_products)(attest_db_t *this); void (*list_products)(attest_db_t *this);
/**
* List all directories stored in the database
*/
void (*list_directories)(attest_db_t *this);
/** /**
* List selected files stored in the database * List selected files stored in the database
*/ */
+24 -33
View File
@@ -1,14 +1,24 @@
/* PTS SQLite database */ /* PTS SQLite database */
DROP TABLE IF EXISTS directories;
CREATE TABLE directories (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
path TEXT NOT NULL
);
DROP INDEX IF EXISTS directories_path;
CREATE INDEX directories_path ON directories (
path
);
DROP TABLE IF EXISTS files; DROP TABLE IF EXISTS files;
CREATE TABLE files ( CREATE TABLE files (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
type INTEGER NOT NULL, dir INTEGER DEFAULT 0,
path TEXT NOT NULL name TEXT NOT NULL
); );
DROP INDEX IF EXISTS files_path; DROP INDEX IF EXISTS files_name;
CREATE INDEX files_path ON files ( CREATE INDEX files_name ON files (
path name
); );
DROP TABLE IF EXISTS products; DROP TABLE IF EXISTS products;
@@ -21,39 +31,20 @@ CREATE INDEX products_name ON products (
name name
); );
DROP TABLE IF EXISTS product_file; DROP TABLE IF EXISTS algorithms;
CREATE TABLE product_file ( CREATE TABLE algorithms (
product INTEGER NOT NULL, id INTEGER PRIMARY KEY,
file INTEGER NOT NULL, name TEXT not NULL
measurement INTEGER DEFAULT 0,
metadata INTEGER DEFAULT 0,
PRIMARY KEY (product, file)
); );
DROP TABLE IF EXISTS file_hashes; DROP TABLE IF EXISTS file_hashes;
CREATE TABLE file_hashes ( CREATE TABLE file_hashes (
file INTEGER NOT NULL,
directory INTEGER DEFAULT 0,
product INTEGER NOT NULL,
key INTEGER DEFAULT 0,
algo INTEGER NOT NULL,
hash BLOB NOT NULL,
PRIMARY KEY(file, directory, product, algo)
);
DROP TABLE IF EXISTS keys;
CREATE TABLE keys (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
keyid BLOB NOT NULL, file INTEGER NOT NULL,
owner TEXT NOT NULL product INTEGER NOT NULL,
); device INTEGER DEFAULT 0,
DROP INDEX IF EXISTS keys_keyid; algo INTEGER NOT NULL,
CREATE INDEX keys_keyid ON keys ( hash BLOB NOT NULL
keyid
);
DROP INDEX IF EXISTS keys_owner;
CREATE INDEX keys_owner ON keys (
owner
); );
DROP TABLE IF EXISTS components; DROP TABLE IF EXISTS components;