From f6a1346e4e738f77afec5c10454edb833a502ba6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 3 Dec 2023 14:53:49 +0100 Subject: [PATCH] tmpfiles: split out helper to open and read a "config file" No functional change. Note that this function will be modified in subsequent commits, and the API will change. --- src/basic/conf-files.c | 82 +++++++++++++++++++++++++++++++++++++++++ src/basic/conf-files.h | 18 +++++++++ src/tmpfiles/tmpfiles.c | 66 ++++----------------------------- 3 files changed, 107 insertions(+), 59 deletions(-) diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c index a56f82f8a3e..d85d651525f 100644 --- a/src/basic/conf-files.c +++ b/src/basic/conf-files.c @@ -9,7 +9,10 @@ #include "conf-files.h" #include "constants.h" #include "dirent-util.h" +#include "errno-util.h" #include "fd-util.h" +#include "fileio.h" +#include "glyph-util.h" #include "hashmap.h" #include "log.h" #include "macro.h" @@ -372,3 +375,82 @@ int conf_files_list_dropins( return conf_files_list_strv(ret, ".conf", root, 0, (const char* const*) dropin_dirs); } + +/** + * Open and read a config file. + * + * The argument may be: + * - '-', meaning stdin. + * - a non-absolute path. In this case are searched. + * - an absolute path. In this case is opened directly. + */ +int conf_file_read( + const char *root, + const char **config_dirs, + const char *fn, + parse_line_t parse_line, + void *userdata, + bool ignore_enoent, + bool *invalid_config) { + + _cleanup_fclose_ FILE *_f = NULL; + _cleanup_free_ char *_fn = NULL; + unsigned v = 0; + FILE *f; + int r; + + assert(fn); + + if (streq(fn, "-")) { + f = stdin; + fn = ""; + + log_debug("Reading config from stdin%s", special_glyph(SPECIAL_GLYPH_ELLIPSIS)); + + } else { + r = search_and_fopen(fn, "re", root, config_dirs, &_f, &_fn); + if (r == -ENOENT && ignore_enoent) { + log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn); + return 0; /* No error, but nothing happened. */ + } + if (r < 0) + return log_error_errno(r, "Failed to read '%s': %m", fn); + + f = _f; + fn = _fn; + log_debug("Reading config file \"%s\"%s", fn, special_glyph(SPECIAL_GLYPH_ELLIPSIS)); + } + + r = 1; /* We entered the part where we may modify state. */ + + for (;;) { + _cleanup_free_ char *line = NULL; + bool invalid_line = false; + int k; + + k = read_stripped_line(f, LONG_LINE_MAX, &line); + if (k < 0) + return log_error_errno(k, "Failed to read '%s': %m", fn); + if (k == 0) + break; + + v++; + + if (IN_SET(line[0], 0, '#')) + continue; + + k = parse_line(fn, v, line, &invalid_line, userdata); + if (k < 0 && invalid_line) { + /* Allow reporting with a special code if the caller requested this. */ + if (invalid_config) + *invalid_config = true; + } else + /* The first error, if any, becomes our return value. */ + RET_GATHER(r, k); + } + + if (ferror(f)) + RET_GATHER(r, log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read from file %s.", fn)); + + return r; +} diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h index 566cc8fda46..cf89ee62c68 100644 --- a/src/basic/conf-files.h +++ b/src/basic/conf-files.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include + #include "macro.h" enum { @@ -29,3 +31,19 @@ int conf_files_list_dropins( const char *dropin_dirname, const char *root, const char * const *dirs); + +typedef int parse_line_t( + const char *fname, + unsigned line, + const char *buffer, + bool *invalid_config, + void *userdata); + +int conf_file_read( + const char *root, + const char **config_dirs, + const char *fn, + parse_line_t parse_line, + void *userdata, + bool ignore_enoent, + bool *invalid_config); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 4e245e36681..a2eb05c6a63 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -3463,12 +3463,13 @@ static bool is_duplicated_item(ItemArray *existing, const Item *i) { } static int parse_line( - Context *c, const char *fname, unsigned line, const char *buffer, - bool *invalid_config) { + bool *invalid_config, + void *context) { + Context *c = ASSERT_PTR(context); _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL; _cleanup_(item_free_contents) Item i = { /* The "age-by" argument considers all file timestamp types by default. */ @@ -3481,7 +3482,6 @@ static int parse_line( bool append_or_force = false, boot = false, allow_failure = false, try_replace = false, unbase64 = false, from_cred = false, missing_user_or_group = false; - assert(c); assert(fname); assert(line >= 1); assert(buffer); @@ -4225,62 +4225,16 @@ static int read_config_file( bool ignore_enoent, bool *invalid_config) { - _cleanup_fclose_ FILE *_f = NULL; - _cleanup_free_ char *pp = NULL; - unsigned v = 0; - FILE *f; ItemArray *ia; int r = 0; assert(c); assert(fn); - if (streq(fn, "-")) { - log_debug("Reading config from stdin%s", special_glyph(SPECIAL_GLYPH_ELLIPSIS)); - fn = ""; - f = stdin; - } else { - r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &_f, &pp); - if (r < 0) { - if (ignore_enoent && r == -ENOENT) { - log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn); - return 0; - } - - return log_error_errno(r, "Failed to open '%s': %m", fn); - } - - log_debug("Reading config file \"%s\"%s", pp, special_glyph(SPECIAL_GLYPH_ELLIPSIS)); - fn = pp; - f = _f; - } - - for (;;) { - _cleanup_free_ char *line = NULL; - bool invalid_line = false; - int k; - - k = read_stripped_line(f, LONG_LINE_MAX, &line); - if (k < 0) - return log_error_errno(k, "Failed to read '%s': %m", fn); - if (k == 0) - break; - - v++; - - if (IN_SET(line[0], 0, '#')) - continue; - - k = parse_line(c, fn, v, line, &invalid_line); - if (k < 0) { - if (invalid_line) - /* Allow reporting with a special code if the caller requested this */ - *invalid_config = true; - else if (r == 0) - /* The first error becomes our return value */ - r = k; - } - } + r = conf_file_read(arg_root, (const char**) config_dirs, fn, + parse_line, c, ignore_enoent, invalid_config); + if (r <= 0) + return r; /* we have to determine age parameter for each entry of type X */ ORDERED_HASHMAP_FOREACH(ia, c->globs) @@ -4319,12 +4273,6 @@ static int read_config_file( } } - if (ferror(f)) { - log_error_errno(errno, "Failed to read from file %s: %m", fn); - if (r == 0) - r = -EIO; - } - return r; } -- 2.47.3