return -EPROTOTYPE;
}
+int fd_is_writable(int fd) {
+ int r;
+
+ assert(fd >= 0);
+
+ r = fd_vet_accmode(fd, O_WRONLY);
+ if (r >= 0)
+ return true;
+
+ if (IN_SET(r, -EPROTOTYPE, -EBADFD, -EISDIR))
+ return false;
+
+ return r;
+}
+
int fd_verify_safe_flags_full(int fd, int extra_flags) {
int flags, unexpected_flags;
int fd_is_opath(int fd);
int fd_vet_accmode(int fd, int mode);
+int fd_is_writable(int fd);
int fd_verify_safe_flags_full(int fd, int extra_flags);
static inline int fd_verify_safe_flags(int fd) {
ASSERT_ERROR(fd_vet_accmode(fd_opath, O_RDWR), EBADFD);
}
+TEST(fd_is_writable) {
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-fd-writable.XXXXXX";
+ _cleanup_close_ int fd_ro = -EBADF, fd_wo = -EBADF, fd_rw = -EBADF, fd_path = -EBADF;
+
+ ASSERT_OK(fd_rw = mkostemp_safe(name));
+ ASSERT_OK_POSITIVE(fd_is_writable(fd_rw));
+
+ ASSERT_OK(fd_ro = open(name, O_RDONLY | O_CLOEXEC));
+ ASSERT_OK_ZERO(fd_is_writable(fd_ro));
+
+ ASSERT_OK(fd_wo = open(name, O_WRONLY | O_CLOEXEC));
+ ASSERT_OK_POSITIVE(fd_is_writable(fd_wo));
+
+ ASSERT_OK(fd_path = open(name, O_PATH | O_CLOEXEC));
+ ASSERT_OK_ZERO(fd_is_writable(fd_path));
+
+ ASSERT_SIGNAL(fd_is_writable(-1), SIGABRT);
+
+ safe_close(fd_ro);
+ ASSERT_ERROR(fd_is_writable(fd_ro), EBADF);
+ TAKE_FD(fd_ro);
+}
+
DEFINE_TEST_MAIN(LOG_DEBUG);