libopkg: fix --force-checksum to cover sha256sum cases as well
[oweals/opkg-lede.git] / libopkg / opkg_install.c
index 779950e5e128a4c764f19885dca78301df07fa96..acb7530c863eabb90fa35464a5199fb92e5fba81 100644 (file)
@@ -21,6 +21,7 @@
 #include <time.h>
 #include <signal.h>
 #include <unistd.h>
+#include <sys/stat.h>
 
 #include "pkg.h"
 #include "pkg_hash.h"
@@ -50,7 +51,7 @@ satisfy_dependencies_for(pkg_t *pkg)
      char **tmp, **unresolved = NULL;
      int ndepends;
 
-     ndepends = pkg_hash_fetch_unsatisfied_dependencies(pkg, depends, 
+     ndepends = pkg_hash_fetch_unsatisfied_dependencies(pkg, depends,
                                                        &unresolved);
 
      if (unresolved) {
@@ -58,7 +59,7 @@ satisfy_dependencies_for(pkg_t *pkg)
                       pkg->name);
          tmp = unresolved;
          while (*unresolved) {
-              opkg_msg(ERROR, "\t%s", *unresolved);
+              opkg_message(ERROR, "\t%s", *unresolved);
               free(*unresolved);
               unresolved++;
          }
@@ -134,7 +135,7 @@ check_conflicts_for(pkg_t *pkg)
          i = 0;
          while (i < conflicts->len)
               opkg_msg(level, "\t%s", conflicts->pkgs[i++]->name);
-         opkg_msg(level, "\n");
+         opkg_message(level, "\n");
          pkg_vec_free(conflicts);
          return -1;
      }
@@ -151,14 +152,17 @@ update_file_ownership(pkg_t *new_pkg, pkg_t *old_pkg)
      if (new_list == NULL)
             return -1;
 
-     for (iter = str_list_first(new_list), niter = str_list_next(new_list, iter); 
-             iter; 
+     for (iter = str_list_first(new_list), niter = str_list_next(new_list, iter);
+             iter;
              iter = niter, niter = str_list_next(new_list, niter)) {
          char *new_file = (char *)iter->data;
          pkg_t *owner = file_hash_get_file_owner(new_file);
-         if (!new_file)
-              opkg_msg(ERROR, "Null new_file for new_pkg=%s\n", new_pkg->name);
-         if (!owner || (owner == old_pkg))
+         pkg_t *obs = hash_table_get(&conf->obs_file_hash, new_file);
+
+         opkg_msg(DEBUG2, "%s: new_pkg=%s wants file %s, from owner=%s\n",
+               __func__, new_pkg->name, new_file, owner?owner->name:"<NULL>");
+
+         if (!owner || (owner == old_pkg) || obs)
               file_hash_set_file_owner(new_file, new_pkg);
      }
 
@@ -169,12 +173,12 @@ update_file_ownership(pkg_t *new_pkg, pkg_t *old_pkg)
                  return -1;
          }
 
