commit 894eac128d474a35c4624557555c33a15ef58c59
parent 75a9e601d9185b156ddd36bb83d3eaf307679731
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 2 Sep 2023 08:43:37 +0900
update diskfs
Diffstat:
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