From 9d91ab906d427f87c5115211b11f0ebef364515c Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Fri, 21 May 2021 22:52:38 +0200 Subject: [PATCH 11/N] Core update --- lib/libalpm/alpm.h | 9 +++ lib/libalpm/package.c | 18 ++++++ lib/libalpm/sync.c | 25 +++++++ src/pacman/sighandler.c | 16 ++++- src/pacman/sync.c | 140 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 207 insertions(+), 1 deletion(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index e7fc7bb..ee7b97c 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -2852,6 +2852,15 @@ int alpm_trans_release(alpm_handle_t *handle); * @return 0 on success, -1 on error (pm_errno is set accordingly) */ int alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade); +#ifdef __MSYS__ +int alpm_sync_sysupgrade_core(alpm_handle_t *handle, int enable_downgrade); + +/** Informs whether a package is a core package. + * @param pkg the package to check + * @return non-zero if this is a core package, zero otherwise + */ +int alpm_pkg_is_core_package(const alpm_pkg_t *pkg); +#endif /** Add a package to the transaction. * If the package was loaded by alpm_pkg_load(), it will be freed upon diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index a294d63..eda22b1 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -900,3 +900,21 @@ int _alpm_pkg_check_meta(alpm_pkg_t *pkg) return error_found; } + +#ifdef __MSYS__ +int SYMEXPORT alpm_pkg_is_core_package(const alpm_pkg_t *pkg) +{ + if (pkg == NULL) + return 0; + return + strcmp(pkg->name, "bash") == 0 || + strcmp(pkg->name, "filesystem") == 0 || + strcmp(pkg->name, "mintty") == 0 || + strcmp(pkg->name, "msys2-runtime") == 0 || + strcmp(pkg->name, "msys2-runtime-devel") == 0 || + strncmp(pkg->name, "msys2-runtime-", + strlen("msys2-runtime-")) == 0 || + strcmp(pkg->name, "pacman") == 0 || + strcmp(pkg->name, "pacman-mirrors") == 0; +} +#endif diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 1653b4b..294a4b9 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -197,7 +197,13 @@ static alpm_list_t *check_replacers(alpm_handle_t *handle, alpm_pkg_t *lpkg, return replacers; } +/** Search for packages to upgrade and add them to the transaction. */ +#ifdef __MSYS__ +static +int SYMEXPORT do_alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade, int core_update) +#else int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) +#endif { alpm_list_t *i, *j; alpm_trans_t *trans; @@ -211,6 +217,13 @@ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) for(i = _alpm_db_get_pkgcache(handle->db_local); i; i = i->next) { alpm_pkg_t *lpkg = i->data; +#ifdef __MSYS__ + /* Skip regular packages in core update, and core packages in regular update */ + if(core_update != alpm_pkg_is_core_package(lpkg)) { + continue; + } +#endif + if(alpm_pkg_find(trans->remove, lpkg->name)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is marked for removal -- skipping\n", lpkg->name); continue; @@ -252,6 +265,18 @@ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) return 0; } +#ifdef __MSYS__ +int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) +{ + return do_alpm_sync_sysupgrade(handle, enable_downgrade, 0); +} + +int SYMEXPORT alpm_sync_sysupgrade_core(alpm_handle_t *handle, int enable_downgrade) +{ + return do_alpm_sync_sysupgrade(handle, enable_downgrade, 1); +} +#endif + alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs, const char *name) { diff --git a/src/pacman/sighandler.c b/src/pacman/sighandler.c index 3e869a3..fc2bac6 100644 --- a/src/pacman/sighandler.c +++ b/src/pacman/sighandler.c @@ -21,6 +21,10 @@ #include #include +#ifdef __MSYS__ +#include +#endif + #include #include "conf.h" @@ -53,8 +57,11 @@ static void _reset_handler(int signum) */ static void soft_interrupt_handler(int signum) { - console_cursor_move_end(); +#ifdef __MSYS__ + struct termios term; +#endif + console_cursor_move_end(); if(signum == SIGINT) { const char msg[] = "\nInterrupt signal received\n"; xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1); @@ -69,6 +76,13 @@ static void soft_interrupt_handler(int signum) return; } alpm_unlock(config->handle); +#ifdef __MSYS__ + /* restore input printing possibly disabled by core update */ + if(tcgetattr(STDIN_FILENO, &term) == 0) { + term.c_lflag |= ECHO; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); + } +#endif /* output a newline to be sure we clear any line we may be on */ xwrite(STDOUT_FILENO, "\n", 1); _Exit(128 + signum); diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 95340db..99712f4 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -28,6 +28,12 @@ #include #include +#ifdef __MSYS__ +#include +#include +#include +#endif + #include #include @@ -699,8 +705,134 @@ cleanup: return ret; } +#ifdef __MSYS__ + +/* Tries to kill all cygwin processes except this one */ +static int kill_all_other_msys_processes() { + DIR *dir; + struct dirent *ent; + char self_winpid[50]; + int found_one = 0; + FILE *self = NULL; + size_t proc_entries = 0; + char **args = NULL; + size_t pos = 0; + + self = fopen("/proc/self/winpid", "r"); + if (self == NULL) + return -1; + fscanf(self, "%s", self_winpid); + fclose(self); + + dir = opendir("/proc"); + if (dir == NULL) + return -1; + + while ((ent = readdir(dir))) + proc_entries++; + seekdir(dir, 0); + + args = alloca(sizeof(char *) * (2 + (proc_entries * 2) + 1)); + args[pos++] = "taskkill"; + args[pos++] = "/F"; + + while ((ent = readdir (dir))) { + FILE *fp = NULL; + char winpid_path[PATH_MAX]; + + strcpy(winpid_path, "/proc/"); + strcat(winpid_path, ent->d_name); + strcat(winpid_path, "/winpid"); + + fp = fopen(winpid_path, "r"); + if (fp != NULL) { + char winpid[50]; + fscanf(fp, "%s", winpid); + + if (strcmp(winpid, self_winpid) != 0) { + args[pos++] = "/pid"; + char *pidarg = alloca(strlen(winpid) + 1); + strcpy(pidarg, winpid); + args[pos++] = pidarg; + found_one = 1; + } + + fclose(fp); + } + } + args[pos] = NULL; + closedir(dir); + + if (!found_one) + return 0; + + setenv("MSYS2_ARG_CONV_EXCL", "*", 1); + if (execvp(args[0], args) == -1) { + return -1; + } + + return 0; +} + +static int core_update(int *needed) +{ + int retval; + alpm_list_t *i; + alpm_list_t *core = NULL; + + colon_printf(_("Starting core system upgrade...\n")); + alpm_logaction(config->handle, PACMAN_CALLER_PREFIX, + "starting core system upgrade\n"); + + if(alpm_sync_sysupgrade_core(config->handle, config->op_s_upgrade >= 2) == -1) { + pm_printf(ALPM_LOG_ERROR, "%s\n", alpm_strerror(alpm_errno(config->handle))); + trans_release(); + return 1; + } + + *needed = 0; + for(i = alpm_trans_get_add(config->handle); i; i = i->next) { + alpm_pkg_t *pkg = i->data; + if (alpm_pkg_is_core_package(pkg)) { + core = alpm_list_add(core, pkg); + *needed = 1; + } + } + + if(!(*needed)) { + if (!config->print) { + printf(_(" there is nothing to do\n")); + } + return 0; + } + + /* hooks are most likely doomed to fail in a core upgrade, so disable them */ + alpm_option_set_hookdirs(config->handle, NULL); + + config->handle->trans->add = core; + pm_printf(ALPM_LOG_WARNING, _("terminate other MSYS2 programs before proceeding\n")); + retval = sync_prepare_execute(); + if(retval == 0) { + int response = 0; + do { + response = yesno(_("To complete this update all MSYS2 processes including this terminal will be closed. Confirm to proceed")); + } while(!response); + + if (kill_all_other_msys_processes() != 0) { + pm_printf(ALPM_LOG_WARNING, _("terminating MSYS2 processes failed\n")); + exit(1); + } + exit(0); + } + return retval; +} +#endif + static int sync_trans(alpm_list_t *targets) { +#ifdef __MSYS__ + int found_core_updates = 0; +#endif int retval = 0; alpm_list_t *i; @@ -723,6 +855,14 @@ static int sync_trans(alpm_list_t *targets) } if(config->op_s_upgrade) { +#ifdef __MSYS__ + if((retval = core_update(&found_core_updates))) { + return retval; + } + if(found_core_updates) { + return retval; + } +#endif if(!config->print) { colon_printf(_("Starting full system upgrade...\n")); alpm_logaction(config->handle, PACMAN_CALLER_PREFIX,