diff options
-rw-r--r-- | src/basic/mkdir.c | 2 | ||||
-rw-r--r-- | src/basic/stat-util.c | 217 | ||||
-rw-r--r-- | src/basic/stat-util.h | 32 | ||||
-rw-r--r-- | src/basic/time-util.c | 2 | ||||
-rw-r--r-- | src/firstboot/firstboot.c | 4 | ||||
-rw-r--r-- | src/kernel-install/kernel-install.c | 2 |
6 files changed, 129 insertions, 130 deletions
diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c index 5dd56c89a4..7c1ad7dd64 100644 --- a/src/basic/mkdir.c +++ b/src/basic/mkdir.c @@ -112,7 +112,7 @@ int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t ui /* drop the last component */ path = strndupa_safe(path, e - path); - r = is_dir_full(dir_fd, path, true); + r = is_dir_at(dir_fd, path, /* follow = */ true); if (r > 0) return 0; if (r == 0) diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 6a8ec1ba2a..ec6273c7d0 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -25,43 +25,130 @@ #include "stat-util.h" #include "string-util.h" -int is_symlink(const char *path) { - struct stat info; +static int verify_stat_at( + int fd, + const char *path, + bool follow, + int (*verify_func)(const struct stat *st), + bool verify) { - assert(path); + struct stat st; + int r; + + assert(fd >= 0 || fd == AT_FDCWD); + assert(!isempty(path) || !follow); + assert(verify_func); - if (lstat(path, &info) < 0) + if (fstatat(fd, strempty(path), &st, + (isempty(path) ? AT_EMPTY_PATH : 0) | (follow ? 0 : AT_SYMLINK_NOFOLLOW)) < 0) return -errno; - return !!S_ISLNK(info.st_mode); + r = verify_func(&st); + return verify ? r : r >= 0; } -int is_dir_full(int atfd, const char* path, bool follow) { - struct stat st; - int r; +int stat_verify_regular(const struct stat *st) { + assert(st); - assert(atfd >= 0 || atfd == AT_FDCWD); - assert(atfd >= 0 || path); + /* Checks whether the specified stat() structure refers to a regular file. If not returns an + * appropriate error code. */ - if (path) - r = fstatat(atfd, path, &st, follow ? 0 : AT_SYMLINK_NOFOLLOW); - else - r = fstat(atfd, &st); - if (r < 0) - return -errno; + if (S_ISDIR(st->st_mode)) + return -EISDIR; + + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (!S_ISREG(st->st_mode)) + return -EBADFD; - return !!S_ISDIR(st.st_mode); + return 0; } -int is_device_node(const char *path) { - struct stat info; +int verify_regular_at(int fd, const char *path, bool follow) { + return verify_stat_at(fd, path, follow, stat_verify_regular, true); +} - assert(path); +int fd_verify_regular(int fd) { + assert(fd >= 0); + return verify_regular_at(fd, NULL, false); +} - if (lstat(path, &info) < 0) - return -errno; +int stat_verify_directory(const struct stat *st) { + assert(st); - return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (!S_ISDIR(st->st_mode)) + return -ENOTDIR; + + return 0; +} + +int fd_verify_directory(int fd) { + assert(fd >= 0); + return verify_stat_at(fd, NULL, false, stat_verify_directory, true); +} + +int is_dir_at(int fd, const char *path, bool follow) { + return verify_stat_at(fd, path, follow, stat_verify_directory, false); +} + +int is_dir(const char *path, bool follow) { + assert(!isempty(path)); + return is_dir_at(AT_FDCWD, path, follow); +} + +int stat_verify_symlink(const struct stat *st) { + assert(st); + + if (S_ISDIR(st->st_mode)) + return -EISDIR; + + if (!S_ISLNK(st->st_mode)) + return -ENOLINK; + + return 0; +} + +int is_symlink(const char *path) { + assert(!isempty(path)); + return verify_stat_at(AT_FDCWD, path, false, stat_verify_symlink, false); +} + +int stat_verify_linked(const struct stat *st) { + assert(st); + + if (st->st_nlink <= 0) + return -EIDRM; /* recognizable error. */ + + return 0; +} + +int fd_verify_linked(int fd) { + assert(fd >= 0); + return verify_stat_at(fd, NULL, false, stat_verify_linked, true); +} + +int stat_verify_device_node(const struct stat *st) { + assert(st); + + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (S_ISDIR(st->st_mode)) + return -EISDIR; + + if (!S_ISBLK(st->st_mode) && !S_ISCHR(st->st_mode)) + return -ENOTTY; + + return 0; +} + +int is_device_node(const char *path) { + assert(!isempty(path)); + return verify_stat_at(AT_FDCWD, path, false, stat_verify_device_node, false); } int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup) { @@ -260,90 +347,6 @@ int path_is_network_fs(const char *path) { return is_network_fs(&s); } -int stat_verify_linked(const struct stat *st) { - assert(st); - - if (st->st_nlink <= 0) - return -EIDRM; /* recognizable error. */ - - return 0; -} - -int fd_verify_linked(int fd) { - struct stat st; - - assert(fd >= 0); - - if (fstat(fd, &st) < 0) - return -errno; - - return stat_verify_linked(&st); -} - -int stat_verify_regular(const struct stat *st) { - assert(st); - - /* Checks whether the specified stat() structure refers to a regular file. If not returns an - * appropriate error code. */ - - if (S_ISDIR(st->st_mode)) - return -EISDIR; - - if (S_ISLNK(st->st_mode)) - return -ELOOP; - - if (!S_ISREG(st->st_mode)) - return -EBADFD; - - return 0; -} - -int fd_verify_regular(int fd) { - struct stat st; - - assert(fd >= 0); - - if (fstat(fd, &st) < 0) - return -errno; - - return stat_verify_regular(&st); -} - -int verify_regular_at(int dir_fd, const char *path, bool follow) { - struct stat st; - - assert(dir_fd >= 0 || dir_fd == AT_FDCWD); - assert(path); - - if (fstatat(dir_fd, path, &st, (isempty(path) ? AT_EMPTY_PATH : 0) | (follow ? 0 : AT_SYMLINK_NOFOLLOW)) < 0) - return -errno; - - return stat_verify_regular(&st); -} - -int stat_verify_directory(const struct stat *st) { - assert(st); - - if (S_ISLNK(st->st_mode)) - return -ELOOP; - - if (!S_ISDIR(st->st_mode)) - return -ENOTDIR; - - return 0; -} - -int fd_verify_directory(int fd) { - struct stat st; - - assert(fd >= 0); - - if (fstat(fd, &st) < 0) - return -errno; - - return stat_verify_directory(&st); -} - int proc_mounted(void) { int r; diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index bab5415357..47445d852a 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -14,14 +14,22 @@ #include "siphash24.h" #include "time-util.h" +int stat_verify_regular(const struct stat *st); +int verify_regular_at(int fd, const char *path, bool follow); +int fd_verify_regular(int fd); + +int stat_verify_directory(const struct stat *st); +int fd_verify_directory(int fd); +int is_dir_at(int fd, const char *path, bool follow); +int is_dir(const char *path, bool follow); + +int stat_verify_symlink(const struct stat *st); int is_symlink(const char *path); -int is_dir_full(int atfd, const char *fname, bool follow); -static inline int is_dir(const char *path, bool follow) { - return is_dir_full(AT_FDCWD, path, follow); -} -static inline int is_dir_fd(int fd) { - return is_dir_full(fd, NULL, false); -} + +int stat_verify_linked(const struct stat *st); +int fd_verify_linked(int fd); + +int stat_verify_device_node(const struct stat *st); int is_device_node(const char *path); int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup); @@ -72,16 +80,6 @@ int path_is_network_fs(const char *path); */ #define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b) -int stat_verify_linked(const struct stat *st); -int fd_verify_linked(int fd); - -int stat_verify_regular(const struct stat *st); -int fd_verify_regular(int fd); -int verify_regular_at(int dir_fd, const char *path, bool follow); - -int stat_verify_directory(const struct stat *st); -int fd_verify_directory(int fd); - int proc_mounted(void); bool stat_inode_same(const struct stat *a, const struct stat *b); diff --git a/src/basic/time-util.c b/src/basic/time-util.c index d1736f0aa3..3601be25fb 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -1573,7 +1573,7 @@ int verify_timezone(const char *name, int log_level) { r = fd_verify_regular(fd); if (r < 0) - return log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t); + return log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t); r = loop_read_exact(fd, buf, 4, false); if (r < 0) diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 7f6c146120..6afabef430 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -1066,10 +1066,8 @@ static int process_root_account(int rfd) { FOREACH_STRING(s, "passwd", "shadow") { r = verify_regular_at(pfd, s, /* follow = */ false); - if (IN_SET(r, -EISDIR, -ELOOP, -EBADFD)) - return log_error_errno(r, "/etc/%s is not a regular file", s); if (r < 0 && r != -ENOENT) - return log_error_errno(r, "Failed to check whether /etc/%s is a regular file: %m", s); + return log_error_errno(r, "Verification of /etc/%s being regular file failed: %m", s); r = should_configure(pfd, s); if (r < 0) diff --git a/src/kernel-install/kernel-install.c b/src/kernel-install/kernel-install.c index 273c1d9c47..4df52c8342 100644 --- a/src/kernel-install/kernel-install.c +++ b/src/kernel-install/kernel-install.c @@ -801,7 +801,7 @@ static int context_ensure_layout(Context *c) { if (!entry_token_path) return log_oom(); - r = is_dir_full(c->rfd, entry_token_path, /* follow = */ false); + r = is_dir_at(c->rfd, entry_token_path, /* follow = */ false); if (r < 0 && r != -ENOENT) return log_error_errno(r, "Failed to check if '%s' is a directory: %m", entry_token_path); if (r > 0) { |