ipkg_install.c

来自「this is the pkg installer for linux」· C语言 代码 · 共 1,943 行 · 第 1/5 页

C
1,943
字号
/* ipkg_install.c - the itsy 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 "ipkg.h"#include <errno.h>#include <dirent.h>#include <glob.h>#include <time.h>#include <signal.h>typedef void (*sighandler_t)(int);#include "pkg.h"#include "pkg_hash.h"#include "pkg_extract.h"#include "ipkg_install.h"#include "ipkg_configure.h"#include "ipkg_download.h"#include "ipkg_remove.h"#include "ipkg_utils.h"#include "ipkg_message.h"#include "sprintf_alloc.h"#include "file_util.h"#include "str_util.h"#include "xsystem.h"#include "user.h"int satisfy_dependencies_for(ipkg_conf_t *conf, pkg_t *pkg);static int verify_pkg_installable(ipkg_conf_t *conf, pkg_t *pkg);static int unpack_pkg_control_files(ipkg_conf_t *conf, pkg_t *pkg);static int prerm_upgrade_old_pkg(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int prerm_upgrade_old_pkg_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int prerm_deconfigure_conflictors(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors);static int prerm_deconfigure_conflictors_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors);static int preinst_configure(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int preinst_configure_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int check_data_file_clashes(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int check_data_file_clashes_change(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int check_data_file_clashes_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int backup_modified_conffiles(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int backup_modified_conffiles_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int postrm_upgrade_old_pkg(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int postrm_upgrade_old_pkg_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int remove_obsolesced_files(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int install_maintainer_scripts(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);static int remove_disappeared(ipkg_conf_t *conf, pkg_t *pkg);static int install_data_files(ipkg_conf_t *conf, pkg_t *pkg);static int resolve_conffiles(ipkg_conf_t *conf, pkg_t *pkg);static int cleanup_temporary_files(ipkg_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);static int backup_make_backup(ipkg_conf_t *conf, const char *file_name);static int backup_exists_for(const char *file_name);static int backup_remove(const char *file_name);int ipkg_install_from_file(ipkg_conf_t *conf, const char *filename){     int err, cmp;     pkg_t *pkg, *old;     char *old_version, *new_version;     pkg = pkg_new();     if (pkg == NULL) {	  return ENOMEM;     }     err = pkg_init_from_file(pkg, filename);     if (err) {	  return err;     }     if (!pkg->architecture) {	  ipkg_message(conf, IPKG_ERROR, "Package %s has no Architecture defined.\n", pkg->name);	  return -EINVAL;     }     /* XXX: CLEANUP: hash_insert_pkg has a nasty side effect of possibly	freeing the pkg that we pass in. It might be nice to clean this up	if possible.  */     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);	  cmp = pkg_compare_versions(old, pkg);          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */             cmp = -1 ;                                       /* then we force ipkg 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 */          } 	  if (cmp > 0) {	         ipkg_message(conf, IPKG_NOTICE,			      "Not downgrading package %s on %s from %s to %s.\n",			      old->name, old->dest->name, old_version, new_version);	         pkg->state_want = SW_DEINSTALL;	         pkg->state_flag |= SF_OBSOLETE;	         free(old_version);	         free(new_version);	         return 0;	  } else {	       free(old_version);	       free(new_version);	  }     }     ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);     return ipkg_install_pkg(conf, pkg,0);}ipkg_error_t ipkg_install_by_name(ipkg_conf_t *conf, const char *pkg_name){     int cmp;     pkg_t *old, *new;     char *old_version, *new_version;     ipkg_message(conf, IPKG_DEBUG2, " Getting old  from pkg_hash_fetch \n" );     old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg_name);     if ( old )         ipkg_message(conf, IPKG_DEBUG2, " Old versions from pkg_hash_fetch %s \n",  old->version );         ipkg_message(conf, IPKG_DEBUG2, " Getting new  from pkg_hash_fetch \n" );     new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name);     if ( new )         ipkg_message(conf, IPKG_DEBUG2, " New versions from pkg_hash_fetch %s \n",  new->version );/* Pigi Basically here is broken the version stuff.   What's happening is that nothing provide the version to differents    functions, so the returned struct is always the latest.   That's why the install by name don't work.*/     ipkg_message(conf, IPKG_DEBUG2, " Versions from pkg_hash_fetch in %s ", __FUNCTION__ );     if ( old )         ipkg_message(conf, IPKG_DEBUG2, " old %s ", old->version );     if ( new )         ipkg_message(conf, IPKG_DEBUG2, " new %s ", new->version );     ipkg_message(conf, IPKG_DEBUG2, " \n");     if (new == NULL) {	  return IPKG_PKG_HAS_NO_CANDIDATE;     }     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 */	     ipkg_message(conf, IPKG_DEBUG, " Forcing downgrade \n");             cmp = -1 ;                                       /* then we force ipkg 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 */          } 	  ipkg_message(conf, IPKG_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) {	       ipkg_message(conf, IPKG_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) {	       ipkg_message(conf, IPKG_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;    /* Here probably the problem for bug 1277 */	  }     }     /* XXX: CLEANUP: The error code of ipkg_install_by_name is really	supposed to be an ipkg_error_t, but ipkg_install_pkg could	return any kind of integer, (might be errno from a syscall,	etc.). This is a real mess and will need to be cleaned up if	anyone ever wants to make a nice libipkg. */     ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);     return ipkg_install_pkg(conf, new,0);}ipkg_error_t ipkg_install_multi_by_name(ipkg_conf_t *conf, const char *pkg_name){     abstract_pkg_vec_t *providers = pkg_hash_fetch_all_installation_candidates (&conf->pkg_hash, pkg_name);     int i;     ipkg_error_t err;     abstract_pkg_t *ppkg ;     if (providers == NULL)	  return IPKG_PKG_HAS_NO_CANDIDATE;     for (i = 0; i < providers->len; i++) {	  ppkg = abstract_pkg_vec_get(providers, i);          ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_by_name %d \n",__FUNCTION__, i);	  err = ipkg_install_by_name(conf, ppkg->name);	  if (err)	       return err;/* XXX Maybe ppkg should be freed ? */     }     return 0;}/* * Walk dependence graph starting with pkg, collect packages to be * installed into pkgs_needed, in dependence order. */int pkg_mark_dependencies_for_installation(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *pkgs_needed){     int i, err;     pkg_vec_t *depends = pkg_vec_alloc();     char **unresolved = NULL;     int ndepends;     ndepends = pkg_hash_fetch_unsatisfied_dependencies(conf, 							pkg, depends, 							&unresolved);     if (unresolved) {	  ipkg_message(conf, IPKG_ERROR,		       "%s: Cannot satisfy the following dependencies for %s:\n\t",		       conf->force_depends ? "Warning" : "ERROR", pkg->name);	  while (*unresolved) {	       ipkg_message(conf, IPKG_ERROR, " %s", *unresolved);	       unresolved++;	  }	  ipkg_message(conf, IPKG_ERROR, "\n");	  if (! conf->force_depends) {	       ipkg_message(conf, IPKG_INFO,			    "This could mean that your package list is out of date or that the packages\n"			    "mentioned above do not yet exist (try 'ipkg update'). To proceed in spite\n"			    "of this problem try again with the '-force-depends' option.\n");	       pkg_vec_free(depends);	       return IPKG_PKG_DEPS_UNSATISFIED;	  }     }     if (ndepends <= 0) {	  pkg_vec_free(depends);	  return 0;     }     for (i = 0; i < depends->len; i++) {	  pkg_t *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)	      && (dep->state_want != SW_INSTALL)) {	       /* Mark packages as to-be-installed */	       dep->state_want = SW_INSTALL;	       /* Dependencies should be installed the same place as pkg */	       if (dep->dest == NULL) {		    dep->dest = pkg->dest;	       }	       err = pkg_mark_dependencies_for_installation(conf, dep, pkgs_needed);	       if (err) {		    pkg_vec_free(depends);		    return err;	       }	  }     }     if (pkgs_needed)	  pkg_vec_insert(pkgs_needed, pkg);     pkg_vec_free(depends);     return 0;}int name_mark_dependencies_for_installation(ipkg_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 IPKG_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 */	    ipkg_message(conf, IPKG_DEBUG, " Forcing downgrade ");             cmp = -1 ;                                       /* then we force ipkg 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 */          } 	  ipkg_message(conf, IPKG_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) {	       ipkg_message(conf, IPKG_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) {	       ipkg_message(conf, IPKG_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);}int satisfy_dependencies_for(ipkg_conf_t *conf, pkg_t *pkg){     int i, err;     pkg_vec_t *depends = pkg_vec_alloc();     pkg_t *dep;     char **unresolved = NULL;     int ndepends;     ndepends = pkg_hash_fetch_unsatisfied_dependencies(conf, 							pkg, depends, 							&unresolved);     if (unresolved) {	  ipkg_message(conf, IPKG_ERROR,		       "%s: Cannot satisfy the following dependencies for %s:\n\t",		       conf->force_depends ? "Warning" : "ERROR", pkg->name);	  while (*unresolved) {	       ipkg_message(conf, IPKG_ERROR, " %s", *unresolved);	       unresolved++;	  }	  ipkg_message(conf, IPKG_ERROR, "\n");	  if (! conf->force_depends) {	       ipkg_message(conf, IPKG_INFO,			    "This could mean that your package list is out of date or that the packages\n"			    "mentioned above do not yet exist (try 'ipkg update'). To proceed in spite\n"			    "of this problem try again with the '-force-depends' option.\n");	       pkg_vec_free(depends);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?