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:
+13
-24
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user