From ad9a66fee8f370b7cc5c491bccb971d9d63129f5 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Tue, 10 Dec 2024 16:14:34 +0100 Subject: [PATCH] basic/fileio: clean up executable_is_script() a bit - Rename to script_get_shebang_interpreter and return -EMEDIUMTYPE if the executable is not a script. We nowadays utilize the scheme of making ret param of getters optional, and use them directly as checkers. - Don't unnecessarily read the whole line, but check only the shebang first. --- src/basic/fileio.c | 53 +++++++++++++++++++++------------ src/basic/fileio.h | 2 +- src/journal/journalctl-filter.c | 15 +++++----- src/test/test-fileio.c | 12 +++----- 4 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 8cf7f21b6bb..9f2bbc13236 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -14,6 +14,7 @@ #include "alloc-util.h" #include "chase.h" +#include "extract-word.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" @@ -856,35 +857,49 @@ int read_full_file_full( return read_full_stream_full(f, filename, offset, size, flags, ret_contents, ret_size); } -int executable_is_script(const char *path, char **interpreter) { - _cleanup_free_ char *line = NULL; - size_t len; - char *ans; +int script_get_shebang_interpreter(const char *path, char **ret) { + _cleanup_fclose_ FILE *f = NULL; int r; assert(path); - r = read_one_line_file(path, &line); - if (r == -ENOBUFS) /* First line overly long? if so, then it's not a script */ - return 0; + f = fopen(path, "re"); + if (!f) + return -errno; + + char c; + r = safe_fgetc(f, &c); if (r < 0) return r; + if (r == 0) + return -EBADMSG; + if (c != '#') + return -EMEDIUMTYPE; + r = safe_fgetc(f, &c); + if (r < 0) + return r; + if (r == 0) + return -EBADMSG; + if (c != '!') + return -EMEDIUMTYPE; - if (!startswith(line, "#!")) - return 0; - - ans = strstrip(line + 2); - len = strcspn(ans, " \t"); + _cleanup_free_ char *line = NULL; + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; - if (len == 0) - return 0; + _cleanup_free_ char *p = NULL; + const char *s = line; - ans = strndup(ans, len); - if (!ans) - return -ENOMEM; + r = extract_first_word(&s, &p, /* separators = */ NULL, /* flags = */ 0); + if (r < 0) + return r; + if (r == 0) + return -ENOEXEC; - *interpreter = ans; - return 1; + if (ret) + *ret = TAKE_PTR(p); + return 0; } /** diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 29518d201ee..bd053050e1a 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -94,7 +94,7 @@ static inline int verify_file(const char *fn, const char *blob, bool accept_extr return verify_file_at(AT_FDCWD, fn, blob, accept_extra_nl); } -int executable_is_script(const char *path, char **interpreter); +int script_get_shebang_interpreter(const char *path, char **ret); int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field); diff --git a/src/journal/journalctl-filter.c b/src/journal/journalctl-filter.c index 1c6348574c5..378e90b3654 100644 --- a/src/journal/journalctl-filter.c +++ b/src/journal/journalctl-filter.c @@ -317,7 +317,7 @@ static int add_matches_for_executable(sd_journal *j, const char *path) { assert(j); assert(path); - if (executable_is_script(path, &interpreter) > 0) { + if (script_get_shebang_interpreter(path, &interpreter) >= 0) { _cleanup_free_ char *comm = NULL; r = path_extract_filename(path, &comm); @@ -329,15 +329,16 @@ static int add_matches_for_executable(sd_journal *j, const char *path) { return log_error_errno(r, "Failed to add match: %m"); /* Append _EXE only if the interpreter is not a link. Otherwise, it might be outdated often. */ - path = is_symlink(interpreter) > 0 ? interpreter : NULL; - } + if (is_symlink(interpreter) > 0) + return 0; - if (path) { - r = journal_add_match_pair(j, "_EXE", path); - if (r < 0) - return log_error_errno(r, "Failed to add match: %m"); + path = interpreter; } + r = journal_add_match_pair(j, "_EXE", path); + if (r < 0) + return log_error_errno(r, "Failed to add match: %m"); + return 0; } diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index 7c222b09327..76f55983258 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -311,26 +311,22 @@ TEST(merge_env_file_invalid) { assert_se(strv_isempty(a)); } -TEST(executable_is_script) { +TEST(script_get_shebang_interpreter) { _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX"; _cleanup_fclose_ FILE *f = NULL; char *command; - int r; assert_se(fmkostemp_safe(t, "w", &f) == 0); fputs("#! /bin/script -a -b \ngoo goo", f); fflush(f); - r = executable_is_script(t, &command); - assert_se(r > 0); + ASSERT_OK(script_get_shebang_interpreter(t, &command)); ASSERT_STREQ(command, "/bin/script"); free(command); - r = executable_is_script("/bin/sh", &command); - assert_se(r == 0); + ASSERT_ERROR(script_get_shebang_interpreter("/bin/sh", NULL), EMEDIUMTYPE); - r = executable_is_script("/usr/bin/yum", &command); - if (r > 0) { + if (script_get_shebang_interpreter("/usr/bin/yum", &command) >= 0) { assert_se(startswith(command, "/")); free(command); } -- 2.47.3