diff --git a/cephfs/file_ops.go b/cephfs/file_ops.go new file mode 100644 index 0000000..b450d7b --- /dev/null +++ b/cephfs/file_ops.go @@ -0,0 +1,34 @@ +//go:build !nautilus && ceph_preview +// +build !nautilus,ceph_preview + +package cephfs + +/* +#cgo LDFLAGS: -lcephfs +#cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64 +#include +#include +*/ +import "C" + +import ( + "unsafe" +) + +// Mknod creates a regular, block or character special file. +// +// Implements: +// +// int ceph_mknod(struct ceph_mount_info *cmount, const char *path, mode_t mode, +// dev_t rdev); +func (mount *MountInfo) Mknod(path string, mode uint16, dev uint16) error { + if err := mount.validate(); err != nil { + return err + } + + cPath := C.CString(path) + defer C.free(unsafe.Pointer(cPath)) + + ret := C.ceph_mknod(mount.mount, cPath, C.mode_t(mode), C.dev_t(dev)) + return getError(ret) +} diff --git a/cephfs/file_ops_test.go b/cephfs/file_ops_test.go new file mode 100644 index 0000000..4ae5e5a --- /dev/null +++ b/cephfs/file_ops_test.go @@ -0,0 +1,54 @@ +//go:build !nautilus && ceph_preview +// +build !nautilus,ceph_preview + +package cephfs + +import ( + "syscall" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMknod(t *testing.T) { + mount := fsConnect(t) + defer fsDisconnect(t, mount) + + file1 := "/file1" + mode1 := uint16(syscall.S_IFIFO | syscall.S_IRUSR | syscall.S_IWUSR) + err := mount.Mknod(file1, mode1, 0) + assert.NoError(t, err) + + file2 := "/file2" + mode2 := uint16(syscall.S_IFCHR) + err = mount.Mknod(file2, mode2, 89) + assert.NoError(t, err) + + file3 := "/file3" + mode3 := uint16(syscall.S_IFBLK) + err = mount.Mknod(file3, mode3, 129) + assert.NoError(t, err) + + defer func() { + assert.NoError(t, mount.Unlink(file1)) + assert.NoError(t, mount.Unlink(file2)) + assert.NoError(t, mount.Unlink(file3)) + }() + + sx, err := mount.Statx(file1, StatxBasicStats, 0) + assert.Equal(t, mode1, sx.Mode&mode1) + + sx, err = mount.Statx(file2, StatxBasicStats, 0) + assert.Equal(t, mode2, sx.Mode&mode2) + assert.Equal(t, uint64(89), sx.Rdev) + + sx, err = mount.Statx(file3, StatxBasicStats, 0) + assert.Equal(t, mode3, sx.Mode&mode3) + assert.Equal(t, uint64(129), sx.Rdev) + + // Test invalid mount value + mount1 := &MountInfo{} + file4 := "/file4" + err = mount1.Mknod(file4, uint16(syscall.S_IFCHR), 64) + assert.Error(t, err) +} diff --git a/docs/api-status.json b/docs/api-status.json index 6b1d653..e4aa422 100644 --- a/docs/api-status.json +++ b/docs/api-status.json @@ -325,6 +325,12 @@ "comment": "MakeDirs creates multiple directories at once.\n\nImplements:\n\n\tint ceph_mkdirs(struct ceph_mount_info *cmount, const char *path, mode_t mode);\n", "added_in_version": "v0.21.0", "expected_stable_version": "v0.23.0" + }, + { + "name": "MountInfo.Mknod", + "comment": "Mknod creates a regular, block or character special file.\n\nImplements:\n\n\tint ceph_mknod(struct ceph_mount_info *cmount, const char *path, mode_t mode,\n\t\t\t\t dev_t rdev);\n", + "added_in_version": "$NEXT_RELEASE", + "expected_stable_version": "$NEXT_RELEASE_STABLE" } ] }, diff --git a/docs/api-status.md b/docs/api-status.md index ea6184c..1693cf5 100644 --- a/docs/api-status.md +++ b/docs/api-status.md @@ -10,6 +10,7 @@ Name | Added in Version | Expected Stable Version | ---- | ---------------- | ----------------------- | MountInfo.SelectFilesystem | v0.20.0 | v0.22.0 | MountInfo.MakeDirs | v0.21.0 | v0.23.0 | +MountInfo.Mknod | $NEXT_RELEASE | $NEXT_RELEASE_STABLE | ## Package: cephfs/admin