]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/cephfs: Add lchmod python binding
authorKotresh HR <khiremat@redhat.com>
Thu, 18 Mar 2021 12:51:05 +0000 (18:21 +0530)
committerKotresh HR <khiremat@redhat.com>
Sat, 20 Mar 2021 03:28:11 +0000 (08:58 +0530)
Fixes: https://tracker.ceph.com/issues/49882
Signed-off-by: Kotresh HR <khiremat@redhat.com>
(cherry picked from commit b2375adce085e98bef521422441b80a945e38c80)

src/pybind/cephfs/c_cephfs.pxd
src/pybind/cephfs/cephfs.pyx
src/pybind/cephfs/mock_cephfs.pxi
src/test/pybind/test_cephfs.py

index b4b2c625144b84676323d5782f6c63a8aaa93453..cb266ecf910123ff21ad9e67742b354ab258997f 100644 (file)
@@ -118,6 +118,7 @@ cdef extern from "cephfs/libcephfs.h" nogil:
     int ceph_lazyio_synchronize(ceph_mount_info *cmount, int fd, int64_t offset, size_t count)
     int ceph_fallocate(ceph_mount_info *cmount, int fd, int mode, int64_t offset, int64_t length)
     int ceph_chmod(ceph_mount_info *cmount, const char *path, mode_t mode)
+    int ceph_lchmod(ceph_mount_info *cmount, const char *path, mode_t mode)
     int ceph_fchmod(ceph_mount_info *cmount, int fd, mode_t mode)
     int ceph_chown(ceph_mount_info *cmount, const char *path, int uid, int gid)
     int ceph_lchown(ceph_mount_info *cmount, const char *path, int uid, int gid)
index 15c07af3ffe3d3c7b39e4bfa6d78d7d322a2a657..412bff3cd0ee8da9427bf27912cd069db18b5998 100644 (file)
@@ -1079,6 +1079,26 @@ cdef class LibCephFS(object):
         if ret < 0:
             raise make_ex(ret, "error in chmod {}".format(path.decode('utf-8')))
 
+    def lchmod(self, path, mode) -> None:
+        """
+        Change file mode. If the path is a symbolic link, it won't be dereferenced.
+
+        :param path: the path of the file. This must be either an absolute path or
+                     a relative path off of the current working directory.
+        :param mode: the permissions to be set .
+        """
+        self.require_state("mounted")
+        path = cstr(path, 'path')
+        if not isinstance(mode, int):
+            raise TypeError('mode must be an int')
+        cdef:
+            char* _path = path
+            int _mode = mode
+        with nogil:
+            ret = ceph_lchmod(self.cluster, _path, _mode)
+        if ret < 0:
+            raise make_ex(ret, "error in chmod {}".format(path.decode('utf-8')))
+
     def fchmod(self, fd, mode) :
         """
         Change file mode based on fd.
index f4ff5b7360cd4c54750cff9eb90d25462aa57852..c871b8b353b3890871dac195239bb4f6f2a6add0 100644 (file)
@@ -189,6 +189,8 @@ cdef nogil:
         pass
     int ceph_chmod(ceph_mount_info *cmount, const char *path, mode_t mode):
         pass
+    int ceph_lchmod(ceph_mount_info *cmount, const char *path, mode_t mode):
+        pass
     int ceph_fchmod(ceph_mount_info *cmount, int fd, mode_t mode):
         pass
     int ceph_chown(ceph_mount_info *cmount, const char *path, int uid, int gid):
index bdb8332ffe73fdf74890fd5a31f4161dcb84604b..a3b1d494e6a952b7a5cb375eed2e35f059a22039 100644 (file)
@@ -1,5 +1,5 @@
 # vim: expandtab smarttab shiftwidth=4 softtabstop=4
-from nose.tools import assert_raises, assert_equal, assert_greater, with_setup
+from nose.tools import assert_raises, assert_equal, assert_not_equal, assert_greater, with_setup
 import cephfs as libcephfs
 import fcntl
 import os
@@ -540,6 +540,31 @@ def test_futimens():
     cephfs.close(fd)
     cephfs.unlink(b'/file-1')
 
+@with_setup(setup_test)
+def test_lchmod():
+    fd = cephfs.open(b'/file-1', 'w', 0o755)
+    cephfs.write(fd, b'0000', 0)
+    cephfs.close(fd)
+
+    cephfs.symlink(b'/file-1', b'/file-2')
+
+    stx_pre_t = cephfs.statx(b'/file-1', libcephfs.CEPH_STATX_MODE, 0)
+    stx_pre_s = cephfs.statx(b'/file-2', libcephfs.CEPH_STATX_MODE, libcephfs.AT_SYMLINK_NOFOLLOW)
+
+    time.sleep(1)
+    cephfs.lchmod(b'/file-2', 0o400)
+
+    stx_post_t = cephfs.statx(b'/file-1', libcephfs.CEPH_STATX_MODE, 0)
+    stx_post_s = cephfs.statx(b'/file-2', libcephfs.CEPH_STATX_MODE, libcephfs.AT_SYMLINK_NOFOLLOW)
+
+    assert_equal(stx_post_t['mode'], stx_pre_t['mode'])
+    assert_not_equal(stx_post_s['mode'], stx_pre_s['mode'])
+    stx_post_s_perm_bits = stx_post_s['mode'] & ~stat.S_IFMT(stx_post_s["mode"])
+    assert_equal(stx_post_s_perm_bits, 0o400)
+
+    cephfs.unlink(b'/file-2')
+    cephfs.unlink(b'/file-1')
+
 @with_setup(setup_test)
 def test_fchmod():
     fd = cephfs.open(b'/file-fchmod', 'w', 0o655)