9P(2) 9P(2) 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 SYNOPSIS #include <u.h> #include <libc.h> #include <auth.h> #include <fcall.h> #include <thread.h> #include <9p.h> typedef struct Fid { ulong fid; char omode;/* -1 if not open */ char uid[NAMELEN]; Qid qid; File *file; Ref ref; void *aux; ... } Fid; typedef struct Req { ulong tag; Ref ref; void *aux; ... } Req; typedef struct File { Dir; File*parent; Refref; void*aux; ... } File; typedef struct Tree { File*root; void(*rmaux)(File *file); 9P(2) 9P(2) ... } Tree; 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) 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; 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) void* _lib9p_emalloc(ulong sz) void* _lib9p_erealloc(void *ptr, ulong newsz) char* _lib9p_estrdup(char *str) 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) Fidpool* allocfidpool(void) void freefidpool(Fidpool *p) Fid* allocfid(Fidpool *p, ulong f) void freefid(Fid *f) 9P(2) 9P(2) void closefid(Fid *f) Fid* lookupfid(Fidpool *p, ulong f) 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) DESCRIPTION These routines provide a library for writing 9P file servers. Fid data structures are allocated one-to-one with active fids in the served 9P connection. They are analogous to Chan structures in the Plan 9 kernel. The fid element is the integer fid used in the 9P connection. Omode is the mode under which the fid was opened, or -1 if this fid has not been opened yet. Note that in addition to the values OREAD, OWRITE, and ORDWR, omode can contain the various flags permissible in an open call. To ignore the flags, use omode&OMASK. Omode should not be changed by the client. Uid contains the name of the user who has authenticated in order to obtain this fid. Qid is set to the last qid returned by an attach, walk, or open function (q.v.). The file element is explained below. The aux element belongs to the client, and may be used to store a per-Fid data pointer. Req data structures are allocated one-to-one with outstand- ing 9P requests. They contain the tag of the request as well as an aux element that may be used by the client to store a per-Req data pointer (often useful for multithreaded servers). The File and Tree structures provide an in-memory file hier- archy that can be used to handle stat, walk, and open requests. If being used, the library will keep the Fid's file element pointing at the appropriate File structure as it is walked over the tree. As with the other structures, the aux element may be used by the client to store a per-File data pointer. The Fid, File, and 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. When creating a new reference by copying a pointer, the count should be incremented with incref. When a Fid is col- lected, the clunkaux function of the Srv structure (described below) is called to collect the pointer stored in 9P(2) 9P(2) aux. Similarly, when a File is collected, the rmaux func- tion in the Tree structure is called to claim the aux pointer. No such function is called when collecting a Req structure: the aux pointer should be removed before calling respond (described below). To destroy a reference to a Fid, File, or Req, call closefid, fclose, or closereq, respec- tively. Mktree creates a new file tree whose root has owner uid, group gid, and permissions perm. It returns a reference to that file. Fcreate creates and returns a reference to a new file called name in the directory dir. The file is owned by user uid, group gid, and has permissions perm. If a file of the same name already exists in the directory, fcreate returns zero. Otherwise it returns a pointer to the newly created File structure. Fremove removes file from its directory. If file is itself a directory that is not empty or is the root, it is not removed, and fremove returns -1. Otherwise fremove returns zero. If removing the file from its directory causes the reference count to go to zero, the file is collected and rmaux is called. Fwalk returns a new reference to the File named name in the directory dir. If no such file exists, it returns zero. It does not decrement dir's reference count. Fdirread fills buf with at most n bytes of entries from the directory dir beginning at offset offset. Note that the use of file trees is not required; it is provided as a convenience. To start a file server, one must fill in a 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 tree pointer is non-zero, that file tree is used as described below. Calling 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, postmountsrv forks off a 9P server and returns. Before returning, if srvname is not zero, the service is posted in /srv/srvname (see srv(3)). If mtpt is not zero, the service is mounted at mtpt with mount flag flag. Threadpostmountsrv is similar but intended for use in pro- grams that use the thread(2) library for process creation. The functions registered in the Srv structure must conform to the following requirements. The first argument of each function is a pointer to a Req that provides context to the library for responding to the request. If a function is provided, it must arrange for respond to be called when the request is satisfied. The first argument to respond should be the 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 9P(2) 9P(2) function to return without calling respond, as long as it has arranged for respond to be called at some point in the future, perhaps by another proc sharing its address space, but see the discussion of flush below. Once respond has been called, the function's pointer arguments must not be dereferenced, as they may point at freed memory. 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. The session function should fill id, dom, and chal with the authentication id and domain of the server, and a challenge, as described in attach(5). Before calling session, the library zeros these fields. Leaving any or all of them zero is permissible. Session may be nil, indicating no authenti- cation information. The attach function should check authentication information if desired, and fill in qid with the qid of the file system root. 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. When a fid is cloned, the library simply copies the aux pointer from the old Fid to create the new one. If further processing is desired, a non-nil 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 aux. If file trees are being used, the 9P server will react to a walk message by attempting to walk the Fid's file. If this fails, a ``file not found'' error is sent back. Otherwise the Fid's file and qid elements are updated. If file trees are in use, the walk function is never called. If file trees are not in use, a walk function must be provided. 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. If file trees are being used, the file metadata will be con- sulted 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. If file trees are not in use or the user has the appropriate permissions, 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 fid structure. If file 9P(2) 9P(2) trees are not in use, an open function must be provided. The create function is passed the fid for the current direc- tory, as well as the name, mode, and permissions for the file to be created. It must fill in the qid on success, and must allocate the new File with fcreate when file trees are in use. Note that the create function must allow for the possibility of fcreate returning nil. If create is nil, a ``creation disallowed'' error will be sent instead. The remove function is called on a request to remove the file associated with a Fid. If using file trees, remove must call fremove itself. If remove is nil, a ``remove dis- allowed'' error will be sent instead. The library correctly detects 9P requests on removed files (via other fid refer- ences), and returns appropriate errors. The read function must be provided; it fills buf with at most *n bytes of data from offset offset of the file. It also sets *n to the number of bytes being returned. If using file trees, the library will handle reads of directo- ries: read will only be called for requests on files. Readstr and readbuf are useful for satisfying read requests on a string or buffer. The write function is similar, but need not be provided: a ``write disallowed'' message will be sent if write is nil. Otherwise, write should attempt to write the *n bytes of buf to offset offset of the file, leaving in *n the number of bytes actually written. The stat function should fill in dir with the stat info for fid. If using file trees, dir will be initialized with the stat info from the tree, and stat itself may be nil. The wstat function takes a fid and a new Dir structure for it, as well as a bitmask specifying which fields to update. Other fields in the Dir structure should be ignored. If using file trees and wstat is successful, the corresponding file's Dir structure will be updated. It is permissible for wstat to be nil, in which case all wstats will fail with the error message ``wstat disallowed''. The flush function is called to cancel the outstanding request oldreq. In single-threaded servers, it is safe to not supply such a function. In multithreaded servers, the client must guarantee that once respond has been called for req, respond will not be called for oldreq. The actual 9P service loop provided by srv (and indirectly by postmountsrv and threadpostmountsrv) is a single thread of execution. If it is expected that some requests might 9P(2) 9P(2) block, arranging for alternate processes is suggested. Implementation 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 them- selves with it. The library uses internally the functions _lib9p_emalloc, _lib9p_erealloc, and _lib9p_estrdup, which are like malloc, realloc, and strdup, but call abort(2) rather than returning zero on error. If alternate behavior is desired, one can link against replacements for all three. An Intmap is a arbitrary mapping from integers to pointers. Allocmap creates a new one, and freemap destroys it. New entries are added to the map by calling insertkey, which will return the previous value associated with the given id, or zero if there was no previous value. Before inserting the value, the inc function used when creating the map is called with the new value; typically this increments a ref- erence count to reflect the creation of the new reference held by the map. Caninsertkey is similar, but only inserts the entry if no entry for id already exists. It returns 1 if the entry was inserted, and 0 otherwise. Lookupkey returns the pointer associated with id, or zero if there is no such pointer. As with the insertion routines, 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 func- tion return and reference increment. Deletekey removes the entry for id from the map, returning the associated pointer, if any. Intmaps are used to implement Fidpools and Reqpools, which are allocation pools for Fids and Reqs. Allocfidpool cre- ates a new fid pool, and freefidpool destroys one. Allocfid returns a reference to a new Fid structure with identifier f. If a structure with that identifier has already been allocated, allocfid returns zero. Closefid destroys a ref- erence to a Fid but leaves it allocated. Freefid deallo- cates a Fid and destroys the passed reference. When the reference count goes to zero, clunkaux will be called on that particular Fid structure. Lookupfid returns a refer- ence to the Fid structure identified with f, or zero if there is no such structure. Allocreqpool, freereqpool, allocreq, closereq, freereq, and lookupreq behave similarly, manipulating request pools. EXAMPLES The file servers archfs(4), cdfs(4), snap(4), and aux/olefs 9P(2) 9P(2) (see doc2txt(1)) are examples of simple single-threaded file servers written using this library. Unlike the others, cdfs does not use the File interface but instead creates its directory entries on the fly. SOURCE /sys/src/lib9p SEE ALSO srv(3), intro(5) BUGS The library is new and not particularly well exercised; send bug reports to rsc@plan9.bell-labs.com.