*/
int ceph_chmod(struct ceph_mount_info *cmount, const char *path, mode_t mode);
+/**
+ * Change the mode bits (permissions) of a file/directory. If the path is a
+ * symbolic link, it's not de-referenced.
+ *
+ * @param cmount the ceph mount handle to use for performing the chmod.
+ * @param path the path of file/directory to change the mode bits on.
+ * @param mode the new permissions to set.
+ * @returns 0 on success or a negative error code on failure.
+ */
+int ceph_lchmod(struct ceph_mount_info *cmount, const char *path, mode_t mode);
+
/**
* Change the mode bits (permissions) of an open file.
*
return -ENOTCONN;
return cmount->get_client()->chmod(path, mode, cmount->default_perms);
}
+extern "C" int ceph_lchmod(struct ceph_mount_info *cmount, const char *path, mode_t mode)
+{
+ if (!cmount->is_mounted())
+ return -ENOTCONN;
+ return cmount->get_client()->lchmod(path, mode, cmount->default_perms);
+}
extern "C" int ceph_fchmod(struct ceph_mount_info *cmount, int fd, mode_t mode)
{
if (!cmount->is_mounted())
ceph_shutdown(cmount);
}
+TEST(LibCephFS, Lchmod) {
+ struct ceph_mount_info *cmount;
+ ASSERT_EQ(ceph_create(&cmount, NULL), 0);
+ ASSERT_EQ(ceph_conf_read_file(cmount, NULL), 0);
+ ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
+ ASSERT_EQ(ceph_mount(cmount, NULL), 0);
+
+ char test_file[256];
+ sprintf(test_file, "test_perms_lchmod_%d", getpid());
+
+ int fd = ceph_open(cmount, test_file, O_CREAT|O_RDWR, 0666);
+ ASSERT_GT(fd, 0);
+
+ // write some stuff
+ const char *bytes = "foobarbaz";
+ ASSERT_EQ(ceph_write(cmount, fd, bytes, strlen(bytes), 0), (int)strlen(bytes));
+ ceph_close(cmount, fd);
+
+ // Create symlink
+ char test_symlink[256];
+ sprintf(test_symlink, "test_lchmod_sym_%d", getpid());
+ ASSERT_EQ(ceph_symlink(cmount, test_file, test_symlink), 0);
+
+ // get symlink stat - lstat
+ struct ceph_statx stx_orig1;
+ ASSERT_EQ(ceph_statx(cmount, test_symlink, &stx_orig1, CEPH_STATX_ALL_STATS, AT_SYMLINK_NOFOLLOW), 0);
+
+ // Change mode on symlink file
+ ASSERT_EQ(ceph_lchmod(cmount, test_symlink, 0400), 0);
+ struct ceph_statx stx_orig2;
+ ASSERT_EQ(ceph_statx(cmount, test_symlink, &stx_orig2, CEPH_STATX_ALL_STATS, AT_SYMLINK_NOFOLLOW), 0);
+
+ // Compare modes
+ ASSERT_NE(stx_orig1.stx_mode, stx_orig2.stx_mode);
+ static const int permbits = S_IRWXU|S_IRWXG|S_IRWXO;
+ ASSERT_EQ(permbits&stx_orig1.stx_mode, 0777);
+ ASSERT_EQ(permbits&stx_orig2.stx_mode, 0400);
+
+ ceph_shutdown(cmount);
+}
+
TEST(LibCephFS, Fchown) {
struct ceph_mount_info *cmount;
ASSERT_EQ(ceph_create(&cmount, NULL), 0);