#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"
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;
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;
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;
}
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;
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 = 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)
{
int old_state_flag;
char* file_md5;
char *pkgid;
-
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 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);
"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);
}
/* 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();
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
*/
signal(SIGINT, old_handler);
else
sigprocmask(SIG_UNBLOCK, &newset, &oldset);
-
+ pkg_vec_free (replacees);
return 0;
else
sigprocmask(SIG_UNBLOCK, &newset, &oldset);
- return err;
+ pkg_vec_free (replacees);
+ return OPKG_ERR_UNKNOWN;
}
opkg_set_current_state (conf, OPKG_STATE_NONE, NULL);
}