hostname-util: rework read_hostname_config() a bit
First of all, let's rename it to read_etc_hostname(), to make clearer what kind of configuration it actually reads: the file format defined in /etc/hostname and nothing else. Secondly: let's port this to use read_line(), i.e. the new way to read lines from a file in a safe, bounded way. Thirdly: let's strip leading/trailing whitespace from what we are reading. Given that we are already pretty lenient what we read (comments and empty lines), let's be permissive regarding whitespace too. Fourthly: let's actually validate the hostname when reading it. So far we tried to make it valid, but that's not always possible (for example, we can't make an empty hostname valid, ever).
This commit is contained in:
+46
-24
@@ -25,6 +25,8 @@
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "def.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "hostname-util.h"
|
||||
@@ -219,35 +221,55 @@ 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;
|
||||
int read_etc_hostname_stream(FILE *f, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(hostname);
|
||||
assert(f);
|
||||
assert(ret);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
char *p;
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) /* EOF without any hostname? the file is empty, let's treat that exactly like no file at all: ENOENT */
|
||||
return -ENOENT;
|
||||
|
||||
p = strstrip(line);
|
||||
|
||||
/* File may have empty lines or comments, ignore them */
|
||||
if (!IN_SET(*p, '\0', '#')) {
|
||||
char *copy;
|
||||
|
||||
hostname_cleanup(p); /* normalize the hostname */
|
||||
|
||||
if (!hostname_is_valid(p, true)) /* check that the hostname we return is valid */
|
||||
return -EBADMSG;
|
||||
|
||||
copy = strdup(p);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = copy;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int read_etc_hostname(const char *path, char **ret) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (!path)
|
||||
path = "/etc/hostname";
|
||||
|
||||
f = fopen(path, "re");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
/* may have comments, ignore them */
|
||||
FOREACH_LINE(l, f, return -errno) {
|
||||
truncate_nl(l);
|
||||
if (!IN_SET(l[0], '\0', '#')) {
|
||||
/* found line with value */
|
||||
name = hostname_cleanup(l);
|
||||
name = strdup(name);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return read_etc_hostname_stream(f, ret);
|
||||
|
||||
if (!name)
|
||||
/* no non-empty line found */
|
||||
return -ENOENT;
|
||||
|
||||
*hostname = name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -39,4 +39,5 @@ bool is_gateway_hostname(const char *hostname);
|
||||
|
||||
int sethostname_idempotent(const char *s);
|
||||
|
||||
int read_hostname_config(const char *path, char **hostname);
|
||||
int read_etc_hostname_stream(FILE *f, char **ret);
|
||||
int read_etc_hostname(const char *path, char **ret);
|
||||
|
||||
Reference in New Issue
Block a user