Fh *f = get_filehandle(fd);
if (!f)
return -EBADF;
+#if defined(__linux__)
+ if (f->flags & O_PATH)
+ return -EBADF;
+#endif
struct stat attr;
attr.st_mode = mode;
return _setattr(f->inode, &attr, CEPH_SETATTR_MODE);
Fh *f = get_filehandle(fd);
if (!f)
return -EBADF;
+#if defined(__linux__)
+ if (f->flags & O_PATH)
+ return -EBADF;
+#endif
struct stat attr;
attr.st_uid = uid;
attr.st_gid = gid;
Fh *fh = NULL;
+#if defined(__linux__)
+ /* When the O_PATH is being specified, others flags than O_DIRECTORY
+ * and O_NOFOLLOW are ignored. Please refer do_entry_open() function
+ * in kernel (fs/open.c). */
+ if (flags & O_PATH)
+ flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
+#endif
+
filepath path(relpath);
Inode *in;
bool created = false;
if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL))
return -EEXIST;
+#if defined(__linux__)
+ if (r == 0 && in->is_symlink() && (flags & O_NOFOLLOW) && !(flags & O_PATH))
+#else
if (r == 0 && in->is_symlink() && (flags & O_NOFOLLOW))
+#endif
return -ELOOP;
if (r == -ENOENT && (flags & O_CREAT)) {
Fh *f = get_filehandle(fd);
if (!f)
return -EBADF;
+#if defined(__linux__)
+ if (f->flags & O_PATH)
+ return -EBADF;
+#endif
return _lseek(f, offset, whence);
}
Fh *f = get_filehandle(fd);
if (!f)
return -EBADF;
+#if defined(__linux__)
+ if (f->flags & O_PATH)
+ return -EBADF;
+#endif
bufferlist bl;
int r = _read(f, offset, size, &bl);
ldout(cct, 3) << "read(" << fd << ", " << (void*)buf << ", " << size << ", " << offset << ") = " << r << dendl;
Fh *fh = get_filehandle(fd);
if (!fh)
return -EBADF;
+#if defined(__linux__)
+ if (fh->flags & O_PATH)
+ return -EBADF;
+#endif
int r = _write(fh, offset, size, buf);
ldout(cct, 3) << "write(" << fd << ", \"...\", " << size << ", " << offset << ") = " << r << dendl;
return r;
Fh *f = get_filehandle(fd);
if (!f)
return -EBADF;
+#if defined(__linux__)
+ if (f->flags & O_PATH)
+ return -EBADF;
+#endif
struct stat attr;
attr.st_size = length;
return _setattr(f->inode, &attr, CEPH_SETATTR_SIZE);
Fh *f = get_filehandle(fd);
if (!f)
return -EBADF;
+#if defined(__linux__)
+ if (f->flags & O_PATH)
+ return -EBADF;
+#endif
int r = _fsync(f, syncdataonly);
ldout(cct, 3) << "fsync(" << fd << ", " << syncdataonly << ") = " << r << dendl;
return r;
Fh *fh = get_filehandle(fd);
if (!fh)
return -EBADF;
+#if defined(__linux__)
+ if (fh->flags & O_PATH)
+ return -EBADF;
+#endif
return _fallocate(fh, mode, offset, length);
}
#include <dirent.h>
#include <sys/xattr.h>
+#ifdef __linux__
+#include <limits.h>
+#endif
+
TEST(LibCephFS, OpenEmptyComponent) {
pid_t mypid = getpid();
fd = ceph_open(cmount, test_file, O_RDWR, 0);
ASSERT_EQ(fd, -EACCES);
+
+ ceph_shutdown(cmount);
+}
+
+#ifdef __linux__
+TEST(LibCephFS, FlagO_PATH) {
+ struct ceph_mount_info *cmount;
+
+ ASSERT_EQ(0, ceph_create(&cmount, NULL));
+ ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
+ ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
+ ASSERT_EQ(0, ceph_mount(cmount, NULL));
+
+ char test_file[PATH_MAX];
+ sprintf(test_file, "test_oflag_%d", getpid());
+
+ int fd = ceph_open(cmount, test_file, O_CREAT|O_RDWR|O_PATH, 0666);
+ ASSERT_EQ(-ENOENT, fd);
+
+ fd = ceph_open(cmount, test_file, O_CREAT|O_RDWR, 0666);
+ ASSERT_GT(fd, 0);
+ ASSERT_EQ(0, ceph_close(cmount, fd));
+
+ // ok, the file has been created. perform real checks now
+ fd = ceph_open(cmount, test_file, O_CREAT|O_RDWR|O_PATH, 0666);
+ ASSERT_GT(fd, 0);
+
+ char buf[128];
+ ASSERT_EQ(-EBADF, ceph_read(cmount, fd, buf, sizeof(buf), 0));
+ ASSERT_EQ(-EBADF, ceph_write(cmount, fd, buf, sizeof(buf), 0));
+
+ // set perms to readable and writeable only by owner
+ ASSERT_EQ(-EBADF, ceph_fchmod(cmount, fd, 0600));
+
+ // change ownership to nobody -- we assume nobody exists and id is always 65534
+ ASSERT_EQ(-EBADF, ceph_fchown(cmount, fd, 65534, 65534));
+
+ // try to sync
+ ASSERT_EQ(-EBADF, ceph_fsync(cmount, fd, false));
+
+ struct stat sb;
+ ASSERT_EQ(0, ceph_fstat(cmount, fd, &sb));
+
+ ASSERT_EQ(0, ceph_close(cmount, fd));
ceph_shutdown(cmount);
}
+#endif /* __linux */
TEST(LibCephFS, Symlinks) {
struct ceph_mount_info *cmount;