opkg: make .opk as the default opkg file extension
[oweals/opkg-lede.git] / libopkg / opkg_install.c
index 7bdd3bac2c4d5ec0fef9192c56714c334387e363..47554d0fe0b02a503c7ed9dbac3e9af55f37cf3b 100644 (file)
@@ -1,4 +1,4 @@
-/* opkg_install.c - the itsy package management system
+/* opkg_install.c - the opkg package management system
 
    Carl D. Worth
 
@@ -15,7 +15,7 @@
    General Public License for more details.
 */
 
-#include "opkg.h"
+#include "includes.h"
 #include <errno.h>
 #include <dirent.h>
 #include <glob.h>
@@ -35,6 +35,7 @@ typedef void (*sighandler_t)(int);
 #include "opkg_utils.h"
 #include "opkg_message.h"
 #include "opkg_state.h"
+#include "opkg_defines.h"
 
 #include "sprintf_alloc.h"
 #include "file_util.h"
@@ -136,7 +137,7 @@ int opkg_install_from_file(opkg_conf_t *conf, const char *filename)
 
 opkg_error_t opkg_install_by_name(opkg_conf_t *conf, const char *pkg_name)
 {
-     int cmp;
+     int cmp, err;
      pkg_t *old, *new;
      char *old_version, *new_version;
 
@@ -146,7 +147,7 @@ opkg_error_t opkg_install_by_name(opkg_conf_t *conf, const char *pkg_name)
         opkg_message(conf, OPKG_DEBUG2, " Old versions from pkg_hash_fetch %s \n",  old->version );
     
      opkg_message(conf, OPKG_DEBUG2, " Getting new  from pkg_hash_fetch \n" );
-     new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name);
+     new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name, &err);
      if ( new ) 
         opkg_message(conf, OPKG_DEBUG2, " New versions from pkg_hash_fetch %s \n",  new->version );
 
@@ -164,7 +165,10 @@ opkg_error_t opkg_install_by_name(opkg_conf_t *conf, const char *pkg_name)
      opkg_message(conf, OPKG_DEBUG2, " \n");
 
      if (new == NULL) {
-         return OPKG_PKG_HAS_NO_CANDIDATE;
+         if (err)
+           return err;
+         else
+           return OPKG_PKG_HAS_NO_CANDIDATE;
      }
 
      new->state_flag |= SF_USER;
@@ -306,7 +310,7 @@ 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;
@@ -359,7 +363,7 @@ int name_mark_dependencies_for_installation(opkg_conf_t *conf, const char *pkg_n
      return pkg_mark_dependencies_for_installation(conf, new, pkgs_needed);
 }
 
-\f
+#endif
 
 int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg)
 {
@@ -393,6 +397,7 @@ int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg)
      }
 
      if (ndepends <= 0) {
+         pkg_vec_free(depends);
          return 0;
      }
 
@@ -501,7 +506,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;
 }
 
@@ -514,7 +521,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;
@@ -753,7 +760,6 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
      int old_state_flag;
      char* file_md5;
      char *pkgid;
-
     
      if ( from_upgrade ) 
         message = 1;            /* Coming from an upgrade, and should change the output message */
@@ -761,7 +767,7 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
      if (!pkg) {
          opkg_message(conf, OPKG_ERROR,
                       "INTERNAL ERROR: null pkg passed to opkg_install_pkg\n");
-         return -EINVAL;
+         return OPKG_INSTALL_ERR_INTERNAL;
      }
 
      opkg_message(conf, OPKG_DEBUG2, "Function: %s calling pkg_arch_supported %s \n", __FUNCTION__, __FUNCTION__);
