sw-collector: Added --check option

This commit is contained in:
Andreas Steffen
2018-04-27 11:42:34 +02:00
parent 8929c700ef
commit 234ec9225d
2 changed files with 103 additions and 6 deletions
+11 -1
View File
@@ -34,6 +34,12 @@ sw-collector \- Extracts software installation events from dpkg history log
.YS .YS
. .
.SY "sw-collector" .SY "sw-collector"
.OP \-\-debug level
.OP \-\-quiet
.BR \-\-check
.YS
.
.SY "sw-collector"
.B \-h .B \-h
| |
.B \-\-help .B \-\-help
@@ -76,7 +82,7 @@ installation status.
.B "\-u, \-\-unregistered" .B "\-u, \-\-unregistered"
Lists all software packages residing in the local collector database but for Lists all software packages residing in the local collector database but for
which no SWID tags exist yet in a central collector database reachable via a which no SWID tags exist yet in a central collector database reachable via a
REST interface. REST interface.
.TP .TP
.B "\-g, \-\-generate" .B "\-g, \-\-generate"
Generates ISO 19770-2:2015 SWID tags for all software packages residing in the Generates ISO 19770-2:2015 SWID tags for all software packages residing in the
@@ -86,6 +92,10 @@ database reachable via a REST interface.
.B "\-m, \-\-migrate" .B "\-m, \-\-migrate"
Can be used to migrate collector database versions. Currently all architecture Can be used to migrate collector database versions. Currently all architecture
suffixes are removed from dpkg package names. suffixes are removed from dpkg package names.
.TP
.B "\-C, \-\-check"
Checks the integrity of the collector database against the actual list of
installed packages obtained with dpkg-query.
. .
.SH "CONFIGURATION" .SH "CONFIGURATION"
. .
+92 -5
View File
@@ -31,9 +31,10 @@
#include <library.h> #include <library.h>
#include <utils/debug.h> #include <utils/debug.h>
#include <utils/lexparser.h> #include <utils/lexparser.h>
#include <collections/hashtable.h>
#include <swid_gen/swid_gen.h> #include <swid_gen/swid_gen.h>
#include <swid_gen/swid_gen_info.h>
/** /**
* global debug output variables * global debug output variables
*/ */
@@ -48,7 +49,8 @@ enum collector_op_t {
COLLECTOR_OP_LIST, COLLECTOR_OP_LIST,
COLLECTOR_OP_UNREGISTERED, COLLECTOR_OP_UNREGISTERED,
COLLECTOR_OP_GENERATE, COLLECTOR_OP_GENERATE,
COLLECTOR_OP_MIGRATE COLLECTOR_OP_MIGRATE,
COLLECTOR_OP_CHECK
}; };
/** /**
@@ -119,7 +121,8 @@ Usage:\n\
--list|-unregistered\n\ --list|-unregistered\n\
sw-collector [--debug <level>] [--quiet] [--installed|--removed] \ sw-collector [--debug <level>] [--quiet] [--installed|--removed] \
[--full] --generate\n\ [--full] --generate\n\
sw-collector [--debug <level>] [--quiet] --migrate\n"); sw-collector [--debug <level>] [--quiet] --migrate\n\
sw-collector [--debug <level>] [--quiet] --check\n");
} }
/** /**
@@ -140,6 +143,7 @@ static collector_op_t do_args(int argc, char *argv[], bool *full_tags,
struct option long_opts[] = { struct option long_opts[] = {
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "check", no_argument, NULL, 'C' },
{ "count", required_argument, NULL, 'c' }, { "count", required_argument, NULL, 'c' },
{ "debug", required_argument, NULL, 'd' }, { "debug", required_argument, NULL, 'd' },
{ "full", no_argument, NULL, 'f' }, { "full", no_argument, NULL, 'f' },
@@ -153,7 +157,7 @@ static collector_op_t do_args(int argc, char *argv[], bool *full_tags,
{ 0,0,0,0 } { 0,0,0,0 }
}; };
c = getopt_long(argc, argv, "hc:d:fgilmqru", long_opts, NULL); c = getopt_long(argc, argv, "hCc:d:fgilmqru", long_opts, NULL);
switch (c) switch (c)
{ {
case EOF: case EOF:
@@ -162,6 +166,9 @@ static collector_op_t do_args(int argc, char *argv[], bool *full_tags,
usage(); usage();
exit(SUCCESS); exit(SUCCESS);
break; break;
case 'C':
op = COLLECTOR_OP_CHECK;
continue;
case 'c': case 'c':
count = atoi(optarg); count = atoi(optarg);
continue; continue;
@@ -537,7 +544,7 @@ end:
} }
/** /**
* Append missing architecture suffix to package entries in the database * Remove architecture suffix from package entries in the database
*/ */
static int migrate(sw_collector_db_t *db) static int migrate(sw_collector_db_t *db)
{ {
@@ -582,6 +589,83 @@ static int migrate(sw_collector_db_t *db)
return status; return status;
} }
/**
* Free hashtable entry
*/
static void free_entry(void *value, void *key)
{
free(value);
free(key);
}
/**
* Check consistency of installed software identifiers in collector database
*/
static int check(sw_collector_db_t *db)
{
sw_collector_dpkg_t *dpkg;
swid_gen_info_t *info;
hashtable_t *table;
enumerator_t *e;
char *dpkg_name, *name, *package, *arch, *version;
uint32_t sw_id, count = 0, installed;
dpkg = sw_collector_dpkg_create();
if (!dpkg)
{
return EXIT_FAILURE;
}
info = swid_gen_info_create();
table = hashtable_create(hashtable_hash_str, hashtable_equals_str, 4096);
/* Store all installed sw identifiers (according to dpkg) in hashtable */
e = dpkg->create_sw_enumerator(dpkg);
while (e->enumerate(e, &package, &arch, &version))
{
dpkg_name = info->create_sw_id(info, package, version);
table->put(table, strdup(package), dpkg_name);
}
e->destroy(e);
info->destroy(info);
dpkg->destroy(dpkg);
e = db->create_sw_enumerator(db, SW_QUERY_ALL, NULL);
if (!e)
{
return EXIT_FAILURE;
}
while (e->enumerate(e, &sw_id, &name, &package, &version, &installed))
{
dpkg_name = table->get(table, package);
if (installed)
{
if (!dpkg_name)
{
printf("%4d %s erroneously noted as installed\n", sw_id, name);
}
else if (!streq(name, dpkg_name))
{
printf("%4d %s erroneously noted as installed instead of\n "
" %s\n", sw_id, name, dpkg_name);
}
}
else
{
if (dpkg_name && streq(name, dpkg_name))
{
printf("%4d %s erroneously noted as removed\n", sw_id, name);
}
}
count++;
}
e->destroy(e);
table->destroy_function(table, (void*)free_entry);
printf("checked %d software identifiers\n", count);
return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@@ -646,6 +730,9 @@ int main(int argc, char *argv[])
case COLLECTOR_OP_MIGRATE: case COLLECTOR_OP_MIGRATE:
status = migrate(db); status = migrate(db);
break; break;
case COLLECTOR_OP_CHECK:
status = check(db);
break;
} }
db->destroy(db); db->destroy(db);