stat-util: unify code that checks whether something is a regular file
Let's add a common implementation for regular file checks, that are careful to return the right error code (EISDIR/EISLNK/EBADFD) when we are encountering a wrong file node.
This commit is contained in:
parent
9c66f52813
commit
3cc4411403
|
@ -232,23 +232,18 @@ int btrfs_subvol_get_read_only_fd(int fd) {
|
|||
}
|
||||
|
||||
int btrfs_reflink(int infd, int outfd) {
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(infd >= 0);
|
||||
assert(outfd >= 0);
|
||||
|
||||
/* Make sure we invoke the ioctl on a regular file, so that no
|
||||
* device driver accidentally gets it. */
|
||||
/* Make sure we invoke the ioctl on a regular file, so that no device driver accidentally gets it. */
|
||||
|
||||
if (fstat(outfd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return -EINVAL;
|
||||
|
||||
r = ioctl(outfd, BTRFS_IOC_CLONE, infd);
|
||||
r = fd_verify_regular(outfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ioctl(outfd, BTRFS_IOC_CLONE, infd) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
|
@ -261,21 +256,17 @@ int btrfs_clone_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offs
|
|||
.src_length = sz,
|
||||
.dest_offset = out_offset,
|
||||
};
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(infd >= 0);
|
||||
assert(outfd >= 0);
|
||||
assert(sz > 0);
|
||||
|
||||
if (fstat(outfd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return -EINVAL;
|
||||
|
||||
r = ioctl(outfd, BTRFS_IOC_CLONE_RANGE, &args);
|
||||
r = fd_verify_regular(outfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ioctl(outfd, BTRFS_IOC_CLONE_RANGE, &args) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
|
@ -760,15 +751,13 @@ int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQu
|
|||
}
|
||||
|
||||
int btrfs_defrag_fd(int fd) {
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return -EINVAL;
|
||||
r = fd_verify_regular(fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0)
|
||||
return -errno;
|
||||
|
|
|
@ -269,3 +269,32 @@ int path_is_temporary_fs(const char *path) {
|
|||
|
||||
return fd_is_temporary_fs(fd);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -75,3 +75,6 @@ int path_is_temporary_fs(const char *path);
|
|||
* signed/unsigned comparison, because the magic can be 32 bit unsigned.
|
||||
*/
|
||||
#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
|
||||
|
||||
int stat_verify_regular(const struct stat *st);
|
||||
int fd_verify_regular(int fd);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "import-common.h"
|
||||
#include "missing.h"
|
||||
#include "ratelimit.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -319,8 +320,9 @@ int raw_export_start(RawExport *e, const char *path, int fd, ImportCompressType
|
|||
|
||||
if (fstat(sfd, &e->st) < 0)
|
||||
return -errno;
|
||||
if (!S_ISREG(e->st.st_mode))
|
||||
return -ENOTTY;
|
||||
r = stat_verify_regular(&e->st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Try to take a reflink snapshot of the file, if we can t make the export atomic */
|
||||
tfd = reflink_snapshot(sfd, path);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "random-util.h"
|
||||
#include "sd-event.h"
|
||||
#include "set.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "xattr-util.h"
|
||||
|
@ -643,6 +644,8 @@ static int journal_file_verify_header(JournalFile *f) {
|
|||
}
|
||||
|
||||
static int journal_file_fstat(JournalFile *f) {
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
assert(f->fd >= 0);
|
||||
|
||||
|
@ -652,10 +655,9 @@ static int journal_file_fstat(JournalFile *f) {
|
|||
f->last_stat_usec = now(CLOCK_MONOTONIC);
|
||||
|
||||
/* Refuse dealing with with files that aren't regular */
|
||||
if (S_ISDIR(f->last_stat.st_mode))
|
||||
return -EISDIR;
|
||||
if (!S_ISREG(f->last_stat.st_mode))
|
||||
return -EBADFD;
|
||||
r = stat_verify_regular(&f->last_stat);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Refuse appending to files that are already deleted */
|
||||
if (f->last_stat.st_nlink <= 0)
|
||||
|
|
|
@ -1303,14 +1303,10 @@ static int add_any_file(
|
|||
r = log_debug_errno(errno, "Failed to fstat file '%s': %m", path);
|
||||
goto finish;
|
||||
}
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
log_debug("Uh, file '%s' is a directory? Refusing.", path);
|
||||
r = -EISDIR;
|
||||
goto finish;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
log_debug("Uh, file '%s' is not a regular file? Refusing.", path);
|
||||
r = -EBADFD;
|
||||
|
||||
r = stat_verify_regular(&st);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Refusing to open '%s', as it is not a regular file.", path);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
@ -2074,14 +2070,9 @@ _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fd
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
r = -EISDIR;
|
||||
r = stat_verify_regular(&st);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
r = -EBADFD;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = add_any_file(j, fds[i], NULL);
|
||||
if (r < 0)
|
||||
|
|
|
@ -1284,10 +1284,10 @@ static int unit_file_load(
|
|||
info->type = UNIT_FILE_TYPE_MASKED;
|
||||
return 0;
|
||||
}
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return -EISDIR;
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return -ENOTTY;
|
||||
|
||||
r = stat_verify_regular(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
f = fdopen(fd, "re");
|
||||
if (!f)
|
||||
|
@ -2163,12 +2163,9 @@ int unit_file_link(
|
|||
|
||||
if (lstat(full, &st) < 0)
|
||||
return -errno;
|
||||
if (S_ISLNK(st.st_mode))
|
||||
return -ELOOP;
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return -EISDIR;
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return -ENOTTY;
|
||||
r = stat_verify_regular(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
q = in_search_path(&paths, *i);
|
||||
if (q < 0)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "loop-util.h"
|
||||
#include "stat-util.h"
|
||||
|
||||
int loop_device_make(int fd, int open_flags, LoopDevice **ret) {
|
||||
const struct loop_info64 info = {
|
||||
|
@ -37,7 +38,7 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) {
|
|||
_cleanup_free_ char *loopdev = NULL;
|
||||
struct stat st;
|
||||
LoopDevice *d;
|
||||
int nr;
|
||||
int nr, r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
@ -69,8 +70,9 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return -EINVAL;
|
||||
r = stat_verify_regular(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
|
||||
if (control < 0)
|
||||
|
|
Loading…
Reference in New Issue