From 7b5e17477dae33be4c759bee42de47e47de5b2a2 Mon Sep 17 00:00:00 2001 From: Rishabh Dave Date: Tue, 4 Nov 2025 18:37:32 +0530 Subject: [PATCH] pybind/cephfs: add python bindings for statxat() Signed-off-by: Rishabh Dave --- src/pybind/cephfs/c_cephfs.pxd | 2 ++ src/pybind/cephfs/cephfs.pyx | 55 +++++++++++++++++++++++++++++++ src/pybind/cephfs/mock_cephfs.pxi | 2 ++ 3 files changed, 59 insertions(+) diff --git a/src/pybind/cephfs/c_cephfs.pxd b/src/pybind/cephfs/c_cephfs.pxd index 88d255c5e5f..a4a96c369ce 100644 --- a/src/pybind/cephfs/c_cephfs.pxd +++ b/src/pybind/cephfs/c_cephfs.pxd @@ -74,6 +74,8 @@ cdef extern from "cephfs/libcephfs.h" nogil: uint64_t ceph_get_instance_id(ceph_mount_info *cmount) int ceph_fstatx(ceph_mount_info *cmount, int fd, statx *stx, unsigned want, unsigned flags) int ceph_statx(ceph_mount_info *cmount, const char *path, statx *stx, unsigned want, unsigned flags) + int ceph_statxat(ceph_mount_info *cmount, int dirfd, const char *relpath, + statx *stx, unsigned want, unsigned flags) int ceph_statfs(ceph_mount_info *cmount, const char *path, statvfs *stbuf) int ceph_setattrx(ceph_mount_info *cmount, const char *relpath, statx *stx, int mask, int flags) diff --git a/src/pybind/cephfs/cephfs.pyx b/src/pybind/cephfs/cephfs.pyx index 3c03c1f06d7..2db40244d72 100644 --- a/src/pybind/cephfs/cephfs.pyx +++ b/src/pybind/cephfs/cephfs.pyx @@ -2170,6 +2170,61 @@ cdef class LibCephFS(object): return dict_result + def statxat(self, fd, relpath, mask, flag): + self.require_state("mounted") + + if not isinstance(fd, int): + raise TypeError('fd must be a int') + if not isinstance(mask, int): + raise TypeError('flag must be a int') + if not isinstance(flag, int): + raise TypeError('flag must be a int') + + relpath = cstr(relpath, 'relpath') + + cdef: + int _fd = fd + char* _relpath = relpath + statx stx + int _mask = mask + int _flag = flag + + with nogil: + ret = ceph_statxat(self.cluster, _fd, _relpath, &stx, _mask, _flag) + + if ret < 0: + raise make_ex(ret, f"error in statxat {relpath.decode('utf-8')}") + + dict_result = dict() + if (_mask & CEPH_STATX_MODE): + dict_result["mode"] = stx.stx_mode + if (_mask & CEPH_STATX_NLINK): + dict_result["nlink"] = stx.stx_nlink + if (_mask & CEPH_STATX_UID): + dict_result["uid"] = stx.stx_uid + if (_mask & CEPH_STATX_GID): + dict_result["gid"] = stx.stx_gid + if (_mask & CEPH_STATX_RDEV): + dict_result["rdev"] = stx.stx_rdev + if (_mask & CEPH_STATX_ATIME): + dict_result["atime"] = datetime.fromtimestamp(stx.stx_atime.tv_sec) + if (_mask & CEPH_STATX_MTIME): + dict_result["mtime"] = datetime.fromtimestamp(stx.stx_mtime.tv_sec) + if (_mask & CEPH_STATX_CTIME): + dict_result["ctime"] = datetime.fromtimestamp(stx.stx_ctime.tv_sec) + if (_mask & CEPH_STATX_INO): + dict_result["ino"] = stx.stx_ino + if (_mask & CEPH_STATX_SIZE): + dict_result["size"] = stx.stx_size + if (_mask & CEPH_STATX_BLOCKS): + dict_result["blocks"] = stx.stx_blocks + if (_mask & CEPH_STATX_BTIME): + dict_result["btime"] = datetime.fromtimestamp(stx.stx_btime.tv_sec) + if (_mask & CEPH_STATX_VERSION): + dict_result["version"] = stx.stx_version + + return dict_result + def setattrx(self, path, dict_stx, mask, flags): """ Set a file's attributes. diff --git a/src/pybind/cephfs/mock_cephfs.pxi b/src/pybind/cephfs/mock_cephfs.pxi index 1c76e659e32..6e94fe623ec 100644 --- a/src/pybind/cephfs/mock_cephfs.pxi +++ b/src/pybind/cephfs/mock_cephfs.pxi @@ -93,6 +93,8 @@ cdef nogil: pass int ceph_statx(ceph_mount_info *cmount, const char *path, statx *stx, unsigned want, unsigned flags): pass + int ceph_statxat(ceph_mount_info *cmount, int dirfd, const char *path, statx *stx, unsigned want, unsigned flags): + pass int ceph_statfs(ceph_mount_info *cmount, const char *path, statvfs *stbuf): pass -- 2.39.5