package ninep
import "git.sr.ht/~moody/ninep"
Example¶
Code:play
package main import ( "errors" "fmt" "log" "git.sr.ht/~moody/ninep" ) // Embed NopFS to cover message types we dont plan // to support. type myfs struct { ninep.NopFS i int msg []byte rootD ninep.Dir fileD ninep.Dir } func (e *myfs) Attach(t *ninep.Tattach) { e.msg = []byte(fmt.Sprintf("You are lucky number %d\n", e.i)) e.fileD = ninep.Dir{ Qid: ninep.Qid{1, 0, 0}, Mode: 0x4, Len: uint64(len(e.msg)), Name: "test", Uid: "moody", Gid: "moody", Muid: "moody", } e.rootD = ninep.Dir{ Qid: ninep.Qid{0, 0, ninep.QTDir}, Name: "/", Mode: ninep.DMDir | 0777, Uid: "moody", Gid: "moody", Muid: "moody", } t.Respond(&e.rootD.Qid) } func (e *myfs) Walk(cur *ninep.Qid, next string) *ninep.Qid { if cur.Path == 0 && next == "test" { return &e.fileD.Qid } return nil } func (e *myfs) Open(t *ninep.Topen, q *ninep.Qid) { t.Respond(q, 8192) } var errNoFile = errors.New("no such file or directory") func (e *myfs) Read(t *ninep.Tread, q *ninep.Qid) { switch q.Path { case 0: ninep.ReadDir(t, []ninep.Dir{e.fileD}) case 1: ninep.ReadBuf(t, e.msg) default: t.Err(errNoFile) } } func (e *myfs) Stat(t *ninep.Tstat, q *ninep.Qid) { switch q.Path { case 0: t.Respond(&e.rootD) case 1: t.Respond(&e.fileD) default: t.Err(errNoFile) } } func main() { i := 0 //Create a new srv, where each new session is given an instance //of myfs. For each session i will be incremented. srv := ninep.NewSrv(func() ninep.FS { i++; return &myfs{i: i} }) srv.Chatty9P = true log.Fatal(srv.ListenAndServe(":9999")) }
Index ¶
- Constants
- func ReadBuf(t *Tread, b []byte)
- func ReadDir(t *Tread, dirs []Dir)
- type Dir
- type FS
- type FSMaker
- type NopFS
- func (n *NopFS) Attach(t *Tattach)
- func (n *NopFS) Clunk(t *Tclunk, q *Qid)
- func (n *NopFS) Create(t *Tcreate, q *Qid)
- func (n *NopFS) Open(t *Topen, q *Qid)
- func (n *NopFS) Read(t *Tread, q *Qid)
- func (n *NopFS) Remove(t *Tremove, q *Qid)
- func (n *NopFS) Stat(t *Tstat, q *Qid)
- func (n *NopFS) Walk(cur *Qid, next string) *Qid
- func (n *NopFS) Write(t *Twrite, q *Qid)
- func (n *NopFS) Wstat(t *Twstat, q *Qid)
- type Qid
- type Srv
- func NewSrv(fsf FSMaker) *Srv
- func (s *Srv) ListenAndServe(port string) error
- func (s *Srv) Serve(l net.Listener) error
- func (s *Srv) ServeIO(r io.Reader, w io.Writer)
- type Tattach
- func (t *Tattach) Err(err error)
- func (t *Tattach) Respond(qid *Qid)
- func (t *Tattach) StrErr(err string)
- func (t *Tattach) String() string
- type Tauth
- func (t *Tauth) Err(err error)
- func (t *Tauth) Respond(qid *Qid)
- func (t *Tauth) StrErr(err string)
- func (t *Tauth) String() string
- type Tclunk
- func (t *Tclunk) Err(err error)
- func (t *Tclunk) Respond()
- func (t *Tclunk) StrErr(err string)
- func (t *Tclunk) String() string
- type Tcreate
- func (t *Tcreate) Err(err error)
- func (t *Tcreate) Respond(qid *Qid, iounit uint32)
- func (t *Tcreate) StrErr(err string)
- func (t *Tcreate) String() string
- type Topen
- func (t *Topen) Err(err error)
- func (t *Topen) Respond(qid *Qid, iounit uint32)
- func (t *Topen) StrErr(err string)
- func (t *Topen) String() string
- type Tread
- func (t *Tread) Err(err error)
- func (t *Tread) Respond(data []byte)
- func (t *Tread) StrErr(err string)
- func (t *Tread) String() string
- type Tremove
- func (t *Tremove) Err(err error)
- func (t *Tremove) Respond()
- func (t *Tremove) StrErr(err string)
- func (t *Tremove) String() string
- type Tstat
- func (t *Tstat) Err(err error)
- func (t *Tstat) Respond(dir *Dir)
- func (t *Tstat) StrErr(err string)
- func (t *Tstat) String() string
- type Twrite
- func (t *Twrite) Err(err error)
- func (t *Twrite) Respond(count uint32)
- func (t *Twrite) StrErr(err string)
- func (t *Twrite) String() string
- type Twstat
Examples ¶
Constants ¶
const ( //Bits for Qid.Type QTDir = 0x80 //Directory QTAppend = 0x40 //Append only QTExcl = 0x20 //Exclusive use QTMount = 0x10 //Mounted channel QTAuth = 0x08 //Auth file QTTemp = 0x04 //Non WORM backed file QTFile = 0 //Regular file )
const ( //Special bits for Dir.Mode DMDir = 0x80000000 //Directory DMAppend = 0x40000000 //Append only DMExcl = 0x20000000 //Exclusive use DMMount = 0x10000000 //Mounted channel DMAuth = 0x08000000 //Auth file DMTmp = 0x04000000 //Non WORM backed file //Unix permissions in Dir.Mode, 3 sets for user, group and other. DMRead = 0x4 DMWrite = 0x2 DMExec = 0x1 )
const Ninep2000 = "9P2000"
Functions ¶
func ReadBuf ¶
ReadBuf is a helper function that takes the offset and count specified within the Tread requests and uses them to slice b and respond.
func ReadDir ¶
ReadDir is a helper function that is used to respond to Tread messages on directories. The dirs slice should contain all of the files within the directory.
Types ¶
type Dir ¶
type Dir struct { Qid Mode uint32 //Unix permissions Atime uint32 //Unix time of last access Mtime uint32 //Unix time of last modification Len uint64 //Length of file, directories set this to 0 Name string //Filename Uid string //User Owner Gid string //Group owner Muid string //User that last modified this file }
Dir contains all of the meta information for a file or directory.
type FS ¶
type FS interface { //Attach is the first message sent on a session, for which //the root Qid should be returned. Attach(t *Tattach) //Walk is called multiple times for a single Twalk request, //once for each walk elemenent within the message. For each //call cur is set to the directory from which the walk is //starting, with next being the path element that the client //wishes to walk to within the directory. The return value //should represent the Qid for the file identified by next //or nil if the file does not exist. Walk(cur *Qid, next string) *Qid //The Qid passed to create is the directory for which //the new file is to be created in. Create(t *Tcreate, q *Qid) //For Open, Read, Write, Stat, Wstat, and Remove. The Qid passed //represents the specific file the client wishes to operate on. //Read is also the message called for listing files within //a directory, a helper function ReadDir is included for //this case. Open(t *Topen, q *Qid) Read(t *Tread, q *Qid) Write(t *Twrite, q *Qid) Stat(t *Tstat, q *Qid) Wstat(t *Twstat, q *Qid) Remove(t *Tremove, q *Qid) //Clunk is sent when the client no longer has any refrences //open to a specific file to allow the server to perform //clenup. Clunk(t *Tclunk, q *Qid) }
FS is the interface that 9p servers must satisfy to be used with Srv. Each function that accepts a T* message is expected to call T*'s Respond method. Respond takes the corespdonding R* message and err string. If the err string is non empty then a Rerror is sent to the client with the string included as the error message instead.
type FSMaker ¶
type FSMaker func() FS
See the Srv documentation
type NopFS ¶
type NopFS struct{}
NopFS is a filesystem that simply errors on each request message. NopFS can be embedded to respond to request types the server does not plan to support.
func (*NopFS) Attach ¶
func (*NopFS) Clunk ¶
func (*NopFS) Create ¶
func (*NopFS) Open ¶
func (*NopFS) Read ¶
func (*NopFS) Remove ¶
func (*NopFS) Stat ¶
func (*NopFS) Walk ¶
func (*NopFS) Write ¶
func (*NopFS) Wstat ¶
type Qid ¶
type Qid struct { Path uint64 //Unique ID of specific file to a specific server. Vers uint32 //The version of the file, incremented for each change. Type byte //The type of the file. }
Qid is the unique identification for a file.
type Srv ¶
type Srv struct { Chatty9P bool // contains filtered or unexported fields }
Srv handles the marshalling and session management for a FS. Setting Chatty9P to true will cause message string representations to be printed to stderr.
func NewSrv ¶
NewSrv allocates a new Srv struct. For each new session a new FS is substantiated through the fsf function, this allows the FS to store session specific state like attached usernames.
func (*Srv) ListenAndServe ¶
ListenAndServe is a helper function that wraps Serve that listens on the specific port before calling Serve.
func (*Srv) Serve ¶
Serve accepts new conenctions and spins off a goroutine for each new connection made.
func (*Srv) ServeIO ¶
ServeIO start the Srv using the arguments as input and output for messages.
type Tattach ¶
func (*Tattach) Err ¶
func (*Tattach) Respond ¶
func (*Tattach) StrErr ¶
func (*Tattach) String ¶
type Tauth ¶
func (*Tauth) Err ¶
func (*Tauth) Respond ¶
func (*Tauth) StrErr ¶
func (*Tauth) String ¶
type Tclunk ¶
type Tclunk struct {
// contains filtered or unexported fields
}
func (*Tclunk) Err ¶
func (*Tclunk) Respond ¶
func (t *Tclunk) Respond()
func (*Tclunk) StrErr ¶
func (*Tclunk) String ¶
type Tcreate ¶
func (*Tcreate) Err ¶
func (*Tcreate) Respond ¶
func (*Tcreate) StrErr ¶
func (*Tcreate) String ¶
type Topen ¶
type Topen struct { Mode byte // contains filtered or unexported fields }
func (*Topen) Err ¶
func (*Topen) Respond ¶
func (*Topen) StrErr ¶
func (*Topen) String ¶
type Tread ¶
func (*Tread) Err ¶
func (*Tread) Respond ¶
func (*Tread) StrErr ¶
func (*Tread) String ¶
type Tremove ¶
type Tremove struct {
// contains filtered or unexported fields
}
func (*Tremove) Err ¶
func (*Tremove) Respond ¶
func (t *Tremove) Respond()
func (*Tremove) StrErr ¶
func (*Tremove) String ¶
type Tstat ¶
type Tstat struct {
// contains filtered or unexported fields
}
func (*Tstat) Err ¶
func (*Tstat) Respond ¶
func (*Tstat) StrErr ¶
func (*Tstat) String ¶
type Twrite ¶
func (*Twrite) Err ¶
func (*Twrite) Respond ¶
func (*Twrite) StrErr ¶
func (*Twrite) String ¶
type Twstat ¶
type Twstat struct { *Dir // contains filtered or unexported fields }
func (*Twstat) Err ¶
func (*Twstat) Respond ¶
func (t *Twstat) Respond()
func (*Twstat) StrErr ¶
func (*Twstat) String ¶
Source Files ¶
dir.go fs.go message.go proto.go srv.go util.go
- Version
- v0.0.0-20240130161350-f9d33473087f (latest)
- Published
- Jan 30, 2024
- Platform
- linux/amd64
- Imports
- 7 packages
- Last checked
- 6 days ago –
Tools for package owners.