-         for (iter = str_list_first(old_list), niter = str_list_next(old_list, iter); 
-                  iter; 
+         for (iter = str_list_first(old_list), niter = str_list_next(old_list, iter);
+                  iter;
                   iter = niter, niter = str_list_next(old_list, niter)) {
               char *old_file = (char *)iter->data;
               pkg_t *owner = file_hash_get_file_owner(old_file);
-              if (owner == old_pkg) {
+              if (!owner || (owner == old_pkg)) {
                    /* obsolete */
                    hash_table_insert(&conf->obs_file_hash, old_file, old_pkg);
               }
@@ -189,20 +193,31 @@ static int
 verify_pkg_installable(pkg_t *pkg)
 {
        unsigned long kbs_available, pkg_size_kbs;
-       char *root_dir;
+       char *root_dir = NULL;
+       struct stat s;
 
        if (conf->force_space || pkg->installed_size == 0)
                return 0;
 
-       root_dir = pkg->dest ? pkg->dest->root_dir :
-                                               conf->default_dest->root_dir;
+       if (pkg->dest)
+       {
+               if (!strcmp(pkg->dest->name, "root") && conf->overlay_root
+                   && !stat(conf->overlay_root, &s) && (s.st_mode & S_IFDIR))
+                       root_dir = conf->overlay_root;
+               else
+                       root_dir = pkg->dest->root_dir;
+       }
+
+       if (!root_dir)
+               root_dir = conf->default_dest->root_dir;
+
        kbs_available = get_available_kbytes(root_dir);
 
        pkg_size_kbs = (pkg->installed_size + 1023)/1024;
 
        if (pkg_size_kbs >= kbs_available) {
-               opkg_msg(ERROR, "Only have %dkb available on filesystem %s, "
-                       "pkg %s needs %d\n",
+               opkg_msg(ERROR, "Only have %ldkb available on filesystem %s, "
+                       "pkg %s needs %ld\n",
                        kbs_available, root_dir, pkg->name, pkg_size_kbs);
                return -1;
        }
@@ -247,7 +262,7 @@ unpack_pkg_control_files(pkg_t *pkg)
          free(conffiles_file_name);
          return 0;
      }
-    
+
      conffiles_file = fopen(conffiles_file_name, "r");
      if (conffiles_file == NULL) {
          opkg_perror(ERROR, "Failed to open %s", conffiles_file_name);
@@ -259,6 +274,7 @@ unpack_pkg_control_files(pkg_t *pkg)
      while (1) {
          char *cf_name;
          char *cf_name_in_dest;
+         int i;
 
          cf_name = file_read_line_alloc(conffiles_file);
          if (cf_name == NULL) {
@@ -267,6 +283,12 @@ unpack_pkg_control_files(pkg_t *pkg)
          if (cf_name[0] == '\0') {
               continue;
          }
+         for (i = strlen(cf_name) - 1;
+              (i >= 0) && (cf_name[i] == ' ' || cf_name[i] == '\t');
+              i--
+         ) {
+              cf_name[i] = '\0';
+         }
 
          /* Prepend dest->root_dir to conffile name.
             Take pains to avoid multiple slashes. */
@@ -295,7 +317,7 @@ unpack_pkg_control_files(pkg_t *pkg)
  * which are no longer a dependency in the new (upgraded) pkg.
  */
 static int
-pkg_remove_orphan_dependent(pkg_t *pkg, pkg_t *old_pkg) 
+pkg_remove_orphan_dependent(pkg_t *pkg, pkg_t *old_pkg)
 {
        int i, j, k, l, found,r, err = 0;
        int n_deps;
@@ -321,7 +343,7 @@ pkg_remove_orphan_dependent(pkg_t *pkg, pkg_t *old_pkg)
                        found = 0;
 
                        for (k=0; k<count1; k++) {
-                               cd1 = &pkg->depends[i];
+                               cd1 = &pkg->depends[k];
                                if (cd1->type != DEPEND)
                                        continue;
                                for (l=0; l<cd1->possibility_count; l++) {
@@ -365,7 +387,7 @@ pkg_remove_orphan_dependent(pkg_t *pkg, pkg_t *old_pkg)
                                r = opkg_remove_pkg(p, 0);
                                if (!err)
                                        err = r;
-                       } else 
+                       } else
                                opkg_msg(INFO, "%s was autoinstalled and is "
                                                "still required by %d "
                                                "installed packages.\n",
@@ -438,7 +460,7 @@ pkg_remove_installed_replacees_unwind(pkg_vec_t *replacees)
 /* compares versions of pkg and old_pkg, returns 0 if OK to proceed with installation of pkg, 1 otherwise */
 static int
 opkg_install_check_downgrade(pkg_t *pkg, pkg_t *old_pkg, int message)
-{        
+{
      if (old_pkg) {
           char message_out[15];
          char *old_version = pkg_version_str_alloc(old_pkg);
@@ -447,12 +469,12 @@ opkg_install_check_downgrade(pkg_t *pkg, pkg_t *old_pkg, int message)
          int rc = 0;
 
           memset(message_out,'\x0',15);
-          strncpy (message_out,"Upgrading ",strlen("Upgrading ")); 
+          strncpy (message_out,"Upgrading ",strlen("Upgrading "));
           if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
-             cmp = -1 ;                                       /* then we force opkg to downgrade */ 
+             cmp = -1 ;                                       /* then we force opkg to downgrade */
              strncpy (message_out,"Downgrading ",strlen("Downgrading "));         /* 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 */
-          } 
+          }
 
          if (cmp > 0) {
               if(!conf->download_only)
@@ -467,27 +489,18 @@ opkg_install_check_downgrade(pkg_t *pkg, pkg_t *old_pkg, int message)
               pkg->dest = old_pkg->dest;
               rc = 0;
          } else /* cmp == 0 */ {
-              if (conf->force_reinstall) {
                if(!conf->download_only)
-                   opkg_msg(NOTICE, "Reinstalling %s (%s) on %s...\n",
-                           pkg->name, new_version, old_pkg->dest->name);
-                   pkg->dest = old_pkg->dest;
-                   rc = 0;
-              } else {
-                   if(!conf->download_only)
-                       opkg_msg(NOTICE, "%s (%s) already install on %s."
-                               " Not reinstalling.\n",
-                               pkg->name, new_version, old_pkg->dest->name);
-                   rc = 1;
-              }
-         } 
+                   opkg_msg(NOTICE, "%s (%s) already install on %s.\n",
+                       pkg->name, new_version, old_pkg->dest->name);
+              rc = 1;
+         }
          free(old_version);
          free(new_version);
          return rc;
      } else {
           char message_out[15] ;
           memset(message_out,'\x0',15);
-          if ( message ) 
+          if ( message )
                strncpy( message_out,"Upgrading ",strlen("Upgrading ") );
           else
                strncpy( message_out,"Installing ",strlen("Installing ") );
@@ -507,7 +520,7 @@ prerm_upgrade_old_pkg(pkg_t *pkg, pkg_t *old_pkg)
 {
      /* DPKG_INCOMPATIBILITY:
        dpkg does some things here that we don't do yet. Do we care?
-       
+
        1. If a version of the package is already installed, call
           old-prerm upgrade new-version
        2. If the script runs but exits with a non-zero exit status
@@ -621,7 +634,7 @@ backup_make_backup(const char *file_name)
 {
      int err;
      char *backup;
-    
+
      backup = backup_filename_alloc(file_name);
      err = file_copy(file_name, backup);
      if (err) {
@@ -674,7 +687,7 @@ backup_modified_conffiles(pkg_t *pkg, pkg_t *old_pkg)
      if (old_pkg) {
          for (iter = nv_pair_list_first(&old_pkg->conffiles); iter; iter = nv_pair_list_next(&old_pkg->conffiles, iter)) {
               char *cf_name;
-              
+
               cf = iter->data;
               cf_name = root_filename_alloc(cf->name);
 
@@ -740,7 +753,7 @@ check_data_file_clashes(pkg_t *pkg, pkg_t *old_pkg)
        can unwind if necessary).  To avoid complexity and redundant
        storage, opkg doesn't do any installation until later, (at the
        point at which dpkg removes the backups.
-       
+
        But, we do have to check for data file clashes, since after
        installing a package with a file clash, removing either of the
        packages involved in the clash has the potential to break the
@@ -748,28 +761,26 @@ check_data_file_clashes(pkg_t *pkg, pkg_t *old_pkg)
      */
      str_list_t *files_list;
      str_list_elt_t *iter, *niter;
-
+     char *filename;
      int clashes = 0;
 
      files_list = pkg_get_installed_files(pkg);
      if (files_list == NULL)
             return -1;
 
-     for (iter = str_list_first(files_list), niter = str_list_next(files_list, iter); 
-             iter; 
+     for (iter = str_list_first(files_list), niter = str_list_next(files_list, iter);
+             iter;
              iter = niter, niter = str_list_next(files_list, iter)) {
-         char *root_filename;
-         char *filename = (char *) iter->data;
-         root_filename = root_filename_alloc(filename);
-         if (file_exists(root_filename) && (! file_is_dir(root_filename))) {
+         filename = (char *) iter->data;
+         if (file_exists(filename) && (! file_is_dir(filename))) {
               pkg_t *owner;
               pkg_t *obs;
 
-              if (backup_exists_for(root_filename)) {
+              if (backup_exists_for(filename)) {
                    continue;
               }
 
-              /* Pre-existing files are OK if force-overwrite was asserted. */ 
+              /* Pre-existing files are OK if force-overwrite was asserted. */
               if (conf->force_overwrite) {
                    /* but we need to change who owns this file */
                    file_hash_set_file_owner(filename, pkg);
@@ -816,14 +827,13 @@ check_data_file_clashes(pkg_t *pkg, pkg_t *old_pkg)
                            "\tBut that file is already provided by package ",
                            pkg->name, filename);
               if (owner) {
-                   opkg_msg(ERROR, "%s\n", owner->name);
+                   opkg_message(ERROR, "%s\n", owner->name);
               } else {
-                   opkg_msg(ERROR, "<no package>\n"
+                   opkg_message(ERROR, "<no package>\n"
                        "Please move this file out of the way and try again.\n");
               }
               clashes++;
          }
-         free(root_filename);
      }
      pkg_free_installed_files(pkg);
 
@@ -853,8 +863,8 @@ check_data_file_clashes_change(pkg_t *pkg, pkg_t *old_pkg)
      if (files_list == NULL)
             return -1;
 
-     for (iter = str_list_first(files_list), niter = str_list_next(files_list, iter); 
-             iter; 
+     for (iter = str_list_first(files_list), niter = str_list_next(files_list, iter);
+             iter;
              iter = niter, niter = str_list_next(files_list, niter)) {
          char *filename = (char *) iter->data;
           if (root_filename) {
@@ -877,7 +887,7 @@ check_data_file_clashes_change(pkg_t *pkg, pkg_t *old_pkg)
               /* Pre-existing files are OK if owned by a package replaced by new pkg. */
               if (owner) {
                    if (pkg_replaces(pkg, owner)) {
-/* It's now time to change the owner of that file. 
+/* It's now time to change the owner of that file.
    It has been "replaced" from the new "Replaces", then I need to inform lists file about that.  */
                         opkg_msg(INFO, "Replacing pre-existing file %s "
                                         "owned by package %s\n",
@@ -971,9 +981,9 @@ remove_obsolesced_files(pkg_t *pkg, pkg_t *old_pkg)
               /* in case obsolete file no longer belongs to old_pkg */
               continue;
          }
+
          /* old file is obsolete */
-         opkg_msg(INFO, "Removing obsolete file %s.\n", old);
+         opkg_msg(NOTICE, "Removing obsolete file %s.\n", old);
          if (!conf->noaction) {
               err = unlink(old);
               if (err) {
@@ -1009,7 +1019,7 @@ remove_disappeared(pkg_t *pkg)
      /* DPKG_INCOMPATIBILITY:
        This is a fairly sophisticated dpkg operation. Shall we
        skip it? */
-     
+
      /* Any packages all of whose files have been overwritten during the
        installation, and which aren't required for dependencies, are
        considered to have been removed. For each such package
@@ -1033,7 +1043,7 @@ install_data_files(pkg_t *pkg)
        than dpkg. Rather than removing backups at this point, we
        actually do the data file installation now. See comments in
        check_data_file_clashes() for more details. */
-    
+
      opkg_msg(INFO, "Extracting data files to %s.\n", pkg->dest->root_dir);
      err = pkg_extract_data_files_to_dir(pkg, pkg->dest->root_dir);
      if (err) {
@@ -1046,7 +1056,7 @@ install_data_files(pkg_t *pkg)
       * XXX: This should be fixed outside of opkg, in the Package list.
       */
      set_flags_from_control(pkg) ;
-     
+
      opkg_msg(DEBUG, "Calling pkg_write_filelist.\n");
      err = pkg_write_filelist(pkg);
      if (err)
@@ -1072,7 +1082,7 @@ resolve_conffiles(pkg_t *pkg)
      conffile_list_elt_t *iter;
      conffile_t *cf;
      char *cf_backup;
-     char *md5sum;
+     char *chksum;
 
      if (conf->noaction) return 0;
 
@@ -1083,7 +1093,7 @@ resolve_conffiles(pkg_t *pkg)
 
          /* Might need to initialize the md5sum for each conffile */
          if (cf->value == NULL) {
-              cf->value = file_md5sum_alloc(root_filename);
+              cf->value = file_sha256sum_alloc(root_filename);
          }
 
          if (!file_exists(root_filename)) {
@@ -1095,15 +1105,23 @@ resolve_conffiles(pkg_t *pkg)
 
           if (file_exists(cf_backup)) {
               /* Let's compute md5 to test if files are changed */
-              md5sum = file_md5sum_alloc(cf_backup);
-              if (md5sum && cf->value && strcmp(cf->value,md5sum) != 0 ) {
+#ifdef HAVE_MD5
+              if(cf->value && strlen(cf->value) > 33) {
+                  chksum = file_sha256sum_alloc(cf_backup);
+              } else {
+                  chksum = file_md5sum_alloc(cf_backup);
+              }
+#else
+              chksum = file_sha256sum_alloc(cf_backup);
+#endif
+              if (chksum && cf->value && strcmp(cf->value,chksum) != 0 ) {
                   if (conf->force_maintainer) {
                       opkg_msg(NOTICE, "Conffile %s using maintainer's setting.\n",
                                      cf_backup);
                   } else {
                       char *new_conffile;
                       sprintf_alloc(&new_conffile, "%s-opkg", root_filename);
-                      opkg_msg(NOTICE, "Existing conffile %s "
+                      opkg_msg(ERROR, "Existing conffile %s "
                            "is different from the conffile in the new package."
                            " The new conffile will be placed at %s.\n",
                            root_filename, new_conffile);
@@ -1113,8 +1131,8 @@ resolve_conffiles(pkg_t *pkg)
                  }
               }
               unlink(cf_backup);
-             if (md5sum)
-                  free(md5sum);
+             if (chksum)
+                  free(chksum);
           }
 
          free(cf_backup);
@@ -1136,15 +1154,17 @@ opkg_install_by_name(const char *pkg_name)
      if (old)
         opkg_msg(DEBUG2, "Old versions from pkg_hash_fetch %s.\n",
                        old->version);
-    
+
      new = pkg_hash_fetch_best_installation_candidate_by_name(pkg_name);
-     if (new == NULL)
+     if (new == NULL) {
+       opkg_msg(NOTICE, "Unknown package '%s'.\n", pkg_name);
        return -1;
+     }
 
      opkg_msg(DEBUG2, "Versions from pkg_hash_fetch:");
-     if ( old ) 
-        opkg_msg(DEBUG2, " old %s ", old->version);
-     opkg_msg(DEBUG2, " new %s\n", new->version);
+     if ( old )
+        opkg_message(DEBUG2, " old %s ", old->version);
+     opkg_message(DEBUG2, " new %s\n", new->version);
 
      new->state_flag |= SF_USER;
      if (old) {
@@ -1154,16 +1174,16 @@ opkg_install_by_name(const char *pkg_name)
          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_msg(DEBUG, "Forcing downgrade\n");
-             cmp = -1 ;                                       /* then we force opkg to 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_msg(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) {
+         if (cmp == 0) {
               opkg_msg(NOTICE,
                            "Package %s (%s) installed in %s is up to date.\n",
                            old->name, old_version, old->dest->name);
@@ -1179,7 +1199,7 @@ opkg_install_by_name(const char *pkg_name)
               return 0;
          } else if (cmp < 0) {
               new->dest = old->dest;
-              old->state_want = SW_DEINSTALL;    /* Here probably the problem for bug 1277 */
+              old->state_want = SW_DEINSTALL;
          }
          free(old_version);
          free(new_version);
@@ -1190,7 +1210,7 @@ opkg_install_by_name(const char *pkg_name)
 }
 
 /**
- *  @brief Really install a pkg_t 
+ *  @brief Really install a pkg_t
  */
 int
 opkg_install_pkg(pkg_t *pkg, int from_upgrade)
@@ -1207,7 +1227,7 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
 #endif
      sigset_t newset, oldset;
 
-     if ( from_upgrade ) 
+     if ( from_upgrade )
         message = 1;            /* Coming from an upgrade, and should change the output message */
 
      opkg_msg(DEBUG2, "Calling pkg_arch_supported.\n");
@@ -1217,12 +1237,12 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
                       pkg->architecture, pkg->name);
          return -1;
      }
-     if (pkg->state_status == SS_INSTALLED && conf->force_reinstall == 0 && conf->nodeps == 0) {
+     if (pkg->state_status == SS_INSTALLED && conf->nodeps == 0) {
          err = satisfy_dependencies_for(pkg);
          if (err)
                  return -1;
 
-         opkg_msg(NOTICE, "Package %s is already installed on %s.\n", 
+         opkg_msg(NOTICE, "Package %s is already installed on %s.\n",
                       pkg->name, pkg->dest->name);
          return 0;
      }
@@ -1238,21 +1258,21 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
             return -1;
 
      pkg->state_want = SW_INSTALL;
-     if (old_pkg){                          
+     if (old_pkg){
          old_pkg->state_want = SW_DEINSTALL; /* needed for check_data_file_clashes of dependencies */
      }
 
      err = check_conflicts_for(pkg);
      if (err)
             return -1;
-    
+
      /* 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
        installed. Then A's installation is started resulting in an
-       uncecessary upgrade */ 
-     if (pkg->state_status == SS_INSTALLED && conf->force_reinstall == 0)
+       uncecessary upgrade */
+     if (pkg->state_status == SS_INSTALLED)
             return 0;
-    
+
      err = verify_pkg_installable(pkg);
      if (err)
             return -1;
@@ -1276,7 +1296,7 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
      }
 
      /* check that the repository is valid */
-     #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
+     #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN)
      char *list_file_name, *sig_file_name, *lists_dir;
 
      /* check to ensure the package has come from a repository */
@@ -1294,13 +1314,15 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
          if (opkg_verify_file (list_file_name, sig_file_name)){
            opkg_msg(ERROR, "Failed to verify the signature of %s.\n",
                            list_file_name);
-           return -1;
+           if (!conf->force_signature)
+             return -1;
          }
        }else{
          opkg_msg(ERROR, "Signature file is missing for %s. "
                          "Perhaps you need to run 'opkg update'?\n",
                         pkg->name);
-         return -1;
+         if (!conf->force_signature)
+           return -1;
        }
 
        free (lists_dir);
@@ -1309,22 +1331,31 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
      }
      #endif
 
+#ifdef HAVE_MD5
      /* Check for md5 values */
      if (pkg->md5sum)
      {
          file_md5 = file_md5sum_alloc(pkg->local_filename);
          if (file_md5 && strcmp(file_md5, pkg->md5sum))
          {
-              opkg_msg(ERROR, "Package %s md5sum mismatch. "
-                       "Either the opkg or the package index are corrupt. "
-                       "Try 'opkg update'.\n",
-                       pkg->name);
-              free(file_md5);
-              return -1;
+              if (!conf->force_checksum)
+              {
+                  opkg_msg(ERROR, "Package %s md5sum mismatch. "
+                           "Either the opkg or the package index are corrupt. "
+                           "Try 'opkg update'.\n",
+                           pkg->name);
+                  free(file_md5);
+                  return -1;
+              }
+              else
+              {
+                  opkg_msg(NOTICE, "Ignored %s md5sum mismatch.\n", pkg->name);
+              }
          }
         if (file_md5)
               free(file_md5);
      }
+#endif
 
 #ifdef HAVE_SHA256
      /* Check for sha256 value */
@@ -1333,12 +1364,22 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
          file_sha256 = file_sha256sum_alloc(pkg->local_filename);
          if (file_sha256 && strcmp(file_sha256, pkg->sha256sum))
          {
-              opkg_msg(ERROR, "Package %s sha256sum mismatch. "
-                       "Either the opkg or the package index are corrupt. "
-                       "Try 'opkg update'.\n",
-                       pkg->name);
-              free(file_sha256);
-              return -1;
+              if (!conf->force_checksum)
+              {
+                  opkg_msg(ERROR,
+                           "Package %s sha256sum mismatch. "
+                           "Either the opkg or the package index are corrupt. "
+                           "Try 'opkg update'.\n",
+                           pkg->name);
+                  free(file_sha256);
+                  return -1;
+              }
+              else
+              {
+                  opkg_msg(NOTICE,
+                           "Ignored %s sha256sum mismatch.\n",
+                           pkg->name);
+              }
          }
         if (file_sha256)
               free(file_sha256);
@@ -1386,11 +1427,13 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
          opkg_state_changed++;
          pkg->state_flag |= SF_FILELIST_CHANGED;
 
-         if (old_pkg)
+         if (old_pkg) {
                pkg_remove_orphan_dependent(pkg, old_pkg);
-
+              old_pkg->is_upgrade = 1;
+              pkg->is_upgrade = 1;
+         }
          /* XXX: BUG: we really should treat replacement more like an upgrade
-          *      Instead, we're going to remove the replacees 
+          *      Instead, we're going to remove the replacees
           */
          err = pkg_remove_installed_replacees(replacees);
          if (err)
@@ -1424,7 +1467,7 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
                  return 0;
 
          /* point of no return: no unwinding after this */
-         if (old_pkg && !conf->force_reinstall) {
+         if (old_pkg) {
               old_pkg->state_want = SW_DEINSTALL;
 
               if (old_pkg->state_flag & SF_NOPRUNE) {
@@ -1441,13 +1484,13 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
                    }
               }
 
-               /* removing files from old package, to avoid ghost files */ 
+               /* removing files from old package, to avoid ghost files */
                remove_data_files_and_list(old_pkg);
                remove_maintainer_scripts(old_pkg);
          }
 
 
-         opkg_msg(INFO, "Installing maintainer scripts.\n");
+         opkg_msg(INFO, "%s maintainer scripts.\n", (pkg->is_upgrade) ? ("Upgrading") : ("Installing"));
          if (install_maintainer_scripts(pkg, old_pkg)) {
                opkg_msg(ERROR, "Failed to extract maintainer scripts for %s."
                               " Package debris may remain!\n",
@@ -1483,9 +1526,8 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
          opkg_msg(DEBUG, "pkg=%s old_state_flag=%x state_flag=%x\n",
                          pkg->name, old_state_flag, pkg->state_flag);
 
-         if (old_pkg && !conf->force_reinstall) {
+         if (old_pkg)
               old_pkg->state_status = SS_NOT_INSTALLED;
-         }
 
          time(&pkg->installed_time);
 
@@ -1496,7 +1538,7 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
          sigprocmask(SIG_UNBLOCK, &newset, &oldset);
           pkg_vec_free (replacees);
          return 0;
-     
+
 
      UNWIND_POSTRM_UPGRADE_OLD_PKG:
          postrm_upgrade_old_pkg_unwind(pkg, old_pkg);