lib9p

Go 9P library.
Log | Files | Refs

commit 70eee120b67ee810ebb1ac82ce87e998f9f399b3
parent 15b4cc60a88211b9b2add737de049c3c9d7fa044
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Tue, 29 Aug 2023 11:03:46 +0900

divide diskfs

Diffstat:
Mcmd/disk.go | 6+++---
Ddisk_unix.go | 151------------------------------------------------------------------------------
Adiskfs/diskfs.go | 32++++++++++++++++++++++++++++++++
Adiskfs/file.go | 195+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adiskfs/qid_unix.go | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfcall.go | 20++++++++++----------
Mfile.go | 178++++++++++++++++++++++++++++++++++++-------------------------------------------
Mfs.go | 30+++++++-----------------------
Mqid.go | 29+++++++++++++++--------------
Dqid_plan9.go | 2--
Dqid_unix.go | 84-------------------------------------------------------------------------------
Mserver.go | 53+++++++++++++++++++++++++----------------------------
Dtime_unix.go | 26--------------------------
Duid_unix.go | 44--------------------------------------------
14 files changed, 442 insertions(+), 481 deletions(-)

diff --git a/cmd/disk.go b/cmd/disk.go @@ -4,12 +4,12 @@ package main import ( "flag" "fmt" - "io/fs" "log" "net" "os" "lib9p" + "lib9p/diskfs" ) var dFlag = flag.Bool("D", false, "Prints chatty message to the stderr.") @@ -36,12 +36,12 @@ func main() { log.Printf("accept connection: %v", err) continue } - disk := os.DirFS(flag.Arg(0)) + disk := diskfs.Open(flag.Arg(0)) go handle(conn, disk) } } -func handle(conn net.Conn, disk fs.FS) { +func handle(conn net.Conn, disk *diskfs.FS) { srv := lib9p.NewServer(disk, 8*1024, conn, conn) srv.Serve() } diff --git a/disk_unix.go b/disk_unix.go @@ -1,151 +0,0 @@ -package lib9p - -import ( - "fmt" - "log" - "io" - "io/fs" - "path" -) - -type DiskFile struct { - fs *FS // file system to which this file belongs - file fs.File // underlying file - path string // absolute path from the root of the fs. -} - -func openFile(fsys *FS, fpath string) (File, error) { - file, err := fsys.fs.Open(fpath) - if err != nil { - return nil, fmt.Errorf("open fs: %v", err) - } - f := &DiskFile{ - fs: fsys, - file: file, - path: fpath, - } - return f, nil -} - -func (f *DiskFile) pathName() string { return f.path } -func (f *DiskFile) t() uint16 { return 0 } -func (f *DiskFile) dev() uint32 { return 0 } -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 (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 := f.qid() - uid := f.uid() - gid := f.gid() - muid := f.muid() - - fi := &fileStat{ - info: fsfi, - stat: &stat{ - qid: &qid, - name: fsfi.Name(), - mode: fsModeTo9Mode(fsfi.Mode()), - aTime: uint32(fsfi.ModTime().Unix()), - mTime: uint32(fsfi.ModTime().Unix()), - length: fsfi.Size(), - uid: uid, // TODO: uid, gid, muid - gid: gid, - muid: muid, - }, - } - return fi, nil -} - -func (f *DiskFile) Close() error { - return f.file.Close() -} - -func (f *DiskFile) Read(b []byte) (int, error) { - return f.file.Read(b) -} - -func (f *DiskFile) ReadAt(p []byte, off int64) (int, error) { - if f, ok := f.file.(io.ReaderAt); ok { - return f.ReadAt(p, off) - } - file := f.file - - buf := make([]byte, 8*1024) // TODO: set appropreate size - var n int64 - for n+int64(len(buf)) < off { - m, err := file.Read(buf) - if err != nil { - return 0, err - } - n += int64(m) - } - m, err := file.Read(buf[:off-n]) - if err != nil { - return 0, err - } - n += int64(m) - if n != off { - panic("wrong offset") - } - return file.Read(p) -} - -func (f *DiskFile) ReadDir(n int) ([]*DirEntry, error) { - fi, err := f.file.Stat() - if err != nil { - return nil, fmt.Errorf("stat: %v", err) - } - dir, ok := f.file.(fs.ReadDirFile) - if !ok || !fi.IsDir() { - return nil, fmt.Errorf("not a directory") - } - fsde, err := dir.ReadDir(n) - if err != nil { - return nil, err - } - de := make([]*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() - if err != nil { - return nil, fmt.Errorf("stat: %v", err) - } - de[i] = &DirEntry{ - dirEnt: fsde[i], - info: info.(*fileStat), - file: file.(File), - } - } - return de, nil -} diff --git a/diskfs/diskfs.go b/diskfs/diskfs.go @@ -0,0 +1,32 @@ +package diskfs + +import ( + "io/fs" + "os" + + "lib9p" +) + +/* +DiskFS is a file system opened by OpenDiskFS +*/ +type FS struct { + fs fs.FS + qidPool *QidPool +} + +func Open(name string) *FS { + fsys := os.DirFS(name) + return &FS{ + fs: fsys, + qidPool: allocQidPool(), + } +} + +func (fsys *FS) Open(name string) (lib9p.File, error) { + file, err := openFile(fsys, name) + if err != nil { + return nil, err + } + return file, nil +} diff --git a/diskfs/file.go b/diskfs/file.go @@ -0,0 +1,195 @@ +package diskfs + +import ( + "fmt" + "io/fs" + "log" + "os" + "os/user" + "path" + "strconv" + "syscall" + + "lib9p" +) + +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. +} + +func openFile(fsys *FS, fpath string) (*File, error) { + file, err := fsys.fs.Open(fpath) + if err != nil { + return nil, fmt.Errorf("open fs: %v", err) + } + f := &File{ + fs: fsys, + file: file.(*os.File), + path: fpath, + } + return f, nil +} + +func (f *File) PathName() string { return f.path } +func (f *File) Type() uint16 { return 0 } +func (f *File) Dev() uint32 { return 0 } + +func (f *File) Qid() lib9p.Qid { + qid, ok := f.fs.qidPool.lookup(f) + if ok { + return qid + } + qid, err := f.fs.qidPool.alloc(f) + if err != nil { + panic(fmt.Errorf("alloc qid: %v", err)) + return lib9p.Qid{} + } + return qid +} + +func (f *File) Length() int64 { + fi, err := f.file.Stat() + if err != nil { + log.Printf("stat: %v", err) + return 0 + } + return fi.Size() +} +func (f *File) Mode() lib9p.FileMode { + fi, err := f.Stat() + if err != nil { + log.Printf("stat: %v", err) + return 0 + } + return fi.Sys().(*lib9p.Stat).Mode +} +func (f *File) Name() string { + fi, err := f.Stat() + if err != nil { + log.Printf("stat: %v", err) + return "" + } + return fi.Name() +} + +func (f *File) 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 *File) 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) +} + +func (f *File) Uid() string { + info, err := f.file.Stat() + if err != nil { + 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 { + log.Printf("LookupId(%d): %v", uid, err) + return "" + } + return user.Username +} + +func (f *File) Gid() string { + info, err := f.file.Stat() + if err != nil { + 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 { + log.Printf("LookupGroupId(%d): %v", gid, err) + return "" + } + return group.Name +} + +func (f *File) Muid() string { + log.Printf("muid not implemented") + return "" +} + +func (f *File) Stat() (fs.FileInfo, error) { + fsfi, err := f.file.Stat() + if err != nil { + return nil, fmt.Errorf("stat file: %v, %v", f, err) + } + qid := f.Qid() + uid := f.Uid() + gid := f.Gid() + muid := f.Muid() + + fi := &lib9p.FileInfo{ + Info: fsfi, + Stat: &lib9p.Stat{ + Qid: &qid, + Name: fsfi.Name(), + Mode: lib9p.FSModeTo9Mode(fsfi.Mode()), + Atime: uint32(fsfi.ModTime().Unix()), + Mtime: uint32(fsfi.ModTime().Unix()), + Length: fsfi.Size(), + Uid: uid, + Gid: gid, + Muid: muid, + }, + } + return fi, nil +} + +func (f *File) Close() error { + return f.file.Close() +} + +func (f *File) Read(b []byte) (int, error) { + return f.file.Read(b) +} + +func (f *File) ReadAt(p []byte, off int64) (int, error) { + return f.file.ReadAt(p, off) +} + +func (f *File) ReadDir(n int) ([]*lib9p.DirEntry, error) { + fsde, err := f.file.ReadDir(n) + if err != nil { + return nil, err + } + 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() + if err != nil { + return nil, fmt.Errorf("stat: %v", err) + } + de[i] = &lib9p.DirEntry{ + DirEnt: fsde[i], + FileInfo: info.(*lib9p.FileInfo), + File: file.(*File), + } + } + return de, nil +} diff --git a/diskfs/qid_unix.go b/diskfs/qid_unix.go @@ -0,0 +1,72 @@ +package diskfs + +import ( + "fmt" + "syscall" + + "lib9p" +) + +type fileID struct { + device uint64 + inode uint64 +} + +type QidPool struct { + m map[fileID]lib9p.Qid + nextQid uint64 +} + +func (f *File) id() (fileID, error) { + fi, err := f.file.Stat() + if err != nil { + return fileID{}, err + } + sys := fi.Sys().(*syscall.Stat_t) + id := fileID{ + device: sys.Dev, + inode: sys.Ino, + } + return id, nil +} + +func allocQidPool() *QidPool { + return &QidPool{ + m: make(map[fileID]lib9p.Qid), + } +} + +func (pool *QidPool) lookup(f *File) (lib9p.Qid, bool) { + id, err := f.id() + if err != nil { + return lib9p.Qid{}, false + } + qid, ok := pool.m[id] + return qid, ok +} + +func (pool *QidPool) alloc(f *File) (lib9p.Qid, error) { + id, err := f.id() + if err != nil { + return lib9p.Qid{}, fmt.Errorf("get id: %v", err) + } + fi, err := f.file.Stat() + if err != nil { + return lib9p.Qid{}, fmt.Errorf("stat %v: %v", f, err) + } + qtype := lib9p.FSModeToQidType(fi.Mode()) + qid := lib9p.Qid{ + Path: pool.nextQid, + Type: qtype, + } + pool.m[id] = qid + return qid, nil +} + +func (pool *QidPool) delete(f *File) { + id, err := f.id() + if err != nil { + return + } + delete(pool.m, id) +} +\ No newline at end of file diff --git a/fcall.go b/fcall.go @@ -33,8 +33,8 @@ const ( Rremove = 123 Tstat = 124 Rstat = 125 - Twstat = 126 - Rwstat = 127 + TwStat = 126 + RwStat = 127 Tmax = 128 ) @@ -823,16 +823,16 @@ func (msg *TStat) String() string { type RStat struct { tag uint16 - info *fileStat + info *FileInfo } func newRStat(buf []byte) *RStat { panic("not implemented") } func (msg *RStat) Size() uint32 { - stat, ok := msg.info.Sys().(*stat) + Stat, ok := msg.info.Sys().(*Stat) if !ok { - panic("not stat") + panic("not Stat") } - return uint32(4 + 1 + 2 + 2 + 2 + stat.size()) + return uint32(4 + 1 + 2 + 2 + 2 + Stat.size()) } func (msg *RStat) Type() MsgType { return Rstat } func (msg *RStat) Tag() uint16 { return msg.tag } @@ -841,11 +841,11 @@ func (msg *RStat) marshal() []byte { pbit32(buf[0:4], msg.Size()) buf[4] = uint8(Rstat) pbit16(buf[5:7], msg.Tag()) - stat, ok := msg.info.Sys().(*stat) + Stat, ok := msg.info.Sys().(*Stat) if !ok { - panic("not stat") + panic("not Stat") } - fiBuf := stat.marshal() + fiBuf := Stat.marshal() pbit16(buf[7:9], uint16(len(fiBuf))) for i := 0; i < len(fiBuf); i++ { buf[9+i] = fiBuf[i] @@ -854,5 +854,5 @@ func (msg *RStat) marshal() []byte { } func (msg *RStat) String() string { - return fmt.Sprintf("Rstat tag %d stat %s", msg.Tag(), msg.info.stat) + return fmt.Sprintf("Rstat tag %d Stat %s", msg.Tag(), msg.info.Stat) } diff --git a/file.go b/file.go @@ -3,7 +3,7 @@ package lib9p import ( "fmt" "io/fs" - "os" +// "os" "time" ) @@ -25,24 +25,24 @@ const ( 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) + return false, fmt.Errorf("Stat: %v", err) } fp := fi.Mode().Perm() - stat, ok := fi.Sys().(*stat) + Stat, ok := fi.Sys().(*Stat) if !ok { - panic("not stat") + panic("not Stat") } m := fp & 7 // other if (p & m) == p { return true, nil } - if stat.uid == uid { + if Stat.Uid == uid { m |= (fp >> 6) & 7 if (p & m) == p { return true, nil } } - if stat.gid == uid { + if Stat.Gid == uid { m |= (fp >> 3) & 7 if (p & m) == p { return true, nil @@ -51,77 +51,77 @@ func hasPerm(f File, uid string, p fs.FileMode) (bool, error) { return false, nil } -type stat struct { - t uint16 - dev uint32 - qid *Qid - mode FileMode - aTime uint32 - mTime uint32 - length int64 - name string - uid string - gid string - muid string +type Stat struct { + Type uint16 + Dev uint32 + Qid *Qid + Mode FileMode + Atime uint32 + Mtime uint32 + Length int64 + Name string + Uid string + Gid string + Muid string } -func (s *stat) size() uint16 { +func (s *Stat) size() uint16 { return uint16(2 + 4 + 13 + 4 + 4 + 4 + 8 + // type + dev + qid + mode + atime + mtime + length - 2 + len(s.name) + - 2 + len(s.uid) + - 2 + len(s.gid) + - 2 + len(s.muid)) + 2 + len(s.Name) + + 2 + len(s.Uid) + + 2 + len(s.Gid) + + 2 + len(s.Muid)) } -func (s *stat) marshal() []byte { +func (s *Stat) marshal() []byte { cur := 0 size := s.size() msg := make([]byte, 2+size) pbit16(msg[cur:cur+2], size) cur += 2 - pbit16(msg[cur:cur+2], s.t) + pbit16(msg[cur:cur+2], s.Type) cur += 2 - pbit32(msg[cur:cur+4], s.dev) + pbit32(msg[cur:cur+4], s.Dev) cur += 4 - msg[cur] = uint8(s.qid.Type()) + msg[cur] = uint8(s.Qid.Type) cur += 1 - pbit32(msg[cur:cur+4], s.qid.Vers()) + pbit32(msg[cur:cur+4], s.Qid.Vers) cur += 4 - pbit64(msg[cur:cur+8], s.qid.Path()) + pbit64(msg[cur:cur+8], s.Qid.Path) cur += 8 - pbit32(msg[cur:cur+4], uint32(s.mode)) + pbit32(msg[cur:cur+4], uint32(s.Mode)) cur += 4 - pbit32(msg[cur:cur+4], s.aTime) + pbit32(msg[cur:cur+4], s.Atime) cur += 4 - pbit32(msg[cur:cur+4], s.mTime) + pbit32(msg[cur:cur+4], s.Mtime) cur += 4 - pbit64(msg[cur:cur+8], uint64(s.length)) + pbit64(msg[cur:cur+8], uint64(s.Length)) cur += 8 - pbit16(msg[cur:cur+2], uint16(len(s.name))) + pbit16(msg[cur:cur+2], uint16(len(s.Name))) cur += 2 - for i := 0; i < len(s.name); i++ { - msg[cur+i] = s.name[i] + for i := 0; i < len(s.Name); i++ { + msg[cur+i] = s.Name[i] } - cur += len(s.name) - pbit16(msg[cur:cur+2], uint16(len(s.uid))) + cur += len(s.Name) + pbit16(msg[cur:cur+2], uint16(len(s.Uid))) cur += 2 - for i := 0; i < len(s.uid); i++ { - msg[cur+i] = s.uid[i] + for i := 0; i < len(s.Uid); i++ { + msg[cur+i] = s.Uid[i] } - cur += len(s.uid) - pbit16(msg[cur:cur+2], uint16(len(s.gid))) + cur += len(s.Uid) + pbit16(msg[cur:cur+2], uint16(len(s.Gid))) cur += 2 - for i := 0; i < len(s.gid); i++ { - msg[cur+i] = s.gid[i] + for i := 0; i < len(s.Gid); i++ { + msg[cur+i] = s.Gid[i] } - cur += len(s.gid) - pbit16(msg[cur:cur+2], uint16(len(s.muid))) + cur += len(s.Gid) + pbit16(msg[cur:cur+2], uint16(len(s.Muid))) cur += 2 - for i := 0; i < len(s.muid); i++ { - msg[cur+i] = s.muid[i] + for i := 0; i < len(s.Muid); i++ { + msg[cur+i] = s.Muid[i] } - cur += len(s.muid) + cur += len(s.Muid) if len(msg) != cur { panic(fmt.Errorf("cursor position %d and msg length %d don't match", @@ -130,44 +130,44 @@ func (s *stat) marshal() []byte { return msg } -func (s *stat) String() string { +func (s *Stat) String() string { return fmt.Sprintf("'%s' '%s' '%s' '%s' q %v m %#o at %d mt %d l %d t %d d %d", - s.name, s.uid, s.gid, s.muid, s.qid, s.mode, - s.aTime, s.mTime, s.length, s.t, s.dev) + s.Name, s.Uid, s.Gid, s.Muid, s.Qid, s.Mode, + s.Atime, s.Mtime, s.Length, s.Type, s.Dev) } /* fs.FileInfo */ -type fileStat struct { - info fs.FileInfo - stat *stat +type FileInfo struct { + Info fs.FileInfo + Stat *Stat } -func (fi *fileStat) Name() string { return fi.info.Name() } -func (fi *fileStat) Size() int64 { return fi.info.Size() } -func (fi *fileStat) Mode() fs.FileMode { return fi.info.Mode() } -func (fi *fileStat) ModTime() time.Time { return fi.info.ModTime() } -func (fi *fileStat) IsDir() bool { return fi.info.IsDir() } -func (fi *fileStat) Sys() any { return fi.stat } -func (fi *fileStat) Qid() *Qid { return fi.Sys().(*stat).qid } +func (fi *FileInfo) Name() string { return fi.Info.Name() } +func (fi *FileInfo) Size() int64 { return fi.Info.Size() } +func (fi *FileInfo) Mode() fs.FileMode { return fi.Info.Mode() } +func (fi *FileInfo) ModTime() time.Time { return fi.Info.ModTime() } +func (fi *FileInfo) IsDir() bool { return fi.Info.IsDir() } +func (fi *FileInfo) Sys() any { return fi.Stat } +func (fi *FileInfo) Qid() *Qid { return fi.Sys().(*Stat).Qid } type File interface { 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 + PathName() string + + Type() uint16 + Dev() uint32 + Qid() Qid + Mode() FileMode + Atime() uint32 + Mtime() uint32 + Length() int64 + Name() string + Uid() string + Gid() string + Muid() string } type ReadDirFile interface { @@ -175,27 +175,13 @@ type ReadDirFile interface { ReadDir(int) ([]*DirEntry, error) } -type hasQid interface { - Qid() *Qid -} - -func sameFile(fi0, fi1 fs.FileInfo) bool { - if hq0, ok := fi0.(hasQid); ok { - if hq1, ok := fi1.(hasQid); ok { - return hq0.Qid().Path() == hq1.Qid().Path() - } - } - return os.SameFile(fi0, fi1) -} - - type DirEntry struct { - dirEnt fs.DirEntry // underlying fs.DirEntry - info *fileStat - file File + DirEnt fs.DirEntry // underlying fs.DirEntry + FileInfo *FileInfo + File File } -func (e *DirEntry) Name() string { return e.dirEnt.Name() } -func (e *DirEntry) IsDir() bool { return e.dirEnt.IsDir() } -func (e *DirEntry) Type() fs.FileMode { return e.dirEnt.Type() } -func (e *DirEntry) Info() (*fileStat, error) { return e.info, nil } +func (e *DirEntry) Name() string { return e.DirEnt.Name() } +func (e *DirEntry) IsDir() bool { return e.DirEnt.IsDir() } +func (e *DirEntry) Type() fs.FileMode { return e.DirEnt.Type() } +func (e *DirEntry) Info() (*FileInfo, error) { return e.FileInfo, nil } diff --git a/fs.go b/fs.go @@ -5,23 +5,14 @@ import ( "path" ) -type FS struct { - fs fs.FS // underlying file system - qidPool *QidPool -} - /* - Returned file must implement File + Open() must return File with Qid() method. */ -func (fsys *FS) Open(name string) (fs.File, error) { - file, err := openFile(fsys, name) - if err != nil { - return nil, err - } - return file, nil +type FS interface { + Open(string) (File, error) } -func (fsys *FS) walk(root string, wnames []string) ([]*Qid, error) { +func walk(fsys FS, root string, wnames []string) ([]*Qid, error) { wqids := make([]*Qid, len(wnames)) curName := root for i, name := range wnames { @@ -30,20 +21,13 @@ func (fsys *FS) walk(root string, wnames []string) ([]*Qid, error) { if err != nil { return wqids, err } - - qid, ok := fsys.qidPool.lookup(f.(File)) - if !ok { - qid, err = fsys.qidPool.alloc(f.(File)) - if err != nil { - return wqids, err - } - } + qid := f.Qid() wqids[i] = &qid } return wqids, nil } -func fsModeToQidType(fm fs.FileMode) QidType { +func FSModeToQidType(fm fs.FileMode) QidType { var qt QidType if fm&fs.ModeDir != 0 { qt |= QTDIR @@ -67,7 +51,7 @@ func fsModeToQidType(fm fs.FileMode) QidType { return qt } -func fsModeTo9Mode(mode fs.FileMode) FileMode { +func FSModeTo9Mode(mode fs.FileMode) FileMode { mode9 := FileMode(mode & fs.ModePerm) if mode&fs.ModeDir != 0 { mode9 |= DMDIR diff --git a/qid.go b/qid.go @@ -19,39 +19,42 @@ const ( ) type Qid struct { - t QidType - vers uint32 - path uint64 + Type QidType + Vers uint32 + Path uint64 } func newQid(b []byte) *Qid { return &Qid{ - t: QidType(b[0]), - vers: gbit32(b[1:5]), - path: gbit64(b[5:13]), + Type: QidType(b[0]), + Vers: gbit32(b[1:5]), + Path: gbit64(b[5:13]), } } -func (q *Qid) Type() QidType { return q.t } +/* +func (q *Qid) Type() QidType { return q.Type } func (q *Qid) SetType(t QidType) { q.t = t } func (q *Qid) Vers() uint32 { return q.vers } func (q *Qid) SetVers(v uint32) { q.vers = v } func (q *Qid) Path() uint64 { return q.path } func (q *Qid) SetPath(p uint64) { q.path = p } +*/ + func (q *Qid) marshal() []byte { buf := make([]byte, 13) - buf[0] = uint8(q.t) - pbit32(buf[1:5], q.vers) - pbit64(buf[5:13], q.path) + buf[0] = uint8(q.Type) + pbit32(buf[1:5], q.Vers) + pbit64(buf[5:13], q.Path) return buf } func (q *Qid) String() string { - return fmt.Sprintf("(%016d %d %s)", q.Path(), q.Vers(), q.typeStr()) + return fmt.Sprintf("(%016d %d %s)", q.Path, q.Vers, q.typeStr()) } // TypeStr returns the q.Type() as string for debugging information. func (q *Qid) typeStr() string { var s string - t := q.Type() + t := q.Type if t&QTDIR != 0 { s += "d" } @@ -66,5 +69,3 @@ func (q *Qid) typeStr() string { } return s } - - diff --git a/qid_plan9.go b/qid_plan9.go @@ -1 +0,0 @@ -package lib9p -\ No newline at end of file diff --git a/qid_unix.go b/qid_unix.go @@ -1,83 +0,0 @@ -package lib9p - -import ( - "fmt" - "syscall" -) - -type fileID struct { - device uint64 - inode uint64 -} - -type QidPool struct { - m map[fileID]Qid - nextQid uint64 -} - -func (f *DiskFile) id() (fileID, error) { - fi, err := f.file.Stat() - if err != nil { - return fileID{}, err - } - sys := fi.Sys().(*syscall.Stat_t) - id := fileID{ - device: sys.Dev, - inode: sys.Ino, - } - return id, nil -} - -func (f *DiskFile) qid() Qid { - qid, ok := f.fs.qidPool.lookup(f) - if ok { - return qid - } - qid, err := f.fs.qidPool.alloc(f) - if err != nil { - panic(fmt.Errorf("alloc qid: %v", err)) - return Qid{} - } - return qid -} - -func allocQidPool() *QidPool { - return &QidPool{ - m: make(map[fileID]Qid), - } -} - -func (pool *QidPool) lookup(f File) (Qid, bool) { - id, err := f.(*DiskFile).id() - if err != nil { - return Qid{}, false - } - qid, ok := pool.m[id] - return qid, ok -} - -func (pool *QidPool) alloc(f File) (Qid, error) { - id, err := f.(*DiskFile).id() - if err != nil { - return Qid{}, fmt.Errorf("get id: %v", err) - } - fi, err := f.(*DiskFile).file.Stat() - if err != nil { - return Qid{}, fmt.Errorf("stat %v: %v", f, err) - } - qtype := fsModeToQidType(fi.Mode()) - qid := Qid{ - path: pool.nextQid, - t: qtype, - } - pool.m[id] = qid - return qid, nil -} - -func (pool *QidPool) delete(f File) { - id, err := f.(*DiskFile).id() - if err != nil { - return - } - delete(pool.m, id) -} -\ No newline at end of file diff --git a/server.go b/server.go @@ -19,7 +19,7 @@ func Chatty() { var EDupTag = fmt.Errorf("duplicate tag") type Server struct { - fs *FS + fs FS MSize uint32 fPool *FidPool rPool *ReqPool @@ -27,18 +27,15 @@ type Server struct { Writer io.Writer } -func NewServer(fsys fs.FS, mSize uint32, r io.Reader, w io.Writer) *Server { - s := new(Server) - s.fs = &FS{ - fs: fsys, - qidPool: allocQidPool(), - } - s.MSize = mSize - s.fPool = allocFidPool() - s.rPool = allocReqPool() - s.Reader = r - s.Writer = w - return s +func NewServer(fsys FS, mSize uint32, r io.Reader, w io.Writer) *Server { + return &Server{ + fs: fsys, + MSize: mSize, + fPool: allocFidPool(), + rPool: allocReqPool(), + Reader: r, + Writer: w, + } } func (s *Server) getReq() (*Req, error) { @@ -143,12 +140,12 @@ func sAttach(s *Server, r *Req) { fid.OMode = OREAD info, err := fid.File.Stat() if err != nil { - log.Printf("stat %s, %v", fid.File, err) + log.Printf("Stat %s, %v", fid.File, err) respond(r, fmt.Errorf("internal error")) return } - stat := info.Sys().(*stat) - fid.Qid = stat.qid + Stat := info.Sys().(*Stat) + fid.Qid = Stat.Qid ofcall := &RAttach{ tag: ifcall.Tag(), @@ -180,7 +177,7 @@ func sWalk(s *Server, r *Req) { return } - wqids, err := s.fs.walk(oldFid.File.pathName(), ifcall.WName()) + wqids, err := walk(s.fs, oldFid.File.PathName(), ifcall.WName()) if err != nil { s.fPool.delete(ifcall.NewFid()) log.Printf("walk fs: %v", err) @@ -189,7 +186,7 @@ func sWalk(s *Server, r *Req) { } relPath := path.Join(ifcall.WName()...) - absPath := path.Join(oldFid.File.pathName(), relPath) + absPath := path.Join(oldFid.File.PathName(), relPath) f, err := s.fs.Open(absPath) if err != nil { log.Printf("open root dir: %v", err) @@ -201,12 +198,12 @@ func sWalk(s *Server, r *Req) { newFid.Uid = oldFid.Uid info, err := newFid.File.Stat() if err != nil { - log.Printf("stat %v, %v", newFid.File, err) + log.Printf("Stat %v, %v", newFid.File, err) respond(r, fmt.Errorf("internal error")) return } - stat := info.Sys().(*stat) - newFid.Qid = stat.qid + Stat := info.Sys().(*Stat) + newFid.Qid = Stat.Qid ofcall := &RWalk{ tag: r.ifcall.Tag(), @@ -231,9 +228,9 @@ func sOpen(s *Server, r *Req) { respond(r, fmt.Errorf("already open")) return } - // TODO: this if statement is from plan9's lib9p. + // TODO: this if Statement is from plan9's lib9p. // I don't understand this. - if fidStruct.Qid.t == QTDIR && ifcall.Mode() & ^ORCLOSE != OREAD { + if fidStruct.Qid.Type == QTDIR && ifcall.Mode() & ^ORCLOSE != OREAD { respond(r, fmt.Errorf("is a directory")) return } @@ -254,7 +251,7 @@ func sOpen(s *Server, r *Req) { if ifcall.Mode()&OTRUNC != 0 { p |= AWRITE } - if fidStruct.Qid.t&QTDIR != 0 && p != AREAD { + if fidStruct.Qid.Type&QTDIR != 0 && p != AREAD { respond(r, fmt.Errorf("permission denied")) return } @@ -307,7 +304,7 @@ func sRead(s *Server, r *Req) { var err error fi, err := fid.File.Stat() if err != nil { - log.Printf("stat: %v") + log.Printf("Stat: %v") respond(r, fmt.Errorf("internal error")) return } @@ -323,7 +320,7 @@ func sRead(s *Server, r *Req) { log.Printf("info: %v", err) continue } - st := info.Sys().(*stat) + st := info.Sys().(*Stat) buf := st.marshal() if n+len(buf) > len(data) { break @@ -385,14 +382,14 @@ func sStat(s *Server, r *Req) { } fileInfo, err := fidStruct.File.Stat() if err != nil { - log.Printf("stat file %v: %v", fidStruct.File, err) + log.Printf("Stat file %v: %v", fidStruct.File, err) respond(r, fmt.Errorf("internal error")) return } ofcall := &RStat{ tag: ifcall.Tag(), - info: fileInfo.(*fileStat), + info: fileInfo.(*FileInfo), } r.ofcall = ofcall diff --git a/time_unix.go b/time_unix.go @@ -1,26 +0,0 @@ -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,43 +0,0 @@ -package lib9p - -import ( - "log" - "os/user" - "strconv" - "syscall" -) - -func (f *DiskFile) uid() string { - info, err := f.file.Stat() - if err != nil { - 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 { - log.Printf("LookupId(%d): %v", uid, err) - return "" - } - return user.Username -} - -func (f *DiskFile) gid() string { - info, err := f.file.Stat() - if err != nil { - 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 { - log.Printf("LookupGroupId(%d): %v", gid, err) - return "" - } - return group.Name -} - -func (f *DiskFile) muid() string { - log.Printf("muid not implemented") - return "" -} -\ No newline at end of file