Check that a file belongs to the package before removing it
[oweals/opkg-lede.git] / libopkg / opkg_remove.c
index 6f80c4dd779467d954ee565afc2ed8ff1f6091dc..4920587859b4e579e9720edb23cf21a0133e72f1 100644 (file)
@@ -1,4 +1,4 @@
-/* opkg_remove.c - the itsy package management system
+/* opkg_remove.c - the opkg package management system
 
    Carl D. Worth
 
 
    Carl D. Worth
 
    General Public License for more details.
 */
 
    General Public License for more details.
 */
 
-#include "opkg.h"
-#include "opkg_message.h"
-
+#include <stdio.h>
 #include <glob.h>
 #include <glob.h>
+#include <unistd.h>
 
 
+#include "opkg_message.h"
 #include "opkg_remove.h"
 #include "opkg_remove.h"
-
+#include "opkg_cmd.h"
 #include "file_util.h"
 #include "sprintf_alloc.h"
 #include "file_util.h"
 #include "sprintf_alloc.h"
-#include "str_util.h"
-
-#include "opkg_cmd.h"
+#include "libbb/libbb.h"
 
 /*
  * Returns number of the number of packages depending on the packages provided by this package.
  * Every package implicitly provides itself.
  */
 
 /*
  * Returns number of the number of packages depending on the packages provided by this package.
  * Every package implicitly provides itself.
  */
