From 9e2c00ee8b487a1873656af84cc1c2b29e48015e Mon Sep 17 00:00:00 2001 From: Juan RP Date: Fri, 17 May 2019 08:19:21 +0200 Subject: [PATCH] libxbps: remove dangling symlinks properly. This fixes removal of packages that contain multiple levels of dangling symlinks, i.e faenza-icon-theme and probably others. Close #23 --- lib/package_remove.c | 5 ++- lib/util.c | 45 +++++++++++++------------ tests/xbps/libxbps/shell/remove_test.sh | 3 ++ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/package_remove.c b/lib/package_remove.c index 7e3dd54f..3b342e2e 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -190,7 +190,10 @@ remove_pkg_files(struct xbps_handle *xhp, bool found; xbps_dictionary_get_cstring_nocopy(obj, "file", &file); - snprintf(path, sizeof(path), "%s/%s", xhp->rootdir, file); + if (strcmp(xhp->rootdir, "/") == 0) + snprintf(path, sizeof(path), "%s", file); + else + snprintf(path, sizeof(path), "%s%s", xhp->rootdir, file); if ((strcmp(key, "files") == 0) || (strcmp(key, "conf_files") == 0)) { diff --git a/lib/util.c b/lib/util.c index b0acbc91..bfe71ceb 100644 --- a/lib/util.c +++ b/lib/util.c @@ -498,7 +498,7 @@ char * xbps_symlink_target(struct xbps_handle *xhp, const char *path, const char *tgt) { struct stat sb; - char *res = NULL, *lnk = NULL; + char *res = NULL, *lnk = NULL, *p = NULL, *dname = NULL; ssize_t r; if (lstat(path, &sb) == -1) @@ -522,38 +522,41 @@ xbps_symlink_target(struct xbps_handle *xhp, const char *path, const char *tgt) return lnk; } - if (strstr(lnk, "./") || lnk[0] != '/') { - char *p, *p1, *dname, buf[PATH_MAX]; - /* relative */ + if (strstr(lnk, "./")) { + /* contains references to relative paths */ + p = realpath(path, NULL); + if (p == NULL) { + /* dangling symlink, use target */ + return strdup(tgt); + } + if (strcmp(xhp->rootdir, "/") == 0) { + res = p; + } else { + res = strdup(p + strlen(xhp->rootdir)); + free(p); + } + free(lnk); + } else if (lnk[0] != '/') { + /* relative path */ p = strdup(path); assert(p); dname = dirname(p); assert(dname); - snprintf(buf, sizeof(buf), "%s/%s", dname, lnk); - free(p); - p = xbps_sanitize_path(buf); - assert(p); - if ((strstr(p, "./")) && (p1 = realpath(p, NULL))) { - if (strcmp(xhp->rootdir, "/") == 0) { - res = strdup(p1); - } else { - res = strdup(p1 + strlen(xhp->rootdir)); - } - free(p1); + if (strcmp(xhp->rootdir, "/") == 0) { + res = xbps_xasprintf("%s/%s", dname, lnk); } else { - if (strcmp(xhp->rootdir, "/") == 0) { - res = strdup(p); - } else { - res = strdup(p + strlen(xhp->rootdir)); - } + char *p1 = strdup(dname + strlen(xhp->rootdir)); + assert(p1); + res = xbps_xasprintf("%s/%s", p1, lnk); + free(p1); } - assert(res); free(lnk); free(p); } else { /* absolute */ res = lnk; } + assert(res); return res; } diff --git a/tests/xbps/libxbps/shell/remove_test.sh b/tests/xbps/libxbps/shell/remove_test.sh index abc55371..a97c62bf 100644 --- a/tests/xbps/libxbps/shell/remove_test.sh +++ b/tests/xbps/libxbps/shell/remove_test.sh @@ -85,6 +85,9 @@ remove_symlinks_dangling_body() { touch -f pkg_A/usr/lib/libfoo.so.1.2.0 ln -sf libfoo.so.2 pkg_A/usr/lib/libfoo.so.1 ln -sf libfoo.so.2 pkg_B/usr/lib/libfoo.so + ln -s ./libfoo.so pkg_B/usr/lib/libfoo.so.3 + ln -s ./libfoo.so.4 pkg_B/usr/lib/libfoo.so.3 + ln -s ../../../libfoo.so.4 pkg_B/usr/lib/libfoo.so.3 cd some_repo xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A