@@ -769,11 +775,11 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
      if (!pkg_arch_supported(conf, pkg)) {
          opkg_message(conf, OPKG_ERROR, "INTERNAL ERROR: architecture %s for pkg %s is unsupported.\n",
                       pkg->architecture, pkg->name);
-         return -EINVAL;
+         return OPKG_INSTALL_ERR_INTERNAL;
      }
      if (pkg->state_status == SS_INSTALLED && conf->force_reinstall == 0 && conf->nodeps == 0) {
          err = satisfy_dependencies_for(conf, pkg);
-         if (err) { return err; }
+         if (err) { return OPKG_INSTALL_ERR_DEPENDENCIES; }
 
          opkg_message(conf, OPKG_NOTICE,
                       "Package %s is already installed in %s.\n", 
@@ -788,7 +794,7 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
      old_pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name);
 
      err = opkg_install_check_downgrade(conf, pkg, old_pkg, message);
-     if (err) { return err; }
+     if (err) { return OPKG_INSTALL_ERR_NO_DOWNGRADE; }
 
      pkg->state_want = SW_INSTALL;
      if (old_pkg){                          
@@ -798,7 +804,7 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
 
      /* Abhaya: conflicts check */
      err = check_conflicts_for(conf, pkg);
-     if (err) { return err; }
+     if (err) { return OPKG_INSTALL_ERR_CONFLICTS; }
     
      /* this setup is to remove the upgrade scenario in the end when
        installing pkg A, A deps B & B deps on A. So both B and A are
@@ -808,7 +814,7 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
         && conf->force_reinstall == 0) return 0;
     
      err = verify_pkg_installable(conf, pkg);
-     if (err) { return err; }
+     if (err) { return OPKG_INSTALL_ERR_NO_SPACE; }
 
      if (pkg->local_filename == NULL) {
          err = opkg_download_pkg(conf, pkg, conf->tmp_dir);
@@ -816,11 +822,37 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
               opkg_message(conf, OPKG_ERROR,
                            "Failed to download %s. Perhaps you need to run 'opkg update'?\n",
                            pkg->name);
-              return err;
+              return OPKG_INSTALL_ERR_DOWNLOAD;
          }
      }
 
-/* Check for md5 values */
+     /* check that the repository is valid */
+     #if HAVE_GPGME
+     char *list_file_name, *sig_file_name, *lists_dir;
+
+     /* check to ensure the package has come from a repository */
+     if (pkg->src)
+     {
+       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);
+     }
+     #endif
+
+     /* Check for md5 values */
      if (pkg->md5sum)
      {
          file_md5 = file_md5sum_alloc(pkg->local_filename);
@@ -830,7 +862,7 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
                            "Package %s md5sum mismatch. Either the opkg or the package index are corrupt. Try 'opkg update'.\n",
                            pkg->name);
               free(file_md5);
-              return err;
+              return OPKG_INSTALL_ERR_MD5;
          }
          free(file_md5);
      }
@@ -843,11 +875,11 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
 /* Pigi: check if it will pass from here when replacing. It seems to fail */
 /* That's rather strange that files don't change owner. Investigate !!!!!!*/
      err = update_file_ownership(conf, pkg, old_pkg);
-     if (err) { return err; }
+     if (err) { return OPKG_ERR_UNKNOWN; }
 
      if (conf->nodeps == 0) {
          err = satisfy_dependencies_for(conf, pkg);
-         if (err) { return err; }
+         if (err) { return OPKG_INSTALL_ERR_DEPENDENCIES; }
      }
 
      replacees = pkg_vec_alloc();
@@ -965,7 +997,7 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
               signal(SIGINT, old_handler);
          else
               sigprocmask(SIG_UNBLOCK, &newset, &oldset);
-
+          pkg_vec_free (replacees);
          return 0;
      
 
@@ -995,7 +1027,8 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
          else
               sigprocmask(SIG_UNBLOCK, &newset, &oldset);
 
-         return err;
+          pkg_vec_free (replacees);
+         return OPKG_ERR_UNKNOWN;
      }
      opkg_set_current_state (conf, OPKG_STATE_NONE, NULL);
 }
@@ -1702,251 +1735,3 @@ static int backup_remove(const char *file_name)
      return 0;
 }
 
