From: Lennart Poettering Date: Wed, 6 May 2026 13:17:36 +0000 (+0200) Subject: fileio: add new read_boolean_file() helper X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=db8046535b419142e2850499552600e2fb0ac558;p=thirdparty%2Fsystemd.git fileio: add new read_boolean_file() helper --- diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 31e9af2e4e0..8149bb8b0dd 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -431,6 +431,20 @@ int read_one_line_file_at(int dir_fd, const char *filename, char **ret) { return read_line(f, LONG_LINE_MAX, ret); } +int read_boolean_file_at(int dir_fd, const char *filename) { + _cleanup_free_ char *s = NULL; + int r; + + assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT)); + assert(filename); + + r = read_one_line_file_at(dir_fd, filename, &s); + if (r < 0) + return r; + + return parse_boolean(s); +} + int verify_file_at(int dir_fd, const char *fn, const char *blob, bool accept_extra_nl) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *buf = NULL; diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 274fdfbd7c8..5e6e3de1fef 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -63,6 +63,10 @@ int read_one_line_file_at(int dir_fd, const char *filename, char **ret); static inline int read_one_line_file(const char *filename, char **ret) { return read_one_line_file_at(AT_FDCWD, filename, ret); } +int read_boolean_file_at(int dir_fd, const char *filename); +static inline int read_boolean_file(const char *filename) { + return read_boolean_file_at(AT_FDCWD, filename); +} int read_full_file_full(int dir_fd, const char *filename, uint64_t offset, size_t size, ReadFullFileFlags flags, const char *bind_name, char **ret_contents, size_t *ret_size); static inline int read_full_file_at(int dir_fd, const char *filename, char **ret_contents, size_t *ret_size) { return read_full_file_full(dir_fd, filename, UINT64_MAX, SIZE_MAX, 0, NULL, ret_contents, ret_size); diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index d27bf7ab5d8..d050522028f 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -823,4 +823,58 @@ TEST(read_one_line_file_at_xat_fdroot) { ASSERT_OK(pidref_wait_for_terminate_and_check("(server)", &pidref, WAIT_LOG)); } +TEST(read_boolean_file) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-read-boolean-file-XXXXXX"; + _cleanup_close_ int fd = -EBADF, dfd = -EBADF; + const char *rel; + + ASSERT_OK(fd = mkostemp_safe(fn)); + + ASSERT_OK(write_string_file(fn, "yes", WRITE_STRING_FILE_TRUNCATE)); + ASSERT_OK_EQ(read_boolean_file(fn), true); + ASSERT_OK_EQ(read_boolean_file_at(AT_FDCWD, fn), true); + + ASSERT_OK(write_string_file(fn, "0", WRITE_STRING_FILE_TRUNCATE)); + ASSERT_OK_EQ(read_boolean_file(fn), false); + ASSERT_OK_EQ(read_boolean_file_at(AT_FDCWD, fn), false); + + ASSERT_OK(write_string_file(fn, "true\nignored\n", WRITE_STRING_FILE_TRUNCATE)); + ASSERT_OK_EQ(read_boolean_file(fn), true); + + ASSERT_OK(write_string_file(fn, "garbage", WRITE_STRING_FILE_TRUNCATE)); + ASSERT_ERROR(read_boolean_file(fn), EINVAL); + + ASSERT_ERROR(read_boolean_file("/tmp/this-file-better-not-exist-XXX"), ENOENT); + + /* Now test XAT_FDROOT: filename is relative, looked up against "/" */ + ASSERT_TRUE(path_startswith(fn, "/")); + rel = fn + 1; + + ASSERT_OK(write_string_file(fn, "on", WRITE_STRING_FILE_TRUNCATE)); + ASSERT_OK_EQ(read_boolean_file_at(XAT_FDROOT, rel), true); + + ASSERT_OK(write_string_file(fn, "off", WRITE_STRING_FILE_TRUNCATE)); + ASSERT_OK_EQ(read_boolean_file_at(XAT_FDROOT, rel), false); + + ASSERT_ERROR(read_boolean_file_at(XAT_FDROOT, "tmp/this-file-better-not-exist-XXX"), ENOENT); + + /* And confirm XAT_FDROOT ignores the cwd: chdir somewhere unrelated, then look up + * the same relative-to-/ path. */ + _cleanup_free_ char *cwd = NULL; + ASSERT_OK(safe_getcwd(&cwd)); + ASSERT_OK_ERRNO(chdir("/usr")); + + ASSERT_OK(write_string_file(fn, "yes", WRITE_STRING_FILE_TRUNCATE)); + ASSERT_OK_EQ(read_boolean_file_at(XAT_FDROOT, rel), true); + + ASSERT_OK_ERRNO(chdir(cwd)); + + /* Also test the dir_fd >= 0 path using an actual fd for /tmp. */ + ASSERT_OK(dfd = open("/tmp", O_DIRECTORY|O_CLOEXEC)); + ASSERT_OK(write_string_file(fn, "1", WRITE_STRING_FILE_TRUNCATE)); + _cleanup_free_ char *bn = NULL; + ASSERT_OK(path_extract_filename(fn, &bn)); + ASSERT_OK_EQ(read_boolean_file_at(dfd, bn), true); +} + DEFINE_TEST_MAIN(LOG_DEBUG);