Implemented pacman in a more reliable way
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 21 Jun 2013 12:15:18 +0000 (14:15 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 21 Jun 2013 21:25:25 +0000 (23:25 +0200)
src/libimcv/imv/data.sql
src/libimcv/plugins/imv_os/imv_os_database.c
src/libimcv/plugins/imv_os/pacman.c
src/libimcv/plugins/imv_os/pacman.sh

index dcc4e75..46e0c44 100644 (file)
@@ -3,61 +3,61 @@
 INSERT INTO products (                 /*  1 */
   name
 ) VALUES (
- 'Debian 7.0'
+ 'Debian 6.0 i686'
 );
 
 INSERT INTO products (                 /*  2 */
   name
 ) VALUES (
- 'Debian 7.0 i686'
+ 'Debian 6.0 x86_64'
 );
 
 INSERT INTO products (                 /*  3 */
   name
 ) VALUES (
- 'Debian 7.0 x86_64'
+ 'Debian 7.0 i686'
 );
 
 INSERT INTO products (                 /*  4 */
   name
 ) VALUES (
- 'Ubuntu 10.04'
+ 'Debian 7.0 x86_64'
 );
 
 INSERT INTO products (                 /*  5 */
   name
 ) VALUES (
- 'Ubuntu 10.04 i686'
+ 'Debian 8.0 i686'
 );
 
 INSERT INTO products (                 /*  6 */
   name
 ) VALUES (
- 'Ubuntu 10.04 x86_64'
+ 'Debian 8.0 x86_64'
 );
 
 INSERT INTO products (                 /*  7 */
   name
 ) VALUES (
- 'Ubuntu 10.10'
+ 'Ubuntu 10.04 i686'
 );
 
 INSERT INTO products (                 /*  8 */
   name
 ) VALUES (
- 'Ubuntu 10.10 i686'
+ 'Ubuntu 10.04 x86_64'
 );
 
 INSERT INTO products (                 /*  9 */
   name
 ) VALUES (
- 'Ubuntu 10.10 x86_64'
+ 'Ubuntu 10.10 i686'
 );
 
 INSERT INTO products (                 /* 10 */
   name
 ) VALUES (
- 'Ubuntu 11.04'
+ 'Ubuntu 10.10 x86_64'
 );
 
 INSERT INTO products (                 /* 11 */
@@ -75,82 +75,58 @@ INSERT INTO products (                      /* 12 */
 INSERT INTO products (                 /* 13 */
   name
 ) VALUES (
- 'Ubuntu 11.10'
-);
-
-INSERT INTO products (                 /* 14 */
-  name
-) VALUES (
  'Ubuntu 11.10 i686'
 );
 
-INSERT INTO products (                 /* 15 */
+INSERT INTO products (                 /* 14 */
   name
 ) VALUES (
  'Ubuntu 11.10 x86_64'
 );
 
-INSERT INTO products (                 /* 16 */
-  name
-) VALUES (
- 'Ubuntu 12.04'
-);
-
-INSERT INTO products (                 /* 17 */
+INSERT INTO products (                 /* 15 */
   name
 ) VALUES (
  'Ubuntu 12.04 i686'
 );
 
-INSERT INTO products (                 /* 18 */
+INSERT INTO products (                 /* 16 */
   name
 ) VALUES (
  'Ubuntu 12.04 x86_64'
 );
 
-INSERT INTO products (                 /* 19 */
-  name
-) VALUES (
- 'Ubuntu 12.10'
-);
-
-INSERT INTO products (                 /* 20 */
+INSERT INTO products (                 /* 17 */
   name
 ) VALUES (
  'Ubuntu 12.10 i686'
 );
 
-INSERT INTO products (                 /* 21 */
+INSERT INTO products (                 /* 18 */
   name
 ) VALUES (
  'Ubuntu 12.10 x86_64'
 );
 
-INSERT INTO products (                 /* 22 */
-  name
-) VALUES (
- 'Ubuntu 13.04'
-);
-
-INSERT INTO products (                 /* 23 */
+INSERT INTO products (                 /* 19 */
   name
 ) VALUES (
  'Ubuntu 13.04 i686'
 );
 
-INSERT INTO products (                 /* 24 */
+INSERT INTO products (                 /* 20 */
   name
 ) VALUES (
  'Ubuntu 13.04 x86_64'
 );
 
-INSERT INTO products (                 /* 25 */
+INSERT INTO products (                 /* 21 */
   name
 ) VALUES (
  'Android 4.1.1'
 );
 
-INSERT INTO products (                 /* 26 */
+INSERT INTO products (                 /* 22 */
   name
 ) VALUES (
  'Android 4.2.1'
@@ -299,109 +275,109 @@ INSERT INTO algorithms (
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  3, 2, 32768, X'6c6f8e12f6cbfba612e780374c4cdcd40f20968a' 
+  4, 2, 32768, X'6c6f8e12f6cbfba612e780374c4cdcd40f20968a' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  3, 2, 16384, X'dbcecd19d59310183cf5c31ddee29e8d7bec64d3f9583aad074330a1b3024b07' 
+  4, 2, 16384, X'dbcecd19d59310183cf5c31ddee29e8d7bec64d3f9583aad074330a1b3024b07' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  3, 2, 8192, X'197c5385e5853003188833d4f991136c1b0875fa416a60b1159f64e57e457b3184762c884a802a2bda194c058e3bd953' 
+  4, 2, 8192, X'197c5385e5853003188833d4f991136c1b0875fa416a60b1159f64e57e457b3184762c884a802a2bda194c058e3bd953' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  3, 4, 32768, X'3ad204f99eb7262efab79cfca02628870ea76361' 
+  4, 4, 32768, X'3ad204f99eb7262efab79cfca02628870ea76361' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  3, 4, 16384, X'3a2170aad92fdd58b55e0e199822bc873cf587b2d1eb1ed7ed8dcea97ae86376' 
+  4, 4, 16384, X'3a2170aad92fdd58b55e0e199822bc873cf587b2d1eb1ed7ed8dcea97ae86376' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  3, 4, 8192, X'f778076baa876b5e4b502494a3db081fb09dd870dee6991d54104a74b7e009c58fe261db5ffd13c11e08ef0cefcfa59f' 
+  4, 4, 8192, X'f778076baa876b5e4b502494a3db081fb09dd870dee6991d54104a74b7e009c58fe261db5ffd13c11e08ef0cefcfa59f' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  3, 5, 32768, X'ecd9c7076cc0572724c7a67db7f19c2831e0445f' 
+  4, 5, 32768, X'ecd9c7076cc0572724c7a67db7f19c2831e0445f' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  3, 5, 16384, X'28f3ea5afd34444c8232ea75003131e294a0c9b847de300e4b205d38c1a41305' 
+  4, 5, 16384, X'28f3ea5afd34444c8232ea75003131e294a0c9b847de300e4b205d38c1a41305' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  3, 5, 8192, X'51921a8b9322f2d3f06d55002ff40a79da67e70cb563b2a50977642d603dfac2ccbb68b3d32a8bb350769b75d6254208' 
+  4, 5, 8192, X'51921a8b9322f2d3f06d55002ff40a79da67e70cb563b2a50977642d603dfac2ccbb68b3d32a8bb350769b75d6254208' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  21, 1, 32768, X'd9309b9e45928239d7a7b18711e690792632cce4' 
+  18, 1, 32768, X'd9309b9e45928239d7a7b18711e690792632cce4' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  21, 1, 16384, X'dbfa1856d278d8707c4989b30dd065b4bcd309908f0f2e6e66ff2aa83ff93f59' 
+  18, 1, 16384, X'dbfa1856d278d8707c4989b30dd065b4bcd309908f0f2e6e66ff2aa83ff93f59' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  21, 1, 8192, X'fb8d027f03bb5ebb47741ed247eb9e174127b714d20229885feb37e0979aeb14a1b74020cded891d680441093625729c' 
+  18, 1, 8192, X'fb8d027f03bb5ebb47741ed247eb9e174127b714d20229885feb37e0979aeb14a1b74020cded891d680441093625729c' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  21, 3, 32768, X'3715f2f94016a91fab5bbc503f0f1d43c5a9fc2b' 
+  18, 3, 32768, X'3715f2f94016a91fab5bbc503f0f1d43c5a9fc2b' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  21, 3, 16384, X'c03a5296b5decb87b01517f9927a8b2349dfb29ff9f5ba084f994c155ca5d4be' 
+  18, 3, 16384, X'c03a5296b5decb87b01517f9927a8b2349dfb29ff9f5ba084f994c155ca5d4be' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  21, 3, 8192, X'b8bc345f56115235cc6091f61e312ce43ea54a5b99e7295002ae7b415fd35e06ec4c731ab70ad00d784bb53a318a2fa0' 
+  18, 3, 8192, X'b8bc345f56115235cc6091f61e312ce43ea54a5b99e7295002ae7b415fd35e06ec4c731ab70ad00d784bb53a318a2fa0' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  21, 5, 32768, X'e59602f4edf24c1b36199588886d06665d4adcd7' 
+  18, 5, 32768, X'e59602f4edf24c1b36199588886d06665d4adcd7' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  21, 5, 16384, X'090e1b77bda7fe665e498c6b5e09dbb7ddc5cfe57f213de48f4fb6736484f500' 
+  18, 5, 16384, X'090e1b77bda7fe665e498c6b5e09dbb7ddc5cfe57f213de48f4fb6736484f500' 
 );
 
 INSERT INTO file_hashes (
   product, file, algo, hash
 ) VALUES (
-  21, 5, 8192, X'7cbdb4612a13443dba910ecdef5161f2213e52c9b4a2eef14bcee5d287e9df931cd022e9e9715518ad9c9b6e3384a668' 
+  18, 5, 8192, X'7cbdb4612a13443dba910ecdef5161f2213e52c9b4a2eef14bcee5d287e9df931cd022e9e9715518ad9c9b6e3384a668' 
 );
 
 /* Packages */
@@ -485,155 +461,180 @@ INSERT INTO components (
 /* Groups */
 
 INSERT INTO groups (                   /*  1 */
-  name, parent
+  name
 ) VALUES (
-  'Debian i686', 6
+  'Default'
 );
 
 INSERT INTO groups (                   /*  2 */
   name, parent
 ) VALUES (
-  'Debian x86_64', 6
+  'Linux', 1
 );
 
 INSERT INTO groups (                   /*  3 */
   name, parent
 ) VALUES (
-  'Ubuntu i686', 6
+  'Android', 1
 );
 
 INSERT INTO groups (                   /*  4 */
   name, parent
 ) VALUES (
-  'Ubuntu x86_64', 6
+  'Debian i686', 2
 );
 
 INSERT INTO groups (                   /*  5 */
   name, parent
 ) VALUES (
-  'Android', 7
+  'Debian x86_64', 2
 );
 
 INSERT INTO groups (                   /*  6 */
   name, parent
 ) VALUES (
-  'Linux', 7
+  'Ubuntu i686', 2
 );
 
 INSERT INTO groups (                   /*  7 */
-  name
+  name, parent
 ) VALUES (
-  'Default'
+  'Ubuntu x86_64', 2
 );
 
+
 /* Default Product Groups */
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  1, 2
+  4, 1
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  4, 3
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  4, 5
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  5, 2
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  5, 4
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  2, 3
+  5, 6
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  3, 5
+  6, 7
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  3, 8
+  6, 9
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  3, 11
+  6, 11
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  3, 14
+  6, 13
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  3, 17
+  6, 15
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  3, 20
+  6, 17
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  3, 23
+  6, 19
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  4, 6
+  7, 8
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  4, 9
+  7, 10
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  4, 12
+  7, 12
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  4, 15
+  7, 14
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  4, 18
+  7, 16
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  4, 21
+  7, 18
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  4, 24
+  7, 20
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  5, 25
+  3, 21
 );
 
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
-  5, 26
+  3, 22
 );
 
 /* Policies */
index c7f9b6b..a4cc015 100644 (file)
@@ -44,10 +44,8 @@ METHOD(imv_os_database_t, check_packages, status_t,
        enumerator_t *package_enumerator)
 {
        char *product, *package, *release, *cur_release;
-       u_char *pos;
-       chunk_t os_name, os_version, name, version;
+       chunk_t name, version;
        os_type_t os_type;
-       size_t os_version_len;
        os_package_state_t package_state;
        int pid, gid;
        int count = 0, count_ok = 0, count_no_match = 0, count_blacklist = 0;
@@ -55,21 +53,12 @@ METHOD(imv_os_database_t, check_packages, status_t,
        status_t status = SUCCESS;
        bool found, match;
 
-       state->get_info(state, &os_type, &os_name, &os_version);
+       product = state->get_info(state, &os_type, NULL, NULL);
 
        if (os_type == OS_TYPE_ANDROID)
        {
                /*no package dependency on Android version */
-               product = strdup(enum_to_name(os_type_names, os_type));
-       }
-       else
-       {
-               /* remove appended platform info */
-               pos = memchr(os_version.ptr, ' ', os_version.len);
-               os_version_len = pos ? (pos - os_version.ptr) : os_version.len;
-               product = malloc(os_name.len + 1 + os_version_len + 1);
-               sprintf(product, "%.*s %.*s", (int)os_name.len, os_name.ptr,
-                                                                         (int)os_version_len, os_version.ptr);
+               product = enum_to_name(os_type_names, os_type);
        }
        DBG1(DBG_IMV, "processing installed '%s' packages", product);
 
@@ -79,13 +68,10 @@ METHOD(imv_os_database_t, check_packages, status_t,
                                DB_TEXT, product, DB_INT);
        if (!e)
        {
-               free(product);
-               return FAILED;
        }
        if (!e->enumerate(e, &pid))
        {
                e->destroy(e);
-               free(product);
                return NOT_FOUND;
        }
        e->destroy(e);
@@ -102,7 +88,6 @@ METHOD(imv_os_database_t, check_packages, status_t,
                                        DB_TEXT, package, DB_INT);
                if (!e)
                {
-                       free(product);
                        free(package);
                        return FAILED;
                }
@@ -130,7 +115,6 @@ METHOD(imv_os_database_t, check_packages, status_t,
                                DB_INT, pid, DB_INT, gid, DB_TEXT, DB_INT);
                if (!e)
                {
-                       free(product);
                        free(package);
                        free(release);
                        return FAILED;
@@ -181,7 +165,6 @@ METHOD(imv_os_database_t, check_packages, status_t,
                free(package);
                free(release);
        }
-       free(product);
        state->set_count(state, count, count_no_match, count_blacklist, count_ok);
 
        return status;
index 25e6376..f8922bf 100644 (file)
 #include <errno.h>
 #include <syslog.h>
 #include <time.h>
+#include <sys/stat.h>
 
 #include "imv_os_state.h"
 
 #include <library.h>
 #include <utils/debug.h>
 
+typedef enum pacman_state_t pacman_state_t;
+
+enum pacman_state_t {
+       PACMAN_STATE_BEGIN_PACKAGE,
+       PACMAN_STATE_VERSION,
+       PACMAN_STATE_END_PACKAGE
+};
+
+typedef struct stats_t stats_t;
+
+struct stats_t {
+       time_t release;
+       int product;
+       int packages;
+       int new_packages;
+       int new_versions;
+       int updated_versions;
+       int deleted_versions;
+};
+
 /**
  * global debug output variables
  */
@@ -88,54 +109,192 @@ static void usage(void)
 }
 
 /**
- * Extract the time the package file was generated
+ * Update the package database
  */
-static time_t extract_time(char *line)
+static bool update_database(database_t *db, char *package, char *version,
+                                                       bool security, stats_t *stats)
 {
-       struct tm t;
-       char wday[4], mon[4];
-       char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                                          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-       int i;
-
-       if (sscanf(line, "Generated: %3s %3s %2d %2d:%2d:%2d %4d UTC", wday, mon,
-                          &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) != 7)
+       char *cur_version, *version_update = NULL, *version_delete = NULL;
+       int cur_security, security_update = 0, security_delete = 0;
+       int pac_id = 0, vid = 0, vid_update = 0, vid_delete = 0;
+       u_int cur_time;
+       bool add_version = TRUE;
+       enumerator_t *e;
+
+       /* increment package count */
+       stats->packages++;
+
+       /* check if package is already in database */
+       e = db->query(db, "SELECT id FROM packages WHERE name = ?",
+                                         DB_TEXT, package, DB_INT);
+       if (!e)
+       {
+               return FALSE;
+       }
+       if (!e->enumerate(e, &pac_id))
+       {
+               pac_id = 0;
+       }
+       e->destroy(e);
+
+       if (!pac_id && security)
+       {
+               if (db->execute(db, &pac_id, "INSERT INTO packages (name) VALUES (?)",
+                                               DB_TEXT, package) != 1)
+               {
+                       fprintf(stderr, "could not store package '%s' to database\n",
+                                                        package);
+                       return FALSE;
+               }
+               stats->new_packages++;
+       }
+
+       /* check for package versions already in database */
+       e = db->query(db,
+                       "SELECT id, release, security, time FROM versions "
+                       "WHERE package = ? AND product = ?", DB_INT, pac_id,
+                        DB_INT, stats->product, DB_INT, DB_TEXT, DB_INT, DB_UINT);
+       if (!e)
        {
-               return UNDEFINED_TIME;
+               return FALSE;
        }
-       t.tm_isdst = 0;
-       t.tm_year -= 1900;
-       t.tm_mon = 12;
 
-       for (i = 0; i < countof(months); i++)
+       while (e->enumerate(e, &vid, &cur_version, &cur_security, &cur_time))
        {
-               if (streq(mon, months[i]))
+               if (streq(version, cur_version))
                {
-                       t.tm_mon = i;
+                       /* already in data base */
+                       add_version = FALSE;
                        break;
                }
+               else if (stats->release >= cur_time)
+               {
+                       if (security)
+                       {
+                               if (cur_security)
+                               {
+                                       vid_update = vid;
+                                       version_update = strdup(cur_version);
+                                       security_update = cur_security;
+                               }
+                               else
+                               {
+                                       vid_delete = vid;
+                                       version_delete = strdup(cur_version);
+                                       security_delete = cur_security;
+                               }
+                       }
+                       else
+                       {
+                               if (!cur_security)
+                               {
+                                       vid_update = vid;
+                                       version_update = strdup(cur_version);
+                                       security_update = cur_security;
+                               }
+                       }
+               }
+               else
+               {
+                       if (security == cur_security)
+                       {
+                               add_version = FALSE;
+                       }
+               }
+       }
+       e->destroy(e);
+
+       if ((!vid && !security) || (vid && !add_version))
+       {
+               free(version_update);
+               free(version_delete);
+               return TRUE;
+       }
+
+       if ((!vid && security) || (vid && !vid_update))
+       {
+               printf("%s (%s) %s\n", package, version, security ? "[s]" : "");
+
+               if (db->execute(db, &vid,
+                       "INSERT INTO versions "
+                       "(package, product, release, security, time) "
+                       "VALUES (?, ?, ?, ?, ?)", DB_INT, pac_id, DB_INT, stats->product,
+                       DB_TEXT, version, DB_INT, security, DB_INT, stats->release) != 1)
+               {
+                       fprintf(stderr, "could not store version '%s' to database\n",
+                                                        version);
+                       free(version_update);
+                       free(version_delete);
+                       return FALSE;
+               }
+               stats->new_versions++;
        }
-       if (t.tm_mon == 12)
+       else
        {
-               return UNDEFINED_TIME;
+               printf("%s (%s) %s updated by\n",
+                          package, version_update, security_update ? "[s]" : "");
+               printf("%s (%s) %s\n", package, version, security ? "[s]" : "");
+
+               if (db->execute(db, NULL,
+                       "UPDATE versions SET release = ?, time = ? WHERE id = ?",
+                       DB_TEXT, version, DB_INT, stats->release, DB_INT, vid_update) <= 0)
+               {
+                       fprintf(stderr, "could not update version '%s' to database\n",
+                                                        version);
+                       free(version_update);
+                       free(version_delete);
+                       return FALSE;
+               }
+               stats->updated_versions++;
        }
 
-       return mktime(&t) - timezone;
+       if (vid_delete)
+       {
+               printf("%s (%s) %s deleted\n",
+                          package, version_delete, security_delete ? "[s]" : "");
+                       if (db->execute(db, NULL,
+                       "DELETE FROM  versions WHERE id = ?",
+                       DB_INT, vid_delete) <= 0)
+               {
+                       fprintf(stderr, "could not delete version '%s' from database\n",
+                                                        version_delete);
+                       free(version_update);
+                       free(version_delete);
+                       return FALSE;
+               }
+               stats->deleted_versions++;
+       }
+       free(version_update);
+       free(version_delete);
+
+       return TRUE;
 }
 
 /**
  * Process a package file and store updates in the database
  */
-static void process_packages(char *filename, char *product, bool update)
+static void process_packages(char *filename, char *product, bool security)
 {
-       char *uri, line[12288], *pos;
-       int count = 0, errored = 0, vulnerable = 0, new_packages = 0;
-       int new_versions = 0, updated_versions = 0, deleted_versions = 0;
-       time_t gen_time;
-       u_int32_t pid = 0;
+       char *uri, line[BUF_LEN], *pos, *package = NULL, *version = NULL;
+       pacman_state_t pacman_state;
        enumerator_t *e;
        database_t *db;
+       int pid;
        FILE *file;
+       struct stat st;
+       stats_t stats;
+       bool success;
+
+       /* initialize statistics */
+       memset(&stats, 0x00, sizeof(stats_t));
+
+       /* getting creation date of package file */
+       if (stat(filename, &st))
+       {
+               fprintf(stderr, "unable to obtain creation date on '%s'", filename);
+               exit(EXIT_FAILURE);
+       }
+       stats.release = st.st_mtime;
 
        /* opening package file */
        printf("loading\"%s\"\n", filename);
@@ -167,13 +326,13 @@ static void process_packages(char *filename, char *product, bool update)
                                  DB_TEXT, product, DB_INT);
        if (e)
        {
-               if (!e->enumerate(e, &pid))
+               if (e->enumerate(e, &pid))
                {
-                       pid = 0;
+                       stats.product = pid;
                }
                e->destroy(e);
        }
-       if (!pid)
+       if (!stats.product)
        {
                if (db->execute(db, &pid, "INSERT INTO products (name) VALUES (?)",
                                                DB_TEXT, product) != 1)
@@ -184,248 +343,78 @@ static void process_packages(char *filename, char *product, bool update)
                        db->destroy(db);
                        exit(EXIT_FAILURE);
                }
+               stats.product = pid;
        }
 
+       pacman_state = PACMAN_STATE_BEGIN_PACKAGE;
+
        while (fgets(line, sizeof(line), file))
        {
-               char *package, *version;
-               char *cur_version, *version_update = NULL, *version_delete = NULL;
-               bool security, add_version = TRUE;
-               int cur_security, security_update = 0, security_delete = 0;
-               u_int32_t gid = 0, vid = 0, vid_update = 0, vid_delete = 0;
-               time_t cur_time;
-
-               count++;
-               if (count == 1)
-               {
-                       printf("%s", line);
-               }
-               if (count == 3)
-               {
-                       gen_time = extract_time(line);
+               /* set read pointer to beginning of line */
+               pos = line;
 
-                       if (gen_time == UNDEFINED_TIME)
-                       {
-                               fprintf(stderr, "could not extract generation time\n");
-                               fclose(file);
-                               db->destroy(db);
-                               exit(EXIT_FAILURE);
-                       }
-                       printf("Generated: %T\n", &gen_time, TRUE);
-               }
-               if (count < 7)
+               switch (pacman_state)
                {
-                       continue;
-               }
-
-               /* look for the package name */
-               pos = strchr(line, ' ');
-               if (!pos)
-               {
-                       fprintf(stderr, "could not extract package name from '%.*s'\n",
-                                       (int)(strlen(line)-1), line);
-                       errored++;
-                       continue;
-               }
-               *pos++ = '\0';
-               package = line;
-
-               /* look for version string in parentheses */
-               if (*pos == '(')
-               {
-                       version = ++pos;
-                       pos = strchr(pos, ')');
-                       if (pos)
-                       {
-                               *pos++ = '\0';
-                       }
-                       else
-                       {
-                               fprintf(stderr, "could not extract package version from "
-                                               "'%.*s'\n", (int)(strlen(line)-1), line);
-                               errored++;
-                               continue;
-                       }
-               }
-               else
-               {
-                       /* no version information, skip entry */
-                       continue;
-               }
-               security = (strstr(pos, "[security]") != NULL);
-               if (security)
-               {
-                       vulnerable++;
-               }
-
-               /* handle non-security packages in update mode only */
-               if (!update && !security)
-               {
-                       continue;
-               }
-
-               /* check if package is already in database */
-               e = db->query(db, "SELECT id FROM packages WHERE name = ?",
-                                                 DB_TEXT, package, DB_INT);
-               if (e)
-               {
-                       if (!e->enumerate(e, &gid))
-                       {
-                               gid = 0;
-                       }
-                       e->destroy(e);
-               }
-               if (!gid && security)
-               {
-                       if (db->execute(db, &gid, "INSERT INTO packages (name) VALUES (?)",
-                                                               DB_TEXT, package) != 1)
-                       {
-                               fprintf(stderr, "could not store package '%s' to database\n",
-                                                                package);
-                               fclose(file);
-                               db->destroy(db);
-                               exit(EXIT_FAILURE);
-                       }
-                       new_packages++;
-               }
-
-               /* check for package versions already in database */
-               e = db->query(db,
-                               "SELECT id, release, security, time FROM versions "
-                               "WHERE package = ? AND product = ?",
-                               DB_INT, gid, DB_INT, pid, DB_INT, DB_TEXT, DB_INT, DB_INT);
-               if (!e)
-               {
-                       break;
-               }
-               while (e->enumerate(e, &vid, &cur_version, &cur_security, &cur_time))
-               {
-                       if (streq(version, cur_version))
-                       {
-                               /* already in data base */
-                               add_version = FALSE;
+                       case PACMAN_STATE_BEGIN_PACKAGE:
+                               pos = strstr(pos, "Package: ");
+                               if (!pos)
+                               {
+                                       continue;
+                               }
+                               pos += 9;
+                               package = pos;
+                               pos = strchr(pos, '\n');
+                               if (pos)
+                               {
+                                       package = strndup(package, pos - package);
+                                       pacman_state = PACMAN_STATE_VERSION;
+                               }
                                break;
-                       }
-                       else if (gen_time > cur_time)
-                       {
-                               if (security)
+                       case PACMAN_STATE_VERSION:
+                               pos = strstr(pos, "Version: ");
+                               if (!pos)
                                {
-                                       if (cur_security)
-                                       {
-                                               vid_update = vid;
-                                               version_update = strdup(cur_version);
-                                               security_update = cur_security;
-                                       }
-                                       else
-                                       {
-                                               vid_delete = vid;
-                                               version_delete = strdup(cur_version);
-                                               security_delete = cur_security;
-                                       }
+                                       continue;
                                }
-                               else
+                               pos += 9;
+                               version = pos;
+                               pos = strchr(pos, '\n');
+                               if (pos)
                                {
-                                       if (!cur_security)
-                                       {
-                                               vid_update = vid;
-                                               version_update = strdup(cur_version);
-                                               security_update = cur_security;
-                                       }
+                                       version = strndup(version, pos - version);
+                                       pacman_state = PACMAN_STATE_END_PACKAGE;
                                }
-                       }
-                       else
-                       {
-                               if (security == cur_security)
+                               break;
+                       case PACMAN_STATE_END_PACKAGE:
+                               if (*pos != '\n')
                                {
-                                       add_version = FALSE;
+                                       continue;
                                }
-                       }
-               }
-               e->destroy(e);
-
-               if ((!vid && !security) || (vid && !add_version))
-               {
-                       free(version_update);
-                       free(version_delete);
-                       continue;
-               }
-
-               if ((!vid && security) || (vid && !vid_update))
-               {
-                       printf("%s (%s) %s\n", package, version, security ? "[s]" : "");
-
-                       if (db->execute(db, &vid,
-                               "INSERT INTO versions "
-                               "(package, product, release, security, time) "
-                               "VALUES (?, ?, ?, ?, ?)", DB_INT, gid, DB_INT, pid,
-                               DB_TEXT, version, DB_INT, security, DB_INT, gen_time) != 1)
-                       {
-                               fprintf(stderr, "could not store version '%s' to database\n",
-                                                                version);
-                               free(version_update);
-                               free(version_delete);
-                               fclose(file);
-                               db->destroy(db);
-                               exit(EXIT_FAILURE);
-                       }
-                       new_versions++;
-               }
-               else
-               {
-                       printf("%s (%s) %s updated by\n",
-                                  package, version_update, security_update ? "[s]" : "");
-                       printf("%s (%s) %s\n", package, version, security ? "[s]" : "");
-
-                       if (db->execute(db, NULL,
-                               "UPDATE versions SET release = ?, time = ? WHERE id = ?",
-                               DB_TEXT, version, DB_INT, gen_time, DB_INT, vid_update) <= 0)
-                       {
-                               fprintf(stderr, "could not update version '%s' to database\n",
-                                                                version);
-                               free(version_update);
-                               free(version_delete);
-                               fclose(file);
-                               db->destroy(db);
-                               exit(EXIT_FAILURE);
-                       }
-                       updated_versions++;
-               }
-
-               if (vid_delete)
-               {
-                       printf("%s (%s) %s deleted\n",
-                                  package, version_delete, security_delete ? "[s]" : "");
-
-                       if (db->execute(db, NULL,
-                               "DELETE FROM  versions WHERE id = ?",
-                               DB_INT, vid_delete) <= 0)
-                       {
-                               fprintf(stderr, "could not delete version '%s' from database\n",
-                                                                version_delete);
-                               free(version_update);
-                               free(version_delete);
-                               fclose(file);
-                               db->destroy(db);
-                               exit(EXIT_FAILURE);
-                       }
-                       deleted_versions++;
+                               success = update_database(db, package, version, security, &stats);
+                               free(package);
+                               free(version);
+                               if (!success)
+                               {
+                                       fclose(file);
+                                       db->destroy(db);
+                                       exit(EXIT_FAILURE);
+                               }
+                               pacman_state = PACMAN_STATE_BEGIN_PACKAGE;
                }
-               free(version_update);
-               free(version_delete);
        }
        fclose(file);
        db->destroy(db);
 
-       printf("processed %d packages, %d security, %d new packages, "
-                  "%d new versions, %d updated versions, %d deleted versions, "
-                  "%d errored\n", count - 6, vulnerable, new_packages, new_versions,
-                  updated_versions, deleted_versions, errored);
+       printf("processed %d packages, %d new packages, %d new versions, "
+                  "%d updated versions, %d deleted versions\n",
+                       stats.packages, stats.new_packages, stats.new_versions,
+                       stats.updated_versions, stats.deleted_versions);
 }
 
 static void do_args(int argc, char *argv[])
 {
        char *filename = NULL, *product = NULL;
-       bool update = FALSE;
+       bool security = FALSE;
 
        /* reinit getopt state */
        optind = 0;
@@ -438,7 +427,7 @@ static void do_args(int argc, char *argv[])
                        { "help", no_argument, NULL, 'h' },
                        { "file", required_argument, NULL, 'f' },
                        { "product", required_argument, NULL, 'p' },
-                       { "update", no_argument, NULL, 'u' },
+                       { "security", no_argument, NULL, 's' },
                        { 0,0,0,0 }
                };
 
@@ -456,8 +445,8 @@ static void do_args(int argc, char *argv[])
                        case 'p':
                                product = optarg;
                                continue;
-                       case 'u':
-                               update = TRUE;
+                       case 's':
+                               security = TRUE;
                                continue;
                }
                break;
@@ -465,7 +454,7 @@ static void do_args(int argc, char *argv[])
 
        if (filename && product)
        {
-               process_packages(filename, product, update);
+               process_packages(filename, product, security);
        }
        else
        {
index e9134ea..af66c94 100755 (executable)
 #!/bin/sh
 
-DATE=`date +%Y%m%d`
-DEBIAN=http://packages.debian.org
-UBUNTU=http://packages.ubuntu.com
-UBUNTU_VERSIONS="quantal precise oneiric lucid"
-PACKAGES=allpackages?format=txt.gz
+DATE=`date +%Y%m%d-%H%M`
+UBUNTU="http://security.ubuntu.com/ubuntu/dists"
+UBUNTU_VERSIONS="raring quantal precise lucid"
+UBUNTU_DIRS="main multiverse restricted universe"
+UBUNTU_ARCH="binary-amd64 binary-i386"
+DEBIAN="http://security.debian.org/dists"
+DEBIAN_VERSIONS="jessie wheezy squeeze"
+DEBIAN_DIRS="main contrib non-free"
+DEBIAN_ARCH="binary-amd64 binary-i386"
 PACMAN=/usr/libexec/ipsec/pacman
 DIR=/etc/pts
 
-cd $DIR
+cd $DIR/dists
 
 for v in $UBUNTU_VERSIONS
 do
-  wget $UBUNTU/$v/$PACKAGES -O $DATE-$v.txt.gz
-  wget $UBUNTU/$v-updates/$PACKAGES -O $DATE-$v-updates.txt.gz
+  for a in $UBUNTU_ARCH
+  do
+    mkdir -p $v-security/$a $v-updates/$a
+    for d in $UBUNTU_DIRS
+    do
+         wget $UBUNTU/$v-security/$d/$a/Packages.bz2 -O $v-security/$a/Packages-$d.bz2
+         wget $UBUNTU/$v-updates/$d/$a/Packages.bz2  -O $v-updates/$a/Packages-$d.bz2
+       done
+    bunzip2 -f $v-security/$a/*.bz2 $v-updates/$a/*.bz2
+  done
 done
 
-wget $DEBIAN/stable/$PACKAGES -O $DATE-squeeze.txt.gz
-gunzip *.gz
+for v in $DEBIAN_VERSIONS
+do
+  for a in $DEBIAN_ARCH
+  do
+    mkdir -p $v-updates/$a
+    for d in $DEBIAN_DIRS
+    do
+         wget $DEBIAN/$v/updates/$d/$a/Packages.bz2  -O $v-updates/$a/Packages-$d.bz2
+       done
+    bunzip2 -f $v-updates/$a/*.bz2
+  done
+done
+
+for f in raring-security/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 13.04 x86_64" --file $f --security
+done
+echo
+for f in raring-updates/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 13.04 x86_64" --file $f
+done
+echo
+for f in raring-security/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 13.04 i686" --file $f --security
+done
+echo
+for f in raring-updates/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 13.04 i686" --file $f
+done
+echo
 
-$PACMAN --product "Ubuntu 12.10" --file $DATE-quantal.txt
+for f in quantal-security/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 12.10 x86_64" --file $f --security
+done
 echo
-$PACMAN --product "Ubuntu 12.10" --file $DATE-quantal-updates.txt --update
+for f in quantal-updates/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 12.10 x86_64" --file $f
+done
 echo
-$PACMAN --product "Ubuntu 12.04" --file $DATE-precise.txt
+for f in quantal-security/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 12.10 i686" --file $f --security
+done
 echo
-$PACMAN --product "Ubuntu 12.04" --file $DATE-precise-updates.txt --update
+for f in quantal-updates/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 12.10 i686" --file $f
+done
 echo
-$PACMAN --product "Ubuntu 11.10" --file $DATE-oneiric.txt
+
+for f in precise-security/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 12.04 x86_64" --file $f --security
+done
 echo
-$PACMAN --product "Ubuntu 11.10" --file $DATE-oneiric-updates.txt --update
+for f in precise-updates/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 12.04 x86_64" --file $f
+done
 echo
-$PACMAN --product "Ubuntu 10.04" --file $DATE-lucid.txt
+for f in precise-security/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 12.04 i686" --file $f --security
+done
 echo
-$PACMAN --product "Ubuntu 10.04" --file $DATE-lucid-updates.txt --update
+for f in precise-updates/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 12.04 i686" --file $f
+done
 echo
-$PACMAN --product "Debian squeeze" --file $DATE-squeeze.txt
 
-cp config.db config.db-$DATE
+for f in lucid-security/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 10.04 x86_64" --file $f --security
+done
+echo
+for f in lucid-updates/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 10.04 x86_64" --file $f
+done
+echo
+for f in lucid-security/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 10.04 i686" --file $f --security
+done
+echo
+for f in lucid-updates/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 10.04 i686" --file $f
+done
+echo
+
+for f in jessie-updates/binary-amd64/*
+do
+  $PACMAN --product "Debian 8.0 x86_64" --file $f --security
+done
+echo
+for f in jessie-updates/binary-i386/*
+do
+  $PACMAN --product "Debian 8.0 i686" --file $f --security
+done
+
+for f in wheezy-updates/binary-amd64/*
+do
+  $PACMAN --product "Debian 7.0 x86_64" --file $f --security
+done
+echo
+for f in wheezy-updates/binary-i386/*
+do
+  $PACMAN --product "Debian 7.0 i686" --file $f --security
+done
+
+for f in squeeze-updates/binary-amd64/*
+do
+  $PACMAN --product "Debian 6.0 x86_64" --file $f --security
+done
+echo
+for f in squeeze-updates/binary-i386/*
+do
+  $PACMAN --product "Debian 6.0 i686" --file $f --security
+done
+
+cp $DIR/config.db $DIR/config.db-$DATE