commit 0b14ec5ecaa1c3bf35928a5ca78f6e67cd273272
parent 02e91e7befd7522bc0b1c0aab79b90525e1e05f4
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 23 Sep 2023 08:38:37 +0900
update cmd
Diffstat:
4 files changed, 137 insertions(+), 150 deletions(-)
diff --git a/cmd/disk.go b/cmd/disk.go
@@ -36,7 +36,10 @@ func main() {
log.Printf("accept connection: %v", err)
continue
}
- disk := diskfs.Open(flag.Arg(0))
+ disk, err := diskfs.Open(flag.Arg(0))
+ if err != nil {
+ log.Fatalf("open file tree.")
+ }
go handle(conn, disk)
}
}
diff --git a/diskfs/diskfs.go b/diskfs/diskfs.go
@@ -1,7 +1,6 @@
package diskfs
import (
- "io/fs"
"os"
"lib9p"
@@ -11,24 +10,31 @@ import (
DiskFS is a file system opened by OpenDiskFS
*/
type FS struct {
- fs fs.FS
rootPath string
+ root *File
qidPool *QidPool
}
-func Open(name string) *FS {
- fsys := os.DirFS(name)
- return &FS{
- fs: fsys,
+func Open(name string) (*FS, error) {
+ f, err := os.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ if err := f.Close(); err != nil {
+ panic(err)
+ }
+ root := &File{
+ path: ".",
+ }
+ fsys := &FS{
+ root: root,
rootPath: name,
qidPool: allocQidPool(),
}
+ root.fs = fsys
+ return fsys, nil
}
-func (fsys *FS) Open(name string) (lib9p.File, error) {
- file, err := openFile(fsys, name, lib9p.ORDWR)
- if err != nil {
- return nil, err
- }
- return file, nil
+func (fsys *FS) Root() lib9p.File {
+ return fsys.root
}
diff --git a/diskfs/file.go b/diskfs/file.go
@@ -4,7 +4,7 @@ import (
"fmt"
"os"
"os/user"
- "path"
+ "path/filepath"
"strconv"
"syscall"
@@ -13,56 +13,8 @@ import (
type File struct {
fs *FS // file system to which this file belongs
- path string // absolute path from the root of the fs.
-}
-
-func getChildEntry(fsys *FS, dir *os.File) ([]*lib9p.DirEntry, error) {
- fi, err := dir.Stat()
- if err != nil {
- return nil, fmt.Errorf("stat: %v", err)
- }
- var childEntry []*lib9p.DirEntry
- if !fi.IsDir() {
- return nil, fmt.Errorf("not a directory")
- }
-
- 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)
- }
- // TODO: unix specific
- 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}
- }
- return childEntry, nil
-}
-
-func openFile(fsys *FS, fpath string, mode lib9p.OpenMode) (*File, error) {
- // TODO: check if path exists.
-/*
- fsfile, err := fsys.fs.Open(fpath)
- if err != nil {
- return nil, fmt.Errorf("fs open: %v", err)
- }
- fsfile.Close()
-*/
-
- f := &File{
- fs: fsys,
- path: fpath,
- }
- return f, nil
+ path string // relative path from the root of the fs.
+ file *os.File // underlying file. nil if not open.
}
func (f *File) Fsys() lib9p.FS {
@@ -70,13 +22,8 @@ func (f *File) Fsys() lib9p.FS {
}
func (f *File) Stat() (*lib9p.FileInfo, error) {
- file, err := f.fs.fs.Open(f.path)
- if err != nil {
- return nil, fmt.Errorf("open: %v", err)
- }
- defer file.Close()
-
- fsfi, err := file.Stat()
+ ospath := filepath.Join(f.fs.rootPath, f.path)
+ fsfi, err := os.Stat(ospath)
if err != nil {
return nil, fmt.Errorf("stat: %v", err)
}
@@ -112,70 +59,42 @@ func (f *File) Stat() (*lib9p.FileInfo, error) {
return &lib9p.FileInfo{stat}, nil
}
-func (f *File) Close() error {
- return nil
-}
-
-func (f *File) Read(b []byte) (int, error) {
- file, err := f.fs.fs.Open(f.path)
- if err != nil {
- return 0, fmt.Errorf("open: %v", err)
- }
- defer file.Close()
- return 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)
+func (f *File) Qid() lib9p.Qid {
+ qid, ok := f.fs.qidPool.lookup(f)
+ if !ok {
+ var err error
+ qid, err = f.fs.qidPool.alloc(f)
+ if err != nil {
+ panic(fmt.Errorf("alloc qid: %v", err))
+ }
}
- return parent, nil
+ return qid
}
-func (f *File) Child() ([]lib9p.File, error) {
- var err error
- dir, err := f.fs.fs.Open(f.path)
- if err != nil {
- return nil, err
+func (f *File) Open(mode lib9p.OpenMode) error {
+ var flag int
+ switch mode&3 {
+ case lib9p.OREAD, lib9p.OEXEC:
+ flag = os.O_RDONLY
+ case lib9p.OWRITE:
+ flag = os.O_WRONLY
+ case lib9p.ORDWR:
+ flag = os.O_RDWR
}
- file := dir.(*os.File)
- childEntry, err := getChildEntry(f.fs, file)
- if err != nil {
- return nil, err
+ if mode&lib9p.OTRUNC != 0 {
+ flag |= os.O_TRUNC
}
-
- files := make([]lib9p.File, 0, len(childEntry))
- for i := 0; i < len(childEntry); i++ {
- cpath := path.Join(f.path, childEntry[i].Name())
- child, e := f.fs.Open(cpath)
- if e != nil {
- err = e
- continue
- }
- files = append(files, child)
+ if mode&lib9p.ORCLOSE != 0 {
+ return fmt.Errorf("not implemented")
}
- return files, err
-}
-func (f *File) ReadAt(p []byte, off int64) (int, error) {
- file, err := f.fs.fs.Open(f.path)
- if err != nil {
- return 0, fmt.Errorf("open: %v", err)
- }
- defer file.Close()
- return file.(*os.File).ReadAt(p, off)
-}
-
-func (f *File) WriteAt(p []byte, off int64) (int, error) {
- file, err := os.OpenFile(path.Join(f.fs.rootPath, f.path), os.O_WRONLY , 0)
+ ospath := filepath.Join(f.fs.rootPath, f.path)
+ file, err := os.OpenFile(ospath, flag, 0)
if err != nil {
- return 0, fmt.Errorf("open: %v", err)
+ return fmt.Errorf("open: %v", err)
}
- defer file.Close()
- n, err := file.WriteAt(p, off)
- return n, err
+ f.file = file
+ return nil
}
func (f *File) Create(name string, uid string,
@@ -188,7 +107,7 @@ func (f *File) Create(name string, uid string,
return nil, fmt.Errorf("not a directory")
}
- ospath := path.Join(f.fs.rootPath, f.path, name)
+ ospath := filepath.Join(f.fs.rootPath, f.path, name)
if perm&lib9p.DMDIR != 0 {
if err := os.Mkdir(ospath, lib9p.Mode9ToFSMode(perm)); err != nil {
return nil, fmt.Errorf("mkdir: %v", err)
@@ -225,15 +144,84 @@ func (f *File) Create(name string, uid string,
return nil, fmt.Errorf("set file mode: %v", err)
}
- file, err := openFile(f.fs, path.Join(f.path, name), mode)
- if err != nil {
+ file := &File{path: filepath.Join(f.path, name), fs: f.fs}
+ if err := file.Open(mode); err != nil {
return nil, fmt.Errorf("open new file: %v", err)
}
-
return file, nil
}
+
+func (f *File) Close() error {
+ if f.file == nil {
+ return fmt.Errorf("not open")
+ }
+ if err := f.file.Close(); err != nil {
+ return err
+ }
+ f.file = nil
+ return nil
+}
+
+func (f *File) Read(b []byte) (int, error) {
+ if f.file == nil {
+ return 0, fmt.Errorf("not open")
+ }
+ return f.file.Read(b)
+}
+
+func (f *File) Parent() (lib9p.File, error) {
+ parentPath := filepath.Dir(f.path)
+ parent, err := os.Open(filepath.Join(f.fs.rootPath, parentPath))
+ if err != nil {
+ return nil, fmt.Errorf("open parent: %v", err)
+ }
+ parent.Close()
+ return &File{path: parentPath, fs: f.fs}, nil
+}
+
+func (f *File) Child() ([]lib9p.File, error) {
+ ospath := filepath.Join(f.fs.rootPath, f.path)
+ osde, err := os.ReadDir(ospath)
+ if err != nil {
+ return nil, fmt.Errorf("readdir: %v", err)
+ }
+
+ files := make([]lib9p.File, 0, len(osde))
+ for _, de := range osde {
+ cpath := filepath.Join(f.path, de.Name())
+ child := &File{
+ path: cpath,
+ fs: f.fs,
+ }
+ files = append(files, child)
+ }
+ return files, nil
+}
+
+func (f *File) ReadAt(p []byte, off int64) (int, error) {
+ if f.file == nil {
+ return 0, fmt.Errorf("not open")
+ }
+ return f.file.ReadAt(p, off)
+}
+
+func (f *File) WriteAt(p []byte, off int64) (int, error) {
+ if f.file == nil {
+ return 0, fmt.Errorf("not open")
+ }
+ return f.file.WriteAt(p, off)
+}
+
func (f *File) Remove() error {
- ospath := path.Join(f.fs.rootPath, f.path)
- return os.Remove(ospath)
+ ospath := filepath.Join(f.fs.rootPath, f.path)
+ if f.file != nil {
+ if err := f.file.Close(); err != nil {
+ return fmt.Errorf("close: %v", err)
+ }
+ }
+ if err := os.Remove(ospath); err != nil {
+ return fmt.Errorf("remove: %v", err)
+ }
+ return nil
}
\ No newline at end of file
diff --git a/diskfs/qid_unix.go b/diskfs/qid_unix.go
@@ -5,6 +5,8 @@ import (
"io/fs"
"syscall"
"time"
+ "path/filepath"
+ "os"
"lib9p"
)
@@ -25,12 +27,8 @@ type QidPool struct {
}
func (f *File) id() (fileID, error) {
- file, err := f.fs.fs.Open(f.path)
- if err != nil {
- return fileID{}, fmt.Errorf("open: %v", err)
- }
- defer file.Close()
- fi, err := file.Stat()
+ ospath := filepath.Join(f.fs.rootPath, f.path)
+ fi, err := os.Stat(ospath)
if err != nil {
return fileID{}, err
}
@@ -58,12 +56,8 @@ func (pool *QidPool) lookup(f *File) (lib9p.Qid, bool) {
if err != nil {
return lib9p.Qid{}, false
}
- file, err := f.fs.fs.Open(f.path)
- if err != nil {
- return lib9p.Qid{}, false
- }
- defer file.Close()
- fsfi, err := file.Stat()
+ ospath := filepath.Join(f.fs.rootPath, f.path)
+ fsfi, err := os.Stat(ospath)
if err != nil {
return lib9p.Qid{}, false
}
@@ -87,12 +81,8 @@ func (pool *QidPool) alloc(f *File) (lib9p.Qid, error) {
if err != nil {
return lib9p.Qid{}, fmt.Errorf("get id: %v", err)
}
- file, err := f.fs.fs.Open(f.path)
- if err != nil {
- return lib9p.Qid{}, fmt.Errorf("open: %v", err)
- }
- defer file.Close()
- fi, err := file.Stat()
+ ospath := filepath.Join(f.fs.rootPath, f.path)
+ fi, err := os.Stat(ospath)
if err != nil {
return lib9p.Qid{}, fmt.Errorf("stat %v: %v", f, err)
}