From a28046332f843bf615ea0154473be0a4c6e611f7 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Sun, 27 Jul 2014 11:24:49 +0200 Subject: [PATCH] Implemented support for pre-remove and post-install messages. Close #44 --- NEWS | 6 +++++ bin/xbps-create/main.c | 54 +++++++++++++++++++++++++++++++++++++ bin/xbps-install/state_cb.c | 3 +++ bin/xbps-remove/main.c | 3 +++ include/xbps.h.in | 8 ++++-- lib/package_configure.c | 41 +++++++++++++++++++++++++--- lib/package_remove.c | 36 ++++++++++++++++++++++++- 7 files changed, 145 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 3d6bfe3c..f8a05426 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,11 @@ xbps-0.38 (???): + * Implemented support for post-install and pre-remove messages, as explained + in issue #44 https://github.com/voidlinux/xbps/issues/44. + + xbps-create(8): will read the {INSTALL,REMOVE}.msg files and will add its contents + into the `{install,remove}-msg` data objects into its metadata plist file. + * xbps-install(8): added support to list packages that will be downloaded, if those were available in a remote repository and were not in the cache directory. diff --git a/bin/xbps-create/main.c b/bin/xbps-create/main.c index d710d665..0533a0b2 100644 --- a/bin/xbps-create/main.c +++ b/bin/xbps-create/main.c @@ -160,6 +160,54 @@ out: xbps_object_release(array); } +static void +process_file(const char *file, const char *key) +{ + void *blob; + FILE *f; + struct stat st; + size_t len; + xbps_data_t data; + + if ((f = fopen(file, "r")) == NULL) + return; + + if (fstat(fileno(f), &st) == -1) { + fclose(f); + die("lstat %s", file); + } + + if (S_ISREG(st.st_mode) == 0) { + fclose(f); + return; + } + + len = st.st_size; + + if ((blob = malloc(len)) == NULL) { + fclose(f); + die("malloc %s", file); + } + + if (fread(blob, len, 1, f) != len) { + if (ferror(f)) { + fclose(f); + die("fread %s", file); + } + } + fclose(f); + + if ((data = xbps_data_create_data(blob, len)) == NULL) + die("xbps_data_create_data %s", file); + + free(blob); + + if (!xbps_dictionary_set(pkg_propsd, key, data)) + die("xbps_dictionary_set %s", key); + + xbps_object_release(data); +} + static bool entry_is_conf_file(const char *file) { @@ -190,6 +238,8 @@ ftw_cb(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf _u /* Ignore metadata files generated by xbps-src and destdir */ if ((strcmp(fpath, ".") == 0) || + (strcmp(fpath, "./INSTALL.msg") == 0) || + (strcmp(fpath, "./REMOVE.msg") == 0) || (strcmp(fpath, "./props.plist") == 0) || (strcmp(fpath, "./files.plist") == 0) || (strcmp(fpath, "./flist") == 0) || @@ -754,6 +804,10 @@ main(int argc, char **argv) if (chdir(destdir) == -1) die("cannot chdir() to destdir %s:", destdir); + + /* Optional INSTALL/REMOVE messages */ + process_file("INSTALL.msg", "install-msg"); + process_file("REMOVE.msg", "remove-msg"); /* * Process XBPS_PKGFILES metadata file. */ diff --git a/bin/xbps-install/state_cb.c b/bin/xbps-install/state_cb.c index b6e27c45..78984938 100644 --- a/bin/xbps-install/state_cb.c +++ b/bin/xbps-install/state_cb.c @@ -133,6 +133,9 @@ state_cb(struct xbps_state_cb_data *xscd, void *cbdata _unused) printf("Fingerprint: %s\n", xscd->arg); rv = yesno("Do you want to import this public key?"); break; + case XBPS_STATE_SHOW_INSTALL_MSG: + printf("%s: post-install message:\n%s", xscd->arg, xscd->desc); + break; /* errors */ case XBPS_STATE_UNPACK_FAIL: case XBPS_STATE_UPDATE_FAIL: diff --git a/bin/xbps-remove/main.c b/bin/xbps-remove/main.c index 5f17a865..918055fb 100644 --- a/bin/xbps-remove/main.c +++ b/bin/xbps-remove/main.c @@ -91,6 +91,9 @@ state_cb_rm(struct xbps_state_cb_data *xscd, void *cbdata _unused) xscd->xhp->rootdir); } break; + case XBPS_STATE_SHOW_REMOVE_MSG: + printf("%s: pre-remove message:\n%s", xscd->arg, xscd->desc); + break; /* errors */ case XBPS_STATE_REMOVE_FAIL: xbps_error_printf("%s\n", xscd->desc); diff --git a/include/xbps.h.in b/include/xbps.h.in index 8fceb8d3..07d36730 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -48,7 +48,7 @@ * * This header documents the full API for the XBPS Library. */ -#define XBPS_API_VERSION "20140713" +#define XBPS_API_VERSION "20140727" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" @@ -276,6 +276,8 @@ extern "C" { * - XBPS_STATE_REPOSYNC_FAIL: syncing remote repositories has failed. * - XBPS_STATE_REPO_KEY_IMPORT: repository is signed and needs to import pubkey. * - XBPS_STATE_INVALID_DEP: package has an invalid dependency. + * - XBPS_STATE_SHOW_INSTALL_MSG: package must show a post-install message. + * - XBPS_STATE_SHOW_REMOVE_MSG: package must show a pre-remove message. */ typedef enum xbps_state { XBPS_STATE_UNKNOWN = 0, @@ -315,7 +317,9 @@ typedef enum xbps_state { XBPS_STATE_REPOSYNC_FAIL, XBPS_STATE_CONFIGURE_DONE, XBPS_STATE_REPO_KEY_IMPORT, - XBPS_STATE_INVALID_DEP + XBPS_STATE_INVALID_DEP, + XBPS_STATE_SHOW_INSTALL_MSG, + XBPS_STATE_SHOW_REMOVE_MSG } xbps_state_t; /** diff --git a/lib/package_configure.c b/lib/package_configure.c index 87d75025..82c18be1 100644 --- a/lib/package_configure.c +++ b/lib/package_configure.c @@ -81,7 +81,11 @@ xbps_configure_pkg(struct xbps_handle *xhp, bool update) { xbps_dictionary_t pkgd, pkgmetad; - char *pkgname, *plist; + xbps_data_t imsg; + FILE *f = NULL; + const void *data = NULL; + size_t len; + char *buf = NULL, *pkgname, *plist; int rv = 0; pkg_state_t state = 0; @@ -161,10 +165,41 @@ xbps_configure_pkg(struct xbps_handle *xhp, pkgver, strerror(rv)); return rv; } - xbps_object_release(pkgmetad); - if (rv == 0) xbps_set_cb_state(xhp, XBPS_STATE_CONFIGURE_DONE, 0, pkgver, NULL); + /* show install-msg if exists */ + imsg = xbps_dictionary_get(pkgmetad, "install-msg"); + if (xbps_object_type(imsg) != XBPS_TYPE_DATA) + goto out; + + data = xbps_data_data_nocopy(imsg); + len = xbps_data_size(imsg); + if ((f = fmemopen(__UNCONST(data), len, "r")) == NULL) { + rv = errno; + xbps_dbg_printf(xhp, "[configure] %s: fmemopen %s\n", pkgver, strerror(rv)); + goto out; + }; + buf = malloc(len); + assert(buf); + if (fread(buf, len, 1, f) != len) { + if (ferror(f)) { + rv = errno; + xbps_dbg_printf(xhp, "[configure] %s: fread %s\n", pkgver, strerror(rv)); + fclose(f); + free(buf); + goto out; + } + } + /* terminate buffer and notify client to show the post-install message */ + buf[len] = '\0'; + xbps_set_cb_state(xhp, XBPS_STATE_SHOW_INSTALL_MSG, 0, pkgver, "%s", buf); + fclose(f); + free(buf); + +out: + if (pkgmetad != NULL) + xbps_object_release(pkgmetad); + return rv; } diff --git a/lib/package_remove.c b/lib/package_remove.c index 18632092..14531564 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -256,9 +256,11 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update) if (state == XBPS_PKG_STATE_HALF_REMOVED) goto purge; /* - * Run the pre remove action. + * Run the pre remove action and show pre-remove message if exists. */ if (pkgd) { + xbps_data_t rmsg; + rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "pre", update); if (rv != 0) { @@ -269,6 +271,38 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update) pkgver, strerror(rv)); goto out; } + /* show remove-msg if exists */ + rmsg = xbps_dictionary_get(pkgd, "remove-msg"); + if (xbps_object_type(rmsg) == XBPS_TYPE_DATA) { + FILE *f; + const void *data; + char *buf; + size_t len; + + data = xbps_data_data_nocopy(rmsg); + len = xbps_data_size(rmsg); + if ((f = fmemopen(__UNCONST(data), len, "r")) == NULL) { + rv = errno; + xbps_dbg_printf(xhp, "[remove] %s: fmemopen %s\n", pkgver, strerror(rv)); + goto out; + }; + buf = malloc(len); + assert(buf); + if (fread(buf, len, 1, f) != len) { + if (ferror(f)) { + rv = errno; + xbps_dbg_printf(xhp, "[remove] %s: fread %s\n", pkgver, strerror(rv)); + free(buf); + fclose(f); + goto out; + } + } + /* terminate buffer and notify client to show the pre-remove message */ + buf[len] = '\0'; + xbps_set_cb_state(xhp, XBPS_STATE_SHOW_REMOVE_MSG, 0, pkgver, "%s", buf); + free(buf); + fclose(f); + } } /* * If updating a package, we just need to execute the current