X-Git-Url: https://git.librecmc.org/?p=oweals%2Fopkg-lede.git;a=blobdiff_plain;f=libopkg%2Fopkg_install.c;h=dc014d3cebec8c7797308ff497c24033e5b66b9e;hp=599ae4d33fdeec0a492a56098d0efc72fa1d84ff;hb=b6a38150404297fd718587d1ffefc160044f2f64;hpb=4b0b7ca249bfa4ecc099c2ca56527eb91776f198 diff --git a/libopkg/opkg_install.c b/libopkg/opkg_install.c index 599ae4d..dc014d3 100644 --- a/libopkg/opkg_install.c +++ b/libopkg/opkg_install.c @@ -1,4 +1,4 @@ -/* opkg_install.c - the itsy package management system +/* opkg_install.c - the opkg package management system Carl D. Worth @@ -15,13 +15,15 @@ General Public License for more details. */ -#include "opkg.h" +#include "includes.h" #include #include #include #include #include +#ifndef __USE_GNU typedef void (*sighandler_t)(int); +#endif #include "pkg.h" #include "pkg_hash.h" @@ -35,6 +37,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 +139,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 +149,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 +167,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; @@ -307,60 +313,6 @@ int pkg_mark_dependencies_for_installation(opkg_conf_t *conf, pkg_t *pkg, pkg_ve return 0; } -int name_mark_dependencies_for_installation(opkg_conf_t *conf, const char *pkg_name, pkg_vec_t *pkgs_needed) -{ - int cmp; - pkg_t *old, *new; - char *old_version, *new_version; - - old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg_name); - - new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name); - if (new == NULL) { - return OPKG_PKG_HAS_NO_CANDIDATE; - } - if (old) { - old_version = pkg_version_str_alloc(old); - new_version = pkg_version_str_alloc(new); - - 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_message(conf, OPKG_DEBUG, " Forcing 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_message(conf, OPKG_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) { - opkg_message(conf, OPKG_NOTICE, - "Package %s (%s) installed in %s is up to date.\n", - old->name, old_version, old->dest->name); - free(old_version); - free(new_version); - return 0; - } else if (cmp > 0) { - opkg_message(conf, OPKG_NOTICE, - "Not downgrading package %s on %s from %s to %s.\n", - old->name, old->dest->name, old_version, new_version); - free(old_version); - free(new_version); - return 0; - } else if (cmp < 0) { - new->dest = old->dest; - old->state_want = SW_DEINSTALL; - old->state_flag |= SF_OBSOLETE; - } - } - return pkg_mark_dependencies_for_installation(conf, new, pkgs_needed); -} - - - int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg) { int i, err; @@ -393,6 +345,7 @@ int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg) } if (ndepends <= 0) { + pkg_vec_free(depends); return 0; } @@ -501,7 +454,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 +469,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; @@ -618,6 +573,59 @@ static int unpack_pkg_control_files(opkg_conf_t *conf, pkg_t *pkg) return 0; } +static int pkg_remove_orphan_dependent(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg) +{ + int i, j, found; + char *buf, *d_str; + pkg_t *p; + if (!old_pkg) + return 0; + if (!pkg) { + fprintf(stderr, "pkg shall not be NULL here. please send to the bugzilla!! [%s %d]\n", __FILE__, __LINE__); + return -1; + } + if (old_pkg->depends_count == 0) + return 0; + for (i=0;idepends_count;i++) { + found = 0; + for (j=0;jdepends_count;j++) { + if (!strcmp(old_pkg->depends_str[i], pkg->depends_str[j])) { + found = 1; + break; + } + } + if (found) + continue; + d_str = old_pkg->depends_str[i]; + buf = malloc (strlen (d_str) + 1); + j=0; + while (d_str[j] != '\0' && d_str[j] != ' ') { + buf[j]=d_str[j]; + ++j; + } + buf[j]='\0'; + buf = realloc (buf, strlen (buf) + 1); + p = pkg_hash_fetch_installed_by_name (&conf->pkg_hash, buf); + if (!p) { + fprintf(stderr, "The pkg %s had been removed!!\n", buf); + free(buf); + continue; + } + if (p->auto_installed) { + int deps; + abstract_pkg_t **dependents; + deps = pkg_has_installed_dependents(conf, NULL, p, &dependents); + if (deps == 0) { + opkg_message (conf, OPKG_NOTICE,"%s was autoinstalled but is now orphaned, remove it.\n", buf); + opkg_remove_pkg(conf, p, 0); + } else + opkg_message (conf, OPKG_INFO, "%s was autoinstalled and is still required by %d installed packages\n", buf, deps); + } + free(buf); + } + return 0; +} + /* returns number of installed replacees */ int pkg_get_installed_replacees(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *installed_replacees) { @@ -753,7 +761,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 +768,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 +776,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 +795,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 +805,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 +815,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 +823,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 +863,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,18 +876,18 @@ 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(); pkg_get_installed_replacees(conf, pkg, replacees); sprintf_alloc (&pkgid, "%s;%s;%s;", pkg->name, pkg->version, pkg->architecture); - opkg_set_current_state (OPKG_STATE_INSTALLING_PKG, pkgid); + opkg_set_current_state (conf, OPKG_STATE_INSTALLING_PKG, pkgid); free (pkgid); /* this next section we do with SIGINT blocked to prevent inconsistency between opkg database and filesystem */ @@ -874,6 +907,8 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade) opkg_state_changed++; pkg->state_flag |= SF_FILELIST_CHANGED; + pkg_remove_orphan_dependent(conf, pkg, old_pkg); + /* XXX: BUG: we really should treat replacement more like an upgrade * Instead, we're going to remove the replacees */ @@ -965,7 +1000,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,9 +1030,10 @@ 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 (OPKG_STATE_NONE, NULL); + opkg_set_current_state (conf, OPKG_STATE_NONE, NULL); } static int prerm_upgrade_old_pkg(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg) @@ -1702,251 +1738,3 @@ static int backup_remove(const char *file_name) return 0; } - - -#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