-\f
-
-#ifdef CONFIG_OPKG_PROCESS_ACTIONS
-
-int opkg_remove_packages(opkg_conf_t *conf, pkg_vec_t *pkgs_to_remove) 
-{
-     /* first, remove the packages that need removing */
-     for (i = 0 ; i < pkgs_to_remove->len; i++ ) {
-         pkg_t *pkg = pkgs_to_remove->pkgs[i];
-         err = opkg_remove_pkg(conf, pkg,0);
-         if (err) return err;
-     }
-     return 0;
-}
-
-int opkg_process_actions_sanity_check(opkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_superseded, pkg_vec_t *pkgs_to_install)
-{
-     int i;
-     /* now one more pass checking on the ones that need to be installed */
-     for (i = 0 ; i < pkgs_to_install->len; i++ ) {
-         pkg_t *pkg = pkgs_to_install->pkgs[i];
-         if (pkg->dest == NULL)
-              pkg->dest = conf->default_dest;
-
-         pkg->state_want = SW_INSTALL;
-
-         /* Abhaya: conflicts check */
-         err = check_conflicts_for(conf, pkg);
-         if (err) { return err; }
-     }
-     return 0;
-}
-
-int opkg_process_actions_unpack_packages(opkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_to_install)
-{
-     int i;
-     /* now one more pass checking on the ones that need to be installed */
-     for (i = 0 ; i < pkgs_to_install->len; i++ ) {
-         pkg_t *pkg = pkgs_to_install->pkgs[i];
-
-         /* XXX: FEATURE: Need to really support Provides/Replaces: here at some point */
-         pkg_vec_t *replacees = pkg_vec_alloc();
-         pkg_get_installed_replacees(conf, pkg, replacees);
-
-         /* XXX: BUG: we really should treat replacement more like an upgrade
-          *      Instead, we're going to remove the replacees 
-          */
-         err = pkg_remove_installed_replacees(conf, replacees);
-         if (err) return err;
-         pkg->state_flag |= SF_REMOVED_REPLACEES;
-     }
-     return 0;
-}
-
-int opkg_process_actions_unpack_packages(opkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_to_install)
-{
-     int i;
-     /* now one more pass checking on the ones that need to be installed */
-     for (i = 0 ; i < pkgs_to_install->len; i++ ) {
-         pkg_t *pkg = pkgs_to_install->pkgs[i];
-         if (pkg->local_filename == NULL) {
-              err = opkg_download_pkg(conf, pkg, conf->tmp_dir);
-              if (err) {
-                   opkg_message(conf, OPKG_ERROR,
-                                "Failed to download %s. Perhaps you need to run 'opkg update'?\n",
-                                pkg->name);
-                   return err;
-              }
-         }
-         if (pkg->tmp_unpack_dir == NULL) {
-              err = unpack_pkg_control_files(conf, pkg);
-              if (err) return err;
-         }
-     }
-     return 0;
-}
-
-int opkg_process_actions_prerm(opkg_conf_t *conf, pkg_vec_t *pkgs_to_install)
-{
-     int i;
-     /* now one more pass checking on the ones that need to be installed */
-     for (i = 0 ; i < pkgs_to_install->len; i++ ) {
-         pkg_t *pkg = pkgs_to_install->pkgs[i];
-         pkg_t *old_pkg = pkg->old_pkg;
-
-         err = prerm_upgrade_old_pkg(conf, pkg, old_pkg);
-         if (err) return err;
-
-         err = prerm_deconfigure_conflictors(conf, pkg, replacees);
-         if (err) return err;
-
-         err = preinst_configure(conf, pkg, old_pkg);
-         if (err) return err;
-
-         err = backup_modified_conffiles(conf, pkg, old_pkg);
-         if (err) return err;
-
-         err = postrm_upgrade_old_pkg(conf, pkg, old_pkg);
-         if (err) return err;
-     }
-     return 0;
-}
-
-int opkg_process_actions_install(opkg_conf_t *conf, pkg_vec_t *pkgs_to_install)
-{
-     int i;
-     /* now one more pass checking on the ones that need to be installed */
-     for (i = 0 ; i < pkgs_to_install->len; i++ ) {
-         pkg_t *pkg = pkgs_to_install->pkgs[i];
-         pkg_t *old_pkg = pkg->old_pkg;
-
-         if (old_pkg) {
-              old_pkg->state_want = SW_DEINSTALL;
-
-              if (old_pkg->state_flag & SF_NOPRUNE) {
-                   opkg_message(conf, OPKG_INFO,
-                                "  not removing obsolesced files because package marked noprune\n");
-              } else {
-                   opkg_message(conf, OPKG_INFO,
-                                "  removing obsolesced files\n");
-                   remove_obsolesced_files(conf, pkg, old_pkg);
-              }
-         }
-
-         opkg_message(conf, OPKG_INFO,
-                      "  installing maintainer scripts\n");
-         install_maintainer_scripts(conf, pkg, old_pkg);
-
-         /* the following just returns 0 */
-         remove_disappeared(conf, pkg);
-
-         opkg_message(conf, OPKG_INFO,
-                      "  installing data files\n");
-         install_data_files(conf, pkg);
-
-         opkg_message(conf, OPKG_INFO,
-                      "  resolving conf files\n");
-         resolve_conffiles(conf, pkg);
-
-         pkg->state_status = SS_UNPACKED;
-
-         if (old_pkg) {
-              old_pkg->state_status = SS_NOT_INSTALLED;
-         }
-
-         time(&pkg->installed_time);
-
-         opkg_message(conf, OPKG_INFO,
-                      "  cleanup temp files\n");
-         cleanup_temporary_files(conf, pkg);
-
-         if (pkg->parent)
-              pkg->parent->state_status = pkg->state_status;
-     }
-     return 0;
-}
-
-int opkg_process_actions_unwind_prerm(opkg_conf_t *conf, pkg_vec_t *pkgs_to_install)
-{
-     int i;
-     /* now one more pass checking on the ones that need to be installed */
-     for (i = 0 ; i < pkgs_to_install->len; i++ ) {
-         pkg_t *pkg = pkgs_to_install->pkgs[i];
-         pkg_t *old_pkg = pkg->old_pkg;
-
-         if (old_pkg) {
-              if (old_pkg->state_flags & SF_POSTRM_UPGRADE)
-                   postrm_upgrade_old_pkg_unwind(conf, pkg, old_pkg);
-              if (old_pkg->state_flags & SF_CHECK_DATA_FILE_CLASHES)
-                   check_data_file_clashes_unwind(conf, pkg, old_pkg);
-              if (old_pkg->state_flags & SF_BACKUP_MODIFIED_CONFFILES)
-                   backup_modified_conffiles_unwind(conf, pkg, old_pkg);
-              if (old_pkg->state_flags & SF_PREINST_CONFIGURE)
-                   preinst_configure_unwind(conf, pkg, old_pkg);
-              if (old_pkg->state_flags & SF_DECONFIGURE_CONFLICTORS)
-                   prerm_deconfigure_conflictors_unwind(conf, pkg, replacees);
-              if (old_pkg->state_flags & SF_PRERM_UPGRADE)
-                   prerm_upgrade_old_pkg_unwind(conf, pkg, old_pkg);
-
-              if (old_pkg->state_flags & SF_REMOVED_REPLACEES)
-                   remove_installed_replacees_unwind(conf, pkg, old_pkg);
-
-         }
-     }
-     return 0;
-}
-
-/* 
- * Perform all the actions.
- *
- * pkgs_to_remove are packages marked for removal.
- * pkgs_superseded are the old packages being replaced by upgrades.
- *
- * Assumes pkgs_to_install includes all dependences, recursively, sorted in installable order.
- */
-int opkg_process_actions(opkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_superseded, pkg_vec_t *pkgs_to_install)
-{
-     int err;
-     int i;
-
-     err = opkg_remove_packages(conf, pkgs_to_remove);
-     if (err) return err;
-
-     err = opkg_process_actions_sanity_check(conf, pkgs_superseded, pkgs_to_install);
-     if (err) return err;
-
-     err = opkg_process_actions_remove_replacees(conf, pkgs_to_install);
-     if (err) goto UNWIND;
-
-     /* @@@@ look at opkg_install_pkg for handling replacements */
-     err = opkg_process_actions_unpack_packages(conf, pkgs_to_install);
-     if (err) goto UNWIND;
-
-     /* 
-      * Now that we have the packages unpacked, we can look for data
-      * file clashes.  First, we mark the files from the superseded
-      * packages as obsolete.  Then we scan the files in
-      * pkgs_to_install, and only complain about clashes with
-      * non-obsolete files.
-      */
-
-     err = opkg_process_actions_check_data_file_clashes(conf, pkgs_superseded, pkgs_to_install);
-     if (err) goto UNWIND;
-
-     /* this was before checking data file clashes */
-     err = opkg_process_actions_prerm(conf, pkgs_superseded, pkgs_to_install);
-     if (err) goto UNWIND;
-
-     /* point of no return: no unwinding after this */
-     err = opkg_process_actions_install(conf, pkgs_to_install);
-     if (err) return err;
-
-     opkg_message(conf, OPKG_INFO, "Done.\n");
-     return 0;
-
- UNWIND:
-     opkg_process_actions_unwind(conf, pkgs_to_install);
-
-     opkg_message(conf, OPKG_INFO,
-                 "  cleanup temp files\n");
-     cleanup_temporary_files(conf, pkg);
-
-     opkg_message(conf, OPKG_INFO,
-                 "Failed.\n");
-     return err;
-}
-
-#endif