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 + -
显示快捷键?