diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index d04da52a78..3e2d191bbb 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -220,6 +220,28 @@ int is_device_node(const char *path) { return verify_stat_at(AT_FDCWD, path, false, stat_verify_device_node, false); } +int stat_verify_regular_or_block(const struct stat *st) { + assert(st); + + if (S_ISDIR(st->st_mode)) + return -EISDIR; + + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (!S_ISREG(st->st_mode) && !S_ISBLK(st->st_mode)) + return -EBADFD; + + return 0; +} + +int fd_verify_regular_or_block(int fd) { + if (IN_SET(fd, AT_FDCWD, XAT_FDROOT)) + return -EISDIR; + + return verify_stat_at(fd, /* path= */ NULL, /* follow= */ false, stat_verify_regular_or_block, /* verify= */ true); +} + int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup) { _cleanup_close_ int fd = -EBADF; struct dirent *buf; diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index 2b50c9c558..6eded0d848 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -31,6 +31,9 @@ int fd_verify_linked(int fd); int stat_verify_device_node(const struct stat *st); int is_device_node(const char *path); +int stat_verify_regular_or_block(const struct stat *st); +int fd_verify_regular_or_block(int fd); + int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup); static inline int dir_is_empty(const char *path, bool ignore_hidden_or_backup) { return dir_is_empty_at(AT_FDCWD, path, ignore_hidden_or_backup); diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index caa05db26f..5342bea21e 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -1250,10 +1250,9 @@ static int open_image_file( if (fstat(image_fd, &st) < 0) return log_error_errno(errno, "Failed to fstat() image file: %m"); - if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode)) - return log_error_errno( - S_ISDIR(st.st_mode) ? SYNTHETIC_ERRNO(EISDIR) : SYNTHETIC_ERRNO(EBADFD), - "Image file %s is not a regular file or block device.", ip); + r = stat_verify_regular_or_block(&st); + if (r < 0) + return log_error_errno(r, "Image file '%s' is not a regular file or block device.", ip); /* Locking block devices doesn't really make sense, as this might interfere with * udev's workings, and these locks aren't network propagated anyway, hence not what diff --git a/src/import/import-raw.c b/src/import/import-raw.c index 05d4bc9c9f..2095a0dde5 100644 --- a/src/import/import-raw.c +++ b/src/import/import-raw.c @@ -22,6 +22,7 @@ #include "pretty-print.h" #include "qcow2-util.h" #include "ratelimit.h" +#include "stat-util.h" #include "string-util.h" #include "terminal-util.h" #include "time-util.h" @@ -309,9 +310,9 @@ static int raw_import_open_disk(RawImport *i) { if (fstat(i->output_fd, &i->output_stat) < 0) return log_error_errno(errno, "Failed to stat() output file: %m"); - if (!S_ISREG(i->output_stat.st_mode) && !S_ISBLK(i->output_stat.st_mode)) - return log_error_errno(SYNTHETIC_ERRNO(EBADFD), - "Target file is not a regular file or block device"); + r = stat_verify_regular_or_block(&i->output_stat); + if (r < 0) + return log_error_errno(r, "Target file is not a regular file or block device."); if (i->offset != UINT64_MAX) { if (lseek(i->output_fd, i->offset, SEEK_SET) < 0) diff --git a/src/mountfsd/mountwork.c b/src/mountfsd/mountwork.c index 3856e9da94..a5d34d4479 100644 --- a/src/mountfsd/mountwork.c +++ b/src/mountfsd/mountwork.c @@ -158,16 +158,10 @@ static int validate_image_fd(int fd, MountImageParameters *p) { assert(fd >= 0); assert(p); - struct stat st; - if (fstat(fd, &st) < 0) - return -errno; - /* Only support regular files and block devices. Let's use stat_verify_regular() here for the nice - * error numbers it generates. */ - if (!S_ISBLK(st.st_mode)) { - r = stat_verify_regular(&st); - if (r < 0) - return r; - } + /* Only support regular files and block devices. */ + r = fd_verify_regular_or_block(fd); + if (r < 0) + return r; fl = fd_verify_safe_flags_full(fd, O_NONBLOCK); if (fl < 0) diff --git a/src/repart/repart.c b/src/repart/repart.c index e9cd0d8569..308ae3aba5 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -3226,26 +3226,6 @@ static int determine_current_padding( return 0; } -static int verify_regular_or_block(int fd) { - struct stat st; - - assert(fd >= 0); - - if (fstat(fd, &st) < 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) && !S_ISBLK(st.st_mode)) - return -EBADFD; - - return 0; -} - static int context_copy_from_one(Context *context, const char *src) { _cleanup_close_ int fd = -EBADF; _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL; @@ -3261,9 +3241,9 @@ static int context_copy_from_one(Context *context, const char *src) { if (r < 0) return r; - r = verify_regular_or_block(fd); + r = fd_verify_regular_or_block(fd); if (r < 0) - return log_error_errno(r, "%s is not a file nor a block device: %m", src); + return log_error_errno(r, "'%s' is not a file nor a block device: %m", src); r = fdisk_new_context_at(fd, /* path= */ NULL, /* read_only= */ true, /* sector_size= */ UINT32_MAX, &c); if (r < 0) diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index 9349a98493..1c843661cc 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -820,7 +820,6 @@ int loop_device_make_by_path_memory( _cleanup_close_ int fd = -EBADF, mfd = -EBADF; _cleanup_free_ char *fn = NULL; - struct stat st; int r; assert(path); @@ -837,11 +836,9 @@ int loop_device_make_by_path_memory( if (fd < 0) return -errno; - if (fstat(fd, &st) < 0) - return -errno; - - if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode)) - return -EBADF; + r = fd_verify_regular_or_block(fd); + if (r < 0) + return r; r = path_extract_filename(path, &fn); if (r < 0)