+ /* 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);
+ }
+
+ /* 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);
+ }
+
+ 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;
+ }
+
+ err = check_data_file_clashes_change(pkg, old_pkg);
+ if (err) {
+ opkg_msg(ERROR, "check_data_file_clashes_change() failed for "
+ "for files belonging to %s.\n", pkg->name);
+ }
+
+ opkg_msg(INFO, "Resolving conf files for %s\n", pkg->name);
+ resolve_conffiles(pkg);
+
+ pkg->state_status = SS_UNPACKED;
+ old_state_flag = pkg->state_flag;
+ pkg->state_flag &= ~SF_PREFER;
+ opkg_msg(DEBUG, "pkg=%s old_state_flag=%x state_flag=%x\n",
+ pkg->name, old_state_flag, pkg->state_flag);
+
+ if (old_pkg)
+ old_pkg->state_status = SS_NOT_INSTALLED;
+
+ now = time(NULL);
+ pkg_set_int(pkg, PKG_INSTALLED_TIME, now);
+
+ ab_pkg = pkg->parent;
+ if (ab_pkg)
+ ab_pkg->state_status = pkg->state_status;
+
+ 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_CHECK_DATA_FILE_CLASHES:
+ check_data_file_clashes_unwind(pkg, old_pkg);
+UNWIND_BACKUP_MODIFIED_CONFFILES:
+ backup_modified_conffiles_unwind(pkg, old_pkg);
+UNWIND_PREINST_CONFIGURE:
+ preinst_configure_unwind(pkg, old_pkg);
+UNWIND_PRERM_DECONFIGURE_CONFLICTORS:
+ prerm_deconfigure_conflictors_unwind(pkg, replacees);
+UNWIND_PRERM_UPGRADE_OLD_PKG:
+ prerm_upgrade_old_pkg_unwind(pkg, old_pkg);
+UNWIND_REMOVE_INSTALLED_REPLACEES:
+ pkg_remove_installed_replacees_unwind(replacees);
+
+pkg_is_hosed:
+ sigprocmask(SIG_UNBLOCK, &newset, &oldset);
+
+ pkg_vec_free(replacees);
+ return -1;