libopkg: make MD5 support optional
[oweals/opkg-lede.git] / libopkg / opkg_install.c
index 484c9e9bd56ca6fea19ab164e842f59de3a13ae2..0db0acdf84e7d6f297da9f690e82aa8d4a41e15e 100644 (file)
@@ -21,6 +21,7 @@
 #include <time.h>
 #include <signal.h>
 #include <unistd.h>
 #include <time.h>
 #include <signal.h>
 #include <unistd.h>
+#include <sys/stat.h>
 
 #include "pkg.h"
 #include "pkg_hash.h"
 
 #include "pkg.h"
 #include "pkg_hash.h"
@@ -50,7 +51,7 @@ satisfy_dependencies_for(pkg_t *pkg)
      char **tmp, **unresolved = NULL;
      int ndepends;
 
      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) {
                                                        &unresolved);
 
      if (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);
          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;
      }
          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;
 
      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);
              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);
      }
 
               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;
          }
 
                  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);
                   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);
               }
                    /* 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;
 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;
 
 
        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) {
        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;
        }
                        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;
      }
          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);
      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;
      while (1) {
          char *cf_name;
          char *cf_name_in_dest;
+         int i;
 
          cf_name = file_read_line_alloc(conffiles_file);
          if (cf_name == NULL) {
 
          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;
          }
          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. */
 
          /* 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
  * 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;
 {
        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++) {
                        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++) {
                                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;
                                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",
                                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)
 /* 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);
      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);
          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 */
           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 */
              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)
 
          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 */ {
               pkg->dest = old_pkg->dest;
               rc = 0;
          } else /* cmp == 0 */ {
-              if (conf->force_reinstall) {
                if(!conf->download_only)
                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);
          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 ") );
                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?
 {
      /* 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
        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;
 {
      int err;
      char *backup;
-    
+
      backup = backup_filename_alloc(file_name);
      err = file_copy(file_name, backup);
      if (err) {
      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;
      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);
 
               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.
        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
        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;
      */
      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;
 
      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)) {
              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;
 
               pkg_t *owner;
               pkg_t *obs;
 
-              if (backup_exists_for(root_filename)) {
+              if (backup_exists_for(filename)) {
                    continue;
               }
 
                    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);
               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) {
                            "\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 {
               } 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++;
          }
                        "Please move this file out of the way and try again.\n");
               }
               clashes++;
          }
-         free(root_filename);
      }
      pkg_free_installed_files(pkg);
 
      }
      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;
 
      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) {
              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)) {
               /* 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",
    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;
          }
               /* in case obsolete file no longer belongs to old_pkg */
               continue;
          }
+
          /* old file is obsolete */
          /* 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) {
          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? */
      /* 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
      /* 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. */
        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) {
      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) ;
       * 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)
      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;
      conffile_list_elt_t *iter;
      conffile_t *cf;
      char *cf_backup;
-     char *md5sum;
+     char *chksum;
 
      if (conf->noaction) return 0;
 
 
      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) {
 
          /* 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)) {
          }
 
          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 */
 
           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);
                   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);
                            "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);
                  }
               }
               unlink(cf_backup);
-             if (md5sum)
-                  free(md5sum);
+             if (chksum)
+                  free(chksum);
           }
 
          free(cf_backup);
           }
 
          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);
      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);
      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;
        return -1;
+     }
 
      opkg_msg(DEBUG2, "Versions from pkg_hash_fetch:");
 
      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) {
 
      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 = 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 */
                                                               /* 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);
          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);
               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;
               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);
          }
          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)
  */
 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;
 
 #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");
         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;
      }
                       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;
 
          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;
      }
                       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;
             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;
          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
      /* 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;
             return 0;
-    
+
      err = verify_pkg_installable(pkg);
      if (err)
             return -1;
      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 */
      }
 
      /* 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 */
      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);
          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);
          }
        }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);
        }
 
        free (lists_dir);
@@ -1309,22 +1331,31 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
      }
      #endif
 
      }
      #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))
          {
      /* 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);
      }
          }
         if (file_md5)
               free(file_md5);
      }
+#endif
 
 #ifdef HAVE_SHA256
      /* Check for sha256 value */
 
 #ifdef HAVE_SHA256
      /* Check for sha256 value */
@@ -1386,11 +1417,13 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
          opkg_state_changed++;
          pkg->state_flag |= SF_FILELIST_CHANGED;
 
          opkg_state_changed++;
          pkg->state_flag |= SF_FILELIST_CHANGED;
 
-         if (old_pkg)
+         if (old_pkg) {
                pkg_remove_orphan_dependent(pkg, 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
          /* 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)
           */
          err = pkg_remove_installed_replacees(replacees);
          if (err)
@@ -1424,7 +1457,7 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
                  return 0;
 
          /* point of no return: no unwinding after this */
                  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) {
               old_pkg->state_want = SW_DEINSTALL;
 
               if (old_pkg->state_flag & SF_NOPRUNE) {
@@ -1441,13 +1474,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);
          }
 
 
                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",
          if (install_maintainer_scripts(pkg, old_pkg)) {
                opkg_msg(ERROR, "Failed to extract maintainer scripts for %s."
                               " Package debris may remain!\n",
@@ -1483,9 +1516,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);
 
          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;
               old_pkg->state_status = SS_NOT_INSTALLED;
-         }
 
          time(&pkg->installed_time);
 
 
          time(&pkg->installed_time);
 
@@ -1496,7 +1528,7 @@ opkg_install_pkg(pkg_t *pkg, int from_upgrade)
          sigprocmask(SIG_UNBLOCK, &newset, &oldset);
           pkg_vec_free (replacees);
          return 0;
          sigprocmask(SIG_UNBLOCK, &newset, &oldset);
           pkg_vec_free (replacees);
          return 0;
-     
+
 
      UNWIND_POSTRM_UPGRADE_OLD_PKG:
          postrm_upgrade_old_pkg_unwind(pkg, old_pkg);
 
      UNWIND_POSTRM_UPGRADE_OLD_PKG:
          postrm_upgrade_old_pkg_unwind(pkg, old_pkg);