-int pkg_has_installed_dependents(opkg_conf_t *conf, abstract_pkg_t *parent_apkg, pkg_t *pkg, abstract_pkg_t *** pdependents)
+int
+pkg_has_installed_dependents(pkg_t *pkg, abstract_pkg_t *** pdependents)
 {
      int nprovides = pkg->provides_count;
      abstract_pkg_t **provides = pkg->provides;
 {
      int nprovides = pkg->provides_count;
      abstract_pkg_t **provides = pkg->provides;
-     int n_installed_dependents = 0;
+     unsigned int n_installed_dependents = 0;
      int i;
      int i;
-     for (i = 0; i <= nprovides; i++) {
+     for (i = 0; i < nprovides; i++) {
          abstract_pkg_t *providee = provides[i];
          abstract_pkg_t **dependers = providee->depended_upon_by;
          abstract_pkg_t *dep_ab_pkg;
          abstract_pkg_t *providee = provides[i];
          abstract_pkg_t **dependers = providee->depended_upon_by;
          abstract_pkg_t *dep_ab_pkg;
@@ -54,15 +53,10 @@ int pkg_has_installed_dependents(opkg_conf_t *conf, abstract_pkg_t *parent_apkg,
      /* if caller requested the set of installed dependents */
      if (pdependents) {
          int p = 0;
      /* if caller requested the set of installed dependents */
      if (pdependents) {
          int p = 0;
-         abstract_pkg_t **dependents = (abstract_pkg_t **)malloc((n_installed_dependents+1)*sizeof(abstract_pkg_t *));
-
-          if ( dependents == NULL ){
-              fprintf(stderr,"%s Unable to allocate memory. REPORT THIS BUG IN BUGZILLA PLEASE\n", __FUNCTION__);
-              return -1;  
-          }
+         abstract_pkg_t **dependents = xcalloc((n_installed_dependents+1), sizeof(abstract_pkg_t *));
 
          *pdependents = dependents;
 
          *pdependents = dependents;
-         for (i = 0; i <= nprovides; i++) {
+         for (i = 0; i < nprovides; i++) {
               abstract_pkg_t *providee = provides[i];
               abstract_pkg_t **dependers = providee->depended_upon_by;
               abstract_pkg_t *dep_ab_pkg;
               abstract_pkg_t *providee = provides[i];
               abstract_pkg_t **dependers = providee->depended_upon_by;
               abstract_pkg_t *dep_ab_pkg;
@@ -85,17 +79,18 @@ int pkg_has_installed_dependents(opkg_conf_t *conf, abstract_pkg_t *parent_apkg,
      return n_installed_dependents;
 }
 
      return n_installed_dependents;
 }
 
-int opkg_remove_dependent_pkgs (opkg_conf_t *conf, pkg_t *pkg, abstract_pkg_t **dependents)
+static int
+opkg_remove_dependent_pkgs(pkg_t *pkg, abstract_pkg_t **dependents)
 {
     int i;
     int a;
     int count;
 {
     int i;
     int a;
     int count;
-    pkg_vec_t *dependent_pkgs = pkg_vec_alloc();
+    pkg_vec_t *dependent_pkgs;
     abstract_pkg_t * ab_pkg;
 
     if((ab_pkg = pkg->parent) == NULL){
     abstract_pkg_t * ab_pkg;
 
     if((ab_pkg = pkg->parent) == NULL){
-       fprintf(stderr, "%s: unable to get dependent pkgs. pkg %s isn't in hash table\n",
-               __FUNCTION__, pkg->name);
+       opkg_msg(ERROR, "Internal error: pkg %s isn't in hash table\n",
+               pkg->name);
        return 0;
     }
     
        return 0;
     }
     
@@ -110,6 +105,8 @@ int opkg_remove_dependent_pkgs (opkg_conf_t *conf, pkg_t *pkg, abstract_pkg_t **
 
     i = 0;
     count = 1;
 
     i = 0;
     count = 1;
+    dependent_pkgs = pkg_vec_alloc();
+
     while (dependents [i] != NULL) {
         abstract_pkg_t *dep_ab_pkg = dependents[i];
        
     while (dependents [i] != NULL) {
         abstract_pkg_t *dep_ab_pkg = dependents[i];
        
@@ -131,114 +128,119 @@ int opkg_remove_dependent_pkgs (opkg_conf_t *conf, pkg_t *pkg, abstract_pkg_t **
         * 2 - to keep track of pkgs whose deps have been checked alrdy  - Karthik */   
     }
     
         * 2 - to keep track of pkgs whose deps have been checked alrdy  - Karthik */   
     }
     
-    if (count == 1)
-           return 0;
+    if (count == 1) {
+        pkg_vec_free(dependent_pkgs);  
+       return 0;
+    }
     
     
     
     
+    int err=0;
     for (i = 0; i < dependent_pkgs->len; i++) {
     for (i = 0; i < dependent_pkgs->len; i++) {
-        int err = opkg_remove_pkg(conf, dependent_pkgs->pkgs[i],0);
-        if (err)
-            return err;
+        err = opkg_remove_pkg(dependent_pkgs->pkgs[i],0);
+        if (err) {
+            pkg_vec_free(dependent_pkgs);
+            break;
+       }
     }
     }
-    return 0;
+    pkg_vec_free(dependent_pkgs);
+    return err;
 }
 
 }
 
-static int user_prefers_removing_dependents(opkg_conf_t *conf, abstract_pkg_t *abpkg, pkg_t *pkg, abstract_pkg_t **dependents)
+static void
+print_dependents_warning(pkg_t *pkg, abstract_pkg_t **dependents)
 {
     abstract_pkg_t *dep_ab_pkg;
 {
     abstract_pkg_t *dep_ab_pkg;
-    opkg_message(conf, OPKG_ERROR, "Package %s is depended upon by packages:\n", pkg->name);
+    opkg_msg(ERROR, "Package %s is depended upon by packages:\n", pkg->name);
     while ((dep_ab_pkg = *dependents++) != NULL) {
         if (dep_ab_pkg->state_status == SS_INSTALLED)
     while ((dep_ab_pkg = *dependents++) != NULL) {
         if (dep_ab_pkg->state_status == SS_INSTALLED)
-             opkg_message(conf, OPKG_ERROR, "\t%s\n", dep_ab_pkg->name);
+             opkg_msg(ERROR, "\t%s\n", dep_ab_pkg->name);
     }
     }
-    opkg_message(conf, OPKG_ERROR, "These might cease to work if package %s is removed.\n\n", pkg->name);
-    opkg_message(conf, OPKG_ERROR, "");
-    opkg_message(conf, OPKG_ERROR, "You can force removal of this package with -force-depends.\n");
-    opkg_message(conf, OPKG_ERROR, "You can force removal of this package and its dependents\n");
-    opkg_message(conf, OPKG_ERROR, "with -force-removal-of-dependent-packages or -recursive\n");
-    opkg_message(conf, OPKG_ERROR, "or by setting option force_removal_of_dependent_packages\n");
-    opkg_message(conf, OPKG_ERROR, "in opkg.conf.\n");
-    return 0;
+    opkg_msg(ERROR, "These might cease to work if package %s is removed.\n\n",
+                   pkg->name);
+    opkg_msg(ERROR, "Force removal of this package with --force-depends.\n");
+    opkg_msg(ERROR, "Force removal of this package and its dependents\n");
+    opkg_msg(ERROR, "with --force-removal-of-dependent-packages.\n");
 }
 
 }
 
-static int remove_autoinstalled (opkg_conf_t *conf, pkg_t *pkg)
+/*
+ * Find and remove packages that were autoinstalled and are orphaned
+ * by the removal of pkg.
+ */
+static int
+remove_autoinstalled(pkg_t *pkg)
 {
 {
-  /*
-   * find and remove packages that were autoinstalled and are orphaned by the removal of pkg
-   */
-
-  char *buffer, *d_str;
-  int i;
-
-  for (i = 0; i < pkg->depends_count; ++i)
-  {
-    int x = 0;
-    pkg_t *p;
-    d_str = pkg->depends_str[i];
-    buffer = malloc (strlen (d_str) + 1);
-    if (!buffer)
-    {
-      fprintf(stderr,"%s Unable to allocate memory.\n", __FUNCTION__);
-      return -1;
-    }
-
-    while (d_str[x] != '\0' && d_str[x] != ' ')
-    {
-      buffer[x] = d_str[x];
-      ++x;
-    }
-    buffer[x] = '\0';
-    buffer = realloc (buffer, strlen (buffer) + 1);
-    p = pkg_hash_fetch_installed_by_name (&conf->pkg_hash, buffer);
-
-    /* if the package is not installed, this could have been a circular
-     * depenancy and the package has already been removed */
-    if (!p)
-      return -1;
-
-    if (p->auto_installed)
-    {
-      int deps;
-      abstract_pkg_t **dependents;
-
-      deps = pkg_has_installed_dependents(conf, NULL, p, &dependents);
-      if (deps == 0)
-      {
-        opkg_message (conf, OPKG_INFO,
-                      "%s was autoinstalled but is now orphaned\n", buffer);
-         opkg_remove_pkg(conf, p,0);
-      }
-       else
-          opkg_message (conf, OPKG_INFO, "%s was autoinstalled and is still required by "
-                        "%d installed packages\n", buffer, deps);
-    }
-    free (buffer);
-  }
+       int i, j;
+       int n_deps;
+       pkg_t *p;
+       struct compound_depend *cdep;
+       abstract_pkg_t **dependents;
+
+       int count = pkg->pre_depends_count +
+                               pkg->depends_count +
+                               pkg->recommends_count +
+                               pkg->suggests_count;
+
+       for (i=0; i<count; i++) {
+               cdep = &pkg->depends[i];
+               if (cdep->type != DEPEND)
+                       continue;
+               for (j=0; j<cdep->possibility_count; j++) {
+                       p = pkg_hash_fetch_installed_by_name(
+                                       cdep->possibilities[j]->pkg->name);
+
+                       /* If the package is not installed, this could have
+                        * been a circular dependency and the package has
+                        * already been removed.
+                        */
+                       if (!p)
+                               return -1;
+
+                       if (!p->auto_installed)
+                               continue;
+
+                       n_deps = pkg_has_installed_dependents(p, &dependents);
+                       if (n_deps == 0) {
+                                opkg_msg(NOTICE, "%s was autoinstalled and is "
+                                              "now orphaned, removing.\n",
+                                              p->name);
+                                opkg_remove_pkg(p, 0);
+                       } else
+                               opkg_msg(INFO, "%s was autoinstalled and is "
+                                               "still required by %d "
+                                               "installed packages.\n",
+                                               p->name, n_deps);
+
+                       if (dependents)
+                               free(dependents);
+               }
+       }
 
 
-  return 0;
+       return 0;
 }
 
 }
 
-int opkg_remove_pkg(opkg_conf_t *conf, pkg_t *pkg,int message)
+int
+opkg_remove_pkg(pkg_t *pkg, int from_upgrade)
 {
 {
-/* Actually, when "message == 1" I have been called from an upgrade, and not from a normal remove
-   thus I wan't check for essential, as I'm upgrading.
-   I hope it won't break anything :) 
-*/
      int err;
      abstract_pkg_t *parent_pkg = NULL;
 
      int err;
      abstract_pkg_t *parent_pkg = NULL;
 
-     if (pkg->essential && !message) {
+/*
+ * If called from an upgrade and not from a normal remove,
+ * ignore the essential flag.
+ */
+     if (pkg->essential && !from_upgrade) {
          if (conf->force_removal_of_essential_packages) {
          if (conf->force_removal_of_essential_packages) {
-              fprintf(stderr, "WARNING: Removing essential package %s under your coercion.\n"
+              opkg_msg(NOTICE,
+                      "Removing essential package %s under your coercion.\n"
                       "\tIf your system breaks, you get to keep both pieces\n",
                       pkg->name);
          } else {
                       "\tIf your system breaks, you get to keep both pieces\n",
                       pkg->name);
          } else {
-              fprintf(stderr, "ERROR: Refusing to remove essential package %s.\n"
+              opkg_msg(NOTICE, "Refusing to remove essential package %s.\n"
                       "\tRemoving an essential package may lead to an unusable system, but if\n"
                       "\tyou enjoy that kind of pain, you can force opkg to proceed against\n"
                       "\tRemoving an essential package may lead to an unusable system, but if\n"
                       "\tyou enjoy that kind of pain, you can force opkg to proceed against\n"
-                      "\tits will with the option: -force-removal-of-essential-packages\n",
+                      "\tits will with the option: --force-removal-of-essential-packages\n",
                       pkg->name);
                       pkg->name);
-              return OPKG_PKG_IS_ESSENTIAL;
+              return -1;
          }
      }
 
          }
      }
 
@@ -253,77 +255,66 @@ int opkg_remove_pkg(opkg_conf_t *conf, pkg_t *pkg,int message)
         && !(pkg->state_flag & SF_REPLACE)) {
          abstract_pkg_t **dependents;
          int has_installed_dependents = 
         && !(pkg->state_flag & SF_REPLACE)) {
          abstract_pkg_t **dependents;
          int has_installed_dependents = 
-              pkg_has_installed_dependents(conf, parent_pkg, pkg, &dependents);
+              pkg_has_installed_dependents(pkg, &dependents);
 
          if (has_installed_dependents) {
               /*
 
          if (has_installed_dependents) {
               /*
-               * if this package is depended up by others, then either we should
+               * if this package is depended upon by others, then either we should
                * not remove it or we should remove it and all of its dependents 
                */
 
                * not remove it or we should remove it and all of its dependents 
                */
 
-              if (!conf->force_removal_of_dependent_packages
-                  && !user_prefers_removing_dependents(conf, parent_pkg, pkg, dependents)) {
-                   return OPKG_PKG_HAS_DEPENDENTS;
+              if (!conf->force_removal_of_dependent_packages) {
+                   print_dependents_warning(pkg, dependents);
+                   free(dependents);
+                   return -1;
               }
 
               /* remove packages depending on this package - Karthik */
               }
 
               /* remove packages depending on this package - Karthik */
-              err = opkg_remove_dependent_pkgs (conf, pkg, dependents);
-              free(dependents);
-              if (err) return err;
+              err = opkg_remove_dependent_pkgs(pkg, dependents);
+              if (err) {
+                free(dependents);
+                 return err;
+               }
          }
          }
+          if (dependents)
+              free(dependents);
      }
 
      }
 
-     if ( message==0 ){
-         opkg_message (conf, OPKG_NOTICE,
-                      "Removing package %s from %s...\n", pkg->name, pkg->dest->name);
-         fflush(stdout);
+     if (from_upgrade == 0) {
+         opkg_msg(NOTICE, "Removing package %s from %s...\n",
+                        pkg->name, pkg->dest->name);
      }
      pkg->state_flag |= SF_FILELIST_CHANGED;
 
      pkg->state_want = SW_DEINSTALL;
      opkg_state_changed++;
 
      }
      pkg->state_flag |= SF_FILELIST_CHANGED;
 
      pkg->state_want = SW_DEINSTALL;
      opkg_state_changed++;
 
-     pkg_run_script(conf, pkg, "prerm", "remove");
+     pkg_run_script(pkg, "prerm", "remove");
 
      /* DPKG_INCOMPATIBILITY: dpkg is slightly different here. It
        maintains an empty filelist rather than deleting it. That seems
        like a big pain, and I don't see that that should make a big
        difference, but for anyone who wants tighter compatibility,
        feel free to fix this. */
 
      /* DPKG_INCOMPATIBILITY: dpkg is slightly different here. It
        maintains an empty filelist rather than deleting it. That seems
        like a big pain, and I don't see that that should make a big
        difference, but for anyone who wants tighter compatibility,
        feel free to fix this. */
-     remove_data_files_and_list(conf, pkg);
-
-     pkg_run_script(conf, pkg, "postrm", "remove");
-
-     remove_maintainer_scripts_except_postrm(conf, pkg);
+     remove_data_files_and_list(pkg);
 
 
-     /* Aman Gupta - Since opkg is made for handheld devices with limited
-      * space, it doesn't make sense to leave extra configurations, files, 
-      * and maintainer scripts left around. So, we make remove like purge, 
-      * and take out all the crap :) */
+     pkg_run_script(pkg, "postrm", "remove");
 
 
-     remove_postrm(conf, pkg);
+     remove_maintainer_scripts(pkg);
      pkg->state_status = SS_NOT_INSTALLED;
 
      if (parent_pkg) 
          parent_pkg->state_status = SS_NOT_INSTALLED;
 
      pkg->state_status = SS_NOT_INSTALLED;
 
      if (parent_pkg) 
          parent_pkg->state_status = SS_NOT_INSTALLED;
 
-
      /* remove autoinstalled packages that are orphaned by the removal of this one */
      if (conf->autoremove)
      /* remove autoinstalled packages that are orphaned by the removal of this one */
      if (conf->autoremove)
-       remove_autoinstalled (conf, pkg);
-
-
+       remove_autoinstalled(pkg);
 
      return 0;
 }
 
 
      return 0;
 }
 
-int opkg_purge_pkg(opkg_conf_t *conf, pkg_t *pkg)
-{
-    opkg_remove_pkg(conf, pkg,0);
-    return 0;
-}
-
-int remove_data_files_and_list(opkg_conf_t *conf, pkg_t *pkg)
+void
+remove_data_files_and_list(pkg_t *pkg)
 {
      str_list_t installed_dirs;
      str_list_t *installed_files;
 {
      str_list_t installed_dirs;
      str_list_t *installed_files;
@@ -332,46 +323,61 @@ int remove_data_files_and_list(opkg_conf_t *conf, pkg_t *pkg)
      conffile_t *conffile;
      int removed_a_dir;
      pkg_t *owner;
      conffile_t *conffile;
      int removed_a_dir;
      pkg_t *owner;
+     int rootdirlen = 0;
 
 
-     str_list_init(&installed_dirs);
      installed_files = pkg_get_installed_files(pkg);
      installed_files = pkg_get_installed_files(pkg);
+     if (installed_files == NULL) {
+            opkg_msg(ERROR, "Failed to determine installed "
+                    "files for %s. None removed.\n", pkg->name);
+            return;
+     }
+
+     str_list_init(&installed_dirs);
 
 
-     for (iter = installed_files->head; iter; iter = iter->next) {
-         file_name = iter->data;
+     /* don't include trailing slash */
+     if (conf->offline_root)
+          rootdirlen = strlen(conf->offline_root);
+
+     for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
+         file_name = (char *)iter->data;
+
+         owner = file_hash_get_file_owner(file_name);
+         if (owner != pkg)
+                 /* File may have been claimed by another package. */
+                 continue;
 
          if (file_is_dir(file_name)) {
 
          if (file_is_dir(file_name)) {
-              str_list_append(&installed_dirs, strdup(file_name));
+              str_list_append(&installed_dirs, file_name);
               continue;
          }
 
               continue;
          }
 
-         conffile = pkg_get_conffile(pkg, file_name);
+         conffile = pkg_get_conffile(pkg, file_name+rootdirlen);
          if (conffile) {
          if (conffile) {
-              /* XXX: QUESTION: Is this right? I figure we only need to
-                 save the conffile if it has been modified. Is that what
-                 dpkg does? Or does dpkg preserve all conffiles? If so,
-                 this seems like a better thing to do to conserve
-                 space. */
-              if (conffile_has_been_modified(conf, conffile)) {
-                   opkg_message (conf, OPKG_NOTICE,
-                                 "  not deleting modified conffile %s\n", file_name);
-                   fflush(stdout);
+              if (conffile_has_been_modified(conffile)) {
+                   opkg_msg(NOTICE, "Not deleting modified conffile %s.\n",
+                                   file_name);
                    continue;
               }
          }
 
                    continue;
               }
          }
 
-         opkg_message(conf, OPKG_INFO, "  deleting %s (noaction=%d)\n", file_name, conf->noaction);
-         if (!conf->noaction)
+         if (!conf->noaction) {
+               opkg_msg(INFO, "Deleting %s.\n", file_name, conf->noaction);
               unlink(file_name);
               unlink(file_name);
+         } else
+               opkg_msg(INFO, "Not deleting %s. (noaction)\n",
+                               file_name);
+
      }
 
      }
 
+     /* Remove empty directories */
      if (!conf->noaction) {
          do {
               removed_a_dir = 0;
      if (!conf->noaction) {
          do {
               removed_a_dir = 0;
-              for (iter = installed_dirs.head; iter; iter = iter->next) {
-                   file_name = iter->data;
+              for (iter = str_list_first(&installed_dirs); iter; iter = str_list_next(&installed_dirs, iter)) {
+                   file_name = (char *)iter->data;
            
                    if (rmdir(file_name) == 0) {
            
                    if (rmdir(file_name) == 0) {
-                        opkg_message(conf, OPKG_INFO, "  deleting %s\n", file_name);
+                        opkg_msg(INFO, "Deleting %s.\n", file_name);
                         removed_a_dir = 1;
                         str_list_remove(&installed_dirs, &iter);
                    }
                         removed_a_dir = 1;
                         str_list_remove(&installed_dirs, &iter);
                    }
@@ -380,15 +386,13 @@ int remove_data_files_and_list(opkg_conf_t *conf, pkg_t *pkg)
      }
 
      pkg_free_installed_files(pkg);
      }
 
      pkg_free_installed_files(pkg);
-     /* We have to remove the file list now, so that
-       find_pkg_owning_file does not always just report this package */
-     pkg_remove_installed_files_list(conf, pkg);
+     pkg_remove_installed_files_list(pkg);
 
      /* Don't print warning for dirs that are provided by other packages */
 
      /* Don't print warning for dirs that are provided by other packages */
-     for (iter = installed_dirs.head; iter; iter = iter->next) {
-         file_name = iter->data;
+     for (iter = str_list_first(&installed_dirs); iter; iter = str_list_next(&installed_dirs, iter)) {
+         file_name = (char *)iter->data;
 
 
-         owner = file_hash_get_file_owner(conf, file_name);
+         owner = file_hash_get_file_owner(file_name);
          if (owner) {
               free(iter->data);
               iter->data = NULL;
          if (owner) {
               free(iter->data);
               iter->data = NULL;
@@ -397,53 +401,35 @@ int remove_data_files_and_list(opkg_conf_t *conf, pkg_t *pkg)
      }
 
      /* cleanup */
      }
 
      /* cleanup */
-     for (iter = installed_dirs.head; iter; iter = iter->next) {
-         free(iter->data);
-         iter->data = NULL;
+     while (!void_list_empty(&installed_dirs)) {
+        iter = str_list_pop(&installed_dirs);
+        free(iter->data);
+        free(iter);
      }
      str_list_deinit(&installed_dirs);
      }
      str_list_deinit(&installed_dirs);
-
-     return 0;
 }
 
 }
 
-int remove_maintainer_scripts_except_postrm(opkg_conf_t *conf, pkg_t *pkg)
+void
+remove_maintainer_scripts(pkg_t *pkg)
 {
 {
-    int i, err;
-    char *globpattern;
-    glob_t globbuf;
-    
-    if (conf->noaction) return 0;
+       int i, err;
+       char *globpattern;
+       glob_t globbuf;
 
 
-    sprintf_alloc(&globpattern, "%s/%s.*",
-                 pkg->dest->info_dir, pkg->name);
-    err = glob(globpattern, 0, NULL, &globbuf);
-    free(globpattern);
-    if (err) {
-       return 0;
-    }
+       if (conf->noaction)
+               return;
 
 
-    for (i = 0; i < globbuf.gl_pathc; i++) {
-       if (str_ends_with(globbuf.gl_pathv[i], ".postrm")) {
-           continue;
-       }
-        opkg_message(conf, OPKG_INFO, "  deleting %s\n", globbuf.gl_pathv[i]);
-       unlink(globbuf.gl_pathv[i]);
-    }
-    globfree(&globbuf);
+       sprintf_alloc(&globpattern, "%s/%s.*",
+                       pkg->dest->info_dir, pkg->name);
 
 
-    return 0;
-}
-
-int remove_postrm(opkg_conf_t *conf, pkg_t *pkg)
-{
-    char *postrm_file_name;
+       err = glob(globpattern, 0, NULL, &globbuf);
+       free(globpattern);
+       if (err)
+               return;
 
 
-    if (conf->noaction) return 0;
-
-    sprintf_alloc(&postrm_file_name, "%s/%s.postrm",
-                 pkg->dest->info_dir, pkg->name);
-    unlink(postrm_file_name);
-    free(postrm_file_name);
-
-    return 0;
+       for (i = 0; i < globbuf.gl_pathc; i++) {
+               opkg_msg(INFO, "Deleting %s.\n", globbuf.gl_pathv[i]);
+               unlink(globbuf.gl_pathv[i]);
+       }
+       globfree(&globbuf);
 }
 }