From 05f879ec098fbd53f2bc7b19e05158a91830a6db Mon Sep 17 00:00:00 2001 From: Juan RP Date: Thu, 19 Feb 2015 09:47:09 +0100 Subject: [PATCH] Introduce xbps_symlink_target() and use it in two places. This code is now shared by xbps-pkgdb and libxbps/xbps-remove. --- bin/xbps-pkgdb/check_pkg_symlinks.c | 94 ++--------------------------- include/xbps.h.in | 15 ++++- lib/package_remove.c | 56 +---------------- lib/util.c | 61 ++++++++++++++++++- 4 files changed, 78 insertions(+), 148 deletions(-) diff --git a/bin/xbps-pkgdb/check_pkg_symlinks.c b/bin/xbps-pkgdb/check_pkg_symlinks.c index c5cb089b..9a9c4397 100644 --- a/bin/xbps-pkgdb/check_pkg_symlinks.c +++ b/bin/xbps-pkgdb/check_pkg_symlinks.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011-2014 Juan Romero Pardines. + * Copyright (c) 2011-2015 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,53 +46,6 @@ * returns 0 if test ran successfully, 1 otherwise and -1 on error. */ -static char * -symlink_target(struct xbps_handle *xhp, const char *path) -{ - struct stat sb; - char *lnk, *res; - ssize_t r; - - if (lstat(path, &sb) == -1) - return NULL; - - lnk = malloc(sb.st_size + 1); - assert(lnk); - - r = readlink(path, lnk, sb.st_size + 1); - if (r < 0 || r > sb.st_size) { - free(lnk); - return NULL; - } - lnk[sb.st_size] = '\0'; - if (lnk[0] != '/') { - char tpath[PATH_MAX], *p, *dname; - - /* relative */ - p = strdup(path); - assert(p); - dname = dirname(p); - assert(dname); - snprintf(tpath, sizeof(tpath), "%s/%s", dname, lnk); - free(p); - if ((res = realpath(tpath, NULL)) == NULL) { - free(lnk); - return NULL; - } - if (strcmp(xhp->rootdir, "/") == 0) - p = strdup(res); - else - p = strdup(res + strlen(xhp->rootdir)); - free(res); - res = p; - free(lnk); - } else { - /* absolute */ - res = lnk; - } - return res; -} - int check_pkg_symlinks(struct xbps_handle *xhp, const char *pkgname, void *arg) { @@ -107,7 +60,7 @@ check_pkg_symlinks(struct xbps_handle *xhp, const char *pkgname, void *arg) for (unsigned int i = 0; i < xbps_array_count(array); i++) { const char *file = NULL, *tgt = NULL; - char path[PATH_MAX], *lnk = NULL, *tlnk = NULL; + char path[PATH_MAX], *lnk = NULL; obj = xbps_array_get(array, i); if (!xbps_dictionary_get_cstring_nocopy(obj, "file", &file)) @@ -124,55 +77,18 @@ check_pkg_symlinks(struct xbps_handle *xhp, const char *pkgname, void *arg) continue; } snprintf(path, sizeof(path), "%s/%s", xhp->rootdir, file); - if ((lnk = symlink_target(xhp, path)) == NULL) { + if ((lnk = xbps_symlink_target(xhp, path)) == NULL) { xbps_error_printf("%s: broken symlink %s (target: %s)\n", pkgname, file, tgt); broken = true; continue; } - if (tgt[0] != '/') { - char *p, *p1, *dname; - - p = strdup(file); - assert(p); - dname = dirname(p); - assert(dname); - snprintf(path, sizeof(path), "%s/%s", dname, tgt); - p1 = realpath(path, NULL); - free(p); - if (p1 == NULL) { - xbps_error_printf("%s: failed to realpath %s: %s\n", - pkgname, file, strerror(errno)); - free(lnk); - continue; - } - if (strcmp(xhp->rootdir, "/") == 0) - tlnk = strdup(p1); - else - tlnk = strdup(p1 + strlen(xhp->rootdir)); - free(p1); - } else { - char *p; - - snprintf(path, sizeof(path), "%s/%s", xhp->rootdir, tgt); - if ((p = realpath(path, NULL))) { - if (strcmp(xhp->rootdir, "/") == 0) - tlnk = strdup(p); - else - tlnk = strdup(p + strlen(xhp->rootdir)); - free(p); - } else { - tlnk = strdup(tgt); - } - } - /* absolute */ - if (strcmp(lnk, tlnk)) { + if (strcmp(lnk, tgt)) { xbps_warn_printf("%s: modified symlink %s " "points to %s (shall be %s)\n", - pkgname, file, lnk, tlnk); + pkgname, file, lnk, tgt); broken = true; } free(lnk); - free(tlnk); } return broken; } diff --git a/include/xbps.h.in b/include/xbps.h.in index 712d9522..6a5de397 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 "20150218" +#define XBPS_API_VERSION "20150219" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" @@ -1937,11 +1937,24 @@ char *xbps_pubkey2fp(struct xbps_handle *xhp, xbps_data_t pubkey); * Returns a buffer with a sanitized path from \a src. * This removes multiple slashes. * + * @param[in] src A path. + * * @return The sanitized path in a buffer. * The returned buffer must be free(3)d when it's no longer necessary. */ char *xbps_sanitize_path(const char *src); +/** + * Returns a sanitized target file of \a path without the rootdir component. + * + * @param[in] xhp The pointer to an xbps_handle struct. + * @param[in] path A path to a filename. + * + * @return The sanitized path in a buffer. + * The returned buffer must be free(3)d when it's no longer necessary. + */ +char *xbps_symlink_target(struct xbps_handle *xhp, const char *path); + /*@}*/ #ifdef __cplusplus diff --git a/lib/package_remove.c b/lib/package_remove.c index 0b586e8b..e8aa5b2a 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -92,60 +92,6 @@ check_remove_pkg_files(struct xbps_handle *xhp, return fail; } -static char * -symlink_target(struct xbps_handle *xhp, const char *path) -{ - struct stat sb; - char *p, *p1, *dname, *lnk, *res = NULL; - ssize_t r; - - if (lstat(path, &sb) == -1) - return NULL; - - lnk = malloc(sb.st_size + 1); - assert(lnk); - - r = readlink(path, lnk, sb.st_size + 1); - if (r < 0 || r > sb.st_size) { - free(lnk); - return NULL; - } - lnk[sb.st_size] = '\0'; - if (strstr(lnk, "./") || lnk[0] != '/') { - /* relative */ - p = strdup(path); - assert(p); - dname = dirname(p); - assert(dname); - p = xbps_xasprintf("%s/%s", dname, lnk); - assert(p); - p1 = xbps_sanitize_path(p); - assert(p1); - free(p); - if ((strstr(p1, "./")) && (p = realpath(p1, NULL))) { - if (strcmp(xhp->rootdir, "/") == 0) - res = strdup(p); - else - res = strdup(p + strlen(xhp->rootdir)); - - free(p); - } - if (res == NULL) { - if (strcmp(xhp->rootdir, "/") == 0) - res = strdup(p1); - else - res = strdup(p1 + strlen(xhp->rootdir)); - } - assert(res); - free(lnk); - free(p1); - } else { - /* absolute */ - res = lnk; - } - return res; -} - static int remove_pkg_files(struct xbps_handle *xhp, xbps_dictionary_t dict, @@ -265,7 +211,7 @@ remove_pkg_files(struct xbps_handle *xhp, const char *target = NULL; char *lnk; - lnk = symlink_target(xhp, path); + lnk = xbps_symlink_target(xhp, path); if (lnk == NULL) { xbps_dbg_printf(xhp, "[remove] %s " "symlink_target: %s\n", path, strerror(errno)); diff --git a/lib/util.c b/lib/util.c index 72b8e7d1..dc423372 100644 --- a/lib/util.c +++ b/lib/util.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "xbps_api_impl.h" @@ -314,9 +315,8 @@ xbps_pkg_has_rundeps(xbps_dictionary_t pkgd) } bool -xbps_pkg_arch_match(struct xbps_handle *xhp, - const char *orig, - const char *target) +xbps_pkg_arch_match(struct xbps_handle *xhp, const char *orig, + const char *target) { const char *arch; @@ -452,3 +452,58 @@ xbps_sanitize_path(const char *src) return dest; } + +char * +xbps_symlink_target(struct xbps_handle *xhp, const char *path) +{ + struct stat sb; + char *p, *p1, *dname, *res = NULL, *lnk = NULL; + ssize_t r; + + if (lstat(path, &sb) == -1) + return NULL; + + lnk = malloc(sb.st_size + 1); + assert(lnk); + + r = readlink(path, lnk, sb.st_size + 1); + if (r < 0 || r > sb.st_size) { + free(lnk); + return NULL; + } + lnk[sb.st_size] = '\0'; + if (strstr(lnk, "./") || lnk[0] != '/') { + /* relative */ + p = strdup(path); + assert(p); + dname = dirname(p); + assert(dname); + p = xbps_xasprintf("%s/%s", dname, lnk); + assert(p); + p1 = xbps_sanitize_path(p); + assert(p1); + free(p); + if ((strstr(p1, "./")) && (p = realpath(p1, NULL))) { + if (strcmp(xhp->rootdir, "/") == 0) + res = strdup(p); + else + res = strdup(p + strlen(xhp->rootdir)); + + free(p); + } + if (res == NULL) { + if (strcmp(xhp->rootdir, "/") == 0) + res = strdup(p1); + else + res = strdup(p1 + strlen(xhp->rootdir)); + } + assert(res); + free(lnk); + free(p1); + } else { + /* absolute */ + res = lnk; + } + + return res; +}