+ pkg->state_want = SW_INSTALL;
+ 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)
+ return 0;
+
+ err = verify_pkg_installable(pkg);
+ if (err)
+ return -1;
+
+ local_filename = pkg_get_string(pkg, PKG_LOCAL_FILENAME);
+
+ if (local_filename == NULL) {
+ if (!conf->cache && conf->download_only) {
+ char cwd[4096];
+ if (getcwd(cwd, sizeof(cwd)) != NULL)
+ err = opkg_download_pkg(pkg, cwd);
+ else
+ return -1;
+ } else {
+ err = opkg_download_pkg(pkg, conf->tmp_dir);
+ }
+ if (err) {
+ opkg_msg(ERROR, "Failed to download %s. "
+ "Perhaps you need to run 'opkg update'?\n",
+ pkg->name);
+ return -1;
+ }
+
+ local_filename = pkg_get_string(pkg, PKG_LOCAL_FILENAME);
+ }
+
+ /* check that the repository is valid */
+#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 */
+ if (conf->check_signature && 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(list_file_name, sig_file_name)) {
+ opkg_msg(ERROR,
+ "Failed to verify the signature of %s.\n",
+ list_file_name);
+ 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);
+ if (!conf->force_signature)
+ return -1;
+ }
+
+ free(lists_dir);
+ free(list_file_name);
+ free(sig_file_name);
+ }
+#endif
+
+#ifdef HAVE_MD5
+ /* Check for md5 values */
+ pkg_md5 = pkg_get_md5(pkg);
+ if (pkg_md5) {
+ file_md5 = file_md5sum_alloc(local_filename);
+ if (file_md5 && strcmp(file_md5, pkg_md5)) {
+ 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 */
+ pkg_sha256 = pkg_get_sha256(pkg);
+ if (pkg_sha256) {
+ file_sha256 = file_sha256sum_alloc(local_filename);
+ if (file_sha256 && strcmp(file_sha256, pkg_sha256)) {
+ 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);
+ }
+#endif
+ if (conf->download_only) {
+ if (conf->nodeps == 0) {
+ err = satisfy_dependencies_for(pkg);
+ if (err)
+ return -1;
+ }
+ return 0;
+ }
+
+ if (!pkg_get_string(pkg, PKG_TMP_UNPACK_DIR)) {
+ if (unpack_pkg_control_files(pkg) == -1) {
+ opkg_msg(ERROR,
+ "Failed to unpack control files from %s.\n",
+ local_filename);
+ return -1;
+ }
+ }
+
+ err = update_file_ownership(pkg, old_pkg);
+ if (err)
+ return -1;
+
+ if (conf->nodeps == 0) {
+ err = satisfy_dependencies_for(pkg);
+ if (err)
+ return -1;
+ if (pkg->state_status == SS_UNPACKED)
+ /* Circular dependency has installed it for us. */
+ return 0;
+ }
+
+ replacees = pkg_vec_alloc();
+ pkg_get_installed_replacees(pkg, replacees);
+
+ /* this next section we do with SIGINT blocked to prevent inconsistency between opkg database and filesystem */
+
+ sigemptyset(&newset);
+ sigaddset(&newset, SIGINT);
+ sigprocmask(SIG_BLOCK, &newset, &oldset);
+
+ opkg_state_changed++;
+ pkg->state_flag |= SF_FILELIST_CHANGED;
+
+ 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
+ */
+ err = pkg_remove_installed_replacees(replacees);
+ if (err)
+ goto UNWIND_REMOVE_INSTALLED_REPLACEES;
+
+ err = prerm_upgrade_old_pkg(pkg, old_pkg);
+ if (err)
+ goto UNWIND_PRERM_UPGRADE_OLD_PKG;
+
+ err = prerm_deconfigure_conflictors(pkg, replacees);
+ if (err)
+ goto UNWIND_PRERM_DECONFIGURE_CONFLICTORS;
+
+ err = preinst_configure(pkg, old_pkg);
+ if (err)
+ goto UNWIND_PREINST_CONFIGURE;
+
+ err = backup_modified_conffiles(pkg, old_pkg);
+ if (err)
+ goto UNWIND_BACKUP_MODIFIED_CONFFILES;
+
+ err = check_data_file_clashes(pkg, old_pkg);
+ if (err)
+ goto UNWIND_CHECK_DATA_FILE_CLASHES;
+
+ err = postrm_upgrade_old_pkg(pkg, old_pkg);
+ if (err)
+ goto UNWIND_POSTRM_UPGRADE_OLD_PKG;
+
+ if (conf->noaction)
+ return 0;
+
+ /* point of no return: no unwinding after this */
+ if (old_pkg) {
+ old_pkg->state_want = SW_DEINSTALL;
+
+ if (old_pkg->state_flag & SF_NOPRUNE) {
+ opkg_msg(INFO, "Not removing obsolesced files because "
+ "package %s marked noprune.\n", old_pkg->name);
+ } else {
+ opkg_msg(INFO, "Removing obsolesced files for %s\n",
+ old_pkg->name);
+ if (remove_obsolesced_files(pkg, old_pkg)) {
+ opkg_msg(ERROR, "Failed to determine "
+ "obsolete files from previously "
+ "installed %s\n", old_pkg->name);
+ }
+ }
+
+ /* removing files from old package, to avoid ghost files */
+ remove_data_files_and_list(old_pkg);
+ remove_maintainer_scripts(old_pkg);
+ }
+
+ 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", pkg->name);
+ goto pkg_is_hosed;
+ }
+
+ /* the following just returns 0 */
+ remove_disappeared(pkg);
+
+ opkg_msg(INFO, "Installing data files for %s.\n", pkg->name);
+
+ if (install_data_files(pkg)) {
+ opkg_msg(ERROR, "Failed to extract data files for %s. "
+ "Package debris may remain!\n", pkg->name);
+ goto pkg_is_hosed;
+ }