ipkg_install.c

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

C
1,943
字号
	       return IPKG_PKG_DEPS_UNSATISFIED;	  }     }     if (ndepends <= 0) {	  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)) {               ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);	       err = ipkg_install_pkg(conf, dep,0);	       if (err) {		    pkg_vec_free(depends);		    return err;	       }	  }     }     pkg_vec_free(depends);     return 0;}/* check all packages have their dependences satisfied, e.g., in case an upgraded package split */ int ipkg_satisfy_all_dependences(ipkg_conf_t *conf){     if (conf->nodeps == 0) {	  int i;	  pkg_vec_t *installed = pkg_vec_alloc();	  pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);	  for (i = 0; i < installed->len; i++) {	       pkg_t *pkg = installed->pkgs[i];	       satisfy_dependencies_for(conf, pkg);	  }	  pkg_vec_free(installed);     }     return 0;}static int check_conflicts_for(ipkg_conf_t *conf, pkg_t *pkg){     int i;     pkg_vec_t *conflicts = NULL;     int level;     const char *prefix;     if (conf->force_depends) {	  level = IPKG_NOTICE;	  prefix = "Warning";     } else {	  level = IPKG_ERROR;	  prefix = "ERROR";     }     if (!conf->force_depends)	  conflicts = (pkg_vec_t *)pkg_hash_fetch_conflicts(&conf->pkg_hash, pkg);     if (conflicts) {	  ipkg_message(conf, level,		       "%s: The following packages conflict with %s:\n\t", prefix, pkg->name);	  i = 0;	  while (i < conflicts->len)	       ipkg_message(conf, level, " %s", conflicts->pkgs[i++]->name);	  ipkg_message(conf, level, "\n");	  pkg_vec_free(conflicts);	  return IPKG_PKG_DEPS_UNSATISFIED;     }     return 0;}static int update_file_ownership(ipkg_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;     for (iter = new_list->head; iter; iter = iter->next) {	  char *new_file = iter->data;	  pkg_t *owner = file_hash_get_file_owner(conf, new_file);	  if (!new_file)	       ipkg_message(conf, IPKG_ERROR, "Null new_file for new_pkg=%s\n", new_pkg->name);	  if (!owner || (owner == old_pkg))	       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;	       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);	       }	  }     }     return 0;}static int verify_pkg_installable(ipkg_conf_t *conf, pkg_t *pkg){    /* XXX: FEATURE: Anything else needed here? Maybe a check on free space? */    /* sma 6.20.02:  yup; here's the first bit */    /*      * 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.     * 3) return a proper error code instead of 1     */     int comp_size, blocks_available;         if (!conf->force_space && pkg->installed_size != NULL) {	  blocks_available = get_available_blocks(conf->default_dest->root_dir);	  comp_size = strtoul(pkg->installed_size, NULL, 0);	  /* round up a blocks count without doing fancy-but-slow casting jazz */ 	  comp_size = (int)((comp_size + 1023) / 1024);	  if (comp_size >= blocks_available) {	       ipkg_message(conf, IPKG_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);	       return ENOSPC;	  }     }     return 0;}static int unpack_pkg_control_files(ipkg_conf_t *conf, pkg_t *pkg){     int err;     char *conffiles_file_name;     char *root_dir;     FILE *conffiles_file;     sprintf_alloc(&pkg->tmp_unpack_dir, "%s/%s-XXXXXX", conf->tmp_dir, pkg->name);     pkg->tmp_unpack_dir = mkdtemp(pkg->tmp_unpack_dir);     if (pkg->tmp_unpack_dir == NULL) {	  ipkg_message(conf, IPKG_ERROR,		       "%s: Failed to create temporary directory '%s': %s\n",		       __FUNCTION__, pkg->tmp_unpack_dir, strerror(errno));	  return errno;     }     err = pkg_extract_control_files_to_dir(pkg, 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 */     if (pkg->conffiles.head) {	  return 0;     }     sprintf_alloc(&conffiles_file_name, "%s/conffiles", pkg->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) {	  fprintf(stderr, "%s: failed to open %s: %s\n",		  __FUNCTION__, conffiles_file_name, strerror(errno));	  free(conffiles_file_name);	  return errno;     }     free(conffiles_file_name);     while (1) {	  char *cf_name;	  char *cf_name_in_dest;	  cf_name = file_read_line_alloc(conffiles_file);	  if (cf_name == NULL) {	       break;	  }	  str_chomp(cf_name);	  if (cf_name[0] == '\0') {	       continue;	  }	  /* 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(&pkg->conffiles, cf_name_in_dest, NULL);	  free(cf_name);	  free(cf_name_in_dest);     }     fclose(conffiles_file);     return 0;}/* returns number of installed replacees */int pkg_get_installed_replacees(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *installed_replacees){     abstract_pkg_t **replaces = pkg->replaces;     int replaces_count = pkg->replaces_count;     int i, j;     for (i = 0; i < replaces_count; i++) {	  abstract_pkg_t *ab_pkg = replaces[i];	  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;}int pkg_remove_installed_replacees(ipkg_conf_t *conf, 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 = ipkg_remove_pkg(conf, replacee,0);	  if (err)	       return err;     }     return 0;}/* to unwind the removal: make sure they are installed */int pkg_remove_installed_replacees_unwind(ipkg_conf_t *conf, 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) {               ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);	       err = ipkg_install_pkg(conf, replacee,0);	       if (err)		    return err;	  }     }     return 0;}int caught_sigint = 0;static void ipkg_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 ipkg_install_check_downgrade(ipkg_conf_t *conf, 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 ipkg 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) {	       ipkg_message(conf, IPKG_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) {	       ipkg_message(conf, IPKG_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->force_reinstall) {		    ipkg_message(conf, IPKG_NOTICE,				 "Reinstalling %s (%s) on %s...\n",				 pkg->name, new_version, old_pkg->dest->name);		    pkg->dest = old_pkg->dest;		    rc = 0;	       } else {		    ipkg_message(conf, IPKG_NOTICE,				 "Not installing %s (%s) on %s -- already installed.\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);      	  ipkg_message(conf, IPKG_NOTICE,		       "%s%s (%s) to %s...\n", message_out,		       pkg->name, version, pkg->dest->name);	  free(version);	  return 0;     }}/* and now the meat... */int ipkg_install_pkg(ipkg_conf_t *conf, 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;     char* file_md5;         if ( from_upgrade )         message = 1;            /* Coming from an upgrade, and should change the output message */     if (!pkg) {	  ipkg_message(conf, IPKG_ERROR,		       "INTERNAL ERROR: null pkg passed to ipkg_install_pkg\n");	  return -EINVAL;     }     ipkg_message(conf, IPKG_DEBUG2, "Function: %s calling pkg_arch_supported %s \n", __FUNCTION__, __FUNCTION__);     if (!pkg_arch_supported(conf, pkg)) {	  ipkg_message(conf, IPKG_ERROR, "INTERNAL ERROR: architecture %s for pkg %s is unsupported.\n",		       pkg->architecture, pkg->name);	  return -EINVAL;     }     if (pkg->state_status == SS_INSTALLED && conf->force_reinstall == 0 && conf->nodeps == 0) {	  err = satisfy_dependencies_for(conf, pkg);	  if (err) { return err; }	  ipkg_message(conf, IPKG_NOTICE,		       "Package %s is already installed in %s.\n", 		       pkg->name, pkg->dest->name);	  return 0;     }

⌨️ 快捷键说明

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