commit 42c5456c307858ab7a7a6693cfe41764a9d9006a
parent 287a65746ba4a3ad22b9c48ee3293e9ddde96fbc
Author: Matsuda Kenji <info@mtkn.jp>
Date: Fri, 8 Sep 2023 14:26:36 +0900
implement diskfs
Diffstat:
| M | diskfs/file.go | | | 94 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
1 file changed, 48 insertions(+), 46 deletions(-)
diff --git a/diskfs/file.go b/diskfs/file.go
@@ -13,10 +13,11 @@ import (
)
type File struct {
- fs *FS // file system to which this file belongs
- file *os.File // underlying file
- path string // absolute path from the root of the fs.
- children []lib9p.File
+ fs *FS // file system to which this file belongs
+ file *os.File // underlying file
+ path string // absolute path from the root of the fs.
+ childEntry []*lib9p.DirEntry
+ diroff int // directory offset for ReadDir()
}
func openFile(fsys *FS, fpath string) (*File, error) {
@@ -24,10 +25,38 @@ func openFile(fsys *FS, fpath string) (*File, error) {
if err != nil {
return nil, fmt.Errorf("open fs: %v", err)
}
+
+ fi, err := file.Stat()
+ if err != nil {
+ return nil, fmt.Errorf("stat: %v", err)
+ }
+ var childEntry []*lib9p.DirEntry
+ if fi.IsDir() {
+ dir := file.(fs.ReadDirFile)
+ de, err := dir.ReadDir(-1)
+ if err != nil {
+ return nil, fmt.Errorf("read dir: %v", err)
+ }
+ childEntry = make([]*lib9p.DirEntry, len(de))
+ for i := 0; i < len(de); i++ {
+ info, err := de[i].Info()
+ if err != nil {
+ return nil, fmt.Errorf("info: %v", err)
+ }
+ sys := info.Sys().(*syscall.Stat_t)
+ id := fileID{
+ device: sys.Dev,
+ inode: sys.Ino,
+ }
+ stat := fiStat(fsys.qidPool, id, info)
+ childEntry[i] = &lib9p.DirEntry{Stat: *stat}
+ }
+ }
f := &File{
- fs: fsys,
- file: file.(*os.File),
- path: fpath,
+ fs: fsys,
+ file: file.(*os.File),
+ path: fpath,
+ childEntry: childEntry,
}
return f, nil
}
@@ -89,13 +118,16 @@ func (f *File) Parent() (lib9p.File, error) {
}
func (f *File) Child() ([]lib9p.File, error) {
- if f.children == nil {
- _, err := f.ReadDir(-1)
+ files := make([]lib9p.File, len(f.childEntry))
+ for i := 0; i < len(f.childEntry); i++ {
+ cpath := path.Join(f.path, f.childEntry[i].Name())
+ child, err := f.fs.Open(cpath)
if err != nil {
- return f.children, fmt.Errorf("read dir: %v")
+ return files, fmt.Errorf("open child unko: %v", err)
}
+ files[i] = child
}
- return f.children, nil
+ return files, nil
}
func (f *File) ReadAt(p []byte, off int64) (int, error) {
@@ -103,41 +135,11 @@ func (f *File) ReadAt(p []byte, off int64) (int, error) {
}
func (f *File) ReadDir(n int) ([]*lib9p.DirEntry, error) {
- fsde, err := f.file.ReadDir(n)
- if err != nil {
- return nil, err
- }
- if len(fsde) == 0 {
- if f.children == nil {
- f.children = make([]lib9p.File, 0)
- }
- de := make([]*lib9p.DirEntry, len(f.children))
- for i := 0; i < len(f.children); i++ {
- fi, err := f.children[i].Stat()
- if err != nil {
- return de, fmt.Errorf("stat: %v", err)
- }
- de[i] = &lib9p.FileInfo{*fi.Sys().(*lib9p.Stat)}
- }
- return de, nil
+ childEntry := f.childEntry[f.diroff:]
+ if n < 0 || len(childEntry) < n {
+ n = len(childEntry)
}
- de := make([]*lib9p.DirEntry, len(fsde))
- children := make([]lib9p.File, len(fsde))
- for i := 0; i < len(de); i++ {
- info, err := fsde[i].Info()
- if err != nil {
- return de, err
- }
- id := idFromInfo(info)
- de[i] = &lib9p.FileInfo{*fiStat(f.fs.qidPool, id, info)}
- childPath := path.Join(f.PathName(), info.Name())
- child, err := f.fs.Open(childPath)
- if err != nil {
- return de, fmt.Errorf("open: %v", err)
- }
- children[i] = child
- }
- f.children = append(f.children, children...)
- return de, nil
+ f.diroff += n
+ return childEntry[:n], nil
}