ipkg_install.c
来自「this is the pkg installer for linux」· C语言 代码 · 共 1,943 行 · 第 1/5 页
C
1,943 行
response = get_user_response(" Configuration file '%s'\n" " ==> File on system created by you or by a script.\n" " ==> File also in package provided by package maintainer.\n" " What would you like to do about it ? Your options are:\n" " Y or I : install the package maintainer's version\n" " N or O : keep your currently-installed version\n" " D : show the differences between the versions (if diff is installed)\n" " The default action is to keep your current version.\n" " *** %s (Y/I/N/O/D) [default=N] ? ", file_name, short_file_name); if (strcmp(response, "y") == 0 || strcmp(response, "i") == 0 || strcmp(response, "yes") == 0) { free(response); return 0; } if (strcmp(response, "d") == 0) { char *cmd; free(response); /* XXX: BUG rewrite to use exec or busybox's internal diff */ sprintf_alloc(&cmd, "diff -u %s %s", backup, file_name); xsystem(cmd); free(cmd); printf(" [Press ENTER to continue]\n"); response = file_read_line_alloc(stdin); free(response); continue; } free(response); return 1; }}/* XXX: CLEANUP: I'd like to move all of the code for creating/cleaning pkg->tmp_unpack_dir directly into pkg.c. (Then, it would make sense to cleanup pkg->tmp_unpack_dir directly from pkg_deinit for example). */static int cleanup_temporary_files(ipkg_conf_t *conf, pkg_t *pkg){ DIR *tmp_dir; struct dirent *dirent; char *tmp_file;#ifdef IPKG_DEBUG_NO_TMP_CLEANUP#error ipkg_message(conf, IPKG_DEBUG, "%s: Not cleaning up %s since ipkg compiled with IPKG_DEBUG_NO_TMP_CLEANUP\n", __FUNCTION__, pkg->tmp_unpack_dir); return 0;#endif if (pkg->tmp_unpack_dir && file_is_dir(pkg->tmp_unpack_dir)) { tmp_dir = opendir(pkg->tmp_unpack_dir); if (tmp_dir) { while (1) { dirent = readdir(tmp_dir); if (dirent == NULL) { break; } sprintf_alloc(&tmp_file, "%s/%s", pkg->tmp_unpack_dir, dirent->d_name); if (! file_is_dir(tmp_file)) { unlink(tmp_file); } free(tmp_file); } closedir(tmp_dir); rmdir(pkg->tmp_unpack_dir); free(pkg->tmp_unpack_dir); pkg->tmp_unpack_dir = NULL; } } ipkg_message(conf, IPKG_INFO, "cleanup_temporary_files: pkg=%s local_filename=%s tmp_dir=%s\n", pkg->name, pkg->local_filename, conf->tmp_dir); if (pkg->local_filename && strncmp(pkg->local_filename, conf->tmp_dir, strlen(conf->tmp_dir)) == 0) { unlink(pkg->local_filename); free(pkg->local_filename); pkg->local_filename = NULL; } return 0;}static char *backup_filename_alloc(const char *file_name){ char *backup; sprintf_alloc(&backup, "%s%s", file_name, IPKG_BACKUP_SUFFIX); return backup;}int backup_make_backup(ipkg_conf_t *conf, const char *file_name){ int err; char *backup; backup = backup_filename_alloc(file_name); err = file_copy(file_name, backup); if (err) { ipkg_message(conf, IPKG_ERROR, "%s: Failed to copy %s to %s\n", __FUNCTION__, 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;}#ifdef CONFIG_IPKG_PROCESS_ACTIONSint ipkg_remove_packages(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove) { /* first, remove the packages that need removing */ for (i = 0 ; i < pkgs_to_remove->len; i++ ) { pkg_t *pkg = pkgs_to_remove->pkgs[i]; err = ipkg_remove_pkg(conf, pkg,0); if (err) return err; } return 0;}int ipkg_process_actions_sanity_check(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_superseded, pkg_vec_t *pkgs_to_install){ int i; /* now one more pass checking on the ones that need to be installed */ for (i = 0 ; i < pkgs_to_install->len; i++ ) { pkg_t *pkg = pkgs_to_install->pkgs[i]; if (pkg->dest == NULL) pkg->dest = conf->default_dest; pkg->state_want = SW_INSTALL; /* Abhaya: conflicts check */ err = check_conflicts_for(conf, pkg); if (err) { return err; } } return 0;}int ipkg_process_actions_unpack_packages(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_to_install){ int i; /* now one more pass checking on the ones that need to be installed */ for (i = 0 ; i < pkgs_to_install->len; i++ ) { pkg_t *pkg = pkgs_to_install->pkgs[i]; /* XXX: FEATURE: Need to really support Provides/Replaces: here at some point */ pkg_vec_t *replacees = pkg_vec_alloc(); pkg_get_installed_replacees(conf, pkg, replacees); /* XXX: BUG: we really should treat replacement more like an upgrade * Instead, we're going to remove the replacees */ err = pkg_remove_installed_replacees(conf, replacees); if (err) return err; pkg->state_flag |= SF_REMOVED_REPLACEES; } return 0;}int ipkg_process_actions_unpack_packages(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_to_install){ int i; /* now one more pass checking on the ones that need to be installed */ for (i = 0 ; i < pkgs_to_install->len; i++ ) { pkg_t *pkg = pkgs_to_install->pkgs[i]; if (pkg->local_filename == NULL) { err = ipkg_download_pkg(conf, pkg, conf->tmp_dir); if (err) { ipkg_message(conf, IPKG_ERROR, "Failed to download %s. Perhaps you need to run 'ipkg update'?\n", pkg->name); return err; } } if (pkg->tmp_unpack_dir == NULL) { err = unpack_pkg_control_files(conf, pkg); if (err) return err; } } return 0;}int ipkg_process_actions_prerm(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_install){ int i; /* now one more pass checking on the ones that need to be installed */ for (i = 0 ; i < pkgs_to_install->len; i++ ) { pkg_t *pkg = pkgs_to_install->pkgs[i]; pkg_t *old_pkg = pkg->old_pkg; err = prerm_upgrade_old_pkg(conf, pkg, old_pkg); if (err) return err; err = prerm_deconfigure_conflictors(conf, pkg, replacees); if (err) return err; err = preinst_configure(conf, pkg, old_pkg); if (err) return err; err = backup_modified_conffiles(conf, pkg, old_pkg); if (err) return err; err = postrm_upgrade_old_pkg(conf, pkg, old_pkg); if (err) return err; } return 0;}int ipkg_process_actions_install(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_install){ int i; /* now one more pass checking on the ones that need to be installed */ for (i = 0 ; i < pkgs_to_install->len; i++ ) { pkg_t *pkg = pkgs_to_install->pkgs[i]; pkg_t *old_pkg = pkg->old_pkg; if (old_pkg) { old_pkg->state_want = SW_DEINSTALL; if (old_pkg->state_flag & SF_NOPRUNE) { ipkg_message(conf, IPKG_INFO, " not removing obsolesced files because package marked noprune\n"); } else { ipkg_message(conf, IPKG_INFO, " removing obsolesced files\n"); remove_obsolesced_files(conf, pkg, old_pkg); } } ipkg_message(conf, IPKG_INFO, " installing maintainer scripts\n"); install_maintainer_scripts(conf, pkg, old_pkg); /* the following just returns 0 */ remove_disappeared(conf, pkg); ipkg_message(conf, IPKG_INFO, " installing data files\n"); install_data_files(conf, pkg); ipkg_message(conf, IPKG_INFO, " resolving conf files\n"); resolve_conffiles(conf, pkg); pkg->state_status = SS_UNPACKED; if (old_pkg) { old_pkg->state_status = SS_NOT_INSTALLED; } time(&pkg->installed_time); ipkg_message(conf, IPKG_INFO, " cleanup temp files\n"); cleanup_temporary_files(conf, pkg); if (pkg->parent) pkg->parent->state_status = pkg->state_status; } return 0;}int ipkg_process_actions_unwind_prerm(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_install){ int i; /* now one more pass checking on the ones that need to be installed */ for (i = 0 ; i < pkgs_to_install->len; i++ ) { pkg_t *pkg = pkgs_to_install->pkgs[i]; pkg_t *old_pkg = pkg->old_pkg; if (old_pkg) { if (old_pkg->state_flags & SF_POSTRM_UPGRADE) postrm_upgrade_old_pkg_unwind(conf, pkg, old_pkg); if (old_pkg->state_flags & SF_CHECK_DATA_FILE_CLASHES) check_data_file_clashes_unwind(conf, pkg, old_pkg); if (old_pkg->state_flags & SF_BACKUP_MODIFIED_CONFFILES) backup_modified_conffiles_unwind(conf, pkg, old_pkg); if (old_pkg->state_flags & SF_PREINST_CONFIGURE) preinst_configure_unwind(conf, pkg, old_pkg); if (old_pkg->state_flags & SF_DECONFIGURE_CONFLICTORS) prerm_deconfigure_conflictors_unwind(conf, pkg, replacees); if (old_pkg->state_flags & SF_PRERM_UPGRADE) prerm_upgrade_old_pkg_unwind(conf, pkg, old_pkg); if (old_pkg->state_flags & SF_REMOVED_REPLACEES) remove_installed_replacees_unwind(conf, pkg, old_pkg); } } return 0;}/* * Perform all the actions. * * pkgs_to_remove are packages marked for removal. * pkgs_superseded are the old packages being replaced by upgrades. * * Assumes pkgs_to_install includes all dependences, recursively, sorted in installable order. */int ipkg_process_actions(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_superseded, pkg_vec_t *pkgs_to_install){ int err; int i; err = ipkg_remove_packages(conf, pkgs_to_remove); if (err) return err; err = ipkg_process_actions_sanity_check(conf, pkgs_superseded, pkgs_to_install); if (err) return err; err = ipkg_process_actions_remove_replacees(conf, pkgs_to_install); if (err) goto UNWIND; /* @@@@ look at ipkg_install_pkg for handling replacements */ err = ipkg_process_actions_unpack_packages(conf, pkgs_to_install); if (err) goto UNWIND; /* * Now that we have the packages unpacked, we can look for data * file clashes. First, we mark the files from the superseded * packages as obsolete. Then we scan the files in * pkgs_to_install, and only complain about clashes with * non-obsolete files. */ err = ipkg_process_actions_check_data_file_clashes(conf, pkgs_superseded, pkgs_to_install); if (err) goto UNWIND; /* this was before checking data file clashes */ err = ipkg_process_actions_prerm(conf, pkgs_superseded, pkgs_to_install); if (err) goto UNWIND; /* point of no return: no unwinding after this */ err = ipkg_process_actions_install(conf, pkgs_to_install); if (err) return err; ipkg_message(conf, IPKG_INFO, "Done.\n"); return 0; UNWIND: ipkg_process_actions_unwind(conf, pkgs_to_install); ipkg_message(conf, IPKG_INFO, " cleanup temp files\n"); cleanup_temporary_files(conf, pkg); ipkg_message(conf, IPKG_INFO, "Failed.\n"); return err;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?