move pkg_compare_name to pkg_vec and remove qsort in hash_get
[project/opkg-lede.git] / libopkg / opkg_install.c
index 3db224f191bd592e2317e7b7d660b60c979a86f2..3a1d69d46467b228eb3c9febecc8ec34b4ee9429 100644 (file)
@@ -21,7 +21,9 @@
 #include <glob.h>
 #include <time.h>
 #include <signal.h>
+#ifndef __USE_GNU
 typedef void (*sighandler_t)(int);
+#endif
 
 #include "pkg.h"
 #include "pkg_hash.h"
@@ -43,7 +45,6 @@ typedef void (*sighandler_t)(int);
 #include "xsystem.h"
 #include "user.h"
 
-int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg);
 static int verify_pkg_installable(opkg_conf_t *conf, pkg_t *pkg);
 static int unpack_pkg_control_files(opkg_conf_t *conf, pkg_t *pkg);
 
@@ -310,60 +311,6 @@ int pkg_mark_dependencies_for_installation(opkg_conf_t *conf, pkg_t *pkg, pkg_ve
 
      return 0;
 }
-#if 0
-int name_mark_dependencies_for_installation(opkg_conf_t *conf, const char *pkg_name, pkg_vec_t *pkgs_needed)
-{
-     int cmp;
-     pkg_t *old, *new;
-     char *old_version, *new_version;
-
-     old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg_name);
-    
-     new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name);
-     if (new == NULL) {
-         return OPKG_PKG_HAS_NO_CANDIDATE;
-     }
-     if (old) {
-         old_version = pkg_version_str_alloc(old);
-         new_version = pkg_version_str_alloc(new);
-
-         cmp = pkg_compare_versions(old, new);
-          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
-           opkg_message(conf, OPKG_DEBUG, " Forcing downgrade ");
-             cmp = -1 ;                                       /* then we force opkg to downgrade */ 
-                                                              /* We need to use a value < 0 because in the 0 case we are asking to */
-                                                              /* reinstall, and some check could fail asking the "force-reinstall" option */
-          } 
-         opkg_message(conf, OPKG_DEBUG, 
-                      "comparing visible versions of pkg %s:"
-                      "\n\t%s is installed "
-                      "\n\t%s is available "
-                      "\n\t%d was comparison result\n",
-                      pkg_name, old_version, new_version, cmp);
-         if (cmp == 0 && !conf->force_reinstall) {
-              opkg_message(conf, OPKG_NOTICE,
-                           "Package %s (%s) installed in %s is up to date.\n",
-                           old->name, old_version, old->dest->name);
-              free(old_version);
-              free(new_version);
-              return 0;
-         } else if (cmp > 0) {
-              opkg_message(conf, OPKG_NOTICE,
-                           "Not downgrading package %s on %s from %s to %s.\n",
-                           old->name, old->dest->name, old_version, new_version);
-              free(old_version);
-              free(new_version);
-              return 0;
-         } else if (cmp < 0) {
-              new->dest = old->dest;
-              old->state_want = SW_DEINSTALL;
-              old->state_flag |= SF_OBSOLETE;
-         }
-     }
-     return pkg_mark_dependencies_for_installation(conf, new, pkgs_needed);
-}
-
-#endif
 
 int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg)
 {
@@ -451,7 +398,6 @@ int opkg_satisfy_all_dependences(opkg_conf_t *conf)
      return 0;
 }
 
-\f
 
 static int check_conflicts_for(opkg_conf_t *conf, pkg_t *pkg)
 {
@@ -506,7 +452,9 @@ static int update_file_ownership(opkg_conf_t *conf, pkg_t *new_pkg, pkg_t *old_p
                    hash_table_insert(&conf->obs_file_hash, old_file, old_pkg);
               }
          }
+          pkg_free_installed_files(old_pkg);
      }
+     pkg_free_installed_files(new_pkg);
      return 0;
 }
 
@@ -519,7 +467,7 @@ static int verify_pkg_installable(opkg_conf_t *conf, pkg_t *pkg)
      * XXX: BUG easy for cworth
      * 1) please point the call below to the correct current root destination
      * 2) we need to resolve how to check the required space for a pending pkg, 
-     *    my diddling with the .ipk file size below isn't going to cut it.
+     *    my diddling with the .opk file size below isn't going to cut it.
      * 3) return a proper error code instead of 1
      */
      int comp_size, blocks_available;
@@ -623,6 +571,59 @@ static int unpack_pkg_control_files(opkg_conf_t *conf, pkg_t *pkg)
      return 0;
 }
 
+static int pkg_remove_orphan_dependent(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg) 
+{
+    int i, j, found;
+    char *buf, *d_str;
+    pkg_t *p;
+    if (!old_pkg) 
+        return 0;
+    if (!pkg) {
+        fprintf(stderr, "pkg shall not be NULL here.  please send to the bugzilla!! [%s %d]\n", __FILE__, __LINE__);
+        return -1;
+    }
+    if (old_pkg->depends_count == 0) 
+        return 0;
+    for (i=0;i<old_pkg->depends_count;i++) {
+        found = 0;
+        for (j=0;j<pkg->depends_count;j++) {
+            if (!strcmp(old_pkg->depends_str[i], pkg->depends_str[j])) {
+                found = 1;
+                break;
+            }
+        }
+        if (found)
+            continue;
+        d_str = old_pkg->depends_str[i];
+        buf = calloc (1, strlen (d_str) + 1);
+        j=0;
+        while (d_str[j] != '\0' && d_str[j] != ' ') {
+            buf[j]=d_str[j];
+            ++j;
+        }
+        buf[j]='\0';
+        buf = realloc (buf, strlen (buf) + 1);
+        p = pkg_hash_fetch_installed_by_name (&conf->pkg_hash, buf);
+        if (!p) {
+            fprintf(stderr, "The pkg %s had been removed!!\n", buf);
+            free(buf);
+            continue;
+        }
+        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_NOTICE,"%s was autoinstalled but is now orphaned, remove it.\n", buf);
+                opkg_remove_pkg(conf, p, 0);
+            } else 
+                opkg_message (conf, OPKG_INFO, "%s was autoinstalled and is still required by %d installed packages\n", buf, deps);
+        }
+        free(buf);
+    }
+    return 0;
+}
+
 /* returns number of installed replacees */
 int pkg_get_installed_replacees(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *installed_replacees)
 {
@@ -747,7 +748,9 @@ static int opkg_install_check_downgrade(opkg_conf_t *conf, pkg_t *pkg, pkg_t *ol
      }
 }
 
-/* and now the meat... */
+/**
+ *  @brief Really install a pkg_t 
+ */
 int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
 {
      int err = 0;
@@ -828,22 +831,26 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
      #if HAVE_GPGME
      char *list_file_name, *sig_file_name, *lists_dir;
 
-     sprintf_alloc (&lists_dir, "%s",
-                   (conf->restrict_to_default_dest)
-                    ? conf->default_dest->lists_dir
-                    : conf->lists_dir);
-     sprintf_alloc (&list_file_name, "%s/%s", lists_dir, pkg->src->name);
-     sprintf_alloc (&sig_file_name, "%s/%s.sig", lists_dir, pkg->src->name);
-
-     if (file_exists (sig_file_name))
+     /* check to ensure the package has come from a repository */
+     if (pkg->src)
      {
-       if (opkg_verify_file (conf, list_file_name, sig_file_name))
-         return OPKG_INSTALL_ERR_SIGNATURE;
+       sprintf_alloc (&lists_dir, "%s",
+                     (conf->restrict_to_default_dest)
+                      ? conf->default_dest->lists_dir
+                      : conf->lists_dir);
+       sprintf_alloc (&list_file_name, "%s/%s", lists_dir, pkg->src->name);
+       sprintf_alloc (&sig_file_name, "%s/%s.sig", lists_dir, pkg->src->name);
+
+       if (file_exists (sig_file_name))
+       {
+         if (opkg_verify_file (conf, list_file_name, sig_file_name))
+           return OPKG_INSTALL_ERR_SIGNATURE;
+       }
+
+       free (lists_dir);
+       free (list_file_name);
+       free (sig_file_name);
      }
-
-     free (lists_dir);
-     free (list_file_name);
-     free (sig_file_name);
      #endif
 
      /* Check for md5 values */
@@ -900,6 +907,8 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
          opkg_state_changed++;
          pkg->state_flag |= SF_FILELIST_CHANGED;
 
+          pkg_remove_orphan_dependent(conf, pkg, old_pkg);
+
          /* XXX: BUG: we really should treat replacement more like an upgrade
           *      Instead, we're going to remove the replacees 
           */