ninep – git.sr.ht/~moody/ninep Index | Examples | Files

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

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

func ReadBuf(t *Tread, b []byte)

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

func ReadDir(t *Tread, dirs []Dir)

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 (n *NopFS) Attach(t *Tattach)

func (*NopFS) Clunk

func (n *NopFS) Clunk(t *Tclunk, q *Qid)

func (*NopFS) Create

func (n *NopFS) Create(t *Tcreate, q *Qid)

func (*NopFS) Open

func (n *NopFS) Open(t *Topen, q *Qid)

func (*NopFS) Read

func (n *NopFS) Read(t *Tread, q *Qid)

func (*NopFS) Remove

func (n *NopFS) Remove(t *Tremove, q *Qid)

func (*NopFS) Stat

func (n *NopFS) Stat(t *Tstat, q *Qid)

func (*NopFS) Walk

func (n *NopFS) Walk(cur *Qid, next string) *Qid

func (*NopFS) Write

func (n *NopFS) Write(t *Twrite, q *Qid)

func (*NopFS) Wstat

func (n *NopFS) Wstat(t *Twstat, q *Qid)

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

func NewSrv(fsf FSMaker) *Srv

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

func (s *Srv) ListenAndServe(port string) error

ListenAndServe is a helper function that wraps Serve that listens on the specific port before calling Serve.

func (*Srv) Serve

func (s *Srv) Serve(l net.Listener) error

Serve accepts new conenctions and spins off a goroutine for each new connection made.

func (*Srv) ServeIO

func (s *Srv) ServeIO(r io.Reader, w io.Writer)

ServeIO start the Srv using the arguments as input and output for messages.

type Tattach

type Tattach struct {
	Uname string
	Aname string
	// contains filtered or unexported fields
}

func (*Tattach) Err

func (t *Tattach) Err(err error)

func (*Tattach) Respond

func (t *Tattach) Respond(qid *Qid)

func (*Tattach) StrErr

func (t *Tattach) StrErr(err string)

func (*Tattach) String

func (t *Tattach) String() string

type Tauth

type Tauth struct {
	Uname string
	Aname string
	// contains filtered or unexported fields
}

func (*Tauth) Err

func (t *Tauth) Err(err error)

func (*Tauth) Respond

func (t *Tauth) Respond(qid *Qid)

func (*Tauth) StrErr

func (t *Tauth) StrErr(err string)

func (*Tauth) String

func (t *Tauth) String() string

type Tclunk

type Tclunk struct {
	// contains filtered or unexported fields
}

func (*Tclunk) Err

func (t *Tclunk) Err(err error)

func (*Tclunk) Respond

func (t *Tclunk) Respond()

func (*Tclunk) StrErr

func (t *Tclunk) StrErr(err string)

func (*Tclunk) String

func (t *Tclunk) String() string

type Tcreate

type Tcreate struct {
	Name string
	Perm uint32
	Mode byte
	// contains filtered or unexported fields
}

func (*Tcreate) Err

func (t *Tcreate) Err(err error)

func (*Tcreate) Respond

func (t *Tcreate) Respond(qid *Qid, iounit uint32)

func (*Tcreate) StrErr

func (t *Tcreate) StrErr(err string)

func (*Tcreate) String

func (t *Tcreate) String() string

type Topen

type Topen struct {
	Mode byte
	// contains filtered or unexported fields
}

func (*Topen) Err

func (t *Topen) Err(err error)

func (*Topen) Respond

func (t *Topen) Respond(qid *Qid, iounit uint32)

func (*Topen) StrErr

func (t *Topen) StrErr(err string)

func (*Topen) String

func (t *Topen) String() string

type Tread

type Tread struct {
	Offset uint64
	Count  uint32
	// contains filtered or unexported fields
}

func (*Tread) Err

func (t *Tread) Err(err error)

func (*Tread) Respond

func (t *Tread) Respond(data []byte)

func (*Tread) StrErr

func (t *Tread) StrErr(err string)

func (*Tread) String

func (t *Tread) String() string

type Tremove

type Tremove struct {
	// contains filtered or unexported fields
}

func (*Tremove) Err

func (t *Tremove) Err(err error)

func (*Tremove) Respond

func (t *Tremove) Respond()

func (*Tremove) StrErr

func (t *Tremove) StrErr(err string)

func (*Tremove) String

func (t *Tremove) String() string

type Tstat

type Tstat struct {
	// contains filtered or unexported fields
}

func (*Tstat) Err

func (t *Tstat) Err(err error)

func (*Tstat) Respond

func (t *Tstat) Respond(dir *Dir)

func (*Tstat) StrErr

func (t *Tstat) StrErr(err string)

func (*Tstat) String

func (t *Tstat) String() string

type Twrite

type Twrite struct {
	Offset uint64
	Data   []byte
	// contains filtered or unexported fields
}

func (*Twrite) Err

func (t *Twrite) Err(err error)

func (*Twrite) Respond

func (t *Twrite) Respond(count uint32)

func (*Twrite) StrErr

func (t *Twrite) StrErr(err string)

func (*Twrite) String

func (t *Twrite) String() string

type Twstat

type Twstat struct {
	*Dir
	// contains filtered or unexported fields
}

func (*Twstat) Err

func (t *Twstat) Err(err error)

func (*Twstat) Respond

func (t *Twstat) Respond()

func (*Twstat) StrErr

func (t *Twstat) StrErr(err string)

func (*Twstat) String

func (t *Twstat) String() 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.