lib9p

Go 9P library.
Log | Files | Refs

commit 894eac128d474a35c4624557555c33a15ef58c59
parent 75a9e601d9185b156ddd36bb83d3eaf307679731
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sat,  2 Sep 2023 08:43:37 +0900

update diskfs

Diffstat:
Mdiskfs/file.go | 39++++++++-------------------------------
Mdiskfs/qid_unix.go | 16+++++++++++++++-
Adiskfs/stat.go | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+), 32 deletions(-)

diff --git a/diskfs/file.go b/diskfs/file.go @@ -6,7 +6,6 @@ import ( "log" "os" "os/user" - "path" "strconv" "syscall" @@ -14,9 +13,9 @@ 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. + fs *FS // file system to which this file belongs + file *os.File // underlying file + path string // absolute path from the root of the fs. } func openFile(fsys *FS, fpath string) (*File, error) { @@ -130,22 +129,7 @@ func (f *File) Muid() string { } func (f *File) Stat() (fs.FileInfo, error) { - qid := f.Qid() - - fi := &lib9p.FileInfo{ - Stat: &lib9p.Stat{ - Qid: &qid, - Name: f.Name(), - Mode: f.Mode(), - Atime: f.Atime(), - Mtime: f.Mtime(), - Length: f.Length(), - Uid: f.Uid(), - Gid: f.Gid(), - Muid: f.Muid(), - }, - } - return fi, nil + return &FileInfo{Stat: lib9p.StatFromFile(f)}, nil } func (f *File) Close() error { @@ -167,20 +151,13 @@ func (f *File) ReadDir(n int) ([]*lib9p.DirEntry, error) { } de := make([]*lib9p.DirEntry, len(fsde)) for i := 0; i < len(de); i++ { - fpath := path.Join(f.path, fsde[i].Name()) - file, err := f.fs.Open(fpath) - if err != nil { - return nil, fmt.Errorf("open file: %v", err) - } - // BUG: TODO: use fsde.Info() - info, err := file.Stat() + info, err := fsde[i].Info() if err != nil { - return nil, fmt.Errorf("stat: %v", err) + return nil, err } + id := idFromInfo(info) de[i] = &lib9p.DirEntry{ - //DirEnt: fsde[i], - Stat: info.(*lib9p.FileInfo).Stat, - //File: file.(*File), + FileInfo: &FileInfo{fiStat(f.fs.qidPool, id, info)}, } } return de, nil diff --git a/diskfs/qid_unix.go b/diskfs/qid_unix.go @@ -2,6 +2,7 @@ package diskfs import ( "fmt" + "io/fs" "syscall" "lib9p" @@ -30,6 +31,11 @@ func (f *File) id() (fileID, error) { return id, nil } +func idFromInfo(info fs.FileInfo) fileID { + stat := info.Sys().(*syscall.Stat_t) + return fileID{device: stat.Dev, inode: stat.Ino} +} + func allocQidPool() *QidPool { return &QidPool{ m: make(map[fileID]lib9p.Qid), @@ -41,6 +47,10 @@ func (pool *QidPool) lookup(f *File) (lib9p.Qid, bool) { if err != nil { return lib9p.Qid{}, false } + return pool.lookupID(id) +} + +func (pool *QidPool) lookupID(id fileID) (lib9p.Qid, bool) { qid, ok := pool.m[id] return qid, ok } @@ -54,7 +64,11 @@ func (pool *QidPool) alloc(f *File) (lib9p.Qid, error) { if err != nil { return lib9p.Qid{}, fmt.Errorf("stat %v: %v", f, err) } - qtype := lib9p.FSModeToQidType(fi.Mode()) + return pool.allocID(id, fi) +} + +func (pool *QidPool) allocID(id fileID, info fs.FileInfo) (lib9p.Qid, error) { + qtype := lib9p.FSModeToQidType(info.Mode()) qid := lib9p.Qid{ Path: pool.nextQid, Type: qtype, diff --git a/diskfs/stat.go b/diskfs/stat.go @@ -0,0 +1,59 @@ +package diskfs + +import ( + "fmt" + "io/fs" + "os/user" + "strconv" + "syscall" + "time" + + "lib9p" +) + +type FileInfo struct { + Stat *lib9p.Stat +} + +func (fi *FileInfo) Name() string { return fi.Stat.Name } +func (fi *FileInfo) Size() int64 { return fi.Stat.Length } +func (fi *FileInfo) Mode() fs.FileMode { return lib9p.Mode9ToFSMode(fi.Stat.Mode) } +func (fi *FileInfo) ModTime() time.Time { return time.Unix(int64(fi.Stat.Mtime), 0) } +func (fi *FileInfo) IsDir() bool { return fi.Stat.Mode&lib9p.DMDIR != 0 } +func (fi *FileInfo) Sys() any { return fi.Stat } +func (fi *FileInfo) Qid() lib9p.Qid { return fi.Sys().(*lib9p.Stat).Qid } + +func fiStat(pool *QidPool, id fileID, info fs.FileInfo) *lib9p.Stat { + qid, ok := pool.lookupID(id) + if !ok { + var err error + qid, err = pool.allocID(id, info) + if err != nil { + panic(fmt.Errorf("allocID: %v", err)) + } + } + + stat := info.Sys().(*syscall.Stat_t) + usr, err := user.LookupId(strconv.Itoa(int(stat.Uid))) + if err != nil { + panic(fmt.Errorf("user: %v", err)) + } + group, err := user.LookupGroupId(strconv.Itoa(int(stat.Gid))) + if err != nil { + panic(fmt.Errorf("group: %v", err)) + } + + return &lib9p.Stat{ + Type: 0, + Dev: 0, + Qid: qid, + Mode: lib9p.FSModeTo9Mode(info.Mode()), + Atime: uint32(stat.Atim.Sec), + Mtime: uint32(stat.Mtim.Sec), + Length: stat.Size, + Name: info.Name(), + Uid: usr.Username, + Gid: group.Name, + Muid: "", + } +} +\ No newline at end of file