lib9p

Go 9P library.
Log | Files | Refs

commit c2a30f351932ac96a20217c786e699fe1d89e070
parent 5b2a845a3d4ac65006109f36f9ef38108ddfe379
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Fri,  8 Sep 2023 08:04:07 +0900

found probrem
fs.ReadDirFile.ReadDir() returns []fs.DirEntry once, and
subsequent call returns nothing.

Diffstat:
Mdiskfs/file.go | 27+++++++++++++++++++++++++++
Mfile.go | 4++++
Mfs.go | 18++++++++++++++++++
Mserver.go | 35++++++++++++++++++-----------------
4 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/diskfs/file.go b/diskfs/file.go @@ -5,6 +5,7 @@ import ( "io/fs" "os" "os/user" + "path" "strconv" "syscall" @@ -77,6 +78,32 @@ func (f *File) Read(b []byte) (int, error) { return f.file.Read(b) } +func (f *File) Parent() (lib9p.File, error) { + parentPath := path.Dir(f.path) + parent, err := f.fs.Open(parentPath) + if err != nil { + return nil, fmt.Errorf("open parent: %v", err) + } + return parent, nil +} + +func (f *File) Child() ([]lib9p.File, error) { + de, err := f.ReadDir(-1) + if err != nil { + return nil, fmt.Errorf("read dir: %v", err) + } + children := make([]lib9p.File, len(de)) + for i := 0; i < len(de); i++ { + childPath := path.Join(f.PathName(), de[i].Name()) + file, err := f.fs.Open(childPath) + if err != nil { + return children, fmt.Errorf("open child: %v", err) + } + children[i] = file + } + return children, nil +} + func (f *File) ReadAt(p []byte, off int64) (int, error) { return f.file.ReadAt(p, off) } diff --git a/file.go b/file.go @@ -6,9 +6,13 @@ import ( type File interface { fs.File + // I think Files should be identified by Qid.Path, but os.Files // are indexed by path. PathName() string // path from the root of the fs which this file belongs to. + + Parent() (File, error) + Child() ([]File, error) } type ReadDirFile interface { diff --git a/fs.go b/fs.go @@ -1,6 +1,7 @@ package lib9p import ( + "fmt" "io/fs" "path" ) @@ -28,6 +29,23 @@ func walk(fsys FS, root string, wnames []string) ([]Qid, error) { return wqids, nil } +func walkfile(f File, name string) (File, error) { + children, err := f.Child() + if err != nil { + return nil, fmt.Errorf("get children: %v", err) + } + for _, child := range children { + s, err := child.Stat() + if err != nil { + return nil, fmt.Errorf("stat: %v", err) + } + if s.Name() == name { + return child, nil + } + } + return nil, fmt.Errorf("not found") +} + func FSModeToQidType(fm fs.FileMode) QidType { var qt QidType if fm&fs.ModeDir != 0 { diff --git a/server.go b/server.go @@ -6,7 +6,6 @@ import ( "io/fs" "log" "os" - "path" "strings" ) @@ -174,24 +173,26 @@ func sWalk(s *Server, r *Req) { return } - wqids, err := walk(s.fs, oldFid.File.PathName(), ifcall.WName()) - if err != nil { - s.fPool.delete(ifcall.NewFid()) - log.Printf("walk fs: %v", err) - respond(r, fmt.Errorf("walk error")) - return - } - - relPath := path.Join(ifcall.WName()...) - absPath := path.Join(oldFid.File.PathName(), relPath) - f, err := s.fs.Open(absPath) - if err != nil { - log.Printf("open root dir: %v", err) - respond(r, fmt.Errorf("internal error")) - return + wqids := make([]Qid, ifcall.NWName()) + cwd := oldFid.File + for i, name := range ifcall.WName() { + child, err := walkfile(cwd, name) + if err != nil { + s.fPool.delete(ifcall.NewFid()) + respond(r, fmt.Errorf("walk: %v", err)) + return + } + stat, err := child.Stat() + if err != nil { + s.fPool.delete(ifcall.NewFid()) + respond(r, fmt.Errorf("stat: %v", err)) + return + } + wqids[i] = stat.(*FileInfo).Qid() + cwd = child } - newFid.File = f.(File) + newFid.File = cwd newFid.Uid = oldFid.Uid info, err := newFid.File.Stat() if err != nil {