diff --git a/TODO b/TODO index a575f9ab737..4e787a7b9e7 100644 --- a/TODO +++ b/TODO @@ -134,9 +134,6 @@ Features: sufficient to build a link by prefixing "http://" and suffixing the CODE_FILE. -* when outputting log data with journalctl and the log data includes references - to configuration files (CONFIG_FILE=), create a clickable link for it. - * Augment MESSAGE_ID with MESSAGE_BASE, in a similar fashion so that we can make clickable links from log messages carrying a MESSAGE_ID, that lead to some explanatory text online. diff --git a/meson.build b/meson.build index 4d40451fa6a..14a56c29c85 100644 --- a/meson.build +++ b/meson.build @@ -29,6 +29,10 @@ substs.set('PROJECT_VERSION', meson.project_version()) # This is to be used instead of meson.source_root(), as the latter will return # the wrong result when systemd is being built as a meson subproject project_source_root = meson.current_source_dir() +relative_source_path = run_command('realpath', + '--relative-to=@0@'.format(meson.current_build_dir()), + project_source_root).stdout().strip() +conf.set_quoted('RELATIVE_SOURCE_PATH', relative_source_path) want_ossfuzz = get_option('oss-fuzz') want_libfuzzer = get_option('llvm-fuzz') diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index 41c8adb16b4..1b071c230e7 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -76,7 +76,7 @@ typedef struct { #if ENABLE_DEBUG_HASHMAP # define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line -# define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__ +# define HASHMAP_DEBUG_SRC_ARGS , __func__, PROJECT_FILE, __LINE__ # define HASHMAP_DEBUG_PASS_ARGS , func, file, line #else # define HASHMAP_DEBUG_PARAMS diff --git a/src/basic/log.c b/src/basic/log.c index c484ff57f60..31ecbd1d1bd 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -351,7 +351,13 @@ static int write_to_console( get_log_colors(LOG_PRI(level), &on, &off, NULL); if (show_location) { - (void) snprintf(location, sizeof location, "(%s:%i) ", file, line); + const char *lon = "", *loff = ""; + if (show_color) { + lon = ANSI_HIGHLIGHT_YELLOW4; + loff = ANSI_NORMAL; + } + + (void) snprintf(location, sizeof location, "%s%s:%i%s: ", lon, file, line, loff); iovec[n++] = IOVEC_MAKE_STRING(location); } @@ -1232,18 +1238,29 @@ int log_syntax_internal( if (unit) unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s"; - if (config_file) - return log_struct_internal( - LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), - error, - file, line, func, - "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, - "CONFIG_FILE=%s", config_file, - "CONFIG_LINE=%u", config_line, - LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer), - unit_fmt, unit, - NULL); - else if (unit) + if (config_file) { + if (config_line > 0) + return log_struct_internal( + LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), + error, + file, line, func, + "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, + "CONFIG_FILE=%s", config_file, + "CONFIG_LINE=%u", config_line, + LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer), + unit_fmt, unit, + NULL); + else + return log_struct_internal( + LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), + error, + file, line, func, + "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, + "CONFIG_FILE=%s", config_file, + LOG_MESSAGE("%s: %s", config_file, buffer), + unit_fmt, unit, + NULL); + } else if (unit) return log_struct_internal( LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), error, diff --git a/src/basic/log.h b/src/basic/log.h index aa3d5b75f13..2e0179b2a58 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -73,6 +73,9 @@ int log_get_max_level_realm(LogRealm realm) _pure_; * for the application itself. */ +assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1) +#define PROJECT_FILE (__FILE__ + STRLEN(RELATIVE_SOURCE_PATH) + 1) + int log_open(void); void log_close(void); void log_forget_fds(void); @@ -210,7 +213,7 @@ void log_assert_failed_return_realm( log_assert_failed_return_realm(LOG_REALM, (text), __VA_ARGS__) #define log_dispatch(level, error, buffer) \ - log_dispatch_internal(level, error, __FILE__, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer) + log_dispatch_internal(level, error, PROJECT_FILE, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer) /* Logging with level */ #define log_full_errno_realm(realm, level, error, ...) \ @@ -218,7 +221,7 @@ void log_assert_failed_return_realm( int _level = (level), _e = (error), _realm = (realm); \ (log_get_max_level_realm(_realm) >= LOG_PRI(_level)) \ ? log_internal_realm(LOG_REALM_PLUS_LEVEL(_realm, _level), _e, \ - __FILE__, __LINE__, __func__, __VA_ARGS__) \ + PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ : -ERRNO_VALUE(_e); \ }) @@ -254,20 +257,20 @@ int log_emergency_level(void); /* Structured logging */ #define log_struct_errno(level, error, ...) \ log_struct_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \ - error, __FILE__, __LINE__, __func__, __VA_ARGS__, NULL) + error, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__, NULL) #define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__) #define log_struct_iovec_errno(level, error, iovec, n_iovec) \ log_struct_iovec_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \ - error, __FILE__, __LINE__, __func__, iovec, n_iovec) + error, PROJECT_FILE, __LINE__, __func__, iovec, n_iovec) #define log_struct_iovec(level, iovec, n_iovec) log_struct_iovec_errno(level, 0, iovec, n_iovec) /* This modifies the buffer passed! */ #define log_dump(level, buffer) \ log_dump_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \ - 0, __FILE__, __LINE__, __func__, buffer) + 0, PROJECT_FILE, __LINE__, __func__, buffer) -#define log_oom() log_oom_internal(LOG_REALM, __FILE__, __LINE__, __func__) +#define log_oom() log_oom_internal(LOG_REALM, PROJECT_FILE, __LINE__, __func__) bool log_on_console(void) _pure_; @@ -320,7 +323,7 @@ int log_syntax_invalid_utf8_internal( ({ \ int _level = (level), _e = (error); \ (log_get_max_level() >= LOG_PRI(_level)) \ - ? log_syntax_internal(unit, _level, config_file, config_line, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \ + ? log_syntax_internal(unit, _level, config_file, config_line, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ : -ERRNO_VALUE(_e); \ }) @@ -328,7 +331,7 @@ int log_syntax_invalid_utf8_internal( ({ \ int _level = (level); \ (log_get_max_level() >= LOG_PRI(_level)) \ - ? log_syntax_invalid_utf8_internal(unit, _level, config_file, config_line, __FILE__, __LINE__, __func__, rvalue) \ + ? log_syntax_invalid_utf8_internal(unit, _level, config_file, config_line, PROJECT_FILE, __LINE__, __func__, rvalue) \ : -EINVAL; \ }) diff --git a/src/basic/macro.h b/src/basic/macro.h index ae8907db04b..81add201fab 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -324,12 +324,12 @@ static inline int __coverity_check__(int condition) { #define assert_message_se(expr, message) \ do { \ if (_unlikely_(!(expr))) \ - log_assert_failed(message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + log_assert_failed(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \ } while (false) #define assert_log(expr, message) ((_likely_(expr)) \ ? (true) \ - : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false)) + : (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__), false)) #endif /* __COVERITY__ */ @@ -345,7 +345,7 @@ static inline int __coverity_check__(int condition) { #define assert_not_reached(t) \ do { \ - log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + log_assert_failed_unreachable(t, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \ } while (false) #if defined(static_assert) diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index 6e5b273c75e..3e39768ab16 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -19,12 +19,13 @@ #define ANSI_GREY "\x1B[0;38;5;245m" /* Bold/highlighted */ -#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m" -#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m" -#define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;38;5;185m" -#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m" -#define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m" -#define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38;5;245m" +#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m" +#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m" +#define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;38;5;185m" +#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m" +#define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m" +#define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38;5;245m" +#define ANSI_HIGHLIGHT_YELLOW4 "\x1B[0;1;38;5;100m" /* Underlined */ #define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m" diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c index 960ba6cc6df..cb136322fe1 100644 --- a/src/core/selinux-access.c +++ b/src/core/selinux-access.c @@ -127,7 +127,7 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" log_internalv(LOG_AUTH | callback_type_to_priority(type), - 0, __FILE__, __LINE__, __FUNCTION__, + 0, PROJECT_FILE, __LINE__, __FUNCTION__, fmt2, ap); #pragma GCC diagnostic pop va_end(ap); diff --git a/src/core/unit.h b/src/core/unit.h index ef495f836bd..f6364592619 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -858,8 +858,8 @@ int unit_test_trigger_loaded(Unit *u); #define log_unit_full(unit, level, error, ...) \ ({ \ const Unit *_u = (unit); \ - _u ? log_object_internal(level, error, __FILE__, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \ - log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + _u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \ + log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ }) #define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__) diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index 449ac8ea1fa..c0bda68811c 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -30,7 +30,7 @@ _noreturn_ static void log_assert_errno(const char *text, int error, const char do { \ int _r_ = (expr); \ if (_unlikely_(_r_ < 0)) \ - log_assert_errno(#expr, -_r_, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + log_assert_errno(#expr, -_r_, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \ } while (false) static JournalFile *test_open(const char *name) { diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h index a0f9c2299fa..e0269b54564 100644 --- a/src/libsystemd-network/dhcp-internal.h +++ b/src/libsystemd-network/dhcp-internal.h @@ -51,5 +51,5 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, ui #define DHCP_CLIENT_DONT_DESTROY(client) \ _cleanup_(sd_dhcp_client_unrefp) _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client) -#define log_dhcp_client_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__) +#define log_dhcp_client_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__) #define log_dhcp_client(client, fmt, ...) log_dhcp_client_errno(client, 0, fmt, ##__VA_ARGS__) diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index b30be7e5b2d..256006ebebf 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -69,8 +69,8 @@ typedef struct DHCPRequest { uint32_t lifetime; } DHCPRequest; -#define log_dhcp_server(client, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__) -#define log_dhcp_server_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__) +#define log_dhcp_server(client, fmt, ...) log_internal(LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__) +#define log_dhcp_server_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__) int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, size_t length); diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h index 157fc0aadde..f28ba68dd1e 100644 --- a/src/libsystemd-network/dhcp6-internal.h +++ b/src/libsystemd-network/dhcp6-internal.h @@ -79,7 +79,7 @@ struct DHCP6IA { typedef struct DHCP6IA DHCP6IA; -#define log_dhcp6_client_errno(p, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__) +#define log_dhcp6_client_errno(p, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__) #define log_dhcp6_client(p, fmt, ...) log_dhcp6_client_errno(p, 0, fmt, ##__VA_ARGS__) int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, diff --git a/src/libsystemd-network/lldp-internal.h b/src/libsystemd-network/lldp-internal.h index 88b54933c39..9598438dbae 100644 --- a/src/libsystemd-network/lldp-internal.h +++ b/src/libsystemd-network/lldp-internal.h @@ -32,7 +32,7 @@ struct sd_lldp { struct ether_addr filter_address; }; -#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__) +#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__) #define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__) const char* lldp_event_to_string(sd_lldp_event e) _const_; diff --git a/src/libsystemd-network/ndisc-internal.h b/src/libsystemd-network/ndisc-internal.h index 28f801cd7fb..c66dc3d4431 100644 --- a/src/libsystemd-network/ndisc-internal.h +++ b/src/libsystemd-network/ndisc-internal.h @@ -37,7 +37,7 @@ struct sd_ndisc { void *userdata; }; -#define log_ndisc_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "NDISC: " fmt, ##__VA_ARGS__) +#define log_ndisc_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "NDISC: " fmt, ##__VA_ARGS__) #define log_ndisc(fmt, ...) log_ndisc_errno(0, fmt, ##__VA_ARGS__) const char* ndisc_event_to_string(sd_ndisc_event e) _const_; diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h index 66f49ed44ec..517e4dc528a 100644 --- a/src/libsystemd-network/radv-internal.h +++ b/src/libsystemd-network/radv-internal.h @@ -98,6 +98,6 @@ struct sd_radv_prefix { usec_t preferred_until; }; -#define log_radv_full(level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "RADV: " fmt, ##__VA_ARGS__) +#define log_radv_full(level, error, fmt, ...) log_internal(level, error, PROJECT_FILE, __LINE__, __func__, "RADV: " fmt, ##__VA_ARGS__) #define log_radv_errno(error, fmt, ...) log_radv_full(LOG_DEBUG, error, fmt, ##__VA_ARGS__) #define log_radv(fmt, ...) log_radv_errno(0, fmt, ##__VA_ARGS__) diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c index c8e34497fd0..d960027a0f9 100644 --- a/src/libsystemd-network/sd-ipv4acd.c +++ b/src/libsystemd-network/sd-ipv4acd.c @@ -72,7 +72,7 @@ struct sd_ipv4acd { void* userdata; }; -#define log_ipv4acd_errno(acd, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "IPV4ACD: " fmt, ##__VA_ARGS__) +#define log_ipv4acd_errno(acd, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "IPV4ACD: " fmt, ##__VA_ARGS__) #define log_ipv4acd(acd, fmt, ...) log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__) static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) { diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index a59a9523265..3104d8c5a8e 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -50,7 +50,7 @@ struct sd_ipv4ll { void* userdata; }; -#define log_ipv4ll_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "IPV4LL: " fmt, ##__VA_ARGS__) +#define log_ipv4ll_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "IPV4LL: " fmt, ##__VA_ARGS__) #define log_ipv4ll(ll, fmt, ...) log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__) static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata); diff --git a/src/libsystemd/sd-device/device-util.h b/src/libsystemd/sd-device/device-util.h index 94f6174bff9..a25682d8936 100644 --- a/src/libsystemd/sd-device/device-util.h +++ b/src/libsystemd/sd-device/device-util.h @@ -39,7 +39,7 @@ \ if (_d && _unlikely_(log_get_max_level() >= _level)) \ (void) sd_device_get_sysname(_d, &_sysname); \ - log_object_internal(_level, _error, __FILE__, __LINE__, __func__, \ + log_object_internal(_level, _error, PROJECT_FILE, __LINE__, __func__, \ _sysname ? "DEVICE=" : NULL, _sysname, \ NULL, NULL, ##__VA_ARGS__); \ }) diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index d63b1912d86..732b563d676 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -193,8 +193,8 @@ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, GPERF_ #define log_netdev_full(netdev, level, error, ...) \ ({ \ const NetDev *_n = (netdev); \ - _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, NULL, NULL, ##__VA_ARGS__) : \ - log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + _n ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _n->ifname, NULL, NULL, ##__VA_ARGS__) : \ + log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ }) #define log_netdev_debug(netdev, ...) log_netdev_full(netdev, LOG_DEBUG, 0, ##__VA_ARGS__) diff --git a/src/shared/condition.c b/src/shared/condition.c index 8c613fcd5f9..e5e6c6cc130 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -788,14 +788,14 @@ bool condition_test_list(Condition *first, const char *(*to_string)(ConditionTyp assert(p); if (r < 0) - logger(userdata, LOG_WARNING, r, __FILE__, __LINE__, __func__, + logger(userdata, LOG_WARNING, r, PROJECT_FILE, __LINE__, __func__, "Couldn't determine result for %s=%s%s%s, assuming failed: %m", to_string(c->type), c->trigger ? "|" : "", c->negate ? "!" : "", p); else - logger(userdata, LOG_DEBUG, 0, __FILE__, __LINE__, __func__, + logger(userdata, LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__, "%s=%s%s%s %s.", to_string(c->type), c->trigger ? "|" : "", diff --git a/src/shared/json.h b/src/shared/json.h index cc2886b0c0b..d78082905a5 100644 --- a/src/shared/json.h +++ b/src/shared/json.h @@ -271,7 +271,7 @@ int json_log_internal(JsonVariant *variant, int level, int error, const char *fi ({ \ int _level = json_dispatch_level(flags), _e = (error); \ (log_get_max_level() >= LOG_PRI(_level)) \ - ? json_log_internal(variant, _level, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \ + ? json_log_internal(variant, _level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ : -ERRNO_VALUE(_e); \ }) diff --git a/src/shared/log-link.h b/src/shared/log-link.h index 99efc0cbabf..2d038026905 100644 --- a/src/shared/log-link.h +++ b/src/shared/log-link.h @@ -17,8 +17,8 @@ #define log_link_full(link, level, error, ...) \ ({ \ const Link *_l = (link); \ - (_l && _l->ifname) ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ - log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + (_l && _l->ifname) ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ + log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ }) \ #define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index aa5bc5b4ed7..21b32510340 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -29,6 +29,7 @@ #include "output-mode.h" #include "parse-util.h" #include "process-util.h" +#include "pretty-print.h" #include "sparse-endian.h" #include "stdio-util.h" #include "string-table.h" @@ -375,8 +376,8 @@ static int output_short( const void *data; size_t length; size_t n = 0; - _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL, *transport = NULL, *unit = NULL, *user_unit = NULL; - size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0, transport_len = 0, unit_len = 0, user_unit_len = 0; + _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL, *transport = NULL, *config_file = NULL, *unit = NULL, *user_unit = NULL; + size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0, transport_len = 0, config_file_len = 0, unit_len = 0, user_unit_len = 0; int p = LOG_INFO; bool ellipsized = false, audit; const ParseFieldVec fields[] = { @@ -390,6 +391,7 @@ static int output_short( PARSE_FIELD_VEC_ENTRY("SYSLOG_IDENTIFIER=", &identifier, &identifier_len), PARSE_FIELD_VEC_ENTRY("_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len), PARSE_FIELD_VEC_ENTRY("_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len), + PARSE_FIELD_VEC_ENTRY("CONFIG_FILE=", &config_file, &config_file_len), PARSE_FIELD_VEC_ENTRY("_SYSTEMD_UNIT=", &unit, &unit_len), PARSE_FIELD_VEC_ENTRY("_SYSTEMD_USER_UNIT=", &user_unit, &user_unit_len), }; @@ -451,7 +453,8 @@ static int output_short( n += hostname_len + 1; } - if (mode == OUTPUT_WITH_UNIT && ((unit && shall_print(unit, unit_len, flags)) || (user_unit && shall_print(user_unit, user_unit_len, flags)))) { + if (mode == OUTPUT_WITH_UNIT && ((unit && shall_print(unit, unit_len, flags)) || + (user_unit && shall_print(user_unit, user_unit_len, flags)))) { if (unit) { fprintf(f, " %.*s", (int) unit_len, unit); n += unit_len + 1; @@ -485,6 +488,34 @@ static int output_short( fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); } else { fputs(": ", f); + + /* URLify config_file string in message, if the message starts with it. + * Skip URLification if the highlighted pattern overlaps. */ + if (config_file && + message_len >= config_file_len && + memcmp(message, config_file, config_file_len) == 0 && + IN_SET(message[config_file_len], ':', ' ', '\0') && + (!highlight || highlight_shifted[0] == 0 || highlight_shifted[0] > config_file_len)) { + + _cleanup_free_ char *t = NULL, *urlified = NULL; + + t = strndup(config_file, config_file_len); + if (t && terminal_urlify_path(t, NULL, &urlified) >= 0) { + size_t shift = strlen(urlified) - config_file_len; + char *joined; + + joined = strjoin(urlified, message + config_file_len); + if (joined) { + free_and_replace(message, joined); + message_len += shift; + if (highlight) { + highlight_shifted[0] += shift; + highlight_shifted[1] += shift; + } + } + } + } + ellipsized |= print_multiline(f, n + 2, n_columns, flags, p, audit, message, message_len, @@ -556,9 +587,11 @@ static int output_verbose( cursor); JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { - const char *c; + const char *c, *p; int fieldlen; const char *on = "", *off = ""; + _cleanup_free_ char *urlified = NULL; + size_t valuelen; c = memchr(data, '=', length); if (!c) @@ -569,20 +602,28 @@ static int output_verbose( r = field_set_test(output_fields, data, fieldlen); if (r < 0) return r; - if (!r) + if (r == 0) continue; - if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) { + valuelen = length - 1 - fieldlen; + + if ((flags & OUTPUT_COLOR) && (p = startswith(data, "MESSAGE="))) { on = ANSI_HIGHLIGHT; off = ANSI_NORMAL; - } + } else if ((p = startswith(data, "CONFIG_FILE="))) { + if (terminal_urlify_path(p, NULL, &urlified) >= 0) { + p = urlified; + valuelen = strlen(urlified); + } + } else + p = c + 1; if ((flags & OUTPUT_SHOW_ALL) || (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH) && utf8_is_printable(data, length))) { fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data); print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, false, - c + 1, length - fieldlen - 1, + p, valuelen, NULL); fputs(off, f); } else { @@ -1040,21 +1081,21 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])( Set *output_fields, const size_t highlight[2]) = { - [OUTPUT_SHORT] = output_short, - [OUTPUT_SHORT_ISO] = output_short, + [OUTPUT_SHORT] = output_short, + [OUTPUT_SHORT_ISO] = output_short, [OUTPUT_SHORT_ISO_PRECISE] = output_short, - [OUTPUT_SHORT_PRECISE] = output_short, - [OUTPUT_SHORT_MONOTONIC] = output_short, - [OUTPUT_SHORT_UNIX] = output_short, - [OUTPUT_SHORT_FULL] = output_short, - [OUTPUT_VERBOSE] = output_verbose, - [OUTPUT_EXPORT] = output_export, - [OUTPUT_JSON] = output_json, - [OUTPUT_JSON_PRETTY] = output_json, - [OUTPUT_JSON_SSE] = output_json, - [OUTPUT_JSON_SEQ] = output_json, - [OUTPUT_CAT] = output_cat, - [OUTPUT_WITH_UNIT] = output_short, + [OUTPUT_SHORT_PRECISE] = output_short, + [OUTPUT_SHORT_MONOTONIC] = output_short, + [OUTPUT_SHORT_UNIX] = output_short, + [OUTPUT_SHORT_FULL] = output_short, + [OUTPUT_VERBOSE] = output_verbose, + [OUTPUT_EXPORT] = output_export, + [OUTPUT_JSON] = output_json, + [OUTPUT_JSON_PRETTY] = output_json, + [OUTPUT_JSON_SSE] = output_json, + [OUTPUT_JSON_SEQ] = output_json, + [OUTPUT_CAT] = output_cat, + [OUTPUT_WITH_UNIT] = output_short, }; int show_journal_entry( diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index 482d914d078..ea96f5b49dc 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -57,25 +57,29 @@ int udev_parse_config_full( * to regulate the code in libudev/ and udev/. */ r = log_set_max_level_from_string_realm(LOG_REALM_UDEV, log); if (r < 0) - log_debug_errno(r, "/etc/udev/udev.conf: failed to set udev log level '%s', ignoring: %m", log); + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set udev log level '%s', ignoring: %m", log); } if (ret_children_max && children_max) { r = safe_atou(children_max, ret_children_max); if (r < 0) - log_notice_errno(r, "/etc/udev/udev.conf: failed to set parse children_max=%s, ignoring: %m", children_max); + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set parse children_max=%s, ignoring: %m", children_max); } if (ret_exec_delay_usec && exec_delay) { r = parse_sec(exec_delay, ret_exec_delay_usec); if (r < 0) - log_notice_errno(r, "/etc/udev/udev.conf: failed to set parse exec_delay=%s, ignoring: %m", exec_delay); + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set parse exec_delay=%s, ignoring: %m", exec_delay); } if (ret_event_timeout_usec && event_timeout) { r = parse_sec(event_timeout, ret_event_timeout_usec); if (r < 0) - log_notice_errno(r, "/etc/udev/udev.conf: failed to set parse event_timeout=%s, ignoring: %m", event_timeout); + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set parse event_timeout=%s, ignoring: %m", event_timeout); } if (ret_resolve_name_timing && resolve_names) { @@ -83,7 +87,8 @@ int udev_parse_config_full( t = resolve_name_timing_from_string(resolve_names); if (t < 0) - log_notice("/etc/udev/udev.conf: failed to set parse resolve_names=%s, ignoring.", resolve_names); + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set parse resolve_names=%s, ignoring.", resolve_names); else *ret_resolve_name_timing = t; } diff --git a/src/test/test-log.c b/src/test/test-log.c index 18ef56ac391..c1f2f8b09dd 100644 --- a/src/test/test-log.c +++ b/src/test/test-log.c @@ -6,6 +6,7 @@ #include "format-util.h" #include "log.h" #include "process-util.h" +#include "string-util.h" #include "util.h" assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_FTP | LOG_DEBUG)) @@ -26,6 +27,14 @@ assert_cc(!IS_SYNTHETIC_ERRNO(0)); #define X100(x) X10(X10(x)) #define X1000(x) X100(X10(x)) +static void test_file(void) { + log_info("__FILE__: %s", __FILE__); + log_info("RELATIVE_SOURCE_PATH: %s", RELATIVE_SOURCE_PATH); + log_info("PROJECT_FILE: %s", PROJECT_FILE); + + assert(startswith(__FILE__, RELATIVE_SOURCE_PATH "/")); +} + static void test_log_struct(void) { log_struct(LOG_INFO, "MESSAGE=Waldo PID="PID_FMT" (no errno)", getpid_cached(), @@ -68,6 +77,8 @@ static void test_log_syntax(void) { int main(int argc, char* argv[]) { int target; + test_file(); + for (target = 0; target < _LOG_TARGET_MAX; target++) { log_set_target(target); log_open(); diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 25a1095ff4c..99efad5b06b 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1726,9 +1726,10 @@ static int run(int argc, char *argv[]) { int r; log_set_target(LOG_TARGET_AUTO); + log_open(); udev_parse_config_full(&arg_children_max, &arg_exec_delay_usec, &arg_event_timeout_usec, &arg_resolve_name_timing); log_parse_environment(); - log_open(); + log_open(); /* Done again to update after reading configuration. */ r = parse_argv(argc, argv); if (r <= 0)