ipkg_install.c
来自「this is the pkg installer for linux」· C语言 代码 · 共 1,943 行 · 第 1/5 页
C
1,943 行
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; int clashes = 0; files_list = pkg_get_installed_files(pkg); for (iter = files_list->head; iter; iter = iter->next) { char *root_filename; char *filename = iter->data; root_filename = root_filename_alloc(conf, filename); if (file_exists(root_filename) && (! file_is_dir(root_filename))) { pkg_t *owner; pkg_t *obs; /* Pre-existing conffiles are OK */ /* @@@@ should have way to check that it is a conffile -Jamey */ if (backup_exists_for(root_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(conf, filename, pkg); continue; } owner = file_hash_get_file_owner(conf, 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) { ipkg_message(conf, IPKG_DEBUG2, "Checking for 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){ ipkg_message(conf, IPKG_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) { ipkg_message(conf, IPKG_INFO, "Pre-exiting file %s is obsolete. obs_pkg=%s\n", filename, obs->name); continue; } /* We have found a clash. */ ipkg_message(conf, IPKG_ERROR, "Package %s wants to install file %s\n" "\tBut that file is already provided by package ", pkg->name, filename); if (owner) { ipkg_message(conf, IPKG_ERROR, "%s\n", owner->name); } else { ipkg_message(conf, IPKG_ERROR, "<no package>\nPlease move this file out of the way and try again.\n"); } clashes++; } free(root_filename); } pkg_free_installed_files(pkg); return clashes;}static int check_data_file_clashes_change(ipkg_conf_t *conf, 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; int clashes = 0; files_list = pkg_get_installed_files(pkg); for (iter = files_list->head; iter; iter = iter->next) { char *root_filename; char *filename = iter->data; root_filename = root_filename_alloc(conf, filename); if (file_exists(root_filename) && (! file_is_dir(root_filename))) { pkg_t *owner; if (conf->force_overwrite) { /* but we need to change who owns this file */ file_hash_set_file_owner(conf, filename, pkg); continue; } owner = file_hash_get_file_owner(conf, filename); /* 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. */ ipkg_message(conf, IPKG_INFO, "Replacing pre-existing file %s owned by package %s\n", filename, owner->name); file_hash_set_file_owner(conf, filename, pkg); continue; } } } free(root_filename); } pkg_free_installed_files(pkg); return clashes;}static int check_data_file_clashes_unwind(ipkg_conf_t *conf, 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(ipkg_conf_t *conf, 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 */ return 0;}static int postrm_upgrade_old_pkg_unwind(ipkg_conf_t *conf, 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(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg){ int err; str_list_t *old_files; str_list_elt_t *of; str_list_t *new_files; str_list_elt_t *nf; if (old_pkg == NULL) { return 0; } old_files = pkg_get_installed_files(old_pkg); new_files = pkg_get_installed_files(pkg); for (of = old_files->head; of; of = of->next) { pkg_t *owner; char *old, *new; old = of->data; for (nf = new_files->head; nf; nf = nf->next) { new = nf->data; if (strcmp(old, new) == 0) { goto NOT_OBSOLETE; } } if (file_is_dir(old)) { continue; } owner = file_hash_get_file_owner(conf, old); if (owner != old_pkg) { /* in case obsolete file no longer belongs to old_pkg */ continue; } /* old file is obsolete */ ipkg_message(conf, IPKG_INFO, " removing obsolete file %s\n", old); if (!conf->noaction) { err = unlink(old); if (err) { ipkg_message(conf, IPKG_ERROR, " Warning: remove %s failed: %s\n", old, strerror(errno)); } } NOT_OBSOLETE: ; } pkg_free_installed_files(old_pkg); pkg_free_installed_files(pkg); return 0;}static int remove_obsolete_maintainer_scripts(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg){ int i; int err = 0; char *globpattern; glob_t globbuf; if (0) { if (!pkg->dest) { ipkg_message(conf, IPKG_ERROR, "%s: no dest for package %s\n", __FUNCTION__, pkg->name); return -1; } sprintf_alloc(&globpattern, "%s/%s.*", pkg->dest->info_dir, pkg->name); err = glob(globpattern, 0, NULL, &globbuf); free(globpattern); if (err) { return err; } /* XXXX this should perhaps only remove the ones that are not overwritten in new package. Jamey 11/11/2003 */ for (i = 0; i < globbuf.gl_pathc; i++) { ipkg_message(conf, IPKG_DEBUG, "Removing control file %s from old_pkg %s\n", globbuf.gl_pathv[i], old_pkg->name); if (!conf->noaction) unlink(globbuf.gl_pathv[i]); } globfree(&globbuf); } return err;}static int install_maintainer_scripts(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg){ int ret; char *prefix; if (old_pkg) remove_obsolete_maintainer_scripts(conf, pkg, old_pkg); 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(ipkg_conf_t *conf, 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(ipkg_conf_t *conf, pkg_t *pkg){ int err; /* ipkg 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. */ ipkg_message(conf, IPKG_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; } /* XXX: BUG or FEATURE : We are actually loosing the Essential flag, so we can't save ourself from removing important packages At this point we (should) have extracted the .control file, so it would be a good idea to reload the data in it, and set the Essential state in *pkg. From now on the Essential is back in status file and we can protect again. We should operate this way: fopen the file ( pkg->dest->root_dir/pkg->name.control ) check for "Essential" in it set the value in pkg->essential. This new routine could be useful also for every other flag Pigi: 16/03/2004 */ set_flags_from_control(conf, pkg) ; ipkg_message(conf, IPKG_DEBUG, " Calling pkg_write_filelist from %s\n", __FUNCTION__); err = pkg_write_filelist(conf, pkg); if (err) return err; /* XXX: FEATURE: ipkg 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 ipkg to install a clashing package with a user force. */ return 0;}static int resolve_conffiles(ipkg_conf_t *conf, pkg_t *pkg){ conffile_list_elt_t *iter; conffile_t *cf; char *cf_backup; char *md5sum; if (conf->noaction) return 0; for (iter = pkg->conffiles.head; iter; iter = iter->next) { char *root_filename; cf = iter->data; root_filename = root_filename_alloc(conf, cf->name); /* Might need to initialize the md5sum for each conffile */ if (cf->value == NULL) { cf->value = file_md5sum_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 */ md5sum = file_md5sum_alloc(cf_backup); if (strcmp( cf->value,md5sum) != 0 ) { if (conf->force_defaults || user_prefers_old_conffile(cf->name, cf_backup) ) { rename(cf_backup, root_filename); } } unlink(cf_backup); free(md5sum); } free(cf_backup); free(root_filename); } return 0;}static int user_prefers_old_conffile(const char *file_name, const char *backup){ char *response; const char *short_file_name; short_file_name = strrchr(file_name, '/'); if (short_file_name) { short_file_name++; } else { short_file_name = file_name; } while (1) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?