Hey Lennart, Lennart Poettering [2015-05-18 17:12 +0200]: > This code will result in ENOENT being returned on OOM... That's not right...
Fixed. > Also consider using strstrip() here. hostname_cleanup() already filters out whitespace, so I don't think that's needed? > Given that this same code is needed twice in different components, > please add a new call read_etc_hostname() to > src/shared/hostname-util.c (which I just added to git). It should then > also do hostname_cleanup() on the name, and thus pretty much replace > read_and_strip_hostname() entirely in hostname-setup.c. Done. However, I called the function read_hostname_config() and give it a path argument. This is mostly so that we can write tests for it, but maybe one of these days we actually want to use it for other purposes (reading hostnames from container root fs). Martin -- Martin Pitt | http://www.piware.de Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
From ef807f60409b26ab1168cef9df5f5de553e4259c Mon Sep 17 00:00:00 2001 From: Martin Pitt <martin.p...@ubuntu.com> Date: Tue, 19 May 2015 07:49:56 +0200 Subject: [PATCH] hostname: Allow comments in /etc/hostname The hostname(1) tool allows comments in /etc/hostname. Introduce a new read_hostname_config() in hostname-util which reads a hostname configuration file like /etc/hostname, strips out comments, whitespace, and cleans the hostname. Use it in hostname-setup.c and hostnamed and remove duplicated code. Update hostname manpage. Add tests. https://launchpad.net/bugs/1053048 --- man/hostname.xml | 11 ++++++----- src/core/hostname-setup.c | 24 +---------------------- src/hostname/hostnamed.c | 2 +- src/shared/hostname-util.c | 33 ++++++++++++++++++++++++++++++++ src/shared/hostname-util.h | 2 ++ src/test/test-util.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 90 insertions(+), 29 deletions(-) diff --git a/man/hostname.xml b/man/hostname.xml index 5d3d46d..9688450 100644 --- a/man/hostname.xml +++ b/man/hostname.xml @@ -57,11 +57,12 @@ name of the local system that is set during boot using the <citerefentry><refentrytitle>sethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call. It should contain a single newline-terminated - hostname string. The hostname may be a free-form string up to 64 - characters in length; however, it is recommended that it consists - only of 7-bit ASCII lower-case characters and no spaces or dots, - and limits itself to the format allowed for DNS domain name - labels, even though this is not a strict requirement.</para> + hostname string. Comments (lines starting with a `#') are ignored. + The hostname may be a free-form string up to 64 characters in length; + however, it is recommended that it consists only of 7-bit ASCII lower-case + characters and no spaces or dots, and limits itself to the format allowed + for DNS domain name labels, even though this is not a strict + requirement.</para> <para>Depending on the operating system, other configuration files might be checked for configuration of the hostname as well, diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c index 217f201..932ddbf 100644 --- a/src/core/hostname-setup.c +++ b/src/core/hostname-setup.c @@ -30,35 +30,13 @@ #include "hostname-util.h" #include "hostname-setup.h" -static int read_and_strip_hostname(const char *path, char **hn) { - char *s; - int r; - - assert(path); - assert(hn); - - r = read_one_line_file(path, &s); - if (r < 0) - return r; - - hostname_cleanup(s, false); - - if (isempty(s)) { - free(s); - return -ENOENT; - } - - *hn = s; - return 0; -} - int hostname_setup(void) { int r; _cleanup_free_ char *b = NULL; const char *hn; bool enoent = false; - r = read_and_strip_hostname("/etc/hostname", &b); + r = read_hostname_config("/etc/hostname", &b); if (r < 0) { if (r == -ENOENT) enoent = true; diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index ab9ddc7..7ff3a4e 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -96,7 +96,7 @@ static int context_read_data(Context *c) { if (!c->data[PROP_HOSTNAME]) return -ENOMEM; - r = read_one_line_file("/etc/hostname", &c->data[PROP_STATIC_HOSTNAME]); + r = read_hostname_config("/etc/hostname", &c->data[PROP_STATIC_HOSTNAME]); if (r < 0 && r != -ENOENT) return r; diff --git a/src/shared/hostname-util.c b/src/shared/hostname-util.c index 2998fdf..e336f26 100644 --- a/src/shared/hostname-util.c +++ b/src/shared/hostname-util.c @@ -158,3 +158,36 @@ int sethostname_idempotent(const char *s) { return 1; } + +int read_hostname_config(const char *path, char **hostname) { + _cleanup_fclose_ FILE *f = NULL; + char l[LINE_MAX]; + char *name = NULL; + + assert(path); + assert(hostname); + + f = fopen(path, "re"); + if (!f) + return -errno; + + /* may have comments, ignore them */ + FOREACH_LINE(l, f, return -errno) { + truncate_nl(l); + if (l[0] != '\0' && l[0] != '#') { + /* found line with value */ + name = hostname_cleanup(l, false); + name = strdup(name); + if (!name) + return -ENOMEM; + break; + } + } + + if (!name) + /* no non-empty line found */ + return -ENOENT; + + *hostname = name; + return 0; +} diff --git a/src/shared/hostname-util.h b/src/shared/hostname-util.h index f2821c3..0c4763c 100644 --- a/src/shared/hostname-util.h +++ b/src/shared/hostname-util.h @@ -35,3 +35,5 @@ char* hostname_cleanup(char *s, bool lowercase); bool is_localhost(const char *hostname); int sethostname_idempotent(const char *s); + +int read_hostname_config(const char *path, char **hostname); diff --git a/src/test/test-util.c b/src/test/test-util.c index 9af3e75..36773c1 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -549,6 +549,52 @@ static void test_hostname_is_valid(void) { assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")); } +static void test_read_hostname_config(void) { + char path[] = "/tmp/hostname.XXXXXX"; + char *hostname; + int fd; + + fd = mkostemp_safe(path, O_RDWR|O_CLOEXEC); + assert(fd > 0); + close(fd); + + /* simple hostname */ + write_string_file(path, "foo"); + assert_se(read_hostname_config(path, &hostname) == 0); + assert_se(streq(hostname, "foo")); + free(hostname); + + /* with comment */ + write_string_file(path, "# comment\nfoo"); + assert_se(read_hostname_config(path, &hostname) == 0); + assert_se(streq(hostname, "foo")); + free(hostname); + + /* with comment and extra whitespace */ + write_string_file(path, "# comment\n\n foo "); + assert_se(read_hostname_config(path, &hostname) == 0); + assert_se(streq(hostname, "foo")); + free(hostname); + + /* cleans up name */ + write_string_file(path, "!foo/bar.com"); + assert_se(read_hostname_config(path, &hostname) == 0); + assert_se(streq(hostname, "foobar.com")); + free(hostname); + + /* no value set */ + hostname = (char*) 0x1234; + write_string_file(path, "# nothing here\n"); + assert_se(read_hostname_config(path, &hostname) == -ENOENT); + assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */ + + /* nonexisting file */ + assert_se(read_hostname_config("/non/existing", &hostname) == -ENOENT); + assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */ + + unlink(path); +} + static void test_u64log2(void) { assert_se(u64log2(0) == 0); assert_se(u64log2(8) == 3); @@ -1481,6 +1527,7 @@ int main(int argc, char *argv[]) { test_foreach_word_quoted(); test_memdup_multiply(); test_hostname_is_valid(); + test_read_hostname_config(); test_u64log2(); test_protect_errno(); test_parse_size(); -- 2.1.4
signature.asc
Description: Digital signature
_______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel