diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 1a05d16ffc75..f76344310311 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -547,13 +547,22 @@ static const char *relative(const tal_t *ctx, const char *dir1, const char *dir2 && 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)); + if (streq(dir1_parts[0], "/")) + backwards = ""; + else{ + /* 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); + } + /* We put some extra characters so that we don't send an empty string to + * path_simplify. */ + return path_simplify(ctx, + tal_fmt(tmpctx, "./%s%s/.", backwards, + tal_strjoin(tmpctx, dir2_parts + common, + PATH_SEP_STR, STR_NO_TRAIL))); } /* Determine the correct daemon dir. */ diff --git a/lightningd/test/run-find_plugins_path.c b/lightningd/test/run-find_plugins_path.c new file mode 100644 index 000000000000..6d6378bc0590 --- /dev/null +++ b/lightningd/test/run-find_plugins_path.c @@ -0,0 +1,349 @@ +#include "config.h" +#define main unused_main +int unused_main(int argc, char *argv[]); +#include "../io_loop_with_timers.c" +#include "../lightningd.c" +#include "../subd.c" +#include + +/* AUTOGENERATED MOCKS START */ +/* Generated stub for begin_topology */ +void begin_topology(struct chain_topology *topo UNNEEDED) +{ fprintf(stderr, "begin_topology called!\n"); abort(); } +/* Generated stub for channel_gossip_notify_new_block */ +void channel_gossip_notify_new_block(struct lightningd *ld UNNEEDED, + u32 block_height UNNEEDED) +{ fprintf(stderr, "channel_gossip_notify_new_block called!\n"); abort(); } +/* Generated stub for channel_notify_new_block */ +void channel_notify_new_block(struct lightningd *ld UNNEEDED, + u32 block_height UNNEEDED) +{ fprintf(stderr, "channel_notify_new_block called!\n"); abort(); } +/* Generated stub for connectd_activate */ +void connectd_activate(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "connectd_activate called!\n"); abort(); } +/* Generated stub for connectd_init */ +int connectd_init(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "connectd_init called!\n"); abort(); } +/* Generated stub for connectd_start_shutdown */ +void connectd_start_shutdown(struct subd *connectd UNNEEDED) +{ fprintf(stderr, "connectd_start_shutdown called!\n"); abort(); } +/* Generated stub for daemon_developer_mode */ +bool daemon_developer_mode(char *argv[]) +{ fprintf(stderr, "daemon_developer_mode called!\n"); abort(); } +/* Generated stub for daemon_poll */ +int daemon_poll(struct pollfd *fds UNNEEDED, nfds_t nfds UNNEEDED, int timeout UNNEEDED) +{ fprintf(stderr, "daemon_poll called!\n"); abort(); } +/* Generated stub for daemon_setup */ +void daemon_setup(const char *argv0 UNNEEDED, + void (*backtrace_print)(const char *fmt UNNEEDED, ...) UNNEEDED, + void (*backtrace_exit)(void)) +{ fprintf(stderr, "daemon_setup called!\n"); abort(); } +/* Generated stub for daemon_shutdown */ +void daemon_shutdown(void) +{ fprintf(stderr, "daemon_shutdown called!\n"); abort(); } +/* Generated stub for db_begin_transaction_ */ +void db_begin_transaction_(struct db *db UNNEEDED, const char *location UNNEEDED) +{ fprintf(stderr, "db_begin_transaction_ called!\n"); abort(); } +/* Generated stub for db_commit_transaction */ +void db_commit_transaction(struct db *db UNNEEDED) +{ fprintf(stderr, "db_commit_transaction called!\n"); abort(); } +/* Generated stub for db_get_intvar */ +s64 db_get_intvar(struct db *db UNNEEDED, const char *varname UNNEEDED, s64 defval UNNEEDED) +{ fprintf(stderr, "db_get_intvar called!\n"); abort(); } +/* Generated stub for db_in_transaction */ +bool db_in_transaction(struct db *db UNNEEDED) +{ fprintf(stderr, "db_in_transaction called!\n"); abort(); } +/* Generated stub for deprecated_ok_ */ +bool deprecated_ok_(bool deprecated_apis UNNEEDED, + const char *feature UNNEEDED, + const char *start UNNEEDED, + const char *end UNNEEDED, + const char **begs UNNEEDED, + void (*complain)(const char *feat UNNEEDED, bool allowing UNNEEDED, void *) UNNEEDED, + void *cbarg UNNEEDED) +{ fprintf(stderr, "deprecated_ok_ called!\n"); abort(); } +/* Generated stub for discard_key */ +void discard_key(struct secret *key TAKES UNNEEDED) +{ fprintf(stderr, "discard_key called!\n"); abort(); } +/* Generated stub for ecdh_hsmd_setup */ +void ecdh_hsmd_setup(int hsm_fd UNNEEDED, + void (*failed)(enum status_failreason UNNEEDED, + const char *fmt UNNEEDED, ...)) +{ fprintf(stderr, "ecdh_hsmd_setup called!\n"); abort(); } +/* Generated stub for fatal */ +void fatal(const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "fatal called!\n"); abort(); } +/* Generated stub for feature_set_for_feature */ +struct feature_set *feature_set_for_feature(const tal_t *ctx UNNEEDED, int feature UNNEEDED) +{ fprintf(stderr, "feature_set_for_feature called!\n"); abort(); } +/* Generated stub for feature_set_or */ +bool feature_set_or(struct feature_set *a UNNEEDED, + const struct feature_set *b TAKES UNNEEDED) +{ fprintf(stderr, "feature_set_or called!\n"); abort(); } +/* Generated stub for fmt_node_id */ +char *fmt_node_id(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED) +{ fprintf(stderr, "fmt_node_id called!\n"); abort(); } +/* Generated stub for free_htlcs */ +void free_htlcs(struct lightningd *ld UNNEEDED, const struct channel *channel UNNEEDED) +{ fprintf(stderr, "free_htlcs called!\n"); abort(); } +/* Generated stub for fromwire_bigsize */ +bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } +/* Generated stub for fromwire_channel_id */ +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, + struct channel_id *channel_id UNNEEDED) +{ fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } +/* Generated stub for fromwire_node_id */ +void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED) +{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); } +/* Generated stub for fromwire_status_fail */ +bool fromwire_status_fail(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, enum status_failreason *failreason UNNEEDED, wirestring **desc UNNEEDED) +{ fprintf(stderr, "fromwire_status_fail called!\n"); abort(); } +/* Generated stub for fromwire_status_peer_billboard */ +bool fromwire_status_peer_billboard(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, bool *perm UNNEEDED, wirestring **happenings UNNEEDED) +{ fprintf(stderr, "fromwire_status_peer_billboard called!\n"); abort(); } +/* Generated stub for fromwire_status_peer_error */ +bool fromwire_status_peer_error(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, bool *disconnect UNNEEDED, wirestring **desc UNNEEDED, bool *warning UNNEEDED, u8 **error_for_them UNNEEDED) +{ fprintf(stderr, "fromwire_status_peer_error called!\n"); abort(); } +/* Generated stub for fromwire_status_version */ +bool fromwire_status_version(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, wirestring **version UNNEEDED) +{ fprintf(stderr, "fromwire_status_version called!\n"); abort(); } +/* Generated stub for gossip_init */ +void gossip_init(struct lightningd *ld UNNEEDED, int connectd_fd UNNEEDED) +{ fprintf(stderr, "gossip_init called!\n"); abort(); } +/* Generated stub for gossip_notify_new_block */ +void gossip_notify_new_block(struct lightningd *ld UNNEEDED, u32 blockheight UNNEEDED) +{ fprintf(stderr, "gossip_notify_new_block called!\n"); abort(); } +/* Generated stub for handle_early_opts */ +void handle_early_opts(struct lightningd *ld UNNEEDED, int argc UNNEEDED, char *argv[]) +{ fprintf(stderr, "handle_early_opts called!\n"); abort(); } +/* Generated stub for handle_opts */ +void handle_opts(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "handle_opts called!\n"); abort(); } +/* Generated stub for hash_htlc_key */ +size_t hash_htlc_key(const struct htlc_key *htlc_key UNNEEDED) +{ fprintf(stderr, "hash_htlc_key called!\n"); abort(); } +/* Generated stub for hsm_init */ +struct ext_key *hsm_init(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "hsm_init called!\n"); abort(); } +/* Generated stub for htlcs_notify_new_block */ +void htlcs_notify_new_block(struct lightningd *ld UNNEEDED, u32 height UNNEEDED) +{ fprintf(stderr, "htlcs_notify_new_block called!\n"); abort(); } +/* Generated stub for htlcs_resubmit */ +void htlcs_resubmit(struct lightningd *ld UNNEEDED, + struct htlc_in_map *unconnected_htlcs_in STEALS UNNEEDED) +{ fprintf(stderr, "htlcs_resubmit called!\n"); abort(); } +/* Generated stub for invoices_start_expiration */ +void invoices_start_expiration(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "invoices_start_expiration called!\n"); abort(); } +/* Generated stub for json_add_string */ +void json_add_string(struct json_stream *js UNNEEDED, + const char *fieldname UNNEEDED, + const char *str TAKES UNNEEDED) +{ fprintf(stderr, "json_add_string called!\n"); abort(); } +/* Generated stub for jsonrpc_listen */ +void jsonrpc_listen(struct jsonrpc *rpc UNNEEDED, struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "jsonrpc_listen called!\n"); abort(); } +/* Generated stub for jsonrpc_setup */ +void jsonrpc_setup(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "jsonrpc_setup called!\n"); abort(); } +/* Generated stub for jsonrpc_stop_all */ +void jsonrpc_stop_all(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "jsonrpc_stop_all called!\n"); abort(); } +/* Generated stub for jsonrpc_stop_listening */ +void jsonrpc_stop_listening(struct jsonrpc *jsonrpc UNNEEDED) +{ fprintf(stderr, "jsonrpc_stop_listening called!\n"); abort(); } +/* Generated stub for load_channels_from_wallet */ +struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld UNNEEDED, + size_t *num_channels UNNEEDED) +{ fprintf(stderr, "load_channels_from_wallet called!\n"); abort(); } +/* Generated stub for log_ */ +void log_(struct logger *logger UNNEEDED, enum log_level level UNNEEDED, + const struct node_id *node_id UNNEEDED, + bool call_notifier UNNEEDED, + const char *fmt UNNEEDED, ...) + +{ fprintf(stderr, "log_ called!\n"); abort(); } +/* Generated stub for log_backtrace_exit */ +void log_backtrace_exit(void) +{ fprintf(stderr, "log_backtrace_exit called!\n"); abort(); } +/* Generated stub for log_backtrace_print */ +void log_backtrace_print(const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "log_backtrace_print called!\n"); abort(); } +/* Generated stub for log_has_io_logging */ +bool log_has_io_logging(const struct logger *log UNNEEDED) +{ fprintf(stderr, "log_has_io_logging called!\n"); abort(); } +/* Generated stub for log_prefix */ +const char *log_prefix(const struct logger *logger UNNEEDED) +{ fprintf(stderr, "log_prefix called!\n"); abort(); } +/* Generated stub for log_status_msg */ +bool log_status_msg(struct logger *log UNNEEDED, + const struct node_id *node_id UNNEEDED, + const u8 *msg UNNEEDED) +{ fprintf(stderr, "log_status_msg called!\n"); abort(); } +/* Generated stub for new_log_book */ +struct log_book *new_log_book(struct lightningd *ld UNNEEDED, size_t max_mem UNNEEDED) +{ fprintf(stderr, "new_log_book called!\n"); abort(); } +/* Generated stub for new_logger */ +struct logger *new_logger(const tal_t *ctx UNNEEDED, struct log_book *record UNNEEDED, + const struct node_id *default_node_id UNNEEDED, + const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "new_logger called!\n"); abort(); } +/* Generated stub for new_peer_fd_arr */ +struct peer_fd *new_peer_fd_arr(const tal_t *ctx UNNEEDED, const int *fd UNNEEDED) +{ fprintf(stderr, "new_peer_fd_arr called!\n"); abort(); } +/* Generated stub for new_topology */ +struct chain_topology *new_topology(struct lightningd *ld UNNEEDED, struct logger *log UNNEEDED) +{ fprintf(stderr, "new_topology called!\n"); abort(); } +/* Generated stub for onchaind_replay_channels */ +void onchaind_replay_channels(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "onchaind_replay_channels called!\n"); abort(); } +/* Generated stub for plugin_hook_call_ */ +bool plugin_hook_call_(struct lightningd *ld UNNEEDED, + const struct plugin_hook *hook UNNEEDED, + const char *cmd_id TAKES UNNEEDED, + tal_t *cb_arg STEALS UNNEEDED) +{ fprintf(stderr, "plugin_hook_call_ called!\n"); abort(); } +/* Generated stub for plugins_config */ +bool plugins_config(struct plugins *plugins UNNEEDED) +{ fprintf(stderr, "plugins_config called!\n"); abort(); } +/* Generated stub for plugins_init */ +void plugins_init(struct plugins *plugins UNNEEDED) +{ fprintf(stderr, "plugins_init called!\n"); abort(); } +/* Generated stub for plugins_new */ +struct plugins *plugins_new(const tal_t *ctx UNNEEDED, struct log_book *log_book UNNEEDED, + struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "plugins_new called!\n"); abort(); } +/* Generated stub for plugins_set_builtin_plugins_dir */ +void plugins_set_builtin_plugins_dir(struct plugins *plugins UNNEEDED, + const char *dir UNNEEDED) +{ fprintf(stderr, "plugins_set_builtin_plugins_dir called!\n"); abort(); } +/* Generated stub for pubkey_from_node_id */ +bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED) +{ fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); } +/* Generated stub for resend_closing_transactions */ +void resend_closing_transactions(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "resend_closing_transactions called!\n"); abort(); } +/* Generated stub for runes_early_init */ +struct runes *runes_early_init(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "runes_early_init called!\n"); abort(); } +/* Generated stub for runes_finish_init */ +void runes_finish_init(struct runes *runes UNNEEDED) +{ fprintf(stderr, "runes_finish_init called!\n"); abort(); } +/* Generated stub for setup_color_and_alias */ +void setup_color_and_alias(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "setup_color_and_alias called!\n"); abort(); } +/* Generated stub for setup_peers */ +void setup_peers(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "setup_peers called!\n"); abort(); } +/* Generated stub for setup_topology */ +void setup_topology(struct chain_topology *topology UNNEEDED) +{ fprintf(stderr, "setup_topology called!\n"); abort(); } +/* Generated stub for shutdown_plugins */ +void shutdown_plugins(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "shutdown_plugins called!\n"); abort(); } +/* Generated stub for stop_topology */ +void stop_topology(struct chain_topology *topo UNNEEDED) +{ fprintf(stderr, "stop_topology called!\n"); abort(); } +/* Generated stub for timer_expired */ +void timer_expired(struct timer *timer UNNEEDED) +{ fprintf(stderr, "timer_expired called!\n"); abort(); } +/* Generated stub for towire_bigsize */ +void towire_bigsize(u8 **pptr UNNEEDED, const bigsize_t val UNNEEDED) +{ fprintf(stderr, "towire_bigsize called!\n"); abort(); } +/* Generated stub for towire_channel_id */ +void towire_channel_id(u8 **pptr UNNEEDED, const struct channel_id *channel_id UNNEEDED) +{ fprintf(stderr, "towire_channel_id called!\n"); abort(); } +/* Generated stub for towire_node_id */ +void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED) +{ fprintf(stderr, "towire_node_id called!\n"); abort(); } +/* Generated stub for trace_span_end */ +void trace_span_end(const void *key UNNEEDED) +{ fprintf(stderr, "trace_span_end called!\n"); abort(); } +/* Generated stub for trace_span_start */ +void trace_span_start(const char *name UNNEEDED, const void *key UNNEEDED) +{ fprintf(stderr, "trace_span_start called!\n"); abort(); } +/* Generated stub for txfilter_add_derkey */ +void txfilter_add_derkey(struct txfilter *filter UNNEEDED, + const u8 derkey[PUBKEY_CMPR_LEN]) +{ fprintf(stderr, "txfilter_add_derkey called!\n"); abort(); } +/* Generated stub for txfilter_new */ +struct txfilter *txfilter_new(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "txfilter_new called!\n"); abort(); } +/* Generated stub for version */ +const char *version(void) +{ fprintf(stderr, "version called!\n"); abort(); } +/* Generated stub for waitblockheight_notify_new_block */ +void waitblockheight_notify_new_block(struct lightningd *ld UNNEEDED, + u32 block_height UNNEEDED) +{ fprintf(stderr, "waitblockheight_notify_new_block called!\n"); abort(); } +/* Generated stub for wallet_new */ +struct wallet *wallet_new(struct lightningd *ld UNNEEDED, struct timers *timers UNNEEDED) +{ fprintf(stderr, "wallet_new called!\n"); abort(); } +/* Generated stub for wallet_sanity_check */ +bool wallet_sanity_check(struct wallet *w UNNEEDED) +{ fprintf(stderr, "wallet_sanity_check called!\n"); abort(); } +/* AUTOGENERATED MOCKS END */ + +struct logger *crashlog; + +#undef main +int main(int argc UNUSED, char *argv[]) +{ + common_setup(argv[0]); + + const char *rel; + + rel = relative(tmpctx, "/i/made/up/this/path/bin", + "/i/made/up/this/path/libexec/plugins"); + assert(streq(rel, "../libexec/plugins")); + + rel = relative(tmpctx, "/i/made/up/this/path/bin", + "/i/made/up/this/path/plugins"); + assert(streq(rel, "../plugins")); + + rel = relative(tmpctx, "/i/made/up/this/path/bin", + "/i/made/up/this/path"); + assert(streq(rel, "..")); + + rel = relative(tmpctx, "/i/made/up/this/path", + "/i/made/up/this/path/libexec/plugins"); + assert(streq(rel, "libexec/plugins")); + + rel = relative(tmpctx, "/i/made/up/this/path", + "/i/made/up/this/path/plugins"); + assert(streq(rel, "plugins")); + + rel = relative(tmpctx, "/i/made/up/this/path", "/i/made/up/this/path"); + assert(streq(rel, ".")); + + rel = relative(tmpctx, "/.///i/made//up//this//path//./bin//", + "/i/made/up/this//path//libexec///plugins//"); + assert(streq(rel, "../libexec/plugins")); + + rel = relative(tmpctx, "/", "/"); + assert(streq(rel, ".")); + + rel = relative(tmpctx, "/bin", "/"); + assert(streq(rel, "..")); + + rel = relative(tmpctx, "/", "/plugins"); + assert(streq(rel, "plugins")); + + rel = relative(tmpctx, "/bin", "/plugins"); + assert(streq(rel, "../plugins")); + + rel = relative(tmpctx, "/bin/exe", "/"); + assert(streq(rel, "../..")); + + rel = relative(tmpctx, "/bin/exe", "/plugins"); + assert(streq(rel, "../../plugins")); + + rel = relative(tmpctx, "/bin/exe", "/mydir/plugins"); + assert(streq(rel, "../../mydir/plugins")); + + assert(!taken_any()); + common_shutdown(); + return 0; +} +