X-Git-Url: https://git.librecmc.org/?p=oweals%2Fopkg-lede.git;a=blobdiff_plain;f=libopkg%2Fopkg_install.c;h=8ced15aa36222a323726a2735909d2589e5cf144;hp=a3893c7131f54e89cc2fc926d15d57f00af2e2cf;hb=a1fc2ffe4491e0df37bb173e0d452c3b2b3ec498;hpb=5b68464bd8b8405fae90c1d96cdd7367a506bd5c diff --git a/libopkg/opkg_install.c b/libopkg/opkg_install.c index a3893c7..8ced15a 100644 --- a/libopkg/opkg_install.c +++ b/libopkg/opkg_install.c @@ -21,7 +21,9 @@ #include #include #include +#ifndef __USE_GNU typedef void (*sighandler_t)(int); +#endif #include "pkg.h" #include "pkg_hash.h" @@ -43,7 +45,6 @@ typedef void (*sighandler_t)(int); #include "xsystem.h" #include "user.h" -int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg); static int verify_pkg_installable(opkg_conf_t *conf, pkg_t *pkg); static int unpack_pkg_control_files(opkg_conf_t *conf, pkg_t *pkg); @@ -137,7 +138,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, err; + int cmp, err = 0; pkg_t *old, *new; char *old_version, *new_version; @@ -310,60 +311,6 @@ int pkg_mark_dependencies_for_installation(opkg_conf_t *conf, pkg_t *pkg, pkg_ve return 0; } -#if 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); -} - -#endif int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg) { @@ -451,7 +398,6 @@ int opkg_satisfy_all_dependences(opkg_conf_t *conf) return 0; } - static int check_conflicts_for(opkg_conf_t *conf, pkg_t *pkg) { @@ -486,10 +432,12 @@ static int check_conflicts_for(opkg_conf_t *conf, pkg_t *pkg) static int update_file_ownership(opkg_conf_t *conf, pkg_t *new_pkg, pkg_t *old_pkg) { str_list_t *new_list = pkg_get_installed_files(new_pkg); - str_list_elt_t *iter; + str_list_elt_t *iter, *niter; - for (iter = new_list->head; iter; iter = iter->next) { - char *new_file = iter->data; + 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(conf, new_file); if (!new_file) opkg_message(conf, OPKG_ERROR, "Null new_file for new_pkg=%s\n", new_pkg->name); @@ -498,8 +446,10 @@ static int update_file_ownership(opkg_conf_t *conf, pkg_t *new_pkg, pkg_t *old_p } if (old_pkg) { str_list_t *old_list = pkg_get_installed_files(old_pkg); - for (iter = old_list->head; iter; iter = iter->next) { - char *old_file = iter->data; + 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(conf, old_file); if (owner == old_pkg) { /* obsolete */ @@ -521,13 +471,15 @@ 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; + char *root_dir; if (!conf->force_space && pkg->installed_size != NULL) { - blocks_available = get_available_blocks(conf->default_dest->root_dir); + root_dir = pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir; + blocks_available = get_available_blocks(root_dir); comp_size = strtoul(pkg->installed_size, NULL, 0); /* round up a blocks count without doing fancy-but-slow casting jazz */ @@ -536,7 +488,7 @@ static int verify_pkg_installable(opkg_conf_t *conf, pkg_t *pkg) if (comp_size >= blocks_available) { opkg_message(conf, OPKG_ERROR, "Only have %d available blocks on filesystem %s, pkg %s needs %d\n", - blocks_available, conf->default_dest->root_dir, pkg->name, comp_size); + blocks_available, root_dir, pkg->name, comp_size); return ENOSPC; } } @@ -571,7 +523,7 @@ static int unpack_pkg_control_files(opkg_conf_t *conf, pkg_t *pkg) move all of unpack_pkg_control_files to that function. */ /* Don't need to re-read conffiles if we already have it */ - if (pkg->conffiles.head) { + if (!nv_pair_list_empty(&pkg->conffiles)) { return 0; } @@ -625,6 +577,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 = calloc (1, 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) { @@ -749,7 +754,9 @@ static int opkg_install_check_downgrade(opkg_conf_t *conf, pkg_t *pkg, pkg_t *ol } } -/* and now the meat... */ +/** + * @brief Really install a pkg_t + */ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade) { int err = 0; @@ -759,6 +766,9 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade) abstract_pkg_t *ab_pkg = NULL; int old_state_flag; char* file_md5; +#ifdef HAVE_SHA256 + char* file_sha256; +#endif char *pkgid; if ( from_upgrade ) @@ -827,11 +837,11 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade) } /* check that the repository is valid */ - #if HAVE_GPGME + #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) char *list_file_name, *sig_file_name, *lists_dir; /* check to ensure the package has come from a repository */ - if (pkg->src) + if (conf->check_signature && pkg->src) { sprintf_alloc (&lists_dir, "%s", (conf->restrict_to_default_dest) @@ -842,8 +852,15 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade) if (file_exists (sig_file_name)) { - if (opkg_verify_file (conf, list_file_name, sig_file_name)) + if (opkg_verify_file (conf, list_file_name, sig_file_name)){ + opkg_message(conf, OPKG_ERROR, "Failed to verify the signature of: %s\n", + list_file_name); return OPKG_INSTALL_ERR_SIGNATURE; + } + }else{ + opkg_message(conf, OPKG_ERROR, "Signature file is missing. " + "Perhaps you need to run 'opkg update'?\n"); + return OPKG_INSTALL_ERR_SIGNATURE; } free (lists_dir); @@ -867,6 +884,22 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade) free(file_md5); } +#ifdef HAVE_SHA256 + /* Check for sha256 value */ + if(pkg->sha256sum) + { + file_sha256 = file_sha256sum_alloc(pkg->local_filename); + if (strcmp(file_sha256, pkg->sha256sum)) + { + opkg_message(conf, OPKG_ERROR, + "Package %s sha256sum mismatch. Either the opkg or the package index are corrupt. Try 'opkg update'.\n", + pkg->name); + free(file_sha256); + return OPKG_INSTALL_ERR_SHA256; + } + } +#endif + if (pkg->tmp_unpack_dir == NULL) { unpack_pkg_control_files(conf, pkg); } @@ -906,6 +939,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 */ @@ -1141,7 +1176,7 @@ static int backup_modified_conffiles(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_p /* Backup all modified conffiles */ if (old_pkg) { - for (iter = old_pkg->conffiles.head; iter; iter = iter->next) { + 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; @@ -1159,9 +1194,9 @@ static int backup_modified_conffiles(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_p } /* Backup all conffiles that were not conffiles in old_pkg */ - for (iter = pkg->conffiles.head; iter; iter = iter->next) { + for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) { char *cf_name; - cf = iter->data; + cf = (conffile_t *)iter->data; cf_name = root_filename_alloc(conf, cf->name); /* Ignore if this was a conffile in old_pkg as well */ if (pkg_get_conffile(old_pkg, cf->name)) { @@ -1185,13 +1220,13 @@ static int backup_modified_conffiles_unwind(opkg_conf_t *conf, pkg_t *pkg, pkg_t conffile_list_elt_t *iter; if (old_pkg) { - for (iter = old_pkg->conffiles.head; iter; iter = iter->next) { - backup_remove(iter->data->name); + for (iter = nv_pair_list_first(&old_pkg->conffiles); iter; iter = nv_pair_list_next(&old_pkg->conffiles, iter)) { + backup_remove(((nv_pair_t *)iter->data)->name); } } - for (iter = pkg->conffiles.head; iter; iter = iter->next) { - backup_remove(iter->data->name); + for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) { + backup_remove(((nv_pair_t *)iter->data)->name); } return 0; @@ -1214,14 +1249,16 @@ static int check_data_file_clashes(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg other package. */ str_list_t *files_list; - str_list_elt_t *iter; + str_list_elt_t *iter, *niter; int clashes = 0; files_list = pkg_get_installed_files(pkg); - for (iter = files_list->head; iter; iter = iter->next) { + 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 = iter->data; + char *filename = (char *) iter->data; root_filename = root_filename_alloc(conf, filename); if (file_exists(root_filename) && (! file_is_dir(root_filename))) { pkg_t *owner; @@ -1301,25 +1338,33 @@ static int check_data_file_clashes_change(opkg_conf_t *conf, pkg_t *pkg, pkg_t * @@@ To change after 1.0 release. */ str_list_t *files_list; - str_list_elt_t *iter; + str_list_elt_t *iter, *niter; + + char *root_filename = NULL; int clashes = 0; files_list = pkg_get_installed_files(pkg); - for (iter = files_list->head; iter; iter = iter->next) { - char *root_filename; - char *filename = iter->data; + 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) { + free(root_filename); + root_filename = NULL; + } root_filename = root_filename_alloc(conf, filename); if (file_exists(root_filename) && (! file_is_dir(root_filename))) { pkg_t *owner; + owner = file_hash_get_file_owner(conf, filename); + if (conf->force_overwrite) { /* but we need to change who owns this file */ file_hash_set_file_owner(conf, filename, pkg); continue; } - owner = file_hash_get_file_owner(conf, filename); /* Pre-existing files are OK if owned by a package replaced by new pkg. */ if (owner) { @@ -1333,7 +1378,10 @@ static int check_data_file_clashes_change(opkg_conf_t *conf, pkg_t *pkg, pkg_t * } } - free(root_filename); + } + if (root_filename) { + free(root_filename); + root_filename = NULL; } pkg_free_installed_files(pkg); @@ -1374,6 +1422,7 @@ static int remove_obsolesced_files(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg str_list_elt_t *of; str_list_t *new_files; str_list_elt_t *nf; + hash_table_t new_files_table; if (old_pkg == NULL) { return 0; @@ -1382,16 +1431,21 @@ static int remove_obsolesced_files(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg old_files = pkg_get_installed_files(old_pkg); new_files = pkg_get_installed_files(pkg); - for (of = old_files->head; of; of = of->next) { + new_files_table.entries = NULL; + hash_table_init("new_files" , &new_files_table, 20); + for (nf = str_list_first(new_files); nf; nf = str_list_next(new_files, nf)) { + if (nf && nf->data) + hash_table_insert(&new_files_table, nf->data, nf->data); + } + + for (of = str_list_first(old_files); of; of = str_list_next(old_files, of)) { pkg_t *owner; char *old, *new; - old = of->data; - for (nf = new_files->head; nf; nf = nf->next) { - new = nf->data; - if (strcmp(old, new) == 0) { - goto NOT_OBSOLETE; - } - } + old = (char *)of->data; + new = (char *) hash_table_get (&new_files_table, old); + if (new) + continue; + if (file_is_dir(old)) { continue; } @@ -1411,11 +1465,9 @@ static int remove_obsolesced_files(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg strerror(errno)); } } - - NOT_OBSOLETE: - ; } + hash_table_deinit(&new_files_table); pkg_free_installed_files(old_pkg); pkg_free_installed_files(pkg); @@ -1546,9 +1598,9 @@ static int resolve_conffiles(opkg_conf_t *conf, pkg_t *pkg) if (conf->noaction) return 0; - for (iter = pkg->conffiles.head; iter; iter = iter->next) { + for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) { char *root_filename; - cf = iter->data; + cf = (conffile_t *)iter->data; root_filename = root_filename_alloc(conf, cf->name); /* Might need to initialize the md5sum for each conffile */ @@ -1564,18 +1616,20 @@ static int resolve_conffiles(opkg_conf_t *conf, pkg_t *pkg) cf_backup = backup_filename_alloc(root_filename); - if (file_exists(cf_backup)) { - /* Let's compute md5 to test if files are changed */ - md5sum = file_md5sum_alloc(cf_backup); - if (strcmp( cf->value,md5sum) != 0 ) { - if (conf->force_defaults - || user_prefers_old_conffile(cf->name, cf_backup) ) { - rename(cf_backup, root_filename); - } - } - unlink(cf_backup); - free(md5sum); - } + if (file_exists(cf_backup)) { + /* Let's compute md5 to test if files are changed */ + md5sum = file_md5sum_alloc(cf_backup); + if (strcmp( cf->value,md5sum) != 0 ) { + if (conf->force_maintainer) { + opkg_message(conf, OPKG_NOTICE, "Conffile %s using maintainer's setting.\n", cf_backup); + } else if (conf->force_defaults + || user_prefers_old_conffile(cf->name, cf_backup) ) { + rename(cf_backup, root_filename); + } + } + unlink(cf_backup); + free(md5sum); + } free(cf_backup); free(root_filename);