123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551 |
- /* opkg_install.c - the opkg package management system
- Carl D. Worth
- Copyright (C) 2001 University of Southern California
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- */
- #include <stdio.h>
- #include <time.h>
- #include <signal.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include "pkg.h"
- #include "pkg_hash.h"
- #include "pkg_extract.h"
- #include "opkg_install.h"
- #include "opkg_configure.h"
- #include "opkg_download.h"
- #include "opkg_remove.h"
- #include "opkg_utils.h"
- #include "opkg_message.h"
- #include "opkg_cmd.h"
- #include "opkg_defines.h"
- #include "sprintf_alloc.h"
- #include "file_util.h"
- #include "xsystem.h"
- #include "libbb/libbb.h"
- static int satisfy_dependencies_for(pkg_t * pkg)
- {
- int i, err;
- pkg_vec_t *depends = pkg_vec_alloc();
- pkg_t *dep;
- char **tmp, **unresolved = NULL, *prev = NULL;
- int ndepends;
- ndepends = pkg_hash_fetch_unsatisfied_dependencies(pkg, depends,
- &unresolved, 0);
- if (unresolved) {
- opkg_msg(ERROR,
- "Cannot satisfy the following dependencies for %s:\n",
- pkg->name);
- tmp = unresolved;
- while (*unresolved) {
- if (!prev || strcmp(*unresolved, prev))
- opkg_message(ERROR, "\t%s\n", *unresolved);
- prev = *unresolved;
- unresolved++;
- }
- unresolved = tmp;
- while (*unresolved) {
- free(*unresolved);
- unresolved++;
- }
- free(tmp);
- if (!conf->force_depends) {
- opkg_msg(INFO,
- "This could mean that your package list is out of date or that the packages\n"
- "mentioned above do not yet exist (try 'opkg update'). To proceed in spite\n"
- "of this problem try again with the '-force-depends' option.\n");
- pkg_vec_free(depends);
- return -1;
- }
- }
- if (ndepends <= 0) {
- pkg_vec_free(depends);
- return 0;
- }
- /* Mark packages as to-be-installed */
- for (i = 0; i < depends->len; i++) {
- /* Dependencies should be installed the same place as pkg */
- if (depends->pkgs[i]->dest == NULL) {
- depends->pkgs[i]->dest = pkg->dest;
- }
- depends->pkgs[i]->state_want = SW_INSTALL;
- }
- for (i = 0; i < depends->len; i++) {
- dep = depends->pkgs[i];
- /* The package was uninstalled when we started, but another
- dep earlier in this loop may have depended on it and pulled
- it in, so check first. */
- if ((dep->state_status != SS_INSTALLED)
- && (dep->state_status != SS_UNPACKED)) {
- opkg_msg(DEBUG2, "Calling opkg_install_pkg.\n");
- err = opkg_install_pkg(dep, 0);
- /* mark this package as having been automatically installed to
- * satisfy a dependancy */
- dep->auto_installed = 1;
- if (err) {
- pkg_vec_free(depends);
- return err;
- }
- }
- }
- pkg_vec_free(depends);
- return 0;
- }
- static int check_conflicts_for(pkg_t * pkg)
- {
- int i;
- pkg_vec_t *conflicts = NULL;
- message_level_t level;
- if (conf->force_depends) {
- level = NOTICE;
- } else {
- level = ERROR;
- }
- if (!conf->force_depends)
- conflicts = pkg_hash_fetch_conflicts(pkg);
- if (conflicts) {
- opkg_msg(level, "The following packages conflict with %s:\n",
- pkg->name);
- i = 0;
- while (i < conflicts->len)
- opkg_msg(level, "\t%s", conflicts->pkgs[i++]->name);
- opkg_message(level, "\n");
- pkg_vec_free(conflicts);
- return -1;
- }
- return 0;
- }
- static int update_file_ownership(pkg_t * new_pkg, pkg_t * old_pkg)
- {
- str_list_t *new_list, *old_list;
- str_list_elt_t *iter, *niter;
- new_list = pkg_get_installed_files(new_pkg);
- if (new_list == NULL)
- return -1;
- 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(new_file);
- pkg_t *obs = hash_table_get(&conf->obs_file_hash, new_file);
- opkg_msg(DEBUG2,
- "%s: new_pkg=%s wants file %s, from owner=%s\n",
- __func__, new_pkg->name, new_file,
- owner ? owner->name : "<NULL>");
- if (!owner || (owner == old_pkg) || obs)
- file_hash_set_file_owner(new_file, new_pkg);
- }
- if (old_pkg) {
- old_list = pkg_get_installed_files(old_pkg);
- if (old_list == NULL) {
- pkg_free_installed_files(new_pkg);
- return -1;
- }
- 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(old_file);
- if (!owner || (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;
- }
- static int verify_pkg_installable(pkg_t * pkg)
- {
- unsigned long kbs_available, pkg_size_kbs;
- unsigned long installed_size;
- char *root_dir = NULL;
- struct stat s;
- installed_size = (unsigned long) pkg_get_int(pkg, PKG_INSTALLED_SIZE);
- if (conf->force_space || installed_size == 0)
- return 0;
- if (pkg->dest) {
- if (!strcmp(pkg->dest->name, "root") && conf->overlay_root
- && !stat(conf->overlay_root, &s) && (s.st_mode & S_IFDIR))
- root_dir = conf->overlay_root;
- else
- root_dir = pkg->dest->root_dir;
- }
- if (!root_dir)
- root_dir = conf->default_dest->root_dir;
- kbs_available = get_available_kbytes(root_dir);
- pkg_size_kbs = (installed_size + 1023) / 1024;
- if (pkg_size_kbs >= kbs_available) {
- opkg_msg(ERROR, "Only have %ldkb available on filesystem %s, "
- "pkg %s needs %ld\n",
- kbs_available, root_dir, pkg->name, pkg_size_kbs);
- return -1;
- }
- return 0;
- }
- static int unpack_pkg_control_files(pkg_t * pkg)
- {
- int err;
- char *conffiles_file_name;
- char *root_dir;
- char *tmp_unpack_dir;
- FILE *conffiles_file;
- conffile_list_t *cl;
- sprintf_alloc(&tmp_unpack_dir, "%s/%s-XXXXXX", conf->tmp_dir,
- pkg->name);
- tmp_unpack_dir = mkdtemp(tmp_unpack_dir);
- if (tmp_unpack_dir == NULL) {
- opkg_perror(ERROR, "Failed to create temporary directory");
- return -1;
- }
- pkg_set_string(pkg, PKG_TMP_UNPACK_DIR, tmp_unpack_dir);
- err = pkg_extract_control_files_to_dir(pkg, tmp_unpack_dir);
- if (err) {
- return err;
- }
- /* XXX: CLEANUP: There might be a cleaner place to read in the
- conffiles. Seems like I should be able to get everything to go
- through pkg_init_from_file. If so, maybe it would make sense to
- move all of unpack_pkg_control_files to that function. */
- /* Don't need to re-read conffiles if we already have it */
- cl = pkg_get_ptr(pkg, PKG_CONFFILES);
- if (cl && !nv_pair_list_empty(cl)) {
- return 0;
- }
- sprintf_alloc(&conffiles_file_name, "%s/conffiles",
- tmp_unpack_dir);
- if (!file_exists(conffiles_file_name)) {
- free(conffiles_file_name);
- return 0;
- }
- conffiles_file = fopen(conffiles_file_name, "r");
- if (conffiles_file == NULL) {
- opkg_perror(ERROR, "Failed to open %s", conffiles_file_name);
- free(conffiles_file_name);
- return -1;
- }
- free(conffiles_file_name);
- cl = xcalloc(1, sizeof(*cl));
- conffile_list_init(cl);
- while (1) {
- char *cf_name;
- char *cf_name_in_dest;
- int i;
- cf_name = file_read_line_alloc(conffiles_file);
- if (cf_name == NULL) {
- break;
- }
- if (cf_name[0] == '\0') {
- continue;
- }
- for (i = strlen(cf_name) - 1;
- (i >= 0) && (cf_name[i] == ' ' || cf_name[i] == '\t');
- i--) {
- cf_name[i] = '\0';
- }
- /* Prepend dest->root_dir to conffile name.
- Take pains to avoid multiple slashes. */
- root_dir = pkg->dest->root_dir;
- if (conf->offline_root)
- /* skip the offline_root prefix */
- root_dir =
- pkg->dest->root_dir + strlen(conf->offline_root);
- sprintf_alloc(&cf_name_in_dest, "%s%s", root_dir,
- cf_name[0] == '/' ? (cf_name + 1) : cf_name);
- /* Can't get an md5sum now, (file isn't extracted yet).
- We'll wait until resolve_conffiles */
- conffile_list_append(cl, cf_name_in_dest, NULL);
- free(cf_name);
- free(cf_name_in_dest);
- }
- pkg_set_ptr(pkg, PKG_CONFFILES, cl);
- fclose(conffiles_file);
- 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(pkg_t * pkg, pkg_t * old_pkg)
- {
- int j, l, found, r, err = 0;
- int n_deps;
- pkg_t *p;
- struct compound_depend *cd0, *cd1;
- abstract_pkg_t **dependents;
- for (cd0 = pkg_get_ptr(old_pkg, PKG_DEPENDS); cd0 && cd0->type; cd0++) {
- if (cd0->type != DEPEND)
- continue;
- for (j = 0; j < cd0->possibility_count; j++) {
- found = 0;
- for (cd1 = pkg_get_ptr(pkg, PKG_DEPENDS); cd1 && cd1->type; cd1++) {
- 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(cd0->
- possibilities[j]->
- pkg->name);
- if (!p)
- continue;
- if (!p->auto_installed)
- continue;
- n_deps = pkg_has_installed_dependents(p, &dependents);
- n_deps--; /* don't count old_pkg */
- if (n_deps == 0) {
- opkg_msg(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;
- r = opkg_remove_pkg(p, 0);
- if (!err)
- err = r;
- } else
- opkg_msg(INFO, "%s was autoinstalled and is "
- "still required by %d "
- "installed packages.\n",
- p->name, n_deps);
- }
- }
- return err;
- }
- /* returns number of installed replacees */
- static int
- pkg_get_installed_replacees(pkg_t * pkg, pkg_vec_t * installed_replacees)
- {
- abstract_pkg_t **replaces = pkg_get_ptr(pkg, PKG_REPLACES);
- int j;
- while (replaces && *replaces) {
- abstract_pkg_t *ab_pkg = *replaces++;
- pkg_vec_t *pkg_vec = ab_pkg->pkgs;
- if (pkg_vec) {
- for (j = 0; j < pkg_vec->len; j++) {
- pkg_t *replacee = pkg_vec->pkgs[j];
- if (!pkg_conflicts(pkg, replacee))
- continue;
- if (replacee->state_status == SS_INSTALLED) {
- pkg_vec_insert(installed_replacees,
- replacee);
- }
- }
- }
- }
- return installed_replacees->len;
- }
- static int pkg_remove_installed_replacees(pkg_vec_t * replacees)
- {
- int i;
- int replaces_count = replacees->len;
- for (i = 0; i < replaces_count; i++) {
- pkg_t *replacee = replacees->pkgs[i];
- int err;
- replacee->state_flag |= SF_REPLACE; /* flag it so remove won't complain */
- err = opkg_remove_pkg(replacee, 0);
- if (err)
- return err;
- }
- return 0;
- }
- /* to unwind the removal: make sure they are installed */
- static int pkg_remove_installed_replacees_unwind(pkg_vec_t * replacees)
- {
- int i, err;
- int replaces_count = replacees->len;
- for (i = 0; i < replaces_count; i++) {
- pkg_t *replacee = replacees->pkgs[i];
- if (replacee->state_status != SS_INSTALLED) {
- opkg_msg(DEBUG2, "Calling opkg_install_pkg.\n");
- err = opkg_install_pkg(replacee, 0);
- if (err)
- return err;
- }
- }
- return 0;
- }
- /* 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(pkg_t * pkg, pkg_t * old_pkg, int message)
- {
- if (old_pkg) {
- char message_out[15];
- char *old_version = pkg_version_str_alloc(old_pkg);
- char *new_version = pkg_version_str_alloc(pkg);
- int cmp = pkg_compare_versions(old_pkg, pkg);
- int rc = 0;
- memset(message_out, '\x0', 15);
- strncpy(message_out, "Upgrading ", strlen("Upgrading "));
- if ((conf->force_downgrade == 1) && (cmp > 0)) { /* We've been asked to allow downgrade and version is precedent */
- cmp = -1; /* then we force opkg to downgrade */
- strncpy(message_out, "Downgrading ", strlen("Downgrading ")); /* 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 */
- }
- if (cmp > 0) {
- if (!conf->download_only)
- opkg_msg(NOTICE,
- "Not downgrading package %s on %s from %s to %s.\n",
- old_pkg->name, old_pkg->dest->name,
- old_version, new_version);
- rc = 1;
- } else if (cmp < 0) {
- if (!conf->download_only)
- opkg_msg(NOTICE,
- "%s%s on %s from %s to %s...\n",
- message_out, pkg->name,
- old_pkg->dest->name, old_version,
- new_version);
- pkg->dest = old_pkg->dest;
- rc = 0;
- } else { /* cmp == 0 */
- if (!conf->download_only)
- opkg_msg(NOTICE,
- "%s (%s) already install on %s.\n",
- pkg->name, new_version,
- old_pkg->dest->name);
- rc = 1;
- }
- free(old_version);
- free(new_version);
- return rc;
- } else {
- char message_out[15];
- memset(message_out, '\x0', 15);
- if (message)
- strncpy(message_out, "Upgrading ",
- strlen("Upgrading "));
- else
- strncpy(message_out, "Installing ",
- strlen("Installing "));
- char *version = pkg_version_str_alloc(pkg);
- if (!conf->download_only)
- opkg_msg(NOTICE, "%s%s (%s) to %s...\n", message_out,
- pkg->name, version, pkg->dest->name);
- free(version);
- }
- return 0;
- }
- static int prerm_upgrade_old_pkg(pkg_t * pkg, pkg_t * old_pkg)
- {
- /* DPKG_INCOMPATIBILITY:
- dpkg does some things here that we don't do yet. Do we care?
- 1. If a version of the package is already installed, call
- old-prerm upgrade new-version
- 2. If the script runs but exits with a non-zero exit status
- new-prerm failed-upgrade old-version
- Error unwind, for both the above cases:
- old-postinst abort-upgrade new-version
- */
- int err;
- char *script_args;
- char *new_version;
- if (!old_pkg || !pkg)
- return 0;
- new_version = pkg_version_str_alloc(pkg);
- sprintf_alloc(&script_args, "upgrade %s", new_version);
- free(new_version);
- err = pkg_run_script(old_pkg, "prerm", script_args);
- free(script_args);
- if (err != 0) {
- opkg_msg(ERROR, "prerm script for package \"%s\" failed\n",
- old_pkg->name);
- return -1;
- }
- return 0;
- }
- static int prerm_upgrade_old_pkg_unwind(pkg_t * pkg, pkg_t * old_pkg)
- {
- /* DPKG_INCOMPATIBILITY:
- dpkg does some things here that we don't do yet. Do we care?
- (See prerm_upgrade_old_package for details)
- */
- return 0;
- }
- static int prerm_deconfigure_conflictors(pkg_t * pkg, pkg_vec_t * conflictors)
- {
- /* DPKG_INCOMPATIBILITY:
- dpkg does some things here that we don't do yet. Do we care?
- 2. If a 'conflicting' package is being removed at the same time:
- 1. If any packages depended on that conflicting package and
- --auto-deconfigure is specified, call, for each such package:
- deconfigured's-prerm deconfigure \
- in-favour package-being-installed version \
- removing conflicting-package version
- Error unwind:
- deconfigured's-postinst abort-deconfigure \
- in-favour package-being-installed-but-failed version \
- removing conflicting-package version
- The deconfigured packages are marked as requiring
- configuration, so that if --install is used they will be
- configured again if possible.
- 2. To prepare for removal of the conflicting package, call:
- conflictor's-prerm remove in-favour package new-version
- Error unwind:
- conflictor's-postinst abort-remove in-favour package new-version
- */
- return 0;
- }
- static int
- prerm_deconfigure_conflictors_unwind(pkg_t * pkg, pkg_vec_t * conflictors)
- {
- /* DPKG_INCOMPATIBILITY: dpkg does some things here that we don't
- do yet. Do we care? (See prerm_deconfigure_conflictors for
- details) */
- return 0;
- }
- static int preinst_configure(pkg_t * pkg, pkg_t * old_pkg)
- {
- int err;
- char *preinst_args;
- if (old_pkg) {
- char *old_version = pkg_version_str_alloc(old_pkg);
- sprintf_alloc(&preinst_args, "upgrade %s", old_version);
- free(old_version);
- } else if (pkg->state_status == SS_CONFIG_FILES) {
- char *pkg_version = pkg_version_str_alloc(pkg);
- sprintf_alloc(&preinst_args, "install %s", pkg_version);
- free(pkg_version);
- } else {
- preinst_args = xstrdup("install");
- }
- err = pkg_run_script(pkg, "preinst", preinst_args);
- if (err) {
- opkg_msg(ERROR, "Aborting installation of %s.\n", pkg->name);
- return -1;
- }
- free(preinst_args);
- return 0;
- }
- static int preinst_configure_unwind(pkg_t * pkg, pkg_t * old_pkg)
- {
- /* DPKG_INCOMPATIBILITY:
- dpkg does the following error unwind, should we?
- pkg->postrm abort-upgrade old-version
- OR pkg->postrm abort-install old-version
- OR pkg->postrm abort-install
- */
- return 0;
- }
- static char *backup_filename_alloc(const char *file_name)
- {
- char *backup;
- sprintf_alloc(&backup, "%s%s", file_name, OPKG_BACKUP_SUFFIX);
- return backup;
- }
- static int backup_make_backup(const char *file_name)
- {
- int err;
- char *backup;
- backup = backup_filename_alloc(file_name);
- err = file_copy(file_name, backup);
- if (err) {
- opkg_msg(ERROR, "Failed to copy %s to %s\n", file_name, backup);
- }
- free(backup);
- return err;
- }
- static int backup_exists_for(const char *file_name)
- {
- int ret;
- char *backup;
- backup = backup_filename_alloc(file_name);
- ret = file_exists(backup);
- free(backup);
- return ret;
- }
- static int backup_remove(const char *file_name)
- {
- char *backup;
- backup = backup_filename_alloc(file_name);
- unlink(backup);
- free(backup);
- return 0;
- }
- static int backup_modified_conffiles(pkg_t * pkg, pkg_t * old_pkg)
- {
- int err;
- conffile_list_elt_t *iter;
- conffile_t *cf;
- conffile_list_t *cl;
- if (conf->noaction)
- return 0;
- /* Backup all modified conffiles */
- if (old_pkg) {
- cl = pkg_get_ptr(old_pkg, PKG_CONFFILES);
- for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
- iter = nv_pair_list_next(cl, iter)) {
- char *cf_name;
- cf = iter->data;
- cf_name = root_filename_alloc(cf->name);
- /* Don't worry if the conffile is just plain gone */
- if (file_exists(cf_name)
- && conffile_has_been_modified(cf)) {
- err = backup_make_backup(cf_name);
- if (err) {
- return err;
- }
- }
- free(cf_name);
- }
- }
- /* Backup all conffiles that were not conffiles in old_pkg */
- cl = pkg_get_ptr(pkg, PKG_CONFFILES);
- for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
- iter = nv_pair_list_next(cl, iter)) {
- char *cf_name;
- cf = (conffile_t *) iter->data;
- cf_name = root_filename_alloc(cf->name);
- /* Ignore if this was a conffile in old_pkg as well */
- if (pkg_get_conffile(old_pkg, cf->name)) {
- continue;
- }
- if (file_exists(cf_name) && (!backup_exists_for(cf_name))) {
- err = backup_make_backup(cf_name);
- if (err) {
- return err;
- }
- }
- free(cf_name);
- }
- return 0;
- }
- static int backup_modified_conffiles_unwind(pkg_t * pkg, pkg_t * old_pkg)
- {
- conffile_list_t *cl;
- conffile_list_elt_t *iter;
- if (old_pkg) {
- cl = pkg_get_ptr(old_pkg, PKG_CONFFILES);
- for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
- iter = nv_pair_list_next(cl, iter)) {
- backup_remove(((nv_pair_t *) iter->data)->name);
- }
- }
- cl = pkg_get_ptr(pkg, PKG_CONFFILES);
- for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
- iter = nv_pair_list_next(cl, iter)) {
- backup_remove(((nv_pair_t *) iter->data)->name);
- }
- return 0;
- }
- static int check_data_file_clashes(pkg_t * pkg, pkg_t * old_pkg)
- {
- /* DPKG_INCOMPATIBILITY:
- opkg takes a slightly different approach than dpkg at this
- point. dpkg installs each file in the new package while
- creating a backup for any file that is replaced, (so that it
- can unwind if necessary). To avoid complexity and redundant
- storage, opkg doesn't do any installation until later, (at the
- point at which dpkg removes the backups.
- But, we do have to check for data file clashes, since after
- installing a package with a file clash, removing either of the
- packages involved in the clash has the potential to break the
- other package.
- */
- str_list_t *files_list;
- str_list_elt_t *iter, *niter;
- char *filename;
- int clashes = 0;
- files_list = pkg_get_installed_files(pkg);
- if (files_list == NULL)
- return -1;
- for (iter = str_list_first(files_list), niter =
- str_list_next(files_list, iter); iter;
- iter = niter, niter = str_list_next(files_list, iter)) {
- filename = (char *)iter->data;
- if (file_exists(filename) && (!file_is_dir(filename))) {
- pkg_t *owner;
- pkg_t *obs;
- if (backup_exists_for(filename)) {
- continue;
- }
- /* Pre-existing files are OK if force-overwrite was asserted. */
- if (conf->force_overwrite) {
- /* but we need to change who owns this file */
- file_hash_set_file_owner(filename, pkg);
- continue;
- }
- owner = file_hash_get_file_owner(filename);
- /* Pre-existing files are OK if owned by the pkg being upgraded. */
- if (owner && old_pkg) {
- if (strcmp(owner->name, old_pkg->name) == 0) {
- continue;
- }
- }
- /* Pre-existing files are OK if owned by a package replaced by new pkg. */
- if (owner) {
- opkg_msg(DEBUG2,
- "Checking replaces for %s in package %s\n",
- filename, owner->name);
- if (pkg_replaces(pkg, owner)) {
- continue;
- }
- /* If the file that would be installed is owned by the same package, ( as per a reinstall or similar )
- then it's ok to overwrite. */
- if (strcmp(owner->name, pkg->name) == 0) {
- opkg_msg(INFO,
- "Replacing pre-existing file %s"
- " owned by package %s\n",
- filename, owner->name);
- continue;
- }
- }
- /* Pre-existing files are OK if they are obsolete */
- obs = hash_table_get(&conf->obs_file_hash, filename);
- if (obs) {
- opkg_msg(INFO,
- "Pre-exiting file %s is obsolete."
- " obs_pkg=%s\n", filename, obs->name);
- continue;
- }
- /* We have found a clash. */
- opkg_msg(ERROR, "Package %s wants to install file %s\n"
- "\tBut that file is already provided by package ",
- pkg->name, filename);
- if (owner) {
- opkg_message(ERROR, "%s\n", owner->name);
- } else {
- opkg_message(ERROR, "<no package>\n"
- "Please move this file out of the way and try again.\n");
- }
- clashes++;
- }
- }
- pkg_free_installed_files(pkg);
- return clashes;
- }
- /*
- * XXX: This function sucks, as does the below comment.
- */
- static int check_data_file_clashes_change(pkg_t * pkg, pkg_t * old_pkg)
- {
- /* Basically that's the worst hack I could do to be able to change ownership of
- file list, but, being that we have no way to unwind the mods, due to structure
- of hash table, probably is the quickest hack too, whishing it would not slow-up thing too much.
- What we do here is change the ownership of file in hash if a replace ( or similar events
- happens )
- Only the action that are needed to change name should be considered.
- @@@ To change after 1.0 release.
- */
- str_list_t *files_list;
- str_list_elt_t *iter, *niter;
- files_list = pkg_get_installed_files(pkg);
- if (files_list == NULL)
- return -1;
- 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 (file_exists(filename) && (!file_is_dir(filename))) {
- pkg_t *owner;
- owner = file_hash_get_file_owner(filename);
- if (conf->force_overwrite) {
- /* but we need to change who owns this file */
- file_hash_set_file_owner(filename, pkg);
- continue;
- }
- /* Pre-existing files are OK if owned by a package replaced by new pkg. */
- if (owner) {
- if (pkg_replaces(pkg, owner)) {
- /* It's now time to change the owner of that file.
- It has been "replaced" from the new "Replaces", then I need to inform lists file about that. */
- opkg_msg(INFO,
- "Replacing pre-existing file %s "
- "owned by package %s\n",
- filename, owner->name);
- file_hash_set_file_owner(filename, pkg);
- continue;
- }
- }
- }
- }
- pkg_free_installed_files(pkg);
- return 0;
- }
- static int check_data_file_clashes_unwind(pkg_t * pkg, pkg_t * old_pkg)
- {
- /* Nothing to do since check_data_file_clashes doesn't change state */
- return 0;
- }
- static int postrm_upgrade_old_pkg(pkg_t * pkg, pkg_t * old_pkg)
- {
- /* DPKG_INCOMPATIBILITY: dpkg does the following here, should we?
- 1. If the package is being upgraded, call
- old-postrm upgrade new-version
- 2. If this fails, attempt:
- new-postrm failed-upgrade old-version
- Error unwind, for both cases:
- old-preinst abort-upgrade new-version */
- int err;
- char *script_args;
- char *new_version;
- if (!old_pkg || !pkg)
- return 0;
- new_version = pkg_version_str_alloc(pkg);
- sprintf_alloc(&script_args, "upgrade %s", new_version);
- free(new_version);
- err = pkg_run_script(old_pkg, "postrm", script_args);
- free(script_args);
- if (err != 0) {
- opkg_msg(ERROR, "postrm script for package \"%s\" failed\n",
- old_pkg->name);
- return -1;
- }
- return 0;
- }
- static int postrm_upgrade_old_pkg_unwind(pkg_t * pkg, pkg_t * old_pkg)
- {
- /* DPKG_INCOMPATIBILITY:
- dpkg does some things here that we don't do yet. Do we care?
- (See postrm_upgrade_old_pkg for details)
- */
- return 0;
- }
- static int remove_obsolesced_files(pkg_t * pkg, pkg_t * old_pkg)
- {
- int err = 0;
- str_list_t *old_files;
- str_list_elt_t *of;
- str_list_t *new_files;
- str_list_elt_t *nf;
- hash_table_t new_files_table;
- old_files = pkg_get_installed_files(old_pkg);
- if (old_files == NULL)
- return -1;
- new_files = pkg_get_installed_files(pkg);
- if (new_files == NULL) {
- pkg_free_installed_files(old_pkg);
- return -1;
- }
- 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 = (char *)of->data;
- new = (char *)hash_table_get(&new_files_table, old);
- if (new)
- continue;
- if (file_is_dir(old)) {
- continue;
- }
- owner = file_hash_get_file_owner(old);
- if (owner != old_pkg) {
- /* in case obsolete file no longer belongs to old_pkg */
- continue;
- }
- /* old file is obsolete */
- opkg_msg(NOTICE, "Removing obsolete file %s.\n", old);
- if (!conf->noaction) {
- err = unlink(old);
- if (err) {
- opkg_perror(ERROR, "unlinking %s failed", old);
- }
- }
- }
- hash_table_deinit(&new_files_table);
- pkg_free_installed_files(old_pkg);
- pkg_free_installed_files(pkg);
- return err;
- }
- static int install_maintainer_scripts(pkg_t * pkg, pkg_t * old_pkg)
- {
- int ret;
- char *prefix;
- sprintf_alloc(&prefix, "%s.", pkg->name);
- ret = pkg_extract_control_files_to_dir_with_prefix(pkg,
- pkg->dest->info_dir,
- prefix);
- free(prefix);
- return ret;
- }
- static int remove_disappeared(pkg_t * pkg)
- {
- /* DPKG_INCOMPATIBILITY:
- This is a fairly sophisticated dpkg operation. Shall we
- skip it? */
- /* Any packages all of whose files have been overwritten during the
- installation, and which aren't required for dependencies, are
- considered to have been removed. For each such package
- 1. disappearer's-postrm disappear overwriter overwriter-version
- 2. The package's maintainer scripts are removed
- 3. It is noted in the status database as being in a sane state,
- namely not installed (any conffiles it may have are ignored,
- rather than being removed by dpkg). Note that disappearing
- packages do not have their prerm called, because dpkg doesn't
- know in advance that the package is going to vanish.
- */
- return 0;
- }
- static int install_data_files(pkg_t * pkg)
- {
- int err;
- /* opkg takes a slightly different approach to data file backups
- than dpkg. Rather than removing backups at this point, we
- actually do the data file installation now. See comments in
- check_data_file_clashes() for more details. */
- opkg_msg(INFO, "Extracting data files to %s.\n", pkg->dest->root_dir);
- err = pkg_extract_data_files_to_dir(pkg, pkg->dest->root_dir);
- if (err) {
- return err;
- }
- opkg_msg(DEBUG, "Calling pkg_write_filelist.\n");
- err = pkg_write_filelist(pkg);
- if (err)
- return err;
- /* XXX: FEATURE: opkg should identify any files which existed
- before installation and which were overwritten, (see
- check_data_file_clashes()). What it must do is remove any such
- files from the filelist of the old package which provided the
- file. Otherwise, if the old package were removed at some point
- it would break the new package. Removing the new package will
- also break the old one, but this cannot be helped since the old
- package's file has already been deleted. This is the importance
- of check_data_file_clashes(), and only allowing opkg to install
- a clashing package with a user force. */
- return 0;
- }
- static int resolve_conffiles(pkg_t * pkg)
- {
- conffile_list_elt_t *iter;
- conffile_list_t *cl;
- conffile_t *cf;
- char *cf_backup;
- char *chksum;
- if (conf->noaction)
- return 0;
- cl = pkg_get_ptr(pkg, PKG_CONFFILES);
- for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
- iter = nv_pair_list_next(cl, iter)) {
- char *root_filename;
- cf = (conffile_t *) iter->data;
- root_filename = root_filename_alloc(cf->name);
- /* Might need to initialize the md5sum for each conffile */
- if (cf->value == NULL) {
- cf->value = file_sha256sum_alloc(root_filename);
- }
- if (!file_exists(root_filename)) {
- free(root_filename);
- continue;
- }
- cf_backup = backup_filename_alloc(root_filename);
- if (file_exists(cf_backup)) {
- /* Let's compute md5 to test if files are changed */
- if (cf->value && strlen(cf->value) > 33) {
- chksum = file_sha256sum_alloc(cf_backup);
- } else {
- chksum = file_md5sum_alloc(cf_backup);
- }
- if (chksum && cf->value
- && strcmp(cf->value, chksum) != 0) {
- if (conf->force_maintainer) {
- opkg_msg(NOTICE,
- "Conffile %s using maintainer's setting.\n",
- cf_backup);
- } else {
- char *new_conffile;
- sprintf_alloc(&new_conffile, "%s-opkg",
- root_filename);
- opkg_msg(ERROR,
- "Existing conffile %s "
- "is different from the conffile in the new package."
- " The new conffile will be placed at %s.\n",
- root_filename, new_conffile);
- rename(root_filename, new_conffile);
- rename(cf_backup, root_filename);
- free(new_conffile);
- }
- }
- unlink(cf_backup);
- if (chksum)
- free(chksum);
- }
- free(cf_backup);
- free(root_filename);
- }
- return 0;
- }
- int opkg_install_by_name(const char *pkg_name)
- {
- int cmp;
- pkg_t *old, *new;
- char *old_version, *new_version;
- old = pkg_hash_fetch_installed_by_name(pkg_name);
- if (old)
- opkg_msg(DEBUG2, "Old versions from pkg_hash_fetch %s.\n",
- pkg_get_string(old, PKG_VERSION));
- new = pkg_hash_fetch_best_installation_candidate_by_name(pkg_name);
- if (new == NULL) {
- opkg_msg(NOTICE, "Unknown package '%s'.\n", pkg_name);
- return -1;
- }
- opkg_msg(DEBUG2, "Versions from pkg_hash_fetch:");
- if (old)
- opkg_message(DEBUG2, " old %s ", pkg_get_string(old, PKG_VERSION));
- opkg_message(DEBUG2, " new %s\n", pkg_get_string(new, PKG_VERSION));
- new->state_flag |= SF_USER;
- 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_msg(DEBUG, "Forcing downgrade\n");
- 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_msg(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) {
- opkg_msg(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_msg(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;
- }
- free(old_version);
- free(new_version);
- }
- opkg_msg(DEBUG2, "Calling opkg_install_pkg.\n");
- return opkg_install_pkg(new, 0);
- }
- /**
- * @brief Really install a pkg_t
- */
- int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
- {
- int err = 0;
- int message = 0;
- pkg_t *old_pkg = NULL;
- pkg_vec_t *replacees;
- abstract_pkg_t *ab_pkg = NULL;
- int old_state_flag;
- sigset_t newset, oldset;
- const char *local_filename;
- time_t now;
- if (from_upgrade)
- message = 1; /* Coming from an upgrade, and should change the output message */
- opkg_msg(DEBUG2, "Calling pkg_arch_supported.\n");
- if (!pkg_arch_supported(pkg)) {
- opkg_msg(ERROR,
- "INTERNAL ERROR: architecture %s for pkg %s is unsupported.\n",
- pkg_get_architecture(pkg), pkg->name);
- return -1;
- }
- if (pkg->state_status == SS_INSTALLED && conf->nodeps == 0) {
- err = satisfy_dependencies_for(pkg);
- if (err)
- return -1;
- opkg_msg(NOTICE, "Package %s is already installed on %s.\n",
- pkg->name, pkg->dest->name);
- return 0;
- }
- if (pkg->dest == NULL) {
- pkg->dest = conf->default_dest;
- }
- old_pkg = pkg_hash_fetch_installed_by_name(pkg->name);
- err = opkg_install_check_downgrade(pkg, old_pkg, message);
- if (err)
- return -1;
- pkg->state_want = SW_INSTALL;
- if (old_pkg) {
- old_pkg->state_want = SW_DEINSTALL; /* needed for check_data_file_clashes of dependencies */
- }
- err = check_conflicts_for(pkg);
- if (err)
- return -1;
- /* 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
- installed. Then A's installation is started resulting in an
- uncecessary upgrade */
- if (pkg->state_status == SS_INSTALLED)
- return 0;
- err = verify_pkg_installable(pkg);
- if (err)
- return -1;
- local_filename = pkg_get_string(pkg, PKG_LOCAL_FILENAME);
- if (local_filename == NULL) {
- if (!conf->cache && conf->download_only) {
- char cwd[4096];
- if (getcwd(cwd, sizeof(cwd)) != NULL)
- err = opkg_download_pkg(pkg, cwd);
- else
- return -1;
- } else {
- err = opkg_download_pkg(pkg, conf->tmp_dir);
- }
- if (err) {
- opkg_msg(ERROR, "Failed to download %s. "
- "Perhaps you need to run 'opkg update'?\n",
- pkg->name);
- return -1;
- }
- local_filename = pkg_get_string(pkg, PKG_LOCAL_FILENAME);
- }
- /* check that the repository is valid */
- #if defined(HAVE_USIGN)
- 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(list_file_name, sig_file_name)) {
- opkg_msg(ERROR,
- "Failed to verify the signature of %s.\n",
- list_file_name);
- if (!conf->force_signature)
- return -1;
- }
- } else {
- opkg_msg(ERROR, "Signature file is missing for %s. "
- "Perhaps you need to run 'opkg update'?\n",
- pkg->name);
- if (!conf->force_signature)
- return -1;
- }
- free(lists_dir);
- free(list_file_name);
- free(sig_file_name);
- }
- #endif
- /* Check integrity (size, checksums) */
- err = opkg_verify_integrity(pkg, local_filename);
- if (err && !conf->force_checksum) {
- opkg_msg(ERROR, "Checksum or size mismatch for package %s. "
- "Either the opkg or the package index are corrupt. "
- "Try 'opkg update'.\n", pkg->name);
- return -1;
- }
- if (err && conf->force_checksum) {
- opkg_msg(NOTICE, "Ignored %s checksum or size mismatch.\n",
- pkg->name);
- }
- if (conf->download_only) {
- if (conf->nodeps == 0) {
- err = satisfy_dependencies_for(pkg);
- if (err)
- return -1;
- }
- return 0;
- }
- if (!pkg_get_string(pkg, PKG_TMP_UNPACK_DIR)) {
- if (unpack_pkg_control_files(pkg) == -1) {
- opkg_msg(ERROR,
- "Failed to unpack control files from %s.\n",
- local_filename);
- return -1;
- }
- }
- err = update_file_ownership(pkg, old_pkg);
- if (err)
- return -1;
- if (conf->nodeps == 0) {
- err = satisfy_dependencies_for(pkg);
- if (err)
- return -1;
- if (pkg->state_status == SS_UNPACKED)
- /* Circular dependency has installed it for us. */
- return 0;
- }
- replacees = pkg_vec_alloc();
- pkg_get_installed_replacees(pkg, replacees);
- /* this next section we do with SIGINT blocked to prevent inconsistency between opkg database and filesystem */
- 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(pkg, old_pkg);
- old_pkg->is_upgrade = 1;
- pkg->is_upgrade = 1;
- }
- /* XXX: BUG: we really should treat replacement more like an upgrade
- * Instead, we're going to remove the replacees
- */
- err = pkg_remove_installed_replacees(replacees);
- if (err)
- goto UNWIND_REMOVE_INSTALLED_REPLACEES;
- err = prerm_upgrade_old_pkg(pkg, old_pkg);
- if (err)
- goto UNWIND_PRERM_UPGRADE_OLD_PKG;
- err = prerm_deconfigure_conflictors(pkg, replacees);
- if (err)
- goto UNWIND_PRERM_DECONFIGURE_CONFLICTORS;
- err = preinst_configure(pkg, old_pkg);
- if (err)
- goto UNWIND_PREINST_CONFIGURE;
- err = backup_modified_conffiles(pkg, old_pkg);
- if (err)
- goto UNWIND_BACKUP_MODIFIED_CONFFILES;
- err = check_data_file_clashes(pkg, old_pkg);
- if (err)
- goto UNWIND_CHECK_DATA_FILE_CLASHES;
- err = postrm_upgrade_old_pkg(pkg, old_pkg);
- if (err)
- goto UNWIND_POSTRM_UPGRADE_OLD_PKG;
- if (conf->noaction)
- return 0;
- /* point of no return: no unwinding after this */
- if (old_pkg) {
- old_pkg->state_want = SW_DEINSTALL;
- if (old_pkg->state_flag & SF_NOPRUNE) {
- opkg_msg(INFO, "Not removing obsolesced files because "
- "package %s marked noprune.\n", old_pkg->name);
- } else {
- opkg_msg(INFO, "Removing obsolesced files for %s\n",
- old_pkg->name);
- if (remove_obsolesced_files(pkg, old_pkg)) {
- opkg_msg(ERROR, "Failed to determine "
- "obsolete files from previously "
- "installed %s\n", old_pkg->name);
- }
- }
- /* removing files from old package, to avoid ghost files */
- remove_data_files_and_list(old_pkg);
- remove_maintainer_scripts(old_pkg);
- }
- opkg_msg(INFO, "%s maintainer scripts.\n",
- (pkg->is_upgrade) ? ("Upgrading") : ("Installing"));
- if (install_maintainer_scripts(pkg, old_pkg)) {
- opkg_msg(ERROR, "Failed to extract maintainer scripts for %s."
- " Package debris may remain!\n", pkg->name);
- goto pkg_is_hosed;
- }
- /* the following just returns 0 */
- remove_disappeared(pkg);
- opkg_msg(INFO, "Installing data files for %s.\n", pkg->name);
- if (install_data_files(pkg)) {
- opkg_msg(ERROR, "Failed to extract data files for %s. "
- "Package debris may remain!\n", pkg->name);
- goto pkg_is_hosed;
- }
- err = check_data_file_clashes_change(pkg, old_pkg);
- if (err) {
- opkg_msg(ERROR, "check_data_file_clashes_change() failed for "
- "for files belonging to %s.\n", pkg->name);
- }
- opkg_msg(INFO, "Resolving conf files for %s\n", pkg->name);
- resolve_conffiles(pkg);
- pkg->state_status = SS_UNPACKED;
- old_state_flag = pkg->state_flag;
- pkg->state_flag &= ~SF_PREFER;
- opkg_msg(DEBUG, "pkg=%s old_state_flag=%x state_flag=%x\n",
- pkg->name, old_state_flag, pkg->state_flag);
- if (old_pkg)
- old_pkg->state_status = SS_NOT_INSTALLED;
- now = time(NULL);
- pkg_set_int(pkg, PKG_INSTALLED_TIME, now);
- ab_pkg = pkg->parent;
- if (ab_pkg)
- ab_pkg->state_status = pkg->state_status;
- sigprocmask(SIG_UNBLOCK, &newset, &oldset);
- pkg_vec_free(replacees);
- return 0;
- UNWIND_POSTRM_UPGRADE_OLD_PKG:
- postrm_upgrade_old_pkg_unwind(pkg, old_pkg);
- UNWIND_CHECK_DATA_FILE_CLASHES:
- check_data_file_clashes_unwind(pkg, old_pkg);
- UNWIND_BACKUP_MODIFIED_CONFFILES:
- backup_modified_conffiles_unwind(pkg, old_pkg);
- UNWIND_PREINST_CONFIGURE:
- preinst_configure_unwind(pkg, old_pkg);
- UNWIND_PRERM_DECONFIGURE_CONFLICTORS:
- prerm_deconfigure_conflictors_unwind(pkg, replacees);
- UNWIND_PRERM_UPGRADE_OLD_PKG:
- prerm_upgrade_old_pkg_unwind(pkg, old_pkg);
- UNWIND_REMOVE_INSTALLED_REPLACEES:
- pkg_remove_installed_replacees_unwind(replacees);
- pkg_is_hosed:
- sigprocmask(SIG_UNBLOCK, &newset, &oldset);
- pkg_vec_free(replacees);
- return -1;
- }
|