diff --git a/cephfs/permissions.go b/cephfs/permissions.go index 77153fb..d55470b 100644 --- a/cephfs/permissions.go +++ b/cephfs/permissions.go @@ -29,3 +29,12 @@ func (mount *MountInfo) Chown(path string, user uint32, group uint32) error { ret := C.ceph_chown(mount.mount, cPath, C.int(user), C.int(group)) return getError(ret) } + +// Lchown changes the ownership of a file/directory/etc without following symbolic links +func (mount *MountInfo) Lchown(path string, user uint32, group uint32) error { + cPath := C.CString(path) + defer C.free(unsafe.Pointer(cPath)) + + ret := C.ceph_lchown(mount.mount, cPath, C.int(user), C.int(group)) + return getError(ret) +} diff --git a/cephfs/permissions_test.go b/cephfs/permissions_test.go index be16811..1d94afc 100644 --- a/cephfs/permissions_test.go +++ b/cephfs/permissions_test.go @@ -64,3 +64,32 @@ func TestChown(t *testing.T) { assert.Equal(t, uint32(sx.Uid), bob) assert.Equal(t, uint32(sx.Gid), bob) } + +func TestLchown(t *testing.T) { + dirname := "four" + var bob uint32 = 1010 + var root uint32 + + mount := fsConnect(t) + defer fsDisconnect(t, mount) + + err := mount.MakeDir(dirname, 0755) + assert.NoError(t, err) + defer mount.RemoveDir(dirname) + + err = mount.SyncFs() + assert.NoError(t, err) + + err = mount.Symlink(dirname, "symlnk") + assert.NoError(t, err) + defer mount.Unlink("symlnk") + + err = mount.Lchown("symlnk", bob, bob) + sx, err := mount.Statx("symlnk", StatxBasicStats, AtSymlinkNofollow) + assert.NoError(t, err) + assert.Equal(t, uint32(sx.Uid), bob) + assert.Equal(t, uint32(sx.Gid), bob) + sx, err = mount.Statx(dirname, StatxBasicStats, AtSymlinkNofollow) + assert.Equal(t, uint32(sx.Uid), root) + assert.Equal(t, uint32(sx.Gid), root) +}