ninep

package module
v0.0.0-...-f9d3347 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 30, 2024 License: MIT Imports: 7 Imported by: 1

README

Go Reference

Ninep is a go library for writing 9p2000 servers. It is heavily influenced by the design of the plan9 lib9p C library. The go.dev link has some examples and more specific details for library usage.

It is reccomended to have some familiarity with 9p itself. The best resource to learn what the server is responsible for is reading through section 5 of the manual.

Documentation

Overview

Example
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"))
}
Output:

Index

Examples

Constants

View Source
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
)
View Source
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
)
View Source
const Ninep2000 = "9P2000"

Variables

This section is empty.

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL