This patch updates Portage package manager support to the new code introduced 
in 2.2.1.  Portage support was broken by that patch, this restores it, while 
making several improvements (like moving from equery to qlist for drastic speed 
improvements).

Note: a lot of Portage-specific code was introduced to do.c; this code is 
essential here because the package code has to modify the package name given to 
it.  This could be handled in package.c if the complete Package* object was 
passed to PackageCheck().  I'll work on a patch for this later.

Index: cfengine-trunk/src/do.c
===================================================================
--- cfengine-trunk.orig/src/do.c
+++ cfengine-trunk/src/do.c
@@ -2738,6 +2738,7 @@ void CheckPackages()
   /* pkgmgr_none will always be the highest number in the enum so set
      the array size with that */
   struct Item *pending_pkgs = NULL;
+  char *wholepackage = NULL;
   enum pkgmgrs prev_pkgmgr = pkgmgr_none;
   enum pkgactions prev_action = pkgaction_none;
 
@@ -2778,8 +2779,31 @@ for (ptr = VPKG; ptr != NULL; ptr=ptr->n
       AddMultipleClasses(ptr->defines);
       if (ptr->action == pkgaction_remove) 
          {
-         PackageList(ptr->name, ptr->pkgmgr, ptr->ver, ptr->cmp, 
&pending_pkgs);
-         AppendItem(&pending_pkgs, ptr->name, NULL);
+         if (ptr->pkgmgr == pkgmgr_portage && (ptr->ver)[0])
+            {
+            /* Portage doesn't use a list, just the package atom */
+            int wholesize = 2 + strlen(ptr->name) + strlen(ptr->ver) + 
strlen(CMPSENSEOPERAND[ptr->cmp]);
+            wholepackage = (char *) malloc(wholesize);
+            strncpy(wholepackage, CMPSENSEOPERAND[ptr->cmp], wholesize - 1);
+            strncat(wholepackage, ptr->name, wholesize - strlen(wholepackage) 
- 1);
+            strncat(wholepackage, "-", wholesize - strlen(wholepackage) - 1);
+            strncat(wholepackage, ptr->ver, wholesize - strlen(wholepackage) - 
1);
+
+            /* Replace pkg->name with package atom */
+            free(ptr->name);
+            ptr->name = wholepackage;
+            wholepackage = NULL;
+
+            AppendItem(&pending_pkgs, ptr->name, NULL);
+            }
+         else if (ptr->pkgmgr == pkgmgr_portage)
+            {
+            AppendItem(&pending_pkgs, ptr->name, NULL);
+            }
+         else
+            {
+            PackageList(ptr->name, ptr->pkgmgr, ptr->ver, ptr->cmp, 
&pending_pkgs);
+            }
 
          /* Some package managers operate best doing things one at a time. */
          if ( (ptr->pkgmgr == pkgmgr_freebsd) || (ptr->pkgmgr == pkgmgr_sun) )
@@ -2798,6 +2822,22 @@ for (ptr = VPKG; ptr != NULL; ptr=ptr->n
       AddMultipleClasses(ptr->elsedef);
       if (ptr->action == pkgaction_install)
          {
+         if (ptr->pkgmgr == pkgmgr_portage && (ptr->ver)[0])
+            {
+            /* Portage wants the version in the package atom */
+            int wholesize = 2 + strlen(ptr->name) + strlen(ptr->ver) + 
strlen(CMPSENSEOPERAND[ptr->cmp]);
+            wholepackage = (char *) malloc(wholesize);
+            strncpy(wholepackage, CMPSENSEOPERAND[ptr->cmp], wholesize - 1);
+            strncat(wholepackage, ptr->name, wholesize - strlen(wholepackage) 
- 1);
+            strncat(wholepackage, "-", wholesize - strlen(wholepackage) - 1);
+            strncat(wholepackage, ptr->ver, wholesize - strlen(wholepackage) - 
1);
+
+            /* Replace pkg->name with package atom */
+            free(ptr->name);
+            ptr->name = wholepackage;
+            wholepackage = NULL;
+            }
+
          AppendItem(&pending_pkgs, ptr->name, NULL);
 
          /* Some package managers operate best doing things one at a time. */
Index: cfengine-trunk/src/package.c
===================================================================
--- cfengine-trunk.orig/src/package.c
+++ cfengine-trunk/src/package.c
@@ -246,7 +246,7 @@ switch(pkgmgr)
       Verbose("InstallPackage(): using '%s'\n", instcmd);
       if (DONTDO)
          {
-         Verbose("--skipping because DONTDO is enabled.");
+         Verbose("--skipping because DONTDO is enabled.\n");
          result = 1;
          }
       else 
@@ -337,6 +337,18 @@ int RemovePackage(enum pkgmgrs pkgmgr, s
             }
          break;
        
+      /* Portage */
+      case pkgmgr_portage:
+         if (!GetMacroValue(CONTEXTID,"PortageRemoveCommand"))
+            {
+               strncpy(rawdelcmd, "/usr/bin/emerge -C %s", 21 );
+            }
+         else
+            {
+            strncpy(rawdelcmd, 
GetMacroValue(CONTEXTID,"PortageRemoveCommand"),CF_BUFSIZE);
+            }
+         break;
+
       /* Default */
       default:
          Verbose("Package removal not yet implemented for this package 
manager.");
@@ -348,7 +360,7 @@ int RemovePackage(enum pkgmgrs pkgmgr, s
       Verbose("RemovePackage(): using '%s'\n", delcmd);
       if (DONTDO)
          {
-         Verbose("--skipping because DONTDO is enabled.");
+         Verbose("--skipping because DONTDO is enabled.\n");
          result = 1;
          }
       else 
@@ -448,7 +460,6 @@ int BuildCommandLine(char *resolvedcmd, 
          strncpy(cmd_ptr, cmd_tail, &resolvedcmd[CF_BUFSIZE*2] - cmd_ptr);
          }
       }
-   Verbose("Resolved command is '%s'\n", resolvedcmd );
    return 1;
 }
       
@@ -1326,27 +1337,21 @@ int v,r,m,f;
 
 int PortagePackageCheck(char *package,char *version,enum cmpsense cmp)
 
-{ FILE *pp;
-  struct Item *ebuildlist = NULL;
-  struct Item *ebuild;
-  enum cmpsense result;
-  int match = 0;
-  char *comparehead = NULL;
-  char *comparetail = NULL;
-  char *installedhead = NULL;
-  char *installedtail = NULL;
-
-  /* Yes, it's an ugly python one-liner that does something beautiful */
-
-snprintf(VBUFF,CF_BUFSIZE,"/usr/bin/python -c 'import portage, re, sys; "
-         
"[sys.stdout.write(re.sub(\"\\w*?\\-\\w*?\\/([a-zA-Z0-9_+]|\\-(?![0-9]))*\\-\", 
\"\", package, 1) + "
-         "\"\\n\") for package in portage.db[\"/\"][\"vartree\"].dbapi.match("
-         "\"%s\")]'", package);
+{  FILE *pp;
+   struct Item *ebuildlist = NULL;
+   struct Item *ebuild;
+   int match = 0;
+   char *result = NULL;
+
+/* Search for installed versions of package */
+snprintf(VBUFF,CF_BUFSIZE,"/usr/bin/qlist -IevC %s",package);
 
 if ((pp = cfpopen(VBUFF, "r")) == NULL)
    {
-   Verbose("Could not execute the equery command.  Assuming package not 
installed.\n");
-   return 0;
+   snprintf(OUTPUT,CF_BUFSIZE,"Could not execute the qlist command.  "
+      "Is portage-utils installed?\n");
+   CfLog(cferror,OUTPUT,"");
+   return -1;
    }
 
 while(!feof(pp))
@@ -1361,14 +1366,7 @@ while(!feof(pp))
       }
    }
 
-/* Non-zero exit status means that we could not find the package, so
- * zero the list and bail. */
-
-if (cfpclose(pp) != 0)
-   {
-   DeleteItemList(ebuildlist);
-   ebuildlist = NULL;
-   }
+cfpclose(pp);
 
 if (ebuildlist == NULL)
    {
@@ -1376,145 +1374,92 @@ if (ebuildlist == NULL)
    return 0;
    }
 
-
 Verbose("PortageCheckPackage(): Requested %s %s %s\n", package, 
CMPSENSETEXT[cmp],(version[0] ? version : "ANY"));
 
-/* If no version was specified, just return 1, because if we got this far
- * some package by that name exists. */
-
+/* If no version was specified, return successful (found something) */
 if (!version[0])
    {
    DeleteItemList(ebuildlist);
    return 1;
    }
 
-/* The rule here will be: if any package in the list matches, then the
- * first one to match wins, and we bail out. */
-
-
+/* Iterate through all installed versions until match is found */
 for (ebuild = ebuildlist; ebuild != NULL; ebuild=ebuild->next)
-  {
-  char *ebuildver;
-  ebuildver = ebuild->name;
-  
-  Verbose("PortageCheckPackage(): Trying installed version %s\n", ebuildver);
-  
-  /* Start out assuming the comparison will be equal. */
-  result = cmpsense_eq;
-  
-  comparehead = version;
-  comparetail = NULL;
-  installedhead = ebuildver;
-  installedtail = NULL;
-  
-  /* Iterate over version portions delimited by `-' */
-  while (result == cmpsense_eq)
-     {
-     if (*comparehead == '\0' && *installedhead == '\0')
-        {
-        /* No substrings remain, break from while */
-        break;
-        }
-     else if (*comparehead == '\0')
-        {
-        /* Installed version has more version substrings than given */
-        result = cmpsense_gt;
-        }
-     else if (*installedhead == '\0')
-        {
-        /* Installed version has less version substrings than given */
-        result = cmpsense_lt;
-        }
-     else
-        {
-        /* New substring in both to test */
-        comparetail = strchr(comparehead, '-');
-        installedtail = strchr(installedhead, '-');
-        
-        /* Throw a \0 over the `-' so just the substring is tested.
-         * If the tail is less than the head, we must be at last substring,
-         * as no `-'s were found (so the `\0' is already there) */
-        if (comparetail > comparehead) *comparetail = '\0';
-        if (installedtail > installedhead) *installedtail = '\0';
-        
-        switch (rpmvercmp(installedhead, comparehead))
-           {
-           case 1:
-               result = cmpsense_gt;
-               break;
-           case -1:
-               result = cmpsense_lt;
-               break;
-           }
-        
-        if (comparetail > comparehead)
-           {
-           /* Restore `-' at tail and move head just past it */
-           *comparetail = '-';
-           comparehead = comparetail + 1;
-           }
-        else
-           {
-           /* Move head to the end of the line (`\0') */
-           comparehead = comparehead + strlen(comparehead);
-           }
-        if (installedtail > installedhead)
-           {
-           /* Restore `-' at tail and move head just past it */
-           *installedtail = '-';
-           installedhead = installedtail + 1;
-           }
-        else
-           {
-           /* Move head to the end of the line (`\0') */
-           installedhead = installedhead + strlen(installedhead);
-           }
-        }
-     }
-  
-  Verbose("Comparison result: %s\n",CMPSENSETEXT[result]);
-  
-  switch(cmp)
-     {
-     case cmpsense_gt:
-         match = (result == cmpsense_gt);
-         break;
-     case cmpsense_ge:
-         match = (result == cmpsense_gt || result == cmpsense_eq);
-         break;
-     case cmpsense_lt:
-         match = (result == cmpsense_lt);
-         break;
-     case cmpsense_le:
-         match = (result == cmpsense_lt || result == cmpsense_eq);
-         break;
-     case cmpsense_eq:
-         match = (result == cmpsense_eq);
-         break;
-     case cmpsense_ne:
-         match = (result != cmpsense_eq);
-         break;
-     }
-  
-  /* If we find a match, just return it now, and don't bother checking
-   * other ebuilds */
+   {
   
-  if (match)
-     {
-     DeleteItemList(ebuildlist);
-     return 1;
-     }
-  }
+   Verbose("PortageCheckPackage(): Trying installed version %s\n", 
ebuild->name);
+
+   /* Run comparison tool to do the grunt work */
+   snprintf(VBUFF,CF_BUFSIZE,"/usr/bin/qatom -cC %s %s-%s", ebuild->name, 
package, version);
+
+   if ((pp = cfpopen(VBUFF, "r")) == NULL)
+      {
+      snprintf(OUTPUT,CF_BUFSIZE,"Could not execute the qatom command.  "
+         "Is portage-utils installed?\n");
+      CfLog(cferror,OUTPUT,"");
+      continue;
+      }
+
+   if (feof(pp))
+      {
+      snprintf(OUTPUT,CF_BUFSIZE,"Internal error!  No output from %s.",VBUFF);
+      CfLog(cferror,OUTPUT,"");
+      continue;
+      }
+
+   /* Format of output is `package < package' */
+   *VBUFF = '\0';
+   ReadLine(VBUFF,CF_BUFSIZE,pp);
+   Verbose("PortagePackageCheck(): Result %s\n",VBUFF);
+   cfpclose(pp);
+
+   /* Find first space, give up otherwise */
+   result = strchr(VBUFF, ' ');
+   if (result == NULL) continue;
+
+   /* Relocate to right of space (the comparison symbol) */
+   ++result;
+
+   switch(cmp)
+   {
+   case cmpsense_gt:
+      match = (*result == *CMPSENSEOPERAND[cmpsense_gt]);
+      break;
+   case cmpsense_ge:
+      match = (*result == *CMPSENSEOPERAND[cmpsense_gt] ||
+               *result == *CMPSENSEOPERAND[cmpsense_eq]);
+      break;
+   case cmpsense_lt:
+      match = (*result == *CMPSENSEOPERAND[cmpsense_lt]);
+      break;
+   case cmpsense_le:
+      match = (*result == *CMPSENSEOPERAND[cmpsense_lt] ||
+               *result == *CMPSENSEOPERAND[cmpsense_eq]);
+      break;
+   case cmpsense_eq:
+      match = (*result == *CMPSENSEOPERAND[cmpsense_eq]);
+      break;
+   case cmpsense_ne:
+      match = (*result != *CMPSENSEOPERAND[cmpsense_eq]);
+      break;
+   }
 
-/* if we manage to make it out of the loop, we did not find a match. */
+   /* Return successful on finding a match */
+   if (match)
+      {
+      DeleteItemList(ebuildlist);
+      return 1;
+      }
+   }
 
+/* No match found, return false */
 DeleteItemList(ebuildlist);
 return 0;
 }
 
 int PortagePackageList(char *package, char *version, enum cmpsense cmp, struct 
Item **pkglist)
 {
-       return 0; /* not implemented yet */
+return 0; /* unused! */
 }
 
 /*********************************************************************/

--
Eric Searcy
OSU Open Source Lab

_______________________________________________
Bug-cfengine mailing list
[email protected]
https://cfengine.org/mailman/listinfo/bug-cfengine

Reply via email to