#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 "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);
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;
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)
{
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_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);
}
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 */
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;
}
+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;i<old_pkg->depends_count;i++) {
+ found = 0;
+ for (j=0;j<pkg->depends_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)
{
}
}
-/* 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;
#if HAVE_GPGME
char *list_file_name, *sig_file_name, *lists_dir;
- 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))
+ /* check to ensure the package has come from a repository */
+ if (conf->check_signature && pkg->src)
{
- if (opkg_verify_file (conf, list_file_name, sig_file_name))
- return OPKG_INSTALL_ERR_SIGNATURE;
+ 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);
}
-
- free (lists_dir);
- free (list_file_name);
- free (sig_file_name);
#endif
/* Check for md5 values */
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
*/
/* 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) {
+ 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;
+ 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);
- 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);
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 (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);