From a0f722565bcd0e09e959507d3fb3df5cc41adfe2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 28 Aug 2024 09:24:15 +0930 Subject: [PATCH] lightningd: fix up installs in subdirectories. Commit a1fdeee76b "Makefile: clean up install path handling." broke the ability to configure with one path and then run in a different path. Turns out people actually do this! So, we have to use relative paths, compared to our existing binary. And we can't use path_rel, because that requires that the path exist (thanks @Lagrang3!). Fixes: https://github.com/ElementsProject/lightning/issues/7595 Signed-off-by: Rusty Russell --- Makefile | 4 ++-- lightningd/lightningd.c | 44 +++++++++++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 43055ffa0e1d..d4551cf79b70 100644 --- a/Makefile +++ b/Makefile @@ -252,7 +252,7 @@ CPATH := /usr/local/include LIBRARY_PATH := /usr/local/lib endif -CPPFLAGS += -DCLN_NEXT_VERSION="\"$(CLN_NEXT_VERSION)\"" -DPKGLIBEXECDIR="\"$(pkglibexecdir)\"" -DPLUGINDIR="\"$(plugindir)\"" -DCCAN_TAL_NEVER_RETURN_NULL=1 +CPPFLAGS += -DCLN_NEXT_VERSION="\"$(CLN_NEXT_VERSION)\"" -DPKGLIBEXECDIR="\"$(pkglibexecdir)\"" -DBINDIR="\"$(bindir)\"" -DPLUGINDIR="\"$(plugindir)\"" -DCCAN_TAL_NEVER_RETURN_NULL=1 CFLAGS = $(CPPFLAGS) $(CWARNFLAGS) $(CDEBUGFLAGS) $(COPTFLAGS) -I $(CCANDIR) $(EXTERNAL_INCLUDE_FLAGS) -I . -I$(CPATH) $(SQLITE3_CFLAGS) $(POSTGRES_INCLUDE) $(FEATURES) $(COVFLAGS) $(DEV_CFLAGS) -DSHACHAIN_BITS=48 -DJSMN_PARENT_LINKS $(PIE_CFLAGS) $(COMPAT_CFLAGS) $(CSANFLAGS) # If CFLAGS is already set in the environment of make (to whatever value, it @@ -886,7 +886,7 @@ uninstall: installcheck: all-programs @rm -rf testinstall || true $(MAKE) DESTDIR=$$(pwd)/testinstall install - DEV_LIGHTNINGD_DESTDIR_PREFIX=$$(pwd)/testinstall/ testinstall$(bindir)/lightningd --test-daemons-only --lightning-dir=testinstall + testinstall$(bindir)/lightningd --test-daemons-only --lightning-dir=testinstall $(MAKE) DESTDIR=$$(pwd)/testinstall uninstall @if test `find testinstall '!' -type d | wc -l` -ne 0; then \ echo 'make uninstall left some files in testinstall directory!'; \ diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 8ed03a250033..1a05d16ffc75 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -530,11 +530,37 @@ static const char *find_my_directory(const tal_t *ctx, const char *argv0) return path_dirname(ctx, take(me)); } +/* How to get from abspath dir1 to abspath dir2? */ +static const char *relative(const tal_t *ctx, const char *dir1, const char *dir2) +{ + char **dir1_parts, **dir2_parts; + size_t common; + char *backwards; + + /* Collapse double /, and split into parts */ + dir1_parts = path_split(tmpctx, take(path_simplify(NULL, dir1))); + dir2_parts = path_split(tmpctx, take(path_simplify(NULL, dir2))); + + for (common = 0; + dir1_parts[common] + && dir2_parts[common] + && streq(dir1_parts[common], dir2_parts[common]); + common++); + + /* We append .. for every non-shared part in dir1_parts */ + for (size_t i = common; dir1_parts[i]; i++) + dir1_parts[i] = ".."; + + backwards = tal_strjoin(tmpctx, dir1_parts + common, PATH_SEP_STR, STR_TRAIL); + return tal_fmt(ctx, "%s%s", backwards, + tal_strjoin(tmpctx, dir2_parts + common, PATH_SEP_STR, STR_NO_TRAIL)); +} + /* Determine the correct daemon dir. */ static void find_subdaemons_and_plugins(struct lightningd *ld, const char *argv0) { const char *my_path = find_my_directory(tmpctx, argv0); - const char *prefix; + const char *rel; /* If we're running in-tree, all the subdaemons are with lightningd. */ if (has_all_subdaemons(my_path)) { @@ -547,14 +573,16 @@ static void find_subdaemons_and_plugins(struct lightningd *ld, const char *argv0 return; } - /* Assume we're running the installed version. Override - * for "make installccheck" though. */ - prefix = getenv("DEV_LIGHTNINGD_DESTDIR_PREFIX"); - if (!prefix) - prefix = ""; - ld->subdaemon_dir = tal_fmt(ld, "%s%s", prefix, PKGLIBEXECDIR); + /* OK, we're running the installed version? But we used to allow + * running in an arbitrary subtree, and people still do (plus, + * installcheck does this). So we use relative paths here. path_rel + * doesn't work if the paths don't exist, so we use our own function. */ + rel = relative(NULL, BINDIR, PKGLIBEXECDIR); + ld->subdaemon_dir = path_join(ld, my_path, take(rel)); + + rel = relative(NULL, BINDIR, PLUGINDIR); plugins_set_builtin_plugins_dir(ld->plugins, - tal_fmt(tmpctx, "%s%s", prefix, PLUGINDIR)); + path_join(tmpctx, my_path, take(rel))); } /*~ We like to free everything on exit, so valgrind doesn't complain (valgrind