mirror of https://github.com/ceph/go-ceph
cephfs: add ReadDir implementing ceph_readdir_r function
Adds a method to ReadDir that implements ceph_readdir_r returning a single dir entry at at time. Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
parent
e98648f76f
commit
fd275e2b9a
|
@ -47,3 +47,48 @@ func (mount *MountInfo) OpenDir(path string) (*Directory, error) {
|
||||||
func (dir *Directory) Close() error {
|
func (dir *Directory) Close() error {
|
||||||
return getError(C.ceph_closedir(dir.mount.mount, dir.dir))
|
return getError(C.ceph_closedir(dir.mount.mount, dir.dir))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inode represents an inode number in the file system.
|
||||||
|
type Inode uint64
|
||||||
|
|
||||||
|
// DirEntry represents an entry within a directory.
|
||||||
|
type DirEntry struct {
|
||||||
|
inode Inode
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the directory entry's name.
|
||||||
|
func (d *DirEntry) Name() string {
|
||||||
|
return d.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inode returns the directory entry's inode number.
|
||||||
|
func (d *DirEntry) Inode() Inode {
|
||||||
|
return d.inode
|
||||||
|
}
|
||||||
|
|
||||||
|
// toDirEntry converts a c struct dirent to our go wrapper.
|
||||||
|
func toDirEntry(de *C.struct_dirent) *DirEntry {
|
||||||
|
return &DirEntry{
|
||||||
|
inode: Inode(de.d_ino),
|
||||||
|
name: C.GoString(&de.d_name[0]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadDir reads a single directory entry from the open Directory.
|
||||||
|
// A nil DirEntry pointer will be returned when the Directory stream has been
|
||||||
|
// exhausted.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int ceph_readdir_r(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp, struct dirent *de);
|
||||||
|
func (dir *Directory) ReadDir() (*DirEntry, error) {
|
||||||
|
var de C.struct_dirent
|
||||||
|
ret := C.ceph_readdir_r(dir.mount.mount, dir.dir, &de)
|
||||||
|
if ret < 0 {
|
||||||
|
return nil, getError(ret)
|
||||||
|
}
|
||||||
|
if ret == 0 {
|
||||||
|
return nil, nil // End-of-stream
|
||||||
|
}
|
||||||
|
return toDirEntry(&de), nil
|
||||||
|
}
|
||||||
|
|
|
@ -36,3 +36,62 @@ func TestOpenCloseDir(t *testing.T) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, dir)
|
assert.Nil(t, dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadDir(t *testing.T) {
|
||||||
|
mount := fsConnect(t)
|
||||||
|
defer fsDisconnect(t, mount)
|
||||||
|
|
||||||
|
dir1 := "/base"
|
||||||
|
err := mount.MakeDir(dir1, 0755)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer func() { assert.NoError(t, mount.RemoveDir(dir1)) }()
|
||||||
|
|
||||||
|
subdirs := []string{"a", "bb", "ccc", "dddd"}
|
||||||
|
for _, s := range subdirs {
|
||||||
|
spath := dir1 + "/" + s
|
||||||
|
err = mount.MakeDir(spath, 0755)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer func(d string) {
|
||||||
|
assert.NoError(t, mount.RemoveDir(d))
|
||||||
|
}(spath)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("root", func(t *testing.T) {
|
||||||
|
dir, err := mount.OpenDir("/")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, dir)
|
||||||
|
defer func() { assert.NoError(t, dir.Close()) }()
|
||||||
|
|
||||||
|
found := []string{}
|
||||||
|
for {
|
||||||
|
entry, err := dir.ReadDir()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if entry == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
assert.NotEqual(t, Inode(0), entry.Inode())
|
||||||
|
assert.NotEqual(t, "", entry.Name())
|
||||||
|
found = append(found, entry.Name())
|
||||||
|
}
|
||||||
|
assert.Contains(t, found, "base")
|
||||||
|
})
|
||||||
|
t.Run("dir1", func(t *testing.T) {
|
||||||
|
dir, err := mount.OpenDir(dir1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, dir)
|
||||||
|
defer func() { assert.NoError(t, dir.Close()) }()
|
||||||
|
|
||||||
|
found := []string{}
|
||||||
|
for {
|
||||||
|
entry, err := dir.ReadDir()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if entry == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
assert.NotEqual(t, Inode(0), entry.Inode())
|
||||||
|
assert.NotEqual(t, "", entry.Name())
|
||||||
|
found = append(found, entry.Name())
|
||||||
|
}
|
||||||
|
assert.Subset(t, found, subdirs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue