rpmdb2solv:
authorKlaus Kaempf <kkaempf@suse.de>
Fri, 15 Aug 2008 12:28:43 +0000 (12:28 +0000)
committerKlaus Kaempf <kkaempf@suse.de>
Fri, 15 Aug 2008 12:28:43 +0000 (12:28 +0000)
 - add usage()
 - call repo_add_products differently
repo_products:
 - fallback to parsing /etc/*-release if not
   products.d directory found

package/libsatsolver.changes
tools/repo_products.c
tools/repo_products.h
tools/rpmdb2solv.c

index 4b3b6c9..696d7d5 100644 (file)
@@ -1,4 +1,10 @@
 -------------------------------------------------------------------
+Fri Aug 15 14:26:29 CEST 2008 - kkaempf@suse.de
+
+- Implement pre-code11 fallback for products, parse /etc/*-release
+  if /etc/products.d is not available.
+
+-------------------------------------------------------------------
 Wed Aug 13 18:06:41 CEST 2008 - kkaempf@suse.de
 
 - provide installtime for installed products.
index 1c9757d..2312958 100644 (file)
@@ -25,6 +25,7 @@
 #include "pool.h"
 #include "repo.h"
 #include "util.h"
+#include "tools_util.h"
 #include "repo_content.h"
 
 struct parsedata {
@@ -36,60 +37,6 @@ struct parsedata {
 
 
 /*
- * join up to three strings into one
- */
-
-static char *
-join(struct parsedata *pd, const char *s1, const char *s2, const char *s3)
-{
-  int l = 1;
-  char *p;
-
-  if (s1)
-    l += strlen(s1);
-  if (s2)
-    l += strlen(s2);
-  if (s3)
-    l += strlen(s3);
-  if (l > pd->tmpl)
-    {
-      pd->tmpl = l + 256;
-      pd->tmp = sat_realloc(pd->tmp, pd->tmpl);
-    }
-  p = pd->tmp;
-  if (s1)
-    {
-      strcpy(p, s1);
-      p += strlen(s1);
-    }
-  if (s2)
-    {
-      strcpy(p, s2);
-      p += strlen(s2);
-    }
-  if (s3)
-    {
-      strcpy(p, s3);
-      p += strlen(s3);
-    }
-  return pd->tmp;
-}
-
-
-/*
- * create epoch:version-release as Id
- */
-
-static Id
-makeevr(Pool *pool, char *s)
-{
-  if (!strncmp(s, "0:", 2) && s[2])
-    s += 2;
-  return str2id(pool, s, 1);
-}
-
-
-/*
  * create localized tag
  */
 
@@ -124,7 +71,7 @@ enum sections
  */
 
 static void
-repo_add_product(struct parsedata *pd, Repodata *data, FILE *fp)
+repo_add_product(struct parsedata *pd, Repodata *data, FILE *fp, int code11)
 {
   Repo *repo = pd->repo;
   Pool *pool = repo->pool;
@@ -159,6 +106,42 @@ repo_add_product(struct parsedata *pd, Repodata *data, FILE *fp)
       *--linep = 0;
       linep = line;
 
+      if (!code11)
+       {
+         /* non-code11, assume /etc/xyz-release
+          * just parse first line
+          * as "<name> <version> (<arch>)"
+          */
+         char *sp[3];
+
+         if (split(linep, sp, 3) == 3)
+           {
+             if (!s)
+               {
+                 struct stat st;
+                 
+                 s = pool_id2solvable(pool, repo_add_solvable(repo));
+                 repodata_extend(data, s - pool->solvables);
+                 handle = repodata_get_handle(data, s - pool->solvables - repo->start);
+                 if (!fstat(fileno(fp), &st))
+                   {
+                     repodata_set_num(data, handle, SOLVABLE_INSTALLTIME, st.st_ctime);
+                   }
+                 else
+                   {
+                     perror("Can't stat()");
+                   }
+               }
+             s->name = str2id(pool, join2("product", ":", sp[0]), 1);
+             s->evr = makeevr(pool, sp[1]);
+           }
+         else
+           {
+             fprintf(stderr, "Can't recognize -release line '%s'\n", linep);
+           }     
+         break; /* just parse single line */
+       }
+      
       /*
        * Very trivial .ini parser
        */
@@ -249,7 +232,7 @@ repo_add_product(struct parsedata *pd, Repodata *data, FILE *fp)
                    }
                }
              if (!strcmp(key, "name"))
-                 s->name = str2id(pool, join(pd, "product", ":", value), 1);
+                 s->name = str2id(pool, join2("product", ":", value), 1);
              else if (!strcmp(key, "version"))
                s->evr = makeevr(pool, value);
              else if (!strcmp(key, "vendor"))
@@ -300,44 +283,82 @@ repo_add_product(struct parsedata *pd, Repodata *data, FILE *fp)
 
 
 /*
- * read all .prod files from directory
- * parse each one as a product
+ * parse dir looking for files ending in suffix
  */
 
-void
-repo_add_products(Repo *repo, Repodata *repodata, const char *proddir)
+static void
+parse_dir(DIR *dir, const char *path, struct parsedata *pd, Repodata *repodata, int code11)
 {
-  DIR *dir = opendir(proddir);
   struct dirent *entry;
-  struct parsedata pd;
-  
-  memset(&pd, 0, sizeof(pd));
-  pd.repo = repo;
-
-  if (!dir)
-    {
-      perror(proddir);
-      return;
-    }
+  char *suffix = code11 ? ".prod" : "-release";
+  int slen = code11 ? 5 : 8;  /* strlen(".prod") : strlen("-release") */
   
   while ((entry = readdir(dir)))
     {
-      const char *dot;
-      dot = strrchr( entry->d_name, '.' );
-      if (dot && strcmp(dot, ".prod") == 0)
+      int len;
+      len = strlen(entry->d_name);
+      
+      /* skip /etc/lsb-release, thats not a product per-se */
+      if (!code11
+         && strcmp(entry->d_name, "lsb-release") == 0)
        {
-         char *fullpath = join(&pd, proddir, "/", entry->d_name);
+         continue;
+       }
+      
+      if (len > slen
+         && strcmp(entry->d_name+len-slen, suffix) == 0)
+       {
+         char *fullpath = join2(path, "/", entry->d_name);
          FILE *fp = fopen(fullpath, "r");
          if (!fp)
            {
              perror(fullpath);
              break;
            }
-         repo_add_product(&pd, repodata, fp);
+         repo_add_product(pd, repodata, fp, code11);
          fclose(fp);
        }
     }
+}
+
+
+/*
+ * read all installed products
+ * 
+ * try proddir (reading all .prod files from this directory) first
+ * if not available, assume non-code11 layout and parse /etc/xyz-release
+ *
+ * parse each one as a product
+ */
+
+void
+repo_add_products(Repo *repo, Repodata *repodata, const char *proddir, const char *root)
+{
+  const char *fullpath = proddir;
+  int code11 = 1;
+  DIR *dir = opendir(fullpath);
+  struct parsedata pd;
+  
+  memset(&pd, 0, sizeof(pd));
+  pd.repo = repo;
+
+  if (!dir)
+    {
+      fullpath = root ? join2(root, "", "/etc") : "/etc";
+      dir = opendir(fullpath);
+      code11 = 0;
+    }
+  if (!dir)
+    {
+      perror(fullpath);
+    }
+  else
+    {
+      parse_dir(dir, fullpath, &pd, repodata, code11);
+    }
+  
   if (pd.tmp)
     sat_free(pd.tmp);
+  join_freemem();
   closedir(dir);
 }
index 2c2114b..9739096 100644 (file)
@@ -5,4 +5,4 @@
  * for further information
  */
 
-void repo_add_products(Repo *repo, Repodata *repodata, const char *proddir);
+void repo_add_products(Repo *repo, Repodata *repodata, const char *proddir, const char *root);
index 29d6f7e..7cbc214 100644 (file)
  * a .solv file of 'installed' solvables.
  * Writes .solv to stdout
  * 
- * Usage:
- * rpmdb2solv [-n] [-x] [-b <basefile>] [-p <productsdir>] [-r <root>] 
- * -n : No packages, do not read rpmdb, useful to only parse products
- * -x : use extrapool
- * -b <basefile> : Write .solv to <basefile>.solv instead of stdout
- * -p <productsdir> : Scan <productsdir> for .prod files, representing installed products
- * -r <root> : Prefix rpmdb path and <productsdir> with <root>
- * 
  */
 
 #include <sys/types.h>
 #include "repo_solv.h"
 #include "common_write.h"
 
+static void
+usage(int status)
+{
+  fprintf(stderr, "\nUsage:\n"
+         "rpmdb2solv [-n] [-x] [-b <basefile>] [-p <productsdir>] [-r <root>]\n"
+         " -n : No packages, do not read rpmdb, useful to only parse products\n"
+         " -x : use extrapool\n"
+         " -b <basefile> : Write .solv to <basefile>.solv instead of stdout\n"
+         " -p <productsdir> : Scan <productsdir> for .prod files, representing installed products\n"
+         " -r <root> : Prefix rpmdb path and <productsdir> with <root>\n"
+        );
+  exit(status);
+}
+
+
 int
 main(int argc, char **argv)
 {
@@ -56,9 +63,12 @@ main(int argc, char **argv)
    * parse arguments
    */
   
-  while ((c = getopt (argc, argv, "nxb:r:p:")) >= 0)
+  while ((c = getopt (argc, argv, "hnxb:r:p:")) >= 0)
     switch (c)
       {
+      case 'h':
+         usage(0);
+       break;
       case 'r':
         root = optarg;
         break;
@@ -75,7 +85,7 @@ main(int argc, char **argv)
         extrapool = 1;
         break;
       default:
-       exit(1);
+       usage(1);
       }
   
   /*
@@ -134,7 +144,7 @@ main(int argc, char **argv)
            }
        }
       
-      repo_add_products(repo, repodata, proddir);
+      repo_add_products(repo, repodata, proddir, root);
     }
       
   if (repodata)