-/* opkg_install.c - the itsy package management system
+/* opkg_install.c - the opkg package management system
Carl D. Worth
General Public License for more details.
*/
-#include "opkg.h"
+#include "includes.h"
#include <errno.h>
#include <dirent.h>
#include <glob.h>
#include <time.h>
#include <signal.h>
+#ifndef __USE_GNU
typedef void (*sighandler_t)(int);
+#endif
#include "pkg.h"
#include "pkg_hash.h"
#include "opkg_utils.h"
#include "opkg_message.h"
-#include "opkg_state.h"
+#include "opkg_cmd.h"
+#include "opkg_defines.h"
#include "sprintf_alloc.h"
#include "file_util.h"
#include "str_util.h"
#include "xsystem.h"
#include "user.h"
+#include "libbb/libbb.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);
static int install_data_files(opkg_conf_t *conf, pkg_t *pkg);
static int resolve_conffiles(opkg_conf_t *conf, pkg_t *pkg);
-static int cleanup_temporary_files(opkg_conf_t *conf, pkg_t *pkg);
-
static int user_prefers_old_conffile(const char *file, const char *backup);
static char *backup_filename_alloc(const char *file_name);
char *old_version, *new_version;
pkg = pkg_new();
- if (pkg == NULL) {
- return ENOMEM;
- }
err = pkg_init_from_file(pkg, filename);
if (err) {
pkg = hash_insert_pkg(&conf->pkg_hash, pkg, 1,conf);
old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name);
- pkg->local_filename = strdup(filename);
-
if (old) {
old_version = pkg_version_str_alloc(old);
new_version = pkg_version_str_alloc(pkg);
opkg_error_t opkg_install_by_name(opkg_conf_t *conf, const char *pkg_name)
{
- int cmp;
+ int cmp, err = 0;
pkg_t *old, *new;
char *old_version, *new_version;
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 );
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;
} else if (cmp < 0) {
new->dest = old->dest;
old->state_want = SW_DEINSTALL; /* Here probably the problem for bug 1277 */
+ free(old_version);
+ free(new_version);
}
}
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);
-}
-
-\f
-
int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg)
{
int i, err;
}
if (ndepends <= 0) {
+ pkg_vec_free(depends);
return 0;
}
return 0;
}
-\f
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_t *new_list = pkg_get_installed_files(conf, new_pkg);
+ 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);
file_hash_set_file_owner(conf, new_file, new_pkg);
}
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;
+ str_list_t *old_list = pkg_get_installed_files(conf, old_pkg);
+ 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 */
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;
}
* 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 */
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;
}
}
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;
}
return 0;
}
+/*
+ * Remove packages which were auto_installed due to a dependency by old_pkg,
+ * which are no longer a dependency in the new (upgraded) pkg.
+ */
+static int
+pkg_remove_orphan_dependent(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
+{
+ int i, j, k, l, found;
+ int n_deps;
+ pkg_t *p;
+ struct compound_depend *cd0, *cd1;
+ abstract_pkg_t **dependents;
+
+ int count0 = old_pkg->pre_depends_count +
+ old_pkg->depends_count +
+ old_pkg->recommends_count +
+ old_pkg->suggests_count;
+ int count1 = pkg->pre_depends_count +
+ pkg->depends_count +
+ pkg->recommends_count +
+ pkg->suggests_count;
+
+ for (i=0; i<count0; i++) {
+ cd0 = &old_pkg->depends[i];
+ if (cd0->type != DEPEND)
+ continue;
+ for (j=0; j<cd0->possibility_count; j++) {
+
+ found = 0;
+
+ for (k=0; k<count1; k++) {
+ cd1 = &pkg->depends[i];
+ if (cd1->type != DEPEND)
+ continue;
+ for (l=0; l<cd1->possibility_count; l++) {
+ if (cd0->possibilities[j]
+ == cd1->possibilities[l]) {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+
+ if (found)
+ continue;
+
+ /*
+ * old_pkg has a dependency that pkg does not.
+ */
+ p = pkg_hash_fetch_installed_by_name (&conf->pkg_hash,
+ cd0->possibilities[j]->pkg->name);
+
+ if (!p)
+ continue;
+
+ if (!p->auto_installed)
+ continue;
+
+ n_deps = pkg_has_installed_dependents(conf, NULL, p,
+ &dependents);
+ n_deps--; /* don't count old_pkg */
+
+ if (n_deps == 0) {
+ opkg_message (conf, OPKG_NOTICE,
+ "%s was autoinstalled and is "
+ "now orphaned, removing.\n",
+ p->name);
+
+ /* p has one installed dependency (old_pkg),
+ * which we need to ignore during removal. */
+ p->state_flag |= SF_REPLACE;
+
+ opkg_remove_pkg(conf, p, 0);
+ } else
+ opkg_message(conf, OPKG_INFO,
+ "%s was autoinstalled and is "
+ "still required by %d "
+ "installed packages.\n",
+ p->name, n_deps);
+
+ }
+ }
+
+ return 0;
+}
+
/* returns number of installed replacees */
int pkg_get_installed_replacees(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *installed_replacees)
{
return 0;
}
-int caught_sigint = 0;
-static void opkg_install_pkg_sigint_handler(int sig)
-{
- caught_sigint = sig;
-}
-
/* 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(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg, int message)
{
}
}
-/* 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;
abstract_pkg_t *ab_pkg = NULL;
int old_state_flag;
char* file_md5;
- char *pkgid;
+#ifdef HAVE_SHA256
+ char* file_sha256;
+#endif
-
if ( from_upgrade )
message = 1; /* Coming from an upgrade, and should change the output message */
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__);
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",
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){
/* 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
&& 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);
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 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 (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 (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);
+ free (list_file_name);
+ free (sig_file_name);
+ }
+ #endif
+
+ /* Check for md5 values */
if (pkg->md5sum)
{
file_md5 = file_md5sum_alloc(pkg->local_filename);
- if (strcmp(file_md5, pkg->md5sum))
+ if (file_md5 && strcmp(file_md5, pkg->md5sum))
{
opkg_message(conf, OPKG_ERROR,
"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;
+ }
+ if (file_md5)
+ free(file_md5);
+ }
+
+#ifdef HAVE_SHA256
+ /* Check for sha256 value */
+ if(pkg->sha256sum)
+ {
+ file_sha256 = file_sha256sum_alloc(pkg->local_filename);
+ if (file_sha256 && 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;
}
- free(file_md5);
+ if (file_sha256)
+ free(file_sha256);
}
+#endif
if (pkg->tmp_unpack_dir == NULL) {
unpack_pkg_control_files(conf, pkg);
/* 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; }
+ if (pkg->state_status == SS_UNPACKED)
+ /* Circular dependency has installed it for us. */
+ return 0;
}
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 (conf, OPKG_STATE_INSTALLING_PKG, pkgid);
- free (pkgid);
-
/* this next section we do with SIGINT blocked to prevent inconsistency between opkg database and filesystem */
{
sigset_t newset, oldset;
- sighandler_t old_handler = NULL;
- int use_signal = 0;
- caught_sigint = 0;
- if (use_signal) {
- old_handler = signal(SIGINT, opkg_install_pkg_sigint_handler);
- } else {
- sigemptyset(&newset);
- sigaddset(&newset, SIGINT);
- sigprocmask(SIG_BLOCK, &newset, &oldset);
- }
+
+ 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(conf, pkg, old_pkg);
+
/* XXX: BUG: we really should treat replacement more like an upgrade
* Instead, we're going to remove the replacees
*/
time(&pkg->installed_time);
- opkg_message(conf, OPKG_INFO,
- " cleanup temp files\n");
- cleanup_temporary_files(conf, pkg);
-
ab_pkg = pkg->parent;
if (ab_pkg)
ab_pkg->state_status = pkg->state_status;
opkg_message(conf, OPKG_INFO, "Done.\n");
- if (use_signal)
- signal(SIGINT, old_handler);
- else
- sigprocmask(SIG_UNBLOCK, &newset, &oldset);
-
+ sigprocmask(SIG_UNBLOCK, &newset, &oldset);
+ pkg_vec_free (replacees);
return 0;
UNWIND_REMOVE_INSTALLED_REPLACEES:
pkg_remove_installed_replacees_unwind(conf, replacees);
- opkg_message(conf, OPKG_INFO,
- " cleanup temp files\n");
- cleanup_temporary_files(conf, pkg);
-
opkg_message(conf, OPKG_INFO,
"Failed.\n");
- if (use_signal)
- signal(SIGINT, old_handler);
- else
- sigprocmask(SIG_UNBLOCK, &newset, &oldset);
- return err;
+ sigprocmask(SIG_UNBLOCK, &newset, &oldset);
+
+ pkg_vec_free (replacees);
+ return OPKG_ERR_UNKNOWN;
}
- 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)
sprintf_alloc(&preinst_args, "install %s", pkg_version);
free(pkg_version);
} else {
- preinst_args = strdup("install");
+ preinst_args = xstrdup("install");
}
err = pkg_run_script(conf, pkg, "preinst", preinst_args);
/* 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;
}
/* 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)) {
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;
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) {
+ files_list = pkg_get_installed_files(conf, pkg);
+ 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;
@@@ 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;
+ files_list = pkg_get_installed_files(conf, pkg);
+ 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) {
}
}
- free(root_filename);
+ }
+ if (root_filename) {
+ free(root_filename);
+ root_filename = NULL;
}
pkg_free_installed_files(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;
}
- old_files = pkg_get_installed_files(old_pkg);
- new_files = pkg_get_installed_files(pkg);
+ old_files = pkg_get_installed_files(conf, old_pkg);
+ new_files = pkg_get_installed_files(conf, 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;
}
strerror(errno));
}
}
-
- NOT_OBSOLETE:
- ;
}
+ hash_table_deinit(&new_files_table);
pkg_free_installed_files(old_pkg);
pkg_free_installed_files(pkg);
return 0;
}
-static int remove_obsolete_maintainer_scripts(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
-{
- int i;
- int err = 0;
- char *globpattern;
- glob_t globbuf;
- if (0) {
- if (!pkg->dest) {
- opkg_message(conf, OPKG_ERROR, "%s: no dest for package %s\n", __FUNCTION__, pkg->name);
- return -1;
- }
- sprintf_alloc(&globpattern, "%s/%s.*", pkg->dest->info_dir, pkg->name);
- err = glob(globpattern, 0, NULL, &globbuf);
- free(globpattern);
- if (err) {
- return err;
- }
- /* XXXX this should perhaps only remove the ones that are not overwritten in new package. Jamey 11/11/2003 */
- for (i = 0; i < globbuf.gl_pathc; i++) {
- opkg_message(conf, OPKG_DEBUG, "Removing control file %s from old_pkg %s\n",
- globbuf.gl_pathv[i], old_pkg->name);
- if (!conf->noaction)
- unlink(globbuf.gl_pathv[i]);
- }
- globfree(&globbuf);
- }
- return err;
-}
-
static int install_maintainer_scripts(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
{
int ret;
char *prefix;
- if (old_pkg)
- remove_obsolete_maintainer_scripts(conf, pkg, old_pkg);
sprintf_alloc(&prefix, "%s.", pkg->name);
ret = pkg_extract_control_files_to_dir_with_prefix(pkg,
pkg->dest->info_dir,
conffile_list_elt_t *iter;
conffile_t *cf;
char *cf_backup;
+ char *md5sum;
- char *md5sum;
-
-
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 */
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 (md5sum && cf->value && 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(root_filename, cf_backup) ) {
+ rename(cf_backup, root_filename);
+ }
+ }
+ unlink(cf_backup);
+ if (md5sum)
+ free(md5sum);
+ }
free(cf_backup);
free(root_filename);
" D : show the differences between the versions (if diff is installed)\n"
" The default action is to keep your current version.\n"
" *** %s (Y/I/N/O/D) [default=N] ? ", file_name, short_file_name);
+
+ if (response == NULL)
+ return 1;
+
if (strcmp(response, "y") == 0
|| strcmp(response, "i") == 0
|| strcmp(response, "yes") == 0) {
}
if (strcmp(response, "d") == 0) {
- char *cmd;
-
- free(response);
- /* XXX: BUG rewrite to use exec or busybox's internal diff */
- sprintf_alloc(&cmd, "diff -u %s %s", backup, file_name);
- xsystem(cmd);
- free(cmd);
+ const char *argv[] = {"diff", "-u", backup, file_name, NULL};
+ xsystem(argv);
printf(" [Press ENTER to continue]\n");
response = file_read_line_alloc(stdin);
free(response);
}
}
-/* XXX: CLEANUP: I'd like to move all of the code for
- creating/cleaning pkg->tmp_unpack_dir directly into pkg.c. (Then,
- it would make sense to cleanup pkg->tmp_unpack_dir directly from
- pkg_deinit for example). */
-static int cleanup_temporary_files(opkg_conf_t *conf, pkg_t *pkg)
-{
- DIR *tmp_dir;
- struct dirent *dirent;
- char *tmp_file;
-
-#ifdef OPKG_DEBUG_NO_TMP_CLEANUP
-#error
- opkg_message(conf, OPKG_DEBUG,
- "%s: Not cleaning up %s since opkg compiled with OPKG_DEBUG_NO_TMP_CLEANUP\n",
- __FUNCTION__, pkg->tmp_unpack_dir);
- return 0;
-#endif
-
- if (pkg->tmp_unpack_dir && file_is_dir(pkg->tmp_unpack_dir)) {
- tmp_dir = opendir(pkg->tmp_unpack_dir);
- if (tmp_dir) {
- while (1) {
- dirent = readdir(tmp_dir);
- if (dirent == NULL) {
- break;
- }
- sprintf_alloc(&tmp_file, "%s/%s",
- pkg->tmp_unpack_dir, dirent->d_name);
- if (! file_is_dir(tmp_file)) {
- unlink(tmp_file);
- }
- free(tmp_file);
- }
- closedir(tmp_dir);
- rmdir(pkg->tmp_unpack_dir);
- free(pkg->tmp_unpack_dir);
- pkg->tmp_unpack_dir = NULL;
- }
- }
-
- opkg_message(conf, OPKG_INFO, "cleanup_temporary_files: pkg=%s local_filename=%s tmp_dir=%s\n",
- pkg->name, pkg->local_filename, conf->tmp_dir);
- if (pkg->local_filename && strncmp(pkg->local_filename, conf->tmp_dir, strlen(conf->tmp_dir)) == 0) {
- unlink(pkg->local_filename);
- free(pkg->local_filename);
- pkg->local_filename = NULL;
- }
-
- return 0;
-}
-
static char *backup_filename_alloc(const char *file_name)
{
char *backup;
return 0;
}
-\f
-
-#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