1
0
mirror of https://github.com/systemd/systemd synced 2026-03-18 19:14:46 +01:00

Compare commits

..

4 Commits

Author SHA1 Message Date
Pablo Fraile Alonso
fd8d4026d4 shared/edit-util: ignore ENOTDIR when trying editors 2026-01-05 22:22:11 +09:00
Yu Watanabe
76ed202b7f compress: do not call lzma_end_wrapper() when failed to load liblzma
Fixes a bug in 3fc72d54132151c131301fc7954e0b44cdd3c860 (v256).
Fixes #40277.
2026-01-05 21:30:27 +09:00
Mike Yuan
429cbac508 idn: drop support for libidn
The current tree doesn't even compile with libidn(1) after
2c7bdaf9f144ad339c72628579183fc849f2b794, which included
a non-existent call to check_dlopen_blocked() somehow.
Hence, it feels safe to just nuke legacy support from
our repo.
2026-01-05 21:29:52 +09:00
Yu Watanabe
47d70d3a1b test-time-util: ignore failure on MSK timezone
Ignore the following failures:
- with glibc
```
TZ=Europe/Volgograd, tzname[0]=MSK, tzname[1]=MSD
@1414277092997572 → Sun 2014-10-26 01:44:52 MSK → @1414273492000000 → Sun 2014-10-26 01:44:52 MSK
src/test/test-time-util.c:448: Assertion failed: Expected "ignore" to be true
```
- with musl
```
TZ=Europe/Kirov, tzname[0]=MSK, tzname[1]=MSK
@1414277092997572 → Sun 2014-10-26 01:44:52 MSK → @1414273492000000 → Sun 2014-10-26 01:44:52 MSK
src/test/test-time-util.c:448: Assertion failed: Expected "ignore" to be true
```
2026-01-05 17:48:36 +09:00
21 changed files with 70 additions and 341 deletions

4
NEWS
View File

@ -7,6 +7,10 @@ CHANGES WITH 260 in spe:
* Meson options '-Dintegration-tests=' and '-Dcryptolib=' (deprecated * Meson options '-Dintegration-tests=' and '-Dcryptolib=' (deprecated
in v258) have been removed. in v258) have been removed.
* Support for libidn has been removed. IDN functionality now requires
libidn2. The corresponding meson option '-Dlibidn=' is deprecated
too and will be dropped in a future release.
CHANGES WITH 259: CHANGES WITH 259:
Announcements of Future Feature Removals and Incompatible Changes: Announcements of Future Feature Removals and Incompatible Changes:

2
README
View File

@ -240,7 +240,7 @@ REQUIREMENTS:
libqrencode >= 3 (optional) libqrencode >= 3 (optional)
libmicrohttpd >= 0.9.33 (optional) libmicrohttpd >= 0.9.33 (optional)
libcurl >= 7.32.0 (optional) libcurl >= 7.32.0 (optional)
libidn2 or libidn (optional) libidn2 (optional)
gnutls >= 3.1.4 (optional) gnutls >= 3.1.4 (optional)
openssl >= 3.0.0 (optional, required to support DNS-over-TLS) openssl >= 3.0.0 (optional, required to support DNS-over-TLS)
p11-kit >= 0.23.3 (optional) p11-kit >= 0.23.3 (optional)

2
TODO
View File

@ -563,8 +563,6 @@ Features:
* port copy.c over to use LabelOps for all labelling. * port copy.c over to use LabelOps for all labelling.
* get rid of compat with libidn.so.11 (retain only for libidn.so.12)
* get rid of compat with libbpf.so.0 (retainly only for libbpf.so.1) * get rid of compat with libbpf.so.0 (retainly only for libbpf.so.1)
* define a generic "report" varlink interface, which services can implement to * define a generic "report" varlink interface, which services can implement to

View File

@ -1290,18 +1290,10 @@ libcurl = dependency('libcurl',
conf.set10('HAVE_LIBCURL', libcurl.found()) conf.set10('HAVE_LIBCURL', libcurl.found())
conf.set10('CURL_NO_OLDIES', conf.get('BUILD_MODE_DEVELOPER') == 1) conf.set10('CURL_NO_OLDIES', conf.get('BUILD_MODE_DEVELOPER') == 1)
feature = get_option('libidn2').disable_auto_if(get_option('libidn').enabled()) libidn2 = dependency('libidn2',
libidn = dependency('libidn2', required : get_option('libidn2'))
required : feature) libidn2_cflags = libidn2.partial_dependency(includes: true, compile_args: true)
have = libidn.found() conf.set10('HAVE_LIBIDN2', libidn2.found())
if not have
# libidn is used for both libidn and libidn2 objects
libidn = dependency('libidn',
required : get_option('libidn'))
endif
libidn_cflags = libidn.partial_dependency(includes: true, compile_args: true)
conf.set10('HAVE_LIBIDN', not have and libidn.found())
conf.set10('HAVE_LIBIDN2', have)
libqrencode = dependency('libqrencode', libqrencode = dependency('libqrencode',
version : '>= 3', version : '>= 3',
@ -3118,7 +3110,6 @@ foreach tuple : [
['libcurl'], ['libcurl'],
['libfdisk'], ['libfdisk'],
['libfido2'], ['libfido2'],
['libidn'],
['libidn2'], ['libidn2'],
['microhttpd'], ['microhttpd'],
['openssl'], ['openssl'],

View File

@ -438,7 +438,7 @@ option('idn', type : 'boolean',
description : 'use IDN when printing hostnames') description : 'use IDN when printing hostnames')
option('libidn2', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' }, option('libidn2', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
description : 'libidn2 support') description : 'libidn2 support')
option('libidn', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' }, option('libidn', type : 'feature', deprecated : true,
description : 'libidn support') description : 'libidn support')
option('libiptc', type : 'feature', deprecated : true, option('libiptc', type : 'feature', deprecated : true,
description : 'libiptc support') description : 'libiptc support')

View File

@ -120,12 +120,6 @@ const char* const systemd_features =
" -IDN2" " -IDN2"
#endif #endif
#if HAVE_LIBIDN
" +IDN"
#else
" -IDN"
#endif
#if HAVE_KMOD #if HAVE_KMOD
" +KMOD" " +KMOD"
#else #else

View File

@ -355,20 +355,18 @@ int decompress_blob_xz(
assert(dst_size); assert(dst_size);
#if HAVE_XZ #if HAVE_XZ
_cleanup_(lzma_end_wrapper) lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret;
size_t space;
int r; int r;
r = dlopen_lzma(); r = dlopen_lzma();
if (r < 0) if (r < 0)
return r; return r;
ret = sym_lzma_stream_decoder(&s, UINT64_MAX, 0); _cleanup_(lzma_end_wrapper) lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret = sym_lzma_stream_decoder(&s, UINT64_MAX, 0);
if (ret != LZMA_OK) if (ret != LZMA_OK)
return -ENOMEM; return -ENOMEM;
space = MIN(src_size * 2, dst_max ?: SIZE_MAX); size_t space = MIN(src_size * 2, dst_max ?: SIZE_MAX);
if (!greedy_realloc(dst, space, 1)) if (!greedy_realloc(dst, space, 1))
return -ENOMEM; return -ENOMEM;
@ -550,23 +548,21 @@ int decompress_startswith_xz(
assert(prefix); assert(prefix);
#if HAVE_XZ #if HAVE_XZ
_cleanup_(lzma_end_wrapper) lzma_stream s = LZMA_STREAM_INIT;
size_t allocated;
lzma_ret ret;
int r; int r;
r = dlopen_lzma(); r = dlopen_lzma();
if (r < 0) if (r < 0)
return r; return r;
ret = sym_lzma_stream_decoder(&s, UINT64_MAX, 0); _cleanup_(lzma_end_wrapper) lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret = sym_lzma_stream_decoder(&s, UINT64_MAX, 0);
if (ret != LZMA_OK) if (ret != LZMA_OK)
return -EBADMSG; return -EBADMSG;
if (!(greedy_realloc(buffer, ALIGN_8(prefix_len + 1), 1))) if (!(greedy_realloc(buffer, ALIGN_8(prefix_len + 1), 1)))
return -ENOMEM; return -ENOMEM;
allocated = MALLOC_SIZEOF_SAFE(*buffer); size_t allocated = MALLOC_SIZEOF_SAFE(*buffer);
s.next_in = src; s.next_in = src;
s.avail_in = src_size; s.avail_in = src_size;
@ -772,22 +768,21 @@ int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes, uint64_t *ret_uncom
assert(fdt >= 0); assert(fdt >= 0);
#if HAVE_XZ #if HAVE_XZ
_cleanup_(lzma_end_wrapper) lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret;
uint8_t buf[BUFSIZ], out[BUFSIZ];
lzma_action action = LZMA_RUN;
int r; int r;
r = dlopen_lzma(); r = dlopen_lzma();
if (r < 0) if (r < 0)
return r; return r;
ret = sym_lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64); _cleanup_(lzma_end_wrapper) lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret = sym_lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64);
if (ret != LZMA_OK) if (ret != LZMA_OK)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Failed to initialize XZ encoder: code %u", "Failed to initialize XZ encoder: code %u",
ret); ret);
uint8_t buf[BUFSIZ], out[BUFSIZ];
lzma_action action = LZMA_RUN;
for (;;) { for (;;) {
if (s.avail_in == 0 && action == LZMA_RUN) { if (s.avail_in == 0 && action == LZMA_RUN) {
size_t m = sizeof(buf); size_t m = sizeof(buf);
@ -952,23 +947,21 @@ int decompress_stream_xz(int fdf, int fdt, uint64_t max_bytes) {
assert(fdt >= 0); assert(fdt >= 0);
#if HAVE_XZ #if HAVE_XZ
_cleanup_(lzma_end_wrapper) lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret;
uint8_t buf[BUFSIZ], out[BUFSIZ];
lzma_action action = LZMA_RUN;
int r; int r;
r = dlopen_lzma(); r = dlopen_lzma();
if (r < 0) if (r < 0)
return r; return r;
ret = sym_lzma_stream_decoder(&s, UINT64_MAX, 0); _cleanup_(lzma_end_wrapper) lzma_stream s = LZMA_STREAM_INIT;
lzma_ret ret = sym_lzma_stream_decoder(&s, UINT64_MAX, 0);
if (ret != LZMA_OK) if (ret != LZMA_OK)
return log_debug_errno(SYNTHETIC_ERRNO(ENOMEM), return log_debug_errno(SYNTHETIC_ERRNO(ENOMEM),
"Failed to initialize XZ decoder: code %u", "Failed to initialize XZ decoder: code %u",
ret); ret);
uint8_t buf[BUFSIZ], out[BUFSIZ];
lzma_action action = LZMA_RUN;
for (;;) { for (;;) {
if (s.avail_in == 0 && action == LZMA_RUN) { if (s.avail_in == 0 && action == LZMA_RUN) {
ssize_t n; ssize_t n;

View File

@ -68,6 +68,7 @@ endif
resolve_common_template = { resolve_common_template = {
'dependencies' : [ 'dependencies' : [
libidn2_cflags,
libopenssl, libopenssl,
libm, libm,
threads, threads,
@ -91,9 +92,6 @@ executables += [
'resolvconf-compat.c', 'resolvconf-compat.c',
'resolvectl.c', 'resolvectl.c',
), ),
'dependencies' : resolve_common_template['dependencies'] + [
libidn,
],
'objects' : ['systemd-resolved'], 'objects' : ['systemd-resolved'],
}, },
resolve_test_template + { resolve_test_template + {

View File

@ -12,11 +12,6 @@
int resolve_system_hostname(char **full_hostname, char **first_label) { int resolve_system_hostname(char **full_hostname, char **first_label) {
_cleanup_free_ char *h = NULL, *n = NULL; _cleanup_free_ char *h = NULL, *n = NULL;
#if HAVE_LIBIDN2
_cleanup_free_ char *utf8 = NULL;
#elif HAVE_LIBIDN
int k;
#endif
char label[DNS_LABEL_MAX+1]; char label[DNS_LABEL_MAX+1];
const char *p, *decoded; const char *p, *decoded;
int r; int r;
@ -38,15 +33,10 @@ int resolve_system_hostname(char **full_hostname, char **first_label) {
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Couldn't find a single label in hostname."); "Couldn't find a single label in hostname.");
#if HAVE_LIBIDN || HAVE_LIBIDN2
r = dlopen_idn();
if (r < 0) {
log_debug_errno(r, "Failed to initialize IDN support, ignoring: %m");
decoded = label; /* no decoding */
} else
#endif
{
#if HAVE_LIBIDN2 #if HAVE_LIBIDN2
_cleanup_free_ char *utf8 = NULL;
if (dlopen_idn() >= 0) {
r = sym_idn2_to_unicode_8z8z(label, &utf8, 0); r = sym_idn2_to_unicode_8z8z(label, &utf8, 0);
if (r != IDN2_OK) if (r != IDN2_OK)
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
@ -55,21 +45,9 @@ int resolve_system_hostname(char **full_hostname, char **first_label) {
r = strlen(utf8); r = strlen(utf8);
decoded = utf8; decoded = utf8;
#elif HAVE_LIBIDN } else
k = dns_label_undo_idna(label, r, label, sizeof label);
if (k < 0)
return log_debug_errno(k, "Failed to undo IDNA: %m");
if (k > 0)
r = k;
if (!utf8_is_valid(label))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"System hostname is not UTF-8 clean.");
decoded = label;
#else
decoded = label; /* no decoding */
#endif #endif
} decoded = label; /* no decoding */
r = dns_label_escape_new(decoded, r, &n); r = dns_label_escape_new(decoded, r, &n);
if (r < 0) if (r < 0)

View File

@ -85,7 +85,7 @@ TEST(dns_query_new_multi_question_different_domain) {
ASSERT_NULL(query); ASSERT_NULL(query);
} }
#if HAVE_LIBIDN || HAVE_LIBIDN2 #if HAVE_LIBIDN2
TEST(dns_query_new_same_utf8_and_idna) { TEST(dns_query_new_same_utf8_and_idna) {
Manager manager = {}; Manager manager = {};
_cleanup_(dns_question_unrefp) DnsQuestion *q_utf8 = NULL, *q_idna = NULL; _cleanup_(dns_question_unrefp) DnsQuestion *q_utf8 = NULL, *q_idna = NULL;
@ -434,7 +434,7 @@ TEST(dns_query_process_cname_one_success_match_dname) {
dns_resource_key_unref(key); dns_resource_key_unref(key);
} }
#if HAVE_LIBIDN || HAVE_LIBIDN2 #if HAVE_LIBIDN2
TEST(dns_query_process_cname_one_success_match_dname_utf8_same) { TEST(dns_query_process_cname_one_success_match_dname_utf8_same) {
Manager manager = {}; Manager manager = {};
_cleanup_(dns_question_unrefp) DnsQuestion *q_utf8 = NULL, *q_idna = NULL; _cleanup_(dns_question_unrefp) DnsQuestion *q_utf8 = NULL, *q_idna = NULL;

View File

@ -62,7 +62,7 @@ TEST(dns_question_new_address) {
ASSERT_OK_POSITIVE(dns_question_contains_key(question, key6)); ASSERT_OK_POSITIVE(dns_question_contains_key(question, key6));
} }
#if HAVE_LIBIDN || HAVE_LIBIDN2 #if HAVE_LIBIDN2
TEST(dns_question_new_address_convert_idna) { TEST(dns_question_new_address_convert_idna) {
_cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
@ -162,7 +162,7 @@ TEST(dns_question_new_service) {
question = dns_question_unref(question); question = dns_question_unref(question);
key = dns_resource_key_unref(key); key = dns_resource_key_unref(key);
#if HAVE_LIBIDN || HAVE_LIBIDN2 #if HAVE_LIBIDN2
/* convert idna with type */ /* convert idna with type */
ASSERT_OK(dns_question_new_service( ASSERT_OK(dns_question_new_service(
&question, &question,

View File

@ -195,7 +195,7 @@ int main(int argc, char* argv[]) {
test_hostname_lookup(bus, "poettering.de", AF_INET, NULL); test_hostname_lookup(bus, "poettering.de", AF_INET, NULL);
test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL); test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL);
#if HAVE_LIBIDN2 || HAVE_LIBIDN #if HAVE_LIBIDN2
/* Unsigned A with IDNA conversion necessary */ /* Unsigned A with IDNA conversion necessary */
test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL); test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL);
test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL); test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL);

View File

@ -301,111 +301,6 @@ int dns_name_parent(const char **name) {
return dns_label_unescape(name, NULL, DNS_LABEL_MAX, 0); return dns_label_unescape(name, NULL, DNS_LABEL_MAX, 0);
} }
#if HAVE_LIBIDN
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
_cleanup_free_ uint32_t *input = NULL;
size_t input_size, l;
bool contains_8_bit = false;
char buffer[DNS_LABEL_MAX+1];
int r;
assert(encoded);
assert(decoded);
/* Converts a U-label into an A-label */
r = dlopen_idn();
if (r < 0)
return r;
if (encoded_size <= 0)
return -EINVAL;
for (const char *p = encoded; p < encoded + encoded_size; p++)
if ((uint8_t) *p > 127)
contains_8_bit = true;
if (!contains_8_bit) {
if (encoded_size > DNS_LABEL_MAX)
return -EINVAL;
return 0;
}
input = sym_stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
if (!input)
return -ENOMEM;
if (sym_idna_to_ascii_4i(input, input_size, buffer, 0) != 0)
return -EINVAL;
l = strlen(buffer);
/* Verify that the result is not longer than one DNS label. */
if (l <= 0 || l > DNS_LABEL_MAX)
return -EINVAL;
if (l > decoded_max)
return -ENOBUFS;
memcpy(decoded, buffer, l);
/* If there's room, append a trailing NUL byte, but only then */
if (decoded_max > l)
decoded[l] = 0;
return (int) l;
}
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
size_t input_size, output_size;
_cleanup_free_ uint32_t *input = NULL;
_cleanup_free_ char *result = NULL;
uint32_t *output = NULL;
size_t w;
int r;
/* To be invoked after unescaping. Converts an A-label into a U-label. */
assert(encoded);
assert(decoded);
r = dlopen_idn();
if (r < 0)
return r;
if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX)
return -EINVAL;
if (!memory_startswith(encoded, encoded_size, IDNA_ACE_PREFIX))
return 0;
input = sym_stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
if (!input)
return -ENOMEM;
output_size = input_size;
output = newa(uint32_t, output_size);
sym_idna_to_unicode_44i(input, input_size, output, &output_size, 0);
result = sym_stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
if (!result)
return -ENOMEM;
if (w <= 0)
return -EINVAL;
if (w > decoded_max)
return -ENOBUFS;
memcpy(decoded, result, w);
/* Append trailing NUL byte if there's space, but only then. */
if (decoded_max > w)
decoded[w] = 0;
return w;
}
#endif
int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **ret) { int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **ret) {
_cleanup_free_ char *result = NULL; _cleanup_free_ char *result = NULL;
size_t n_result = 0, n_unescaped = 0; size_t n_result = 0, n_unescaped = 0;
@ -1369,7 +1264,7 @@ int dns_name_apply_idna(const char *name, char **ret) {
/* Return negative on error, 0 if not implemented, positive on success. */ /* Return negative on error, 0 if not implemented, positive on success. */
#if HAVE_LIBIDN2 || HAVE_LIBIDN2 #if HAVE_LIBIDN2
int r; int r;
r = dlopen_idn(); r = dlopen_idn();
@ -1379,9 +1274,7 @@ int dns_name_apply_idna(const char *name, char **ret) {
} }
if (r < 0) if (r < 0)
return r; return r;
#endif
#if HAVE_LIBIDN2
_cleanup_free_ char *t = NULL; _cleanup_free_ char *t = NULL;
assert(name); assert(name);
@ -1429,55 +1322,6 @@ int dns_name_apply_idna(const char *name, char **ret) {
return -ENOSPC; return -ENOSPC;
return -EINVAL; return -EINVAL;
#elif HAVE_LIBIDN
_cleanup_free_ char *buf = NULL;
size_t n = 0;
bool first = true;
int r, q;
assert(name);
assert(ret);
for (;;) {
char label[DNS_LABEL_MAX+1];
r = dns_label_unescape(&name, label, sizeof label, 0);
if (r < 0)
return r;
if (r == 0)
break;
q = dns_label_apply_idna(label, r, label, sizeof label);
if (q < 0)
return q;
if (q > 0)
r = q;
if (!GREEDY_REALLOC(buf, n + !first + DNS_LABEL_ESCAPED_MAX))
return -ENOMEM;
r = dns_label_escape(label, r, buf + n + !first, DNS_LABEL_ESCAPED_MAX);
if (r < 0)
return r;
if (first)
first = false;
else
buf[n++] = '.';
n += r;
}
if (n > DNS_HOSTNAME_MAX)
return -EINVAL;
if (!GREEDY_REALLOC(buf, n + 1))
return -ENOMEM;
buf[n] = 0;
*ret = TAKE_PTR(buf);
return 1;
#else #else
*ret = NULL; *ret = NULL;
return 0; return 0;

View File

@ -16,11 +16,6 @@ int dns_label_escape_new(const char *p, size_t l, char **ret);
int dns_name_parent(const char **name); int dns_name_parent(const char **name);
#if HAVE_LIBIDN
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
#endif
int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **ret); int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **ret);
static inline int dns_name_normalize(const char *s, DNSLabelFlags flags, char **ret) { static inline int dns_name_normalize(const char *s, DNSLabelFlags flags, char **ret) {

View File

@ -298,6 +298,12 @@ static int run_editor_child(const EditFileContext *context) {
execvp(args[0], (char* const*) args); execvp(args[0], (char* const*) args);
if (errno == ENOTDIR) {
log_debug_errno(errno,
"Failed to execute '%s': a path component is not a directory, skipping...",
name);
continue;
}
/* We do not fail if the editor doesn't exist because we want to try each one of them /* We do not fail if the editor doesn't exist because we want to try each one of them
* before failing. */ * before failing. */
if (errno != ENOENT) if (errno != ENOENT)

View File

@ -1,21 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#if HAVE_LIBIDN2
# include <idn2.h>
#elif HAVE_LIBIDN
# include <idna.h>
# include <stringprep.h>
#endif
#include "dlfcn-util.h"
#include "idn-util.h" #include "idn-util.h"
#include "log.h" /* IWYU pragma: keep */ #include "log.h" /* IWYU pragma: keep */
#if HAVE_LIBIDN || HAVE_LIBIDN2
static void* idn_dl = NULL; static void* idn_dl = NULL;
#endif
#if HAVE_LIBIDN2
DLSYM_PROTOTYPE(idn2_lookup_u8) = NULL; DLSYM_PROTOTYPE(idn2_lookup_u8) = NULL;
const char *(*sym_idn2_strerror)(int rc) _const_ = NULL; const char *(*sym_idn2_strerror)(int rc) _const_ = NULL;
DLSYM_PROTOTYPE(idn2_to_unicode_8z8z) = NULL; DLSYM_PROTOTYPE(idn2_to_unicode_8z8z) = NULL;
@ -32,56 +21,3 @@ int dlopen_idn(void) {
DLSYM_ARG(idn2_strerror), DLSYM_ARG(idn2_strerror),
DLSYM_ARG(idn2_to_unicode_8z8z)); DLSYM_ARG(idn2_to_unicode_8z8z));
} }
#endif
#if HAVE_LIBIDN
DLSYM_PROTOTYPE(idna_to_ascii_4i) = NULL;
DLSYM_PROTOTYPE(idna_to_unicode_44i) = NULL;
DLSYM_PROTOTYPE(stringprep_ucs4_to_utf8) = NULL;
DLSYM_PROTOTYPE(stringprep_utf8_to_ucs4) = NULL;
int dlopen_idn(void) {
int r;
ELF_NOTE_DLOPEN("idn",
"Support for internationalized domain names",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libidn.so.12", "libidn.so.11");
if (idn_dl)
return 0; /* Already loaded */
r = check_dlopen_blocked("libidn.so.12");
if (r < 0)
return r;
_cleanup_(dlclosep) void *dl = NULL;
r = dlopen_safe("libidn.so.12", &dl, /* reterr_dlerror= */ NULL);
if (r < 0) {
/* libidn broke ABI in 1.34, but not in a way we care about (a new field got added to an
* open-coded struct we do not use), hence support both versions. */
const char *dle = NULL;
r = dlopen_safe("libidn.so.11", &dl, &dle);
if (r < 0) {
log_debug_errno(r, "libidn support is not available: %s", dle ?: STRERROR(r));
return -EOPNOTSUPP; /* turn into recognizable error */
}
log_debug("Loaded 'libidn.so.11' via dlopen()");
} else
log_debug("Loaded 'libidn.so.12' via dlopen()");
r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(idna_to_ascii_4i),
DLSYM_ARG(idna_to_unicode_44i),
DLSYM_ARG(stringprep_ucs4_to_utf8),
DLSYM_ARG(stringprep_utf8_to_ucs4));
if (r < 0)
return r;
idn_dl = TAKE_PTR(dl);
return 1;
}
#endif

View File

@ -1,34 +1,20 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once #pragma once
#if HAVE_LIBIDN2
# include <idn2.h>
#elif HAVE_LIBIDN
# include <idna.h>
# include <stringprep.h>
#endif
#include "shared-forward.h" #include "shared-forward.h"
#if HAVE_LIBIDN2 || HAVE_LIBIDN #if HAVE_LIBIDN2
#include <idn2.h>
#include "dlfcn-util.h" #include "dlfcn-util.h"
extern DLSYM_PROTOTYPE(idn2_lookup_u8);
extern const char *(*sym_idn2_strerror)(int rc) _const_;
extern DLSYM_PROTOTYPE(idn2_to_unicode_8z8z);
int dlopen_idn(void); int dlopen_idn(void);
#else #else
static inline int dlopen_idn(void) { static inline int dlopen_idn(void) {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
#endif #endif
#if HAVE_LIBIDN2
extern DLSYM_PROTOTYPE(idn2_lookup_u8);
extern const char *(*sym_idn2_strerror)(int rc) _const_;
extern DLSYM_PROTOTYPE(idn2_to_unicode_8z8z);
#endif
#if HAVE_LIBIDN
extern DLSYM_PROTOTYPE(idna_to_ascii_4i);
extern DLSYM_PROTOTYPE(idna_to_unicode_44i);
extern DLSYM_PROTOTYPE(stringprep_ucs4_to_utf8);
extern DLSYM_PROTOTYPE(stringprep_utf8_to_ucs4);
#endif

View File

@ -92,7 +92,6 @@ shared_sources = files(
'hostname-setup.c', 'hostname-setup.c',
'hwdb-util.c', 'hwdb-util.c',
'id128-print.c', 'id128-print.c',
'idn-util.c',
'ima-util.c', 'ima-util.c',
'image-policy.c', 'image-policy.c',
'import-util.c', 'import-util.c',
@ -271,6 +270,10 @@ if conf.get('HAVE_LIBMOUNT') == 1
shared_sources += files('libmount-util.c') shared_sources += files('libmount-util.c')
endif endif
if conf.get('HAVE_LIBIDN2') == 1
shared_sources += files('idn-util.c')
endif
generate_ip_protocol_list = files('generate-ip-protocol-list.sh') generate_ip_protocol_list = files('generate-ip-protocol-list.sh')
ip_protocol_list_txt = custom_target( ip_protocol_list_txt = custom_target(
input : [generate_ip_protocol_list, ipproto_sources], input : [generate_ip_protocol_list, ipproto_sources],
@ -374,7 +377,7 @@ libshared_deps = [threads,
libelf_cflags, libelf_cflags,
libfido2_cflags, libfido2_cflags,
libgcrypt_cflags, libgcrypt_cflags,
libidn_cflags, libidn2_cflags,
libkmod_cflags, libkmod_cflags,
libmount_cflags, libmount_cflags,
libopenssl, libopenssl,

View File

@ -47,7 +47,7 @@ static int run(int argc, char **argv) {
ASSERT_DLOPEN(dlopen_dw, HAVE_ELFUTILS); ASSERT_DLOPEN(dlopen_dw, HAVE_ELFUTILS);
ASSERT_DLOPEN(dlopen_elf, HAVE_ELFUTILS); ASSERT_DLOPEN(dlopen_elf, HAVE_ELFUTILS);
ASSERT_DLOPEN(dlopen_gcrypt, HAVE_GCRYPT); ASSERT_DLOPEN(dlopen_gcrypt, HAVE_GCRYPT);
ASSERT_DLOPEN(dlopen_idn, HAVE_LIBIDN2 || HAVE_LIBIDN); ASSERT_DLOPEN(dlopen_idn, HAVE_LIBIDN2);
ASSERT_DLOPEN(dlopen_libacl, HAVE_ACL); ASSERT_DLOPEN(dlopen_libacl, HAVE_ACL);
ASSERT_DLOPEN(dlopen_libapparmor, HAVE_APPARMOR); ASSERT_DLOPEN(dlopen_libapparmor, HAVE_APPARMOR);
ASSERT_DLOPEN(dlopen_libarchive, HAVE_LIBARCHIVE); ASSERT_DLOPEN(dlopen_libarchive, HAVE_LIBARCHIVE);

View File

@ -788,7 +788,7 @@ static void test_dns_name_apply_idna_one(const char *s, int expected, const char
} }
TEST(dns_name_apply_idna) { TEST(dns_name_apply_idna) {
const int ret = HAVE_LIBIDN2 | HAVE_LIBIDN; const int ret = HAVE_LIBIDN2;
/* IDNA2008 forbids names with hyphens in third and fourth positions /* IDNA2008 forbids names with hyphens in third and fourth positions
* (https://tools.ietf.org/html/rfc5891#section-4.2.3.1). * (https://tools.ietf.org/html/rfc5891#section-4.2.3.1).
@ -798,7 +798,6 @@ TEST(dns_name_apply_idna) {
* labels. If registrars follow IDNA2008 we'll just be performing a * labels. If registrars follow IDNA2008 we'll just be performing a
* useless lookup. * useless lookup.
*/ */
const int ret2 = HAVE_LIBIDN;
test_dns_name_apply_idna_one("", ret, ""); test_dns_name_apply_idna_one("", ret, "");
test_dns_name_apply_idna_one("foo", ret, "foo"); test_dns_name_apply_idna_one("foo", ret, "foo");
@ -811,14 +810,13 @@ TEST(dns_name_apply_idna) {
test_dns_name_apply_idna_one("föö.bär.", ret, "xn--f-1gaa.xn--br-via"); test_dns_name_apply_idna_one("föö.bär.", ret, "xn--f-1gaa.xn--br-via");
test_dns_name_apply_idna_one("xn--f-1gaa.xn--br-via", ret, "xn--f-1gaa.xn--br-via"); test_dns_name_apply_idna_one("xn--f-1gaa.xn--br-via", ret, "xn--f-1gaa.xn--br-via");
test_dns_name_apply_idna_one("_443._tcp.fedoraproject.org", ret2, test_dns_name_apply_idna_one("_443._tcp.fedoraproject.org", 0,
"_443._tcp.fedoraproject.org"); "_443._tcp.fedoraproject.org");
test_dns_name_apply_idna_one("_443", ret2, "_443"); test_dns_name_apply_idna_one("_443", 0, "_443");
test_dns_name_apply_idna_one("gateway", ret, "gateway"); test_dns_name_apply_idna_one("gateway", 0, "gateway");
test_dns_name_apply_idna_one("_gateway", ret2, "_gateway"); test_dns_name_apply_idna_one("_gateway", 0, "_gateway");
test_dns_name_apply_idna_one("r3---sn-ab5l6ne7.googlevideo.com", ret2, test_dns_name_apply_idna_one("r3---sn-ab5l6ne7.googlevideo.com", 0, "");
ret2 ? "r3---sn-ab5l6ne7.googlevideo.com" : "");
} }
TEST(dns_name_is_valid_or_address) { TEST(dns_name_is_valid_or_address) {

View File

@ -433,11 +433,13 @@ static void test_format_timestamp_impl(usec_t x) {
if (x_sec == y_sec && streq(xx, yy)) if (x_sec == y_sec && streq(xx, yy))
return; /* Yay! */ return; /* Yay! */
/* When the timezone is built with rearguard being enabled (e.g. old Ubuntu and RHEL), the following /* When the timezone is built with rearguard being enabled (e.g. old Ubuntu and RHEL), the timezone
* timezone may provide time shifted 1 hour from the original. See * Africa/Windhoek may provide time shifted 1 hour from the original. See
* https://github.com/systemd/systemd/issues/28472 and https://github.com/systemd/systemd/pull/35471 */ * https://github.com/systemd/systemd/issues/28472 and https://github.com/systemd/systemd/pull/35471.
* Also, the same may happen on MSK timezone (e.g. Europe/Volgograd or Europe/Kirov). */
bool ignore = bool ignore =
streq_ptr(getenv("TZ"), "Africa/Windhoek") && (streq_ptr(getenv("TZ"), "Africa/Windhoek") ||
streq_ptr(get_tzname(/* dst= */ false), "MSK")) &&
(x_sec > y_sec ? x_sec - y_sec : y_sec - x_sec) == 3600; (x_sec > y_sec ? x_sec - y_sec : y_sec - x_sec) == 3600;
log_full(ignore ? LOG_WARNING : LOG_ERR, log_full(ignore ? LOG_WARNING : LOG_ERR,
@ -459,6 +461,9 @@ static void test_format_timestamp_loop(void) {
test_format_timestamp_impl(1504938962980066); test_format_timestamp_impl(1504938962980066);
test_format_timestamp_impl(1509482094632752); test_format_timestamp_impl(1509482094632752);
/* With tzdata-2025c, the timestamp (randomly?) fails on MSK time zone (e.g. Europe/Volgograd). */
test_format_timestamp_impl(1414277092997572);
for (unsigned i = 0; i < TRIAL; i++) { for (unsigned i = 0; i < TRIAL; i++) {
usec_t x; usec_t x;