/*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2013 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
#include <string.h>
#include <errno.h>
#include <syslog.h>
+#include <libgen.h>
#include <library.h>
#include <utils/debug.h>
*/
attest_db_t *attest;
+
/**
* atexit handler to close db on shutdown
*/
OP_KEYS,
OP_COMPONENTS,
OP_DEVICES,
+ OP_DIRECTORIES,
OP_FILES,
OP_HASHES,
OP_MEASUREMENTS,
{ "help", no_argument, NULL, 'h' },
{ "components", no_argument, NULL, 'c' },
{ "devices", no_argument, NULL, 'e' },
+ { "directories", no_argument, NULL, 'd' },
+ { "dirs", no_argument, NULL, 'd' },
{ "files", no_argument, NULL, 'f' },
{ "keys", no_argument, NULL, 'k' },
{ "packages", no_argument, NULL, 'g' },
{ "hashes", no_argument, NULL, 'H' },
{ "measurements", no_argument, NULL, 'm' },
{ "add", no_argument, NULL, 'a' },
- { "delete", no_argument, NULL, 'd' },
- { "del", no_argument, NULL, 'd' },
+ { "delete", no_argument, NULL, 'r' },
+ { "del", no_argument, NULL, 'r' },
+ { "remove", no_argument, NULL, 'r' },
{ "aik", required_argument, NULL, 'A' },
{ "blacklist", no_argument, NULL, 'B' },
{ "component", required_argument, NULL, 'C' },
case 'c':
op = OP_COMPONENTS;
continue;
+ case 'd':
+ op = OP_DIRECTORIES;
+ continue;
case 'e':
op = OP_DEVICES;
continue;
case 'a':
op = OP_ADD;
continue;
- case 'd':
+ case 'r':
op = OP_DEL;
continue;
case 'A':
}
continue;
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);
}
continue;
+ }
case 'G':
if (!attest->set_package(attest, optarg, op == OP_ADD))
{
case OP_DEVICES:
attest->list_devices(attest);
break;
+ case OP_DIRECTORIES:
+ attest->list_directories(attest);
+ break;
case OP_FILES:
attest->list_files(attest);
break;
int did;
/**
- * TRUE if directory has been set
- */
- bool dir_set;
-
- /**
* Measurement file to be queried
*/
char *file;
int fid;
/**
- * TRUE if file has been set
- */
- bool file_set;
-
- /**
* AIK to be queried
*/
chunk_t key;
private_attest_db_t *this, char *dir, bool create)
{
enumerator_t *e;
+ int did;
size_t len;
- if (this->dir_set)
+ if (this->did)
{
printf("directory has already been set\n");
return FALSE;
}
- free(this->dir);
- /* remove trailing '/' character */
+ /* remove trailing '/' character if not root directory */
len = strlen(dir);
- if (len && dir[len-1] == '/')
+ if (len > 1 && dir[len-1] == '/')
{
dir[len-1] = '\0';
}
this->dir = strdup(dir);
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);
if (e)
{
- if (e->enumerate(e, &this->did))
+ if (e->enumerate(e, &did))
{
- this->dir_set = TRUE;
+ this->did = did;
}
e->destroy(e);
}
- if (this->dir_set)
+ if (this->did)
{
return TRUE;
}
}
/* Add a new database entry */
- this->dir_set = this->db->execute(this->db, &this->did,
- "INSERT INTO files (type, path) VALUES (1, ?)",
- DB_TEXT, dir) == 1;
-
+ if (1 == this->db->execute(this->db, &did,
+ "INSERT INTO directories (path) VALUES (?)", DB_TEXT, dir))
+ {
+ this->did = did;
+ }
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,
enumerator_t *e;
char *dir;
- if (this->dir_set)
+ if (this->did)
{
printf("directory has already been set\n");
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);
if (e)
{
if (e->enumerate(e, &dir))
{
- free(this->dir);
this->dir = strdup(dir);
- this->dir_set = TRUE;
+ this->did = did;
}
else
{
}
e->destroy(e);
}
- return this->dir_set;
+ return this->did > 0;
}
METHOD(attest_db_t, set_file, bool,
private_attest_db_t *this, char *file, bool create)
{
+ int fid;
+ char *sep;
enumerator_t *e;
- char *filename;
- if (this->file_set)
+ if (this->file)
{
printf("file has already been set\n");
return FALSE;
}
this->file = strdup(file);
- filename = this->relative ? basename(file) : file;
- e = this->db->query(this->db, "SELECT id FROM files WHERE path = ?",
- DB_TEXT, filename, DB_INT);
+ if (!this->did)
+ {
+ 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->enumerate(e, &this->fid))
+ if (e->enumerate(e, &fid))
{
- this->file_set = TRUE;
+ this->fid = fid;
}
e->destroy(e);
}
- if (this->file_set)
+ if (this->fid)
{
return TRUE;
}
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;
}
/* Add a new database entry */
- this->file_set = this->db->execute(this->db, &this->fid,
- "INSERT INTO files (type, path) VALUES (0, ?)",
- DB_TEXT, filename) == 1;
-
- printf("file '%s' %sinserted into database\n", filename,
- this->file_set ? "" : "could not be ");
+ if (1 == this->db->execute(this->db, &fid,
+ "INSERT INTO files (dir, name) VALUES (?, ?)",
+ 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 ");
- return this->file_set;
+ return this->fid > 0;
}
METHOD(attest_db_t, set_fid, bool,
private_attest_db_t *this, int fid)
{
enumerator_t *e;
+ int did;
char *file;
- if (this->file_set)
+ if (this->fid)
{
printf("file has already been set\n");
return FALSE;
}
- this->fid = fid;
- e = this->db->query(this->db, "SELECT path FROM files WHERE id = ?",
- DB_UINT, fid, DB_TEXT);
+ e = this->db->query(this->db, "SELECT dir, name FROM files WHERE id = ?",
+ DB_UINT, fid, DB_INT, DB_TEXT);
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_set = TRUE;
+ this->fid = fid;
}
else
{
}
e->destroy(e);
}
- return this->file_set;
+ return this->fid > 0;
}
METHOD(attest_db_t, set_key, bool,
private_attest_db_t *this)
{
enumerator_t *e;
- char *file, *file_type[] = { " ", "d", "r" };
- int fid, type, meas, meta, count = 0;
+ char *dir, *file;
+ int did, last_did = 0, fid, count = 0;
- if (this->pid)
+ if (this->did)
{
e = this->db->query(this->db,
- "SELECT f.id, f.type, f.path, pf.measurement, pf.metadata "
- "FROM files AS f "
- "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);
+ "SELECT id, name FROM files WHERE dir = ? ORDER BY name",
+ DB_INT, this->did, DB_INT, DB_TEXT);
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%s| %s %s\n", fid, meas ? "M":" ", meta ? "T":" ",
- file_type[type], file);
+ printf("%4d: %s\n", fid, file);
count++;
}
e->destroy(e);
}
+ printf("%d file%s found in directory '%s'\n", count,
+ (count == 1) ? "" : "s", this->dir);
}
else
{
e = this->db->query(this->db,
- "SELECT id, type, path FROM files "
- "ORDER BY path",
- DB_INT, DB_INT, DB_TEXT);
+ "SELECT d.id, d.path, f.id, f.name FROM files AS f "
+ "JOIN directories AS d ON f.dir = d.id "
+ "ORDER BY d.path, f.name",
+ DB_INT, DB_TEXT, DB_INT, DB_TEXT);
if (e)
{
- while (e->enumerate(e, &fid, &type, &file))
+ while (e->enumerate(e, &did, &dir, &fid, &file))
{
- type = (type < 0 || type > 2) ? 0 : type;
- printf("%4d: %s %s\n", fid, file_type[type], file);
+ if (did != last_did)
+ {
+ printf("%4d: %s\n", did, dir);
+ last_did = did;
+ }
+ printf("%4d: %s\n", fid, file);
count++;
}
e->destroy(e);
}
+ printf("%d file%s found\n", count, (count == 1) ? "" : "s");
}
+}
- printf("%d file%s found", count, (count == 1) ? "" : "s");
- if (this->product_set)
+METHOD(attest_db_t, list_directories, void,
+ 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,
}
printf("%d product%s found", count, (count == 1) ? "" : "s");
- if (this->file_set)
+ if (this->fid)
{
printf(" for file '%s'", this->file);
}
private_attest_db_t *this)
{
bool success;
+ int id, count = 0;
+ char *name;
+ enumerator_t *e;
/* delete a file measurement hash for a given product */
if (this->algo && this->pid && this->fid)
return success;
}
- if (this->did)
+ if (this->fid)
{
success = this->db->execute(this->db, NULL,
- "DELETE FROM files WHERE type = 1 AND id = ?",
- DB_UINT, this->did) > 0;
+ "DELETE FROM files WHERE id = ?",
+ DB_UINT, this->fid) > 0;
- printf("directory '%s' %sdeleted from database\n", this->dir,
+ printf("file '%s%s%s' %sdeleted from database\n", this->dir,
+ streq(this->dir, "/") ? "" : "/", this->file,
success ? "" : "could not be ");
return success;
}
- if (this->fid)
+ if (this->did)
{
- success = this->db->execute(this->db, NULL,
- "DELETE FROM files WHERE id = ?",
- DB_UINT, this->fid) > 0;
+ 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);
- printf("file '%s' %sdeleted from database\n", this->file,
+ 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 ");
return success;
}
.list_packages = _list_packages,
.list_products = _list_products,
.list_files = _list_files,
+ .list_directories = _list_directories,
.list_components = _list_components,
.list_devices = _list_devices,
.list_keys = _list_keys,
.delete = _delete,
.destroy = _destroy,
},
- .dir = strdup(""),
.db = lib->db->create(lib->db, uri),
);