lib9p

Go 9P library.
Log | Files | Refs

commit c9d25ef21910519cd1efa5baa16a0be4e4d6ba88
parent 5ebffe30824b8f1148066c185df189339db089ba
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Mon, 31 Jul 2023 15:35:21 +0900

change data structure

Diffstat:
Adisk.go | 2++
Mfcall.go | 61+++++++++++++++++++++++++++++++++++--------------------------
Mfid.go | 38+++++++++++++++++++++++++++++++++++++-
Mfile.go | 206+++++++++++++++++++++----------------------------------------------------------
Afs.go | 30++++++++++++++++++++++++++++++
Mserver.go | 56++++++++++++++++++++++++++++++++++++++++++++++++++------
6 files changed, 208 insertions(+), 185 deletions(-)

diff --git a/disk.go b/disk.go @@ -0,0 +1,2 @@ +package lib9p + diff --git a/fcall.go b/fcall.go @@ -70,9 +70,8 @@ type Msg interface { // Tag returns the tag of msg. Tag() uint16 - // Conv2M convert Msg to byte array to be transmitted. - // This name is derived from plan9port's lib9p: convS2M. - conv2M() []byte + // Marshal convert Msg to byte array to be transmitted. + marshal() []byte String() string } @@ -82,7 +81,7 @@ type bufMsg []byte func (msg bufMsg) Size() uint32 { return gbit32(msg[0:4]) } func (msg bufMsg) Type() MsgType { return MsgType(msg[4]) } func (msg bufMsg) Tag() uint16 { return gbit16(msg[5:7]) } -func (msg bufMsg) conv2M() []byte { return []byte(msg)[:msg.Size()] } +func (msg bufMsg) marshal() []byte { return []byte(msg)[:msg.Size()] } func (msg bufMsg) String() string { return fmt.Sprint([]byte(msg[:msg.Size()])) } // TVersion represents Tversion message of 9P. @@ -107,7 +106,7 @@ func (msg *TVersion) Type() MsgType { return Tversion } func (msg *TVersion) Tag() uint16 { return msg.tag } func (msg *TVersion) MSize() uint32 { return msg.mSize } func (msg *TVersion) Version() string { return msg.version } -func (msg *TVersion) conv2M() []byte { +func (msg *TVersion) marshal() []byte { m := make([]byte, msg.Size()) pbit32(m[0:4], msg.Size()) m[4] = uint8(Tversion) @@ -140,7 +139,7 @@ func (msg *RVersion) MSize() uint32 { return msg.mSize } func (msg *RVersion) SetMSize(s uint32) { msg.mSize = s } func (msg *RVersion) Version() string { return msg.version } func (msg *RVersion) SetVersion(v string) { msg.version = v } -func (msg *RVersion) conv2M() []byte { +func (msg *RVersion) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -204,7 +203,7 @@ func (msg TAuth) Tag() uint16 { return msg.tag } func (msg TAuth) AFid() uint32 { return msg.afid } func (msg TAuth) UName() string { return msg.uname } func (msg TAuth) AName() string { return msg.aname } -func (msg TAuth) conv2M() []byte { +func (msg TAuth) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -253,7 +252,7 @@ func (msg RAuth) Size() uint32 { return 4 + 1 + 2 + 13 } func (msg RAuth) Type() MsgType { return Rauth } func (msg RAuth) Tag() uint16 { return msg.tag } func (msg RAuth) AQid() *Qid { return msg.aqid } -func (msg RAuth) conv2M() []byte { +func (msg RAuth) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -262,7 +261,7 @@ func (msg RAuth) conv2M() []byte { cur += 1 pbit16(buf[cur:cur+2], msg.Tag()) cur += 2 - qid := msg.AQid().conv2M() + qid := msg.AQid().marshal() for i := 0; i < len(qid); i++ { buf[cur+i] = qid[i] } @@ -318,7 +317,7 @@ func (msg TAttach) Fid() uint32 { return msg.fid } func (msg TAttach) AFid() uint32 { return msg.afid } func (msg TAttach) UName() string { return msg.uname } func (msg TAttach) AName() string { return msg.aname } -func (msg TAttach) conv2M() []byte { +func (msg TAttach) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -373,7 +372,7 @@ func (msg RAttach) Size() uint32 { return 4 + 1 + 2 + 13 } func (msg RAttach) Type() MsgType { return Rattach } func (msg RAttach) Tag() uint16 { return msg.tag } func (msg RAttach) Qid() *Qid { return msg.qid } -func (msg RAttach) conv2M() []byte { +func (msg RAttach) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -382,7 +381,7 @@ func (msg RAttach) conv2M() []byte { cur += 1 pbit16(buf[cur:cur+2], msg.Tag()) cur += 2 - qid := msg.Qid().conv2M() + qid := msg.Qid().marshal() for i := 0; i < len(qid); i++ { buf[cur+i] = qid[i] } @@ -407,7 +406,7 @@ func (msg *RError) Size() uint32 { return uint32(4 + 1 + 2 + 2 + len(msg.EName func (msg *RError) Type() MsgType { return Rerror } func (msg *RError) Tag() uint16 { return msg.tag } func (msg *RError) EName() string { return msg.ename.Error() } -func (msg *RError) conv2M() []byte { +func (msg *RError) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -466,7 +465,7 @@ func (msg *TWalk) Fid() uint32 { return msg.fid } func (msg *TWalk) NewFid() uint32 { return msg.newFid } func (msg *TWalk) NWName() uint16 { return uint16(len(msg.wname)) } func (msg *TWalk) WName() []string { return msg.wname } -func (msg *TWalk) conv2M() []byte { +func (msg *TWalk) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -514,7 +513,7 @@ func (msg *RWalk) Size() uint32 { func (msg *RWalk) Type() MsgType { return Rwalk } func (msg *RWalk) Tag() uint16 { return msg.tag } func (msg *RWalk) Qid() []*Qid { return msg.qid } -func (msg *RWalk) conv2M() []byte { +func (msg *RWalk) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -526,7 +525,7 @@ func (msg *RWalk) conv2M() []byte { pbit16(buf[cur:cur+2], uint16(len(msg.Qid()))) cur += 2 for _, qid := range msg.Qid() { - for i, bit := range qid.conv2M() { + for i, bit := range qid.marshal() { buf[cur+i] = bit } cur += 13 @@ -573,7 +572,7 @@ func (msg *TOpen) Type() MsgType { return Topen } func (msg *TOpen) Tag() uint16 { return msg.tag } func (msg *TOpen) Fid() uint32 { return msg.fid } func (msg *TOpen) Mode() OpenMode { return msg.mode } -func (msg *TOpen) conv2M() []byte { +func (msg *TOpen) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -611,7 +610,7 @@ func (msg *ROpen) Type() MsgType { return Ropen } func (msg *ROpen) Tag() uint16 { return msg.tag } func (msg *ROpen) Qid() *Qid { return msg.qid } func (msg *ROpen) IoUnit() uint32 { return msg.iounit } -func (msg *ROpen) conv2M() []byte { +func (msg *ROpen) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -620,7 +619,7 @@ func (msg *ROpen) conv2M() []byte { cur += 1 pbit16(buf[cur:cur+2], msg.Tag()) cur += 2 - for i, bit := range msg.Qid().conv2M() { + for i, bit := range msg.Qid().marshal() { buf[cur+i] = bit } cur += 13 @@ -670,7 +669,7 @@ func (msg *TRead) Tag() uint16 { return msg.tag } func (msg *TRead) Fid() uint32 { return msg.fid } func (msg *TRead) Offset() uint64 { return msg.offset } func (msg *TRead) Count() uint32 { return msg.count } -func (msg *TRead) conv2M() []byte { +func (msg *TRead) marshal() []byte { cur := 0 buf := make([]byte, msg.Size()) pbit32(buf[cur:cur+4], msg.Size()) @@ -709,7 +708,7 @@ func (msg *RRead) Type() MsgType { return Rread } func (msg *RRead) Tag() uint16 { return msg.tag } func (msg *RRead) Count() uint32 { return msg.count } func (msg *RRead) Data() []byte { return msg.data } -func (msg *RRead) conv2M() []byte { +func (msg *RRead) marshal() []byte { if uint32(len(msg.Data())) != msg.Count() { panic(fmt.Errorf("data size %d and count %d don't match", len(msg.Data()), msg.Count())) @@ -756,7 +755,7 @@ func (msg *TStat) Size() uint32 { return msg.size } func (msg *TStat) Type() MsgType { return Tstat } func (msg *TStat) Tag() uint16 { return msg.tag } func (msg *TStat) Fid() uint32 { return msg.fid } -func (msg *TStat) conv2M() []byte { +func (msg *TStat) marshal() []byte { m := make([]byte, msg.Size()) pbit32(m[0:4], msg.Size()) m[4] = uint8(Tstat) @@ -775,15 +774,25 @@ type RStat struct { } func newRStat(buf []byte) *RStat { panic("not implemented") } -func (msg *RStat) Size() uint32 { return uint32(4 + 1 + 2 + 2 + 2 + msg.info.statSize()) } // TODO: collect ? +func (msg *RStat) Size() uint32 { + stat, ok := msg.info.Sys().(*stat) + if !ok { + panic("not stat") + } + return uint32(4 + 1 + 2 + 2 + 2 + stat.size()) +} func (msg *RStat) Type() MsgType { return Rstat } func (msg *RStat) Tag() uint16 { return msg.tag } -func (msg *RStat) conv2M() []byte { +func (msg *RStat) marshal() []byte { buf := make([]byte, msg.Size()) pbit32(buf[0:4], msg.Size()) buf[4] = uint8(Rstat) pbit16(buf[5:7], msg.Tag()) - fiBuf := msg.info.conv2M() + stat, ok := msg.info.Sys().(*stat) + if !ok { + panic("not stat") + } + fiBuf := stat.marshal() pbit16(buf[7:9], uint16(len(fiBuf))) for i := 0; i < len(fiBuf); i++ { buf[9+i] = fiBuf[i] @@ -791,4 +800,4 @@ func (msg *RStat) conv2M() []byte { return buf } -func (msg *RStat) String() string { return fmt.Sprintf("Rstat tag %d stat %s", msg.Tag(), msg.info) } +func (msg *RStat) String() string { return fmt.Sprintf("Rstat tag %d stat %s", msg.Tag(), msg.info.stat) } diff --git a/fid.go b/fid.go @@ -89,7 +89,7 @@ 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) conv2M() []byte { +func (q *Qid) marshal() []byte { buf := make([]byte, 13) buf[0] = uint8(q.t) pbit32(buf[1:5], q.vers) @@ -119,6 +119,42 @@ func (q *Qid) typeStr() string { return s } +type QidPool struct { + m map[*File]*Qid + nextQid uint64 +} + +func allocQidPool() *QidPool { + q := new(QidPool) + q.m = make(map[*File]*Qid) + return q +} + +func (pool *QidPool) lookup(f *File) (*Qid, bool) { + q, ok := pool.m[f] + return q, ok +} + +func (pool *QidPool) alloc(f *File) (*Qid, error) { + _, ok := pool.m[f] + if ok { + return nil, fmt.Errorf("qid already exist for file %v", f) + } + + s, err := f.Stat() + if err != nil { + return nil, fmt.Errorf("stat %v: %v", f, err) + } + t := fsModeToQidType(s.Mode()) + q := &Qid{t: t, path:pool.nextQid} + pool.nextQid++ + if q.path > pool.nextQid { + panic("qid overflow") + } + pool.m[f] = q + return q, nil +} + type FidPool struct { m map[uint32]*Fid } diff --git a/file.go b/file.go @@ -5,6 +5,7 @@ import ( "io" "io/fs" "time" + "path" ) const ( @@ -26,17 +27,21 @@ func hasPerm(f *File, uid string, p fs.FileMode) (bool, error) { return false, fmt.Errorf("stat: %v", err) } fp := fi.Mode().Perm() + stat, ok := fi.Sys().(*stat) + if !ok { + panic("not stat") + } m := fp & 7 // other if (p & m) == p { return true, nil } - if fi.statUid() == uid { + if stat.uid == uid { m |= (fp >> 6) & 7 if (p & m) == p { return true, nil } } - if fi.statGid() == uid { + if stat.gid == uid { m |= (fp >> 3) & 7 if (p & m) == p { return true, nil @@ -45,14 +50,13 @@ func hasPerm(f *File, uid string, p fs.FileMode) (bool, error) { return false, nil } -/* type stat struct { t uint16 dev uint32 qid *Qid - mode fs.FileMode - aTime time.Time - mTime time.Time + mode uint32 + aTime uint32 + mTime uint32 length int64 name string uid string @@ -69,7 +73,7 @@ func (s *stat) size() uint16 { 2 + len(s.muid)) } -func (s *stat) conv2M() []byte { +func (s *stat) marshal() []byte { cur := 0 size := s.size() msg := make([]byte, 2+size) @@ -85,11 +89,11 @@ func (s *stat) conv2M() []byte { cur += 4 pbit64(msg[cur:cur+8], s.qid.Path()) cur += 8 - pbit32(msg[cur:cur+4], uint32(s.mode)) + pbit32(msg[cur:cur+4], s.mode) cur += 4 - pbit32(msg[cur:cur+4], uint32(s.aTime.Unix())) + pbit32(msg[cur:cur+4], s.aTime) cur += 4 - pbit32(msg[cur:cur+4], uint32(s.mTime.Unix())) + pbit32(msg[cur:cur+4], s.mTime) cur += 4 pbit64(msg[cur:cur+8], uint64(s.length)) cur += 8 @@ -127,27 +131,13 @@ func (s *stat) conv2M() []byte { 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, uint32(s.mode), - s.aTime.Unix(), s.mTime.Unix(), 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.t, s.dev) } -*/ type FileInfo struct { info fs.FileInfo - qid *Qid - /* - t uint16 - dev uint32 - qid *Qid - mode fs.FileMode - aTime time.Time - mTime time.Time - length int64 - name string - uid string - gid string - muid string - */ + stat *stat } func (fi *FileInfo) Name() string { return fi.info.Name() } @@ -155,97 +145,26 @@ 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 } - -func (fi *FileInfo) statSize() uint16 { - return uint16(2 + 4 + 13 + 4 + 4 + 4 + 8 + - 2 + len(fi.statName()) + 2 + len(fi.statUid()) + - 2 + len(fi.statGid()) + 2 + len(fi.statMuid())) -} -func (fi *FileInfo) statType() uint16 { return 0 } -func (fi *FileInfo) statDev() uint32 { return 0 } -func (fi *FileInfo) statQid() *Qid { return fi.qid } -func (fi *FileInfo) statMode() uint32 { return DMDIR|0777 } -func (fi *FileInfo) statATime() uint32 { return uint32(fi.ModTime().Unix()) } -func (fi *FileInfo) statMTime() uint32 { return uint32(fi.ModTime().Unix()) } -func (fi *FileInfo) statLength() uint64 { - if fi.IsDir() { - return 0 - } else { - return uint64(fi.Size()) - } -} -func (fi *FileInfo) statName() string { return fi.Name() } // TODO: "/" for root -func (fi *FileInfo) statUid() string { return "" } -func (fi *FileInfo) statGid() string { return "" } -func (fi *FileInfo) statMuid() string { return "" } -func (fi *FileInfo) conv2M() []byte { - cur := 0 - buf := make([]byte, 2 + fi.statSize()) - pbit16(buf[cur:cur+2], fi.statSize()) - cur += 2 - pbit16(buf[cur:cur+2], fi.statType()) - cur += 2 - pbit32(buf[cur:cur+4], fi.statDev()) - cur += 4 - qidBuf := fi.statQid().conv2M() - for i := 0; i < len(qidBuf); i++ { - buf[cur+i] = qidBuf[i] - } - cur += len(qidBuf) - pbit32(buf[cur:cur+4], fi.statMode()) - cur += 4 - pbit32(buf[cur:cur+4], fi.statATime()) - cur += 4 - pbit32(buf[cur:cur+4], fi.statMTime()) - cur += 4 - pbit64(buf[cur:cur+8], fi.statLength()) - cur += 8 - name := fi.statName() - pbit16(buf[cur:cur+2], uint16(len(name))) - cur += 2 - for i := 0; i < len(name); i++ { - buf[cur+i] = name[i] - } - cur += len(name) - uid := fi.statUid() - pbit16(buf[cur:cur+2], uint16(len(uid))) - cur += 2 - for i := 0; i < len(uid); i++ { - buf[cur+i] = uid[i] - } - cur += len(uid) - gid := fi.statGid() - pbit16(buf[cur:cur+2], uint16(len(gid))) - cur += 2 - for i := 0; i < len(gid); i++ { - buf[cur+i] = gid[i] - } - cur += len(gid) - muid := fi.statMuid() - pbit16(buf[cur:cur+2], uint16(len(muid))) - cur += 2 - for i := 0; i < len(muid); i++ { - buf[cur+i] = muid[i] - } - cur += len(muid) - if len(buf) != cur { - panic(fmt.Errorf("cursor position %d and buf length %d don't match", - cur, len(buf))) - } - return buf -} -func (fi *FileInfo) String() string { - return fmt.Sprintf("'%s' '%s' '%s' '%s' q %v m %#o at %d mt %d l %d t %d d %d", - fi.statName(), fi.statUid(), fi.statGid(), fi.statMuid(), - fi.statQid(), fi.statMode(), fi.statATime(), fi.statMTime(), - fi.statLength(), fi.statType(), fi.statDev()) -} +func (fi *FileInfo) Sys() any { return fi.stat } type File struct { fs *FS // file system to which this file belongs file fs.File // underlying file qid *Qid + path string // absolute path from the root of the fs. +} + +func newFile(fsys *FS, file fs.File) (*File, error) { + f := &File{ + fs: fsys, + file: file, + } + q, err := fsys.qidPool.alloc(f) + if err != nil { + return nil, fmt.Errorf("alloc qid for file %v: %v", file, err) + } + f.qid = q + return f, nil } func (f *File) Stat() (*FileInfo, error) { @@ -254,9 +173,13 @@ func (f *File) Stat() (*FileInfo, error) { return nil, fmt.Errorf("stat file: %v, %v", f, err) } fi := &FileInfo{ - info: fsfi, - qid: f.qid, - // TODO: t, dev, uid, gid, muid + info: fsfi, + stat: &stat{ + qid: f.qid, + name: path.Base(f.path), + mode: uint32(fsfi.Mode()), // TODO: convert + }, + // TODO: ..., uid, gid, muid } return fi, nil } @@ -306,15 +229,21 @@ func (f *File) ReadDir(n int) ([]*DirEntry, error) { } de := make([]*DirEntry, len(fsde)) for i := 0; i < len(de); i++ { - fsinfo, err := fsde[i].Info() + 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) + } + file.path = fpath + info, err := file.Stat() if err != nil { return nil, fmt.Errorf("stat: %v", err) } de[i] = &DirEntry{ dirEnt: fsde[i], - info: &FileInfo{fsinfo, &Qid{path:f.fs.nextQid}}, // TODO: need mutex? + info: info, + file: file, } - f.fs.nextQid++ } return de, nil } @@ -322,6 +251,7 @@ func (f *File) ReadDir(n int) ([]*DirEntry, error) { type DirEntry struct { dirEnt fs.DirEntry // underlying fs.DirEntry info *FileInfo + file *File } func (e *DirEntry) Name() string { return e.dirEnt.Name() } @@ -334,8 +264,8 @@ func (f *File) Close() error { } type FS struct { - nextQid uint64 // next qid to be used - fs fs.FS // underlying file system + fs fs.FS // underlying file system + qidPool *QidPool } func (fsys *FS) Open(name string) (*File, error) { @@ -343,39 +273,11 @@ func (fsys *FS) Open(name string) (*File, error) { if err != nil { return nil, fmt.Errorf("open file %s: %v", name, err) } - qid := newQid(make([]byte, 13)) - qid.SetPath(fsys.nextQid) - fi, err := f.Stat() + file, err := newFile(fsys, f) if err != nil { - return nil, fmt.Errorf("stat file %v: %v", f, err) - } - mode := fi.Mode() - var qtype QidType - if mode&fs.ModeDir != 0 { - qtype |= QTDIR - } - if mode&fs.ModeAppend != 0 { - qtype |= QTAPPEND - } - if mode&fs.ModeExclusive != 0 { - qtype |= QTEXCL + return nil, fmt.Errorf("newFile(%v): %v", file, err) } - if mode&fs.ModeTemporary != 0 { - qtype |= QTTMP - } - if mode&fs.ModeSymlink != 0 { - qtype |= QTSYMLINK - } - // TODO: QTAUTH - qid.SetType(qtype) - fsys.nextQid++ - - file := &File{ - fs: fsys, - file: f, - qid: qid, - } - + file.path = name return file, nil } diff --git a/fs.go b/fs.go @@ -0,0 +1,29 @@ +package lib9p + +import ( + "io/fs" +) + +func fsModeToQidType(fm fs.FileMode) QidType { + var qt QidType + if fm | fs.ModeDir != 0 { + qt |= QTDIR + } + if fm | fs.ModeAppend != 0 { + qt |= QTAPPEND + } + if fm | fs.ModeExclusive != 0 { + qt |= QTEXCL + } + if fm | fs.ModeTemporary != 0 { + qt |= QTTMP + } + if fm | fs.ModeSymlink != 0 { + qt |= QTSYMLINK + } + // QTMOUNT is not in fs.FileMode. + // ModeDevice, ModeNamedPope, ModeSocket, ModeSetuid, + // ModeSetgid, ModeCharDevice, ModeSticky, ModeIrregular + // are not in QidType. + return qt +} +\ No newline at end of file diff --git a/server.go b/server.go @@ -28,7 +28,10 @@ type Server struct { func NewServer(fs fs.FS, mSize uint32, r io.Reader, w io.Writer) *Server { s := new(Server) - s.FS = &FS{fs: fs} + s.FS = &FS{ + fs: fs, + qidPool: allocQidPool(), + } s.MSize = mSize s.fPool = allocFidPool() s.rPool = allocReqPool() @@ -139,7 +142,17 @@ func sAttach(s *Server, r *Req) { fid.Uid = ifcall.UName() fid.OMode = OREAD - fid.Qid = fid.File.qid + info, err := fid.File.Stat() + if err != nil { + log.Printf("stat %s, %v", fid.File, err) + respond(r, fmt.Errorf("internal error")) + return + } + stat, ok := info.Sys().(*stat) + if !ok { + panic("not stat") + } + fid.Qid = stat.qid ofcall := &RAttach{ tag: ifcall.Tag(), @@ -184,7 +197,17 @@ func sWalk(s *Server, r *Req) { return } newFid.Uid = oldFid.Uid - newFid.Qid = newFid.File.qid + info, err := newFid.File.Stat() + if err != nil { + log.Printf("stat %v, %v", newFid.File, err) + respond(r, fmt.Errorf("internal error")) + return + } + stat, ok := info.Sys().(*stat) + if !ok { + panic("not stat") + } + newFid.Qid = stat.qid ofcall := &RWalk{ tag: r.ifcall.Tag(), @@ -244,10 +267,12 @@ func sOpen(s *Server, r *Req) { respond(r, fmt.Errorf("internal error")) return } + /* if !ok { respond(r, fmt.Errorf("permission denied")) return } + */ if ifcall.Mode()&ORCLOSE != 0 { panic("ORCLOSE not implemented") @@ -294,7 +319,27 @@ func sRead(s *Server, r *Req) { return } if fi.IsDir() { - + de, err := fid.File.ReadDir(-1) + if err != nil { + respond(r, err) + return + } + for _, e := range de { + info, err := e.Info() + if err != nil { + respond(r, err) + return + } + st, ok := info.Sys().(*stat) + if !ok { + panic("not stat") + } + buf := st.marshal() + for i := 0; i < len(buf); i++ { + data[n+i] = buf[i] + } + n += len(buf) + } } else { n, err = fid.File.ReadAt(data, int64(ifcall.Offset())) if err != nil { @@ -302,7 +347,6 @@ func sRead(s *Server, r *Req) { return } } - ofcall := &RRead{ tag: ifcall.Tag(), count: uint32(n), @@ -421,7 +465,7 @@ func respond(r *Req, err error) { if chatty9P { fmt.Fprintf(os.Stderr, "--> %s\n", r.ofcall) } - r.srv.Writer.Write(r.ofcall.conv2M()) + r.srv.Writer.Write(r.ofcall.marshal()) // free tag. if r.pool == nil && err != EDupTag {