stat-util: introduce a common (stat|fd)_verify_regular_or_block() helper

We already had one in repart.c, let's generalize it, and use it
everywhere.
This commit is contained in:
Lennart Poettering
2026-04-13 13:20:42 +02:00
parent 2c664b9531
commit 6b0a3ef8c7
7 changed files with 41 additions and 45 deletions
+22
View File
@@ -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;
+3
View File
@@ -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);
+3 -4
View File
@@ -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
+4 -3
View File
@@ -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)
+4 -10
View File
@@ -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)
+2 -22
View File
@@ -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)
+3 -6
View File
@@ -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)