From 63a92e72204f57f8e8b31a3fc4b7bb0bf375e0c5 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 24 Apr 2014 15:05:42 +0100 Subject: [PATCH] Add helpers for resolving path to resources in build tree Add virFileFindResource which will try to locate files in the local build tree if the calling binary (eg libvirtd or test suite) is being run from the build tree. The corresponding virFileActivateDirOverride should be called at startup passing in argv[0]. This will be examined for evidence of libtool magic binary prefix / sub-directory in order to activate the override. Signed-off-by: Daniel P. Berrange --- src/Makefile.am | 2 + src/libvirt_private.syms | 3 ++ src/util/virfile.c | 87 ++++++++++++++++++++++++++++++++++++++++ src/util/virfile.h | 14 +++++++ 4 files changed, 106 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 21d56fc74f..5fb9e88b03 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,6 +18,7 @@ # old automake does not provide abs_{src,build}dir variables abs_builddir = $(shell pwd) +abs_topbuilddir = $(shell cd .. && pwd) abs_srcdir = $(shell cd $(srcdir) && pwd) # No libraries with the exception of LIBXML should be listed @@ -30,6 +31,7 @@ INCLUDES = -I../gnulib/lib \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/util \ -DIN_LIBVIRT \ + -Dabs_topbuilddir="\"$(abs_topbuilddir)\"" \ $(GETTEXT_CPPFLAGS) AM_CFLAGS = $(LIBXML_CFLAGS) \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 4cee2eb06d..9919ca40f9 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1222,6 +1222,7 @@ virBuildPathInternal; virDirCreate; virFileAbsPath; virFileAccessibleAs; +virFileActivateDirOverride; virFileBuildPath; virFileClose; virFileDeleteTree; @@ -1230,6 +1231,8 @@ virFileExists; virFileFclose; virFileFdopen; virFileFindMountPoint; +virFileFindResource; +virFileFindResourceFull; virFileGetMountReverseSubtree; virFileGetMountSubtree; virFileHasSuffix; diff --git a/src/util/virfile.c b/src/util/virfile.c index cffcbc1b70..4e2ff32810 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -1542,6 +1542,93 @@ virFindFileInPath(const char *file) return fullpath; } + +static bool useDirOverride; + +/** + * virFileFindResourceFull: + * @filename: libvirt distributed filename without any path + * @prefix: optional string to prepend to filename + * @suffix: optional string to append to filename + * @builddir: location of the binary in the source tree build tree + * @installdir: location of the installed binary + * @envname: environment variable used to override all dirs + * + * A helper which will return a path to @filename within + * the current build tree, if the calling binary is being + * run from the source tree. Otherwise it will return the + * path in the installed location. + * + * If @envname is non-NULL it will override all other + * directory lookup + * + * Only use this with @filename files that are part of + * the libvirt tree, not 3rd party binaries/files. + * + * Returns the resolved path (caller frees) or NULL on error + */ +char * +virFileFindResourceFull(const char *filename, + const char *prefix, + const char *suffix, + const char *builddir, + const char *installdir, + const char *envname) +{ + char *ret = NULL; + const char *envval = envname ? virGetEnvBlockSUID(envname) : NULL; + + if (!prefix) + prefix = ""; + if (!suffix) + suffix = ""; + + if (envval) { + if (virAsprintf(&ret, "%s/%s%s%s", envval, prefix, filename, suffix) < 0) + return NULL; + } else if (useDirOverride) { + if (virAsprintf(&ret, "%s/%s/%s%s%s", abs_topbuilddir, builddir, prefix, filename, suffix) < 0) + return NULL; + } else { + if (virAsprintf(&ret, "%s/%s%s%s", installdir, prefix, filename, suffix) < 0) + return NULL; + } + + VIR_DEBUG("Resolved '%s' to '%s'", filename, ret); + return ret; +} + +char * +virFileFindResource(const char *filename, + const char *builddir, + const char *installdir) +{ + return virFileFindResourceFull(filename, NULL, NULL, builddir, installdir, NULL); +} + + +/** + * virFileActivateDirOverride: + * @argv0: argv[0] of the calling program + * + * Look at @argv0 and try to detect if running from + * a build directory, by looking for a 'lt-' prefix + * on the binary name, or '/.libs/' in the path + */ +void +virFileActivateDirOverride(const char *argv0) +{ + char *file = strrchr(argv0, '/'); + if (!file || file[1] == '\0') + return; + file++; + if (STRPREFIX(file, "lt-") || + strstr(argv0, "/.libs/")) { + useDirOverride = true; + VIR_DEBUG("Activating build dir override for %s", argv0); + } +} + bool virFileIsDir(const char *path) { diff --git a/src/util/virfile.h b/src/util/virfile.h index 46ef781479..5d0d6995d2 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -160,6 +160,20 @@ int virFileIsLink(const char *linkpath) char *virFindFileInPath(const char *file); +char *virFileFindResource(const char *filename, + const char *builddir, + const char *installdir) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +char *virFileFindResourceFull(const char *filename, + const char *prefix, + const char *suffix, + const char *builddir, + const char *installdir, + const char *envname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); +void virFileActivateDirOverride(const char *argv0) + ATTRIBUTE_NONNULL(1); + bool virFileIsDir (const char *file) ATTRIBUTE_NONNULL(1); bool virFileExists(const char *file) ATTRIBUTE_NONNULL(1); bool virFileIsExecutable(const char *file) ATTRIBUTE_NONNULL(1);