commit 6589901ae37b7c51764260dc48e1eec9e34b0b67
parent 8fffae3c4fb8bd753629de8519fea5b3b83621b4
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 26 Aug 2023 08:11:47 +0900
implement DiskFile
Diffstat:
7 files changed, 120 insertions(+), 67 deletions(-)
diff --git a/fid.go b/fid.go
@@ -19,7 +19,7 @@ const ( // TODO: is the mode should be implemented using interfaces?
type Fid struct {
Fid uint32
OMode OpenMode /* -1 = not open */
- File *File
+ File File
Uid string
Qid *Qid
}
diff --git a/file.go b/file.go
@@ -2,8 +2,8 @@ package lib9p
import (
"fmt"
- "io"
"io/fs"
+ "io"
"log"
"os"
"path"
@@ -25,7 +25,7 @@ const (
AREAD
)
-func hasPerm(f *File, uid string, p fs.FileMode) (bool, error) {
+func hasPerm(f File, uid string, p fs.FileMode) (bool, error) {
fi, err := f.Stat()
if err != nil {
return false, fmt.Errorf("stat: %v", err)
@@ -178,17 +178,25 @@ type DiskFile struct {
}
type File interface {
- Type() uint16
- Dev() uint32
- Qid() Qid
- Mode() FileMode
- Atime() uint32
- Mtime() uint32
- Length() int64
- Name() string
- Uid() string
- Gid() string
- Muid() string
+ fs.File
+ pathName() string
+
+ t() uint16
+ dev() uint32
+ qid() Qid
+ mode() FileMode
+ atime() uint32
+ mtime() uint32
+ length() int64
+ name() string
+ uid() string
+ gid() string
+ muid() string
+}
+
+type ReadDirFile interface {
+ File
+ ReadDir(int) ([]*DirEntry, error)
}
type hasQid interface {
@@ -204,12 +212,40 @@ func sameFile(fi0, fi1 fs.FileInfo) bool {
return os.SameFile(fi0, fi1)
}
-func openFile(fsys *FS, fpath string) (*File, error) {
+func (f *DiskFile) pathName() string { return f.path }
+func (f *DiskFile) t() uint16 { return f.Type }
+func (f *DiskFile) dev() uint32 { return f.Dev }
+func (f *DiskFile) length() int64 {
+ fi, err := f.file.Stat()
+ if err != nil {
+ log.Printf("stat: %v", err)
+ return 0
+ }
+ return fi.Size()
+}
+func (f *DiskFile) mode() FileMode {
+ fi, err := f.Stat()
+ if err != nil {
+ log.Printf("stat: %v", err)
+ return 0
+ }
+ return fi.Sys().(*stat).mode
+}
+func (f *DiskFile) name() string {
+ fi, err := f.Stat()
+ if err != nil {
+ log.Printf("stat: %v", err)
+ return ""
+ }
+ return fi.Name()
+}
+
+func openFile(fsys *FS, fpath string) (*DiskFile, error) {
file, err := fsys.fs.Open(fpath)
if err != nil {
return nil, fmt.Errorf("open fs: %v", err)
}
- f := &File{
+ f := &DiskFile{
fs: fsys,
file: file,
path: fpath,
@@ -217,30 +253,15 @@ func openFile(fsys *FS, fpath string) (*File, error) {
return f, nil
}
-func (f *File) Stat() (*FileInfo, error) {
+func (f *DiskFile) Stat() (fs.FileInfo, error) {
fsfi, err := f.file.Stat()
if err != nil {
return nil, fmt.Errorf("stat file: %v, %v", f, err)
}
- qid, err := f.qid()
- if err != nil {
- return nil, fmt.Errorf("get qid: %v")
- }
- uid, err := f.uid()
- if err != nil {
- log.Printf("get uid: %v\n", err)
- uid = ""
- }
- gid, err := f.gid()
- if err != nil {
- log.Printf("get gid: %v\n", err)
- gid = ""
- }
- muid, err := f.muid()
- if err != nil {
- log.Printf("get muid: %v\n", err)
- muid = ""
- }
+ qid := f.qid()
+ uid := f.uid()
+ gid := f.gid()
+ muid := f.muid()
fi := &FileInfo{
info: fsfi,
@@ -259,15 +280,15 @@ func (f *File) Stat() (*FileInfo, error) {
return fi, nil
}
-func (f *File) Close() error {
+func (f *DiskFile) Close() error {
return f.file.Close()
}
-func (f *File) Read(b []byte) (int, error) {
+func (f *DiskFile) Read(b []byte) (int, error) {
return f.file.Read(b)
}
-func (f *File) ReadAt(p []byte, off int64) (int, error) {
+func (f *DiskFile) ReadAt(p []byte, off int64) (int, error) {
if f, ok := f.file.(io.ReaderAt); ok {
return f.ReadAt(p, off)
}
@@ -293,7 +314,7 @@ func (f *File) ReadAt(p []byte, off int64) (int, error) {
return file.Read(p)
}
-func (f *File) ReadDir(n int) ([]*DirEntry, error) {
+func (f *DiskFile) ReadDir(n int) ([]*DirEntry, error) {
fi, err := f.file.Stat()
if err != nil {
return nil, fmt.Errorf("stat: %v", err)
@@ -320,7 +341,7 @@ func (f *File) ReadDir(n int) ([]*DirEntry, error) {
}
de[i] = &DirEntry{
dirEnt: fsde[i],
- info: info,
+ info: info.(*FileInfo),
file: file,
}
}
@@ -330,7 +351,7 @@ func (f *File) ReadDir(n int) ([]*DirEntry, error) {
type DirEntry struct {
dirEnt fs.DirEntry // underlying fs.DirEntry
info *FileInfo
- file *File
+ file File
}
func (e *DirEntry) Name() string { return e.dirEnt.Name() }
diff --git a/fs.go b/fs.go
@@ -11,7 +11,7 @@ type FS struct {
qidPool *QidPool
}
-func (fsys *FS) Open(name string) (*File, error) {
+func (fsys *FS) Open(name string) (*DiskFile, error) {
file, err := openFile(fsys, name)
if err != nil {
return nil, fmt.Errorf("openFile(%v, %s): %v", fsys, name, err)
diff --git a/qid_unix.go b/qid_unix.go
@@ -15,7 +15,7 @@ type QidPool struct {
nextQid uint64
}
-func (f *File) id() (fileID, error) {
+func (f *DiskFile) id() (fileID, error) {
fi, err := f.file.Stat()
if err != nil {
return fileID{}, err
@@ -28,16 +28,17 @@ func (f *File) id() (fileID, error) {
return id, nil
}
-func (f *File) qid() (Qid, error) {
+func (f *DiskFile) qid() Qid {
qid, ok := f.fs.qidPool.lookup(f)
if ok {
- return qid, nil
+ return qid
}
qid, err := f.fs.qidPool.alloc(f)
if err != nil {
- return Qid{}, fmt.Errorf("alloc qid: %v", err)
+ panic(fmt.Errorf("alloc qid: %v", err))
+ return Qid{}
}
- return qid, nil
+ return qid
}
func allocQidPool() *QidPool {
@@ -46,7 +47,7 @@ func allocQidPool() *QidPool {
}
}
-func (pool *QidPool) lookup(f *File) (Qid, bool) {
+func (pool *QidPool) lookup(f *DiskFile) (Qid, bool) {
id, err := f.id()
if err != nil {
return Qid{}, false
@@ -55,7 +56,7 @@ func (pool *QidPool) lookup(f *File) (Qid, bool) {
return qid, ok
}
-func (pool *QidPool) alloc(f *File) (Qid, error) {
+func (pool *QidPool) alloc(f *DiskFile) (Qid, error) {
id, err := f.id()
if err != nil {
return Qid{}, fmt.Errorf("get id: %v", err)
@@ -73,7 +74,7 @@ func (pool *QidPool) alloc(f *File) (Qid, error) {
return qid, nil
}
-func (pool *QidPool) delete(f *File) {
+func (pool *QidPool) delete(f *DiskFile) {
id, err := f.id()
if err != nil {
return
diff --git a/server.go b/server.go
@@ -179,7 +179,7 @@ func sWalk(s *Server, r *Req) {
return
}
- wqids, err := s.fs.walk(oldFid.File.path, ifcall.WName())
+ wqids, err := s.fs.walk(oldFid.File.pathName(), ifcall.WName())
if err != nil {
s.fPool.delete(ifcall.NewFid())
log.Printf("walk fs: %v", err)
@@ -188,7 +188,7 @@ func sWalk(s *Server, r *Req) {
}
relPath := path.Join(ifcall.WName()...)
- absPath := path.Join(oldFid.File.path, relPath)
+ absPath := path.Join(oldFid.File.pathName(), relPath)
newFid.File, err = s.fs.Open(absPath)
if err != nil {
log.Printf("open root dir: %v", err)
@@ -315,7 +315,7 @@ func sRead(s *Server, r *Req) {
return
}
if fi.IsDir() {
- de, err := fid.File.ReadDir(-1)
+ de, err := fid.File.(ReadDirFile).ReadDir(-1)
if err != nil {
log.Printf("read dir: %v", err)
}
@@ -337,7 +337,7 @@ func sRead(s *Server, r *Req) {
n += len(buf)
}
} else {
- n, err = fid.File.ReadAt(data, int64(ifcall.Offset()))
+ n, err = fid.File.(io.ReaderAt).ReadAt(data, int64(ifcall.Offset()))
if err != io.EOF && err != nil {
log.Printf("sRead: %v\n", err)
respond(r, err)
@@ -395,7 +395,7 @@ func sStat(s *Server, r *Req) {
ofcall := &RStat{
tag: ifcall.Tag(),
- info: fileInfo,
+ info: fileInfo.(*FileInfo),
}
r.ofcall = ofcall
diff --git a/time_unix.go b/time_unix.go
@@ -0,0 +1,26 @@
+package lib9p
+
+import (
+ "log"
+ "syscall"
+)
+
+func (f *DiskFile) atime() uint32 {
+ fi, err := f.file.Stat()
+ if err != nil {
+ log.Printf("stat error: %v", err)
+ return 0 // TODO: error check?
+ }
+ sys := fi.Sys()
+ return uint32(sys.(syscall.Stat_t).Atim.Sec)
+}
+
+func (f *DiskFile) mtime() uint32 {
+ fi, err := f.file.Stat()
+ if err != nil {
+ log.Printf("stat error: %v", err)
+ return 0 // TODO: error check?
+ }
+ sys := fi.Sys()
+ return uint32(sys.(syscall.Stat_t).Mtim.Sec)
+}
diff --git a/uid_unix.go b/uid_unix.go
@@ -1,38 +1,43 @@
package lib9p
import (
- "fmt"
+ "log"
"os/user"
"strconv"
"syscall"
)
-func (f *File) uid() (string, error) {
+func (f *DiskFile) uid() string {
info, err := f.file.Stat()
if err != nil {
- return "", fmt.Errorf("stat %v: %v", f, err)
+ log.Printf("stat %v: %v", f, err)
+ return ""
}
uid := info.Sys().(*syscall.Stat_t).Uid
user, err := user.LookupId(strconv.Itoa(int(uid)))
if err != nil {
- return "", fmt.Errorf("LookupId(%d): %v", uid, err)
+ log.Printf("LookupId(%d): %v", uid, err)
+ return ""
}
- return user.Username, nil
+ return user.Username
}
-func (f *File) gid() (string, error) {
+func (f *DiskFile) gid() string {
info, err := f.file.Stat()
if err != nil {
- return "", fmt.Errorf("stat %v: %v", f, err)
+ log.Printf("stat %v: %v", f, err)
+ return ""
}
gid := info.Sys().(*syscall.Stat_t).Gid
group, err := user.LookupGroupId(strconv.Itoa(int(gid)))
if err != nil {
- return "", fmt.Errorf("LookupGroupId(%d): %v", gid, err)
+ log.Printf("LookupGroupId(%d): %v", gid, err)
+ return ""
}
- return group.Name, nil
+ return group.Name
}
-func (f *File) muid() (string, error) {
- return "", fmt.Errorf("not implemented on unix")
+func (f *DiskFile) muid() string {
+ log.Printf("muid not implemented")
+ return ""
}
\ No newline at end of file