.TH 9P 2
.SH NAME
Fid, File, Req, Srv, Tree,
allocmap, allocfid, allocfidpool, allocreq, allocreqpool, caninsertkey, closefid,
deletekey, fcreate, freefid, freemap, freereq, fremove, fwalk, mktree,
fdirread, insertkey, lookupfid, lookupkey, lookupreq, srv, postmountsrv, 
readbuf, readstr, respond, threadpostmountsrv,
_lib9p_emalloc, _lib9p_erealloc, _lib9p_estrdup \- 9P file server functions
.SH SYNOPSIS
.PP
.ft L
.nf
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
.fi
.PP
.ft L
.nf
.ta \w'\fL    'u +\w'\fLulong 'u
typedef struct Fid
{
	ulong	fid;
	char	omode;	/* -1 if not open */
	char	uid[NAMELEN];
	Qid	qid;
	File	*file;
	Ref	ref;
	void	*aux;
	\fR...\fP
} Fid;
.fi
.PP
.ft L
.nf
.ta \w'\fL    'u +\w'\fLulong 'u
typedef struct Req
{
	ulong	tag;
	Ref	ref;
	void	*aux;
	\fR...\fP
} Req;
.fi
.PP
.ft L
.nf
.ta \w'\fL    'u+\w'\fLFile 'u
typedef struct File
{
	Dir;
	File	*parent;
	Ref	ref;
	void	*aux;
	\fR...\fP
} File;
.fi
.PP
.ft L
.nf
typedef struct Tree
{
	File	*root;
	void	(*rmaux)(File *file);
	\fR...\fP
} Tree;
.PP
.nf
.ft L
.ta \w'\fLFile* 'u
Tree*	mktree(char *uid, char *gid, ulong perm)
File*	fcreate(File *dir, char *name, char *uid, char *gid, ulong perm)
int	fremove(File *file)
void	fclose(File *file)
File*	fwalk(File *file, char *name)
char*	fdirread(File *dir, char *buf, long *n, vlong off)
.fi
.PP
.nf
.ft L
.ta \w'\fL    'u +\w'\fLTree 'u
typedef struct Srv {
	Tree	*tree;
	void	(*session)(Req *req, char *id, char *dom, char *chal);
	void	(*attach)(Req *req, Fid *fid, char *spec, Qid *qid);
	void	(*clone) (Req *req, Fid *old, Fid *new);
	void	(*walk)  (Req *req, Fid *fid, char *name, Qid *qid);
	void	(*open)  (Req *req, Fid *fid, int omode, Qid *qid);
	void	(*create)(Req *req, Fid *fid, char *name, int omode,
		             ulong perm, Qid *qid);
	void	(*remove)(Req *req, Fid *fid);
	void	(*read)  (Req *req, Fid *fid, void *buf,
		             long *count, vlong offset);
	void	(*write) (Req *req, Fid *fid, void *buf,
		             long *count, vlong offset);
	void	(*stat)  (Req *req, Fid *fid, Dir *d);
	void	(*wstat) (Req *req, Fid *fid, Dir *d);
	void	(*flush) (Req *req, Req *oldreq);
	void	(*clunkaux)(Fid *fid);
} Srv;
.fi
.PP
.nf
.ft L
.ta \w'\fLFile* 'u
void	srv(Srv *s, int fd)
void	postmountsrv(Srv *s, char *srvname, char *mtpt, int flag)
void	threadpostmountsrv(Srv *s, char *srvname, char *mtpt, int flag)
void	respond(Req *req, char *error)
void	readstr(vlong offset, void *dst, long *ndst, char *src)
void	readbuf(vlong offset, void *dst, long *ndst, void *src, long nsrc)
.fi
.PP
.nf
.ft L
.ta \w'\fLFile* 'u
void*	_lib9p_emalloc(ulong sz)
void*	_lib9p_erealloc(void *ptr, ulong newsz)
char*	_lib9p_estrdup(char *str)
.fi
.PP
.ta \w'\fLFidpool* 'u
.ft L
.nf
Intmap*	allocmap(void (*inc)(void*))
void	freemap(Intmap *map)
void*	lookupkey(Intmap *map, ulong key)
void*	insertkey(Intmap *map, ulong key, void *val)
int	caninsertkey(Intmap *map, ulong key, void *val)
void*	deletekey(Intmap *map, ulong key)
.fi
.PP
.ta \w'\fLFidpool* 'u
.nf
.ft L
Fidpool*	allocfidpool(void)
void	freefidpool(Fidpool *p)
Fid*	allocfid(Fidpool *p, ulong f)
void	freefid(Fid *f)
void	closefid(Fid *f)
Fid*	lookupfid(Fidpool *p, ulong f)
.fi
.PP
.ta \w'\fLFidpool* 'u
.nf
.ft L
Reqpool*	allocreqpool(void)
void	freereqpool(Reqpool *p)
Req*	allocreq(Reqpool *p, ulong tag)
void	freereq(Req *r)
void	closereq(Req *r)
Req*	lookupreq(Reqpool *p, ulong tag)
.fi
.SH DESCRIPTION
These routines provide a library for writing 
9P file servers.
.PP
.B Fid
data structures are allocated one-to-one
with active fids in the served 9P connection.
They are analogous to
.B Chan
structures in the Plan 9 kernel.
The 
.B fid
element is the integer fid used in the 9P connection.
.B Omode
is the mode under which the fid was opened, or 
.B -1 
if this fid has not been opened yet.
Note that in addition to the values 
.BR OREAD ,
.BR OWRITE ,
and
.BR ORDWR ,
.B omode
can contain the various flags permissible in
an open call.
To ignore the flags, use
.BR omode&OMASK .
.B Omode
should not be changed by the client.
.B Uid
contains the name of the user who has authenticated
in order to obtain this fid.
.B Qid
is set to the last 
qid returned by
an
.BR attach ,
.BR walk ,
or
.B open
function
.RI  ( q.v. ).
The
.B file
element is explained below.
The
.B aux
element belongs to the client, and
may be used to store a
.RB per- Fid
data pointer.
.PP
.B Req
data structures are allocated one-to-one
with outstanding 9P requests.
They contain the tag of the request
as well as 
an
.B aux
element that may be used by the client
to store a 
.BR per- Req
data pointer (often useful for multithreaded servers).
.PP
The
.B File
and
.B Tree
structures provide an in-memory file hierarchy
that can be used to handle stat, walk, and open requests.
If being used, the library will keep the
.BR Fid 's
.B file
element pointing at the appropriate 
.B File
structure 
as it is walked over the tree.
As with the other structures,
the
.B aux
element may be used by the client
to store a
.RB per- File
data pointer.
.PP
The 
.BR Fid ,
.BR File ,
and
.B Req
structures are garbage collected by reference counting,
so that (for example) clunking a fid will not
free it while another request using that fid is still pending.
.PP
When creating a new reference by copying a pointer, the count should
be incremented with
.IR incref .
When a
.B Fid
is collected, the 
.B clunkaux
function of the
.B Srv
structure (described below) is called
to collect the pointer stored in 
.BR aux .
Similarly, when a 
.B File
is collected, the
.B rmaux
function in the
.B Tree
structure is called to claim the
.B aux
pointer.
No such function is called when
collecting a 
.B Req
structure: the
.B aux
pointer should be removed before
calling
.I respond
(described below).
To destroy a reference to a 
.BR Fid ,
.BR File ,
or
.BR Req ,
call
.IR closefid ,
.IR fclose ,
or
.IR closereq ,
respectively.
.PP
.I Mktree
creates a new file tree whose root has
owner
.BR uid ,
group
.BR gid ,
and
permissions
.BR perm .
It returns a reference to that file.
.I Fcreate
creates and returns a reference to a new file called
.B name
in the directory
.BR dir .
The file is owned by
user
.BR uid ,
group
.BR gid ,
and
has permissions
.BR perm .
If a file of the same name already exists
in the directory, 
.B fcreate
returns zero.
Otherwise it returns a pointer to the newly
created
.B File
structure.
.I Fremove
removes 
.B file
from its directory.
If
.B file
is itself a directory 
that is not empty or is the root, 
it is not removed, and
.I fremove
returns \-1.
Otherwise 
.I fremove
returns zero.
If removing the file from its directory
causes the reference count to go to zero,
the file is collected and
.B rmaux
is called.
.I Fwalk
returns a new reference to the
.B File
named
.B name
in the directory
.BR dir .
If no such file exists, it returns zero.
It does not decrement 
.BR dir 's
reference count.
.I Fdirread
fills
.B buf
with at most
.B n
bytes of 
entries from the
directory 
.B dir
beginning at offset
.BR offset .
Note that the use of file trees is not required;
it is provided as a convenience.
.PP
To start a file server, one must fill in a 
.B Srv
structure with pointers to the functions satisfying
9P requests.
As explained below, in almost all cases,
using a nil function pointer results in 
sensible default behavior.
If the
.B tree
pointer is non-zero, that file tree is used as described below.
Calling
.B srv
with such a structure
and a file descriptor
causes it to serve 9P on that
file descriptor.  It does not return
until the 9P conversation terminates.
In contrast,
.B postmountsrv
forks off a 9P server and returns.
Before returning, if 
.B srvname
is not zero, the service
is posted in
.B /srv/srvname
(see 
.IR srv (3)).
If 
.B mtpt 
is not zero, the service
is mounted at
.B mtpt
with mount flag
.BR flag .
.I Threadpostmountsrv
is similar but intended for use in 
programs that use the 
.IR thread (2)
library for process creation.
.PP
The functions registered in the
.B Srv
structure must conform to the following
requirements.
The first argument of each function
is a pointer to a 
.B Req
that provides context to the
library for responding to the request.
If a function is provided, 
it
.I must
arrange for
.I respond
to be called when the request is satisfied.
The first argument to
.I respond
should
be the 
.B Req
pointer; the
second is an error string.
If the request was satisfied successfully, the
error string should be a nil pointer.
Note that it is permissible for a function to return
without calling
.IR respond ,
as long as it has arranged for
.IR respond
to be called at some point in the future,
perhaps by another proc sharing its address space, but
see
the discussion of
.B flush
below.
Once 
.I respond
has been called, the function's pointer arguments must not
be dereferenced, as they may point at freed memory.
.PP
If the library detects an error in a request (e.g.,
an attempt to reuse an extant fid, an open of an
already open fid, a read from a fid opened for write),
it will reply with an error
without consulting any of the registered functions.
.PP
The
.B session
function should fill  
.BR id ,
.BR dom ,
and
.B chal 
with the authentication id and domain of the server,
and a challenge, as described in
.IR attach (5).
Before calling
.BR session ,
the library zeros these fields.
Leaving any or all of them zero is permissible.
.B Session
may be nil, indicating no authentication information.
.PP
The
.B attach
function should check authentication information
if desired, and fill in 
.B qid
with the qid of the file system root.
.B Attach
may be nil only if file trees are being used,
in which case the qid will be filled in from
the tree, and no authentication will be done.
.PP
When a fid is cloned, the library simply
copies the
.B aux
pointer from the old
.B Fid
to create the new one.
If further processing is desired,
a non-nil
.B clone
function will be called after this copying 
has been done.
A typical use of this function might be to
increment a reference count in the structure
pointed at by
.BR aux .
.PP
If file trees are being used, 
the 9P server will react to a walk message by
attempting to walk the 
.BR Fid 's
.BR file .
If this fails, a ``file not found'' error is sent back.
Otherwise the
.BR Fid 's
.B file
and
.B qid 
elements are updated.
If file trees are in use, the
.B walk
function is never called.
If file trees are not in use, 
a 
.B walk
function
.I must
be provided.
.PP
Clwalk messages are translated by the library into
a clone followed (when successful) by a walk; the
library's client need not worry about them.
.PP
If file trees are being used, the file metadata will
be consulted on open, create, and remove to see if the requester
has the appropriate permissions.  If not, an error
will be sent back without calling a registered function.
.PP
If file trees are not in use or the user has the appropriate
permissions, 
.B open
is called with the fid being opened,
the open mode, and a pointer to a qid to be filled in.
The qid defaults to the one stored in the
.B fid 
structure.
If file trees are not in use, an
.B open
function
.I must
be provided.
.PP
The
.B create
function is passed the
.B fid 
for the current directory, as well as the
name, mode, and permissions for the file to
be created.
It must fill in the 
.B qid 
on success, and must allocate the new 
.B File
with
.I fcreate
when file trees are in use.
Note that the 
.B create
function must allow
for the possibility of
.I fcreate
returning nil.
If
.B create 
is nil, a ``creation disallowed'' error
will be sent instead.
.PP
The
.B remove
function is called on a request to 
remove the file associated with a 
.BR Fid .
If using file trees, 
.B remove
must call
.I fremove
itself.
If
.B remove
is nil, a
``remove disallowed'' error
will be sent instead.
The library correctly detects 9P requests on 
removed files (via other fid references), and returns
appropriate errors.
.PP
The
.B read
function must be provided;
it fills
.B buf
with at most
.B *n
bytes of data from offset
.B offset
of the file.
It also sets
.B *n 
to the number of bytes being returned.
If using file trees, the library will handle reads of
directories:
.B read
will only be called for requests on files.
.I Readstr
and
.I readbuf
are useful for satisfying read requests on a string or buffer.
.PP
The
.B write
function is similar, but need not be provided:
a ``write disallowed'' message will be sent if 
.B write
is nil.
Otherwise, 
.B write
should attempt to write the 
.B *n
bytes of
.B buf
to offset
.B offset
of the file,
leaving in
.B *n
the number of bytes actually written.
.PP
The 
.B stat
function should fill in 
.B dir
with the stat info for 
.BR fid .
If using file trees, 
.B dir
will be initialized with the stat info
from the tree, and 
.B stat 
itself may be nil.
.PP
The
.B wstat 
function takes a fid and a
new
.B Dir
structure for it,
as well as a bitmask specifying which fields to update.
Other fields in the 
.B Dir
structure should be ignored.
If using file trees and
.B wstat
is successful, the corresponding file's 
.B Dir
structure will be updated.
It is permissible for 
.B wstat
to be nil, in which case all wstats will fail
with the error message ``wstat disallowed''.
.PP
The 
.B flush
function is called to cancel the outstanding request
.BR oldreq .
In single-threaded servers, it is safe to not supply
such a function.
In multithreaded servers, the client must guarantee
that once
.B respond
has been called for
.BR req ,
.B respond
will 
.I not
be called for
.BR oldreq .
.PP
The actual 9P service loop provided by
.I srv
(and indirectly by
.I postmountsrv
and
.IR threadpostmountsrv )
is a single thread of execution.
If it is expected that some requests might block,
arranging for alternate processes is suggested.
.SS Implementation
.PP
The rest of the text of this manual page describes the structures
used to implement the library.
This is useful for some applications, but most users need not
concern themselves with it.
.PP
The library uses internally the functions
.BR _lib9p_emalloc ,
.BR _lib9p_erealloc ,
and
.BR _lib9p_estrdup ,
which are like 
.BR malloc ,
.BR realloc ,
and
.BR strdup ,
but call
.IR abort (2)
rather than returning zero on error.
If alternate behavior is desired, one can
link against replacements for all three.
.PP
An
.B Intmap
is a arbitrary mapping from 
integers to pointers.
.I Allocmap
creates a new one,
and
.I freemap
destroys it.
New entries are added to the map by calling
.BR insertkey ,
which will return the previous value associated
with the given 
.BR id ,
or zero if there was no previous value.
Before inserting the value, the
.B inc
function used when creating the map
is called with the new value; typically this
increments a reference count to reflect the creation
of the new reference held by the map.
.I Caninsertkey
is similar, but only inserts the entry if no
entry for
.B id
already exists.
It returns 1 if the entry was inserted,
and 0 otherwise.
.I Lookupkey
returns the pointer associated with
.BR id ,
or zero if there is no such pointer.
As with the insertion routines,
.B inc
is called on the pointer before it is returned.
The reference count must be incremented by
these routines rather than their callers to avoid
the entry being deleted between function return
and reference increment.
.I Deletekey
removes the entry for
.B id
from the map, returning the associated pointer, if any.
.PP
.BR Intmap s
are used to implement
.BR Fidpool s
and
.BR Reqpool s,
which are allocation pools for
.BR Fid s
and
.BR Req s.
.I Allocfidpool 
creates a new fid pool, and
.I freefidpool
destroys one.
.I Allocfid
returns a reference to a new
.B Fid
structure with identifier 
.BR f .
If a structure with that identifier has
already been allocated,
.I allocfid
returns zero.
.I Closefid
destroys a reference to a 
.B Fid
but leaves it allocated.
.I Freefid
deallocates a 
.B Fid
and destroys the passed reference.
When the reference count goes to zero, 
.B clunkaux
will be called on that particular
.B Fid
structure.
.I Lookupfid
returns a reference to the
.B Fid 
structure identified with
.BR f ,
or zero if there is no such structure.
.PP
.IR Allocreqpool ,
.IR freereqpool ,
.IR allocreq ,
.IR closereq ,
.IR freereq ,
and
.IR lookupreq
behave similarly, manipulating request pools.
.SH EXAMPLES
The file servers
.IR archfs (4),
.IR cdfs (4),
.IR snap (4),
and 
.I aux/olefs
(see
.IR doc2txt (1))
are examples of simple single-threaded file servers
written using this library.
Unlike the others,
.I cdfs 
does not use the
.B File
interface but instead creates its
directory entries on the fly.
.SH SOURCE
.B /sys/src/lib9p
.SH SEE ALSO
.IR srv (3),
.IR intro (5)
.SH BUGS
The library is new and not particularly well exercised; send bug reports to
.BR rsc@plan9.bell-labs.com .
