mirror of
https://github.com/systemd/systemd.git
synced 2025-01-09 01:18:19 +03:00
basic/fileio: two modernizations (#35559)
This commit is contained in:
commit
1c43f92a2a
@ -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;
|
||||
|
||||
_cleanup_free_ char *line = NULL;
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!startswith(line, "#!"))
|
||||
_cleanup_free_ char *p = NULL;
|
||||
const char *s = line;
|
||||
|
||||
r = extract_first_word(&s, &p, /* separators = */ NULL, /* flags = */ 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return -ENOEXEC;
|
||||
|
||||
if (ret)
|
||||
*ret = TAKE_PTR(p);
|
||||
return 0;
|
||||
|
||||
ans = strstrip(line + 2);
|
||||
len = strcspn(ans, " \t");
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
ans = strndup(ans, len);
|
||||
if (!ans)
|
||||
return -ENOMEM;
|
||||
|
||||
*interpreter = ans;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -957,19 +972,21 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
|
||||
return 0;
|
||||
}
|
||||
|
||||
DIR *xopendirat(int fd, const char *name, int flags) {
|
||||
_cleanup_close_ int nfd = -EBADF;
|
||||
DIR* xopendirat(int dir_fd, const char *name, int flags) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
assert(!(flags & O_CREAT));
|
||||
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
|
||||
assert(name);
|
||||
assert(!(flags & (O_CREAT|O_TMPFILE)));
|
||||
|
||||
if (fd == AT_FDCWD && flags == 0)
|
||||
if (dir_fd == AT_FDCWD && flags == 0)
|
||||
return opendir(name);
|
||||
|
||||
nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
|
||||
if (nfd < 0)
|
||||
fd = openat(dir_fd, name, O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
return take_fdopendir(&nfd);
|
||||
return take_fdopendir(&fd);
|
||||
}
|
||||
|
||||
int fopen_mode_to_flags(const char *mode) {
|
||||
|
@ -94,11 +94,11 @@ 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);
|
||||
|
||||
DIR *xopendirat(int dirfd, const char *name, int flags);
|
||||
DIR* xopendirat(int dir_fd, const char *name, int flags);
|
||||
|
||||
typedef enum XfopenFlags {
|
||||
XFOPEN_UNLOCKED = 1 << 0, /* call __fsetlocking(FSETLOCKING_BYCALLER) after opened */
|
||||
@ -148,6 +148,14 @@ typedef enum ReadLineFlags {
|
||||
} ReadLineFlags;
|
||||
|
||||
int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret);
|
||||
static inline int read_line(FILE *f, size_t limit, char **ret) {
|
||||
return read_line_full(f, limit, 0, ret);
|
||||
}
|
||||
static inline int read_nul_string(FILE *f, size_t limit, char **ret) {
|
||||
return read_line_full(f, limit, READ_LINE_ONLY_NUL, ret);
|
||||
}
|
||||
|
||||
int read_stripped_line(FILE *f, size_t limit, char **ret);
|
||||
|
||||
static inline bool file_offset_beyond_memory_size(off_t x) {
|
||||
if (x < 0) /* off_t is signed, filter that out */
|
||||
@ -155,16 +163,6 @@ static inline bool file_offset_beyond_memory_size(off_t x) {
|
||||
return (uint64_t) x > (uint64_t) SIZE_MAX;
|
||||
}
|
||||
|
||||
static inline int read_line(FILE *f, size_t limit, char **ret) {
|
||||
return read_line_full(f, limit, 0, ret);
|
||||
}
|
||||
|
||||
static inline int read_nul_string(FILE *f, size_t limit, char **ret) {
|
||||
return read_line_full(f, limit, READ_LINE_ONLY_NUL, ret);
|
||||
}
|
||||
|
||||
int read_stripped_line(FILE *f, size_t limit, char **ret);
|
||||
|
||||
int safe_fgetc(FILE *f, char *ret);
|
||||
|
||||
int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line);
|
||||
|
@ -249,7 +249,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);
|
||||
@ -261,14 +261,15 @@ 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;
|
||||
|
||||
path = interpreter;
|
||||
}
|
||||
|
||||
if (path) {
|
||||
r = journal_add_match_pair(j, "_EXE", path);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user