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