libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

commit c9664b1bccd3e65497502704fede2ad26423c12f
parent a5200bef5950630fd25a207ce180d8d302b058bb
Author: Kris Maglione <kris@suckless.org>
Date:   Wed, 16 Jun 2010 15:48:34 -0400

Doc updates and minor API changes.

Diffstat:
NEWS | 7+++++++
include/ixp.h | 391+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
include/ixp_local.h | 32+++++++++++++++++++++-----------
include/ixp_srvutil.h | 5++++-
lib/libixp/client.c | 15++++++---------
lib/libixp/convert.c | 138++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
lib/libixp/error.c | 27++++++++++++++++-----------
lib/libixp/map.c | 14+++++++-------
lib/libixp/message.c | 65++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
lib/libixp/request.c | 233+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
lib/libixp/server.c | 13++++++-------
lib/libixp/srv_util.c | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
lib/libixp/timer.c | 6+++---
lib/libixp/transport.c | 23++++++++++++++++++++++-
lib/libixp/util.c | 37++++++++++++++++++++++++++++++-------
man/Ixp9Srv.3 | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/IxpFcall.3 | 186+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/IxpFid.3 | 41+++++++++++++++++++++++++++++++++++++++++
man/IxpMsg.3 | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/IxpThread.3 | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_close.3 | 2++
man/ixp_dial.3 | 2++
man/ixp_emalloc.3 | 30++++++++++++++++++++++++++++++
man/ixp_eprint.3 | 22++++++++++++++++++++++
man/ixp_errbuf.3 | 23+++++++++++++++--------
man/ixp_fcall2msg.3 | 34++++++++++++++++++++++++++++++++++
man/ixp_freestat.3 | 25+++++++++++++++++++++++++
man/ixp_hangup.3 | 2++
man/ixp_listen.3 | 21+++++++++++----------
man/ixp_mount.3 | 2++
man/ixp_msec.3 | 2++
man/ixp_namespace.3 | 2++
man/ixp_nexttimer.3 | 30------------------------------
man/ixp_open.3 | 8+++++---
man/ixp_pdata.3 | 35+++++++++++++++++++++++++++++++++++
man/ixp_pending_write.3 | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_pfcall.3 | 43+++++++++++++++++++++++++++++++++++++++++++
man/ixp_print.3 | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_printfcall.3 | 28++++++++++++++++++++++++++++
man/ixp_pstring.3 | 38++++++++++++++++++++++++++++++++++++++
man/ixp_pstrings.3 | 42++++++++++++++++++++++++++++++++++++++++++
man/ixp_pu8.3 | 41+++++++++++++++++++++++++++++++++++++++++
man/ixp_read.3 | 4+++-
man/ixp_remove.3 | 2++
man/ixp_respond.3 | 30++++++++++++++++++++++++++++++
man/ixp_sendmsg.3 | 41+++++++++++++++++++++++++++++++++++++++++
man/ixp_serverloop.3 | 2++
man/ixp_settimer.3 | 2++
man/ixp_smprint.3 | 22++++++++++++++++++++++
man/ixp_srv_clonefiles.3 | 2++
man/ixp_srv_data2cstring.3 | 2++
man/ixp_srv_freefile.3 | 2++
man/ixp_srv_getfile.3 | 4+++-
man/ixp_srv_readbuf.3 | 40++++++++++++++++++++++++++++++++++++++++
man/ixp_srv_walkandclone.3 | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_srv_writectl.3 | 28++++++++++++++++++++++++++++
man/ixp_stat.3 | 22++++++++++++----------
man/ixp_unmount.3 | 2++
man/ixp_unsettimer.3 | 2++
man/ixp_vprint.3 | 57---------------------------------------------------------
man/ixp_write.3 | 4+++-
man/targets.mk | 29+++++++++++++++++++++++++----
util/grepdoc | 50++++++++++++++++++++++++++++++++++++++------------
util/link | 2+-
64 files changed, 2047 insertions(+), 492 deletions(-)

diff --git a/NEWS b/NEWS @@ -0,0 +1,7 @@ + +0.6: + Add API documentation and manual pages. + Now fully MIT licensed. + Fix build problems on case insensitive filesystems. + Change ixp_srv_clonefiles specification. + diff --git a/include/ixp.h b/include/ixp.h @@ -4,10 +4,11 @@ */ #include <stdarg.h> +#include <stdint.h> #include <sys/types.h> #include <sys/select.h> -#define IXP_API 116 +#define IXP_API 127 /* Gunk */ #if defined(IXP_NEEDAPI) && IXP_API < IXP_NEEDAPI @@ -17,18 +18,29 @@ # warning This version of libixp has a newer API than this compilation requires. #endif +#if defined(IXP_NEEDAPI) && IXP_NEEDAPI < 127 +# undef ushort +# undef ulong +# undef vlong +# undef uvlong +# define ushort _ixpushort +# define ulong _ixpulong +# define vlong _ixpvlong +# define uvlong _ixpuvlong + +typedef uint16_t ushort; +typedef uint32_t ulong; +typedef uint64_t uvlong; + +typedef int64_t vlong; +#endif + #undef uchar -#undef ushort #undef uint -#undef ulong -#undef vlong -#undef uvlong -#define uchar _ixpuchar -#define ushort _ixpushort -#define uint _ixpuint -#define ulong _ixpulong -#define vlong _ixpvlong -#define uvlong _ixpuvlong +#define uchar _ixpuchar +#define uint _ixpuint +typedef unsigned char uchar; +typedef unsigned int uint; #ifdef KENC # define STRUCT(x) struct {x}; @@ -36,23 +48,11 @@ #elif defined(__GNUC__) # define STRUCT(x) __extension__ struct {x}; # define UNION(x) __extension__ union {x}; -#else -# define IXP_NEEDAPI 89 -# define STRUCT(x) x -# define UNION(x) x #endif /* End Gunk */ -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned long long uvlong; - -typedef long long vlong; - #define IXP_VERSION "9P2000" -#define IXP_NOTAG ((ushort)~0) /* Dummy tag */ +#define IXP_NOTAG ((uint16_t)~0) /* Dummy tag */ #define IXP_NOFID (~0U) enum { @@ -244,44 +244,47 @@ enum { }; struct IxpMutex { - void* aux; + void* aux; }; -struct IxpRWLock { - void* aux; +struct IxpRendez { + IxpMutex* mutex; + void* aux; }; -struct IxpRendez { - IxpMutex* mutex; +struct IxpRWLock { void* aux; }; -enum { MsgPack, MsgUnpack, }; +enum IxpMsgMode { + MsgPack, + MsgUnpack, +}; struct IxpMsg { - char* data; - char* pos; - char* end; - uint size; - uint mode; + char* data; /* Begining of buffer. */ + char* pos; /* Current position in buffer. */ + char* end; /* End of message. */ + uint size; /* Size of buffer. */ + uint mode; /* MsgPack or MsgUnpack. */ }; struct IxpQid { - uchar type; - ulong version; - uvlong path; + uint8_t type; + uint32_t version; + uint64_t path; /* Private members */ - uchar dir_type; + uint8_t dir_type; }; /* stat structure */ struct IxpStat { - ushort type; - ulong dev; - IxpQid qid; - ulong mode; - ulong atime; - ulong mtime; - uvlong length; + uint16_t type; + uint32_t dev; + IxpQid qid; + uint32_t mode; + uint32_t atime; + uint32_t mtime; + uint64_t length; char* name; char* uid; char* gid; @@ -313,122 +316,122 @@ typedef struct IxpFIO IxpFIO; typedef struct IxpFVersion IxpFVersion; struct IxpFHdr { - uchar type; - ushort tag; - ulong fid; + uint8_t type; + uint16_t tag; + uint32_t fid; }; struct IxpFVersion { - IxpFHdr hdr; - ulong msize; - char* version; + IxpFHdr hdr; + uint32_t msize; + char* version; }; struct IxpFTFlush { - IxpFHdr hdr; - ushort oldtag; + IxpFHdr hdr; + uint16_t oldtag; }; struct IxpFError { - IxpFHdr hdr; - char* ename; + IxpFHdr hdr; + char* ename; }; struct IxpFROpen { - IxpFHdr hdr; - IxpQid qid; /* +Rattach */ - ulong iounit; + IxpFHdr hdr; + IxpQid qid; /* +Rattach */ + uint32_t iounit; }; struct IxpFRAuth { - IxpFHdr hdr; - IxpQid aqid; + IxpFHdr hdr; + IxpQid aqid; }; struct IxpFAttach { - IxpFHdr hdr; - ulong afid; - char* uname; - char* aname; + IxpFHdr hdr; + uint32_t afid; + char* uname; + char* aname; }; struct IxpFTCreate { - IxpFHdr hdr; - ulong perm; - char* name; - uchar mode; /* +Topen */ + IxpFHdr hdr; + uint32_t perm; + char* name; + uint8_t mode; /* +Topen */ }; struct IxpFTWalk { IxpFHdr hdr; - ulong newfid; - ushort nwname; - char* wname[IXP_MAX_WELEM]; + uint32_t newfid; + uint16_t nwname; + char* wname[IXP_MAX_WELEM]; }; struct IxpFRWalk { - IxpFHdr hdr; - ushort nwqid; - IxpQid wqid[IXP_MAX_WELEM]; + IxpFHdr hdr; + uint16_t nwqid; + IxpQid wqid[IXP_MAX_WELEM]; }; struct IxpFIO { - IxpFHdr hdr; - uvlong offset; /* Tread, Twrite */ - ulong count; /* Tread, Twrite, Rread */ - char* data; /* Twrite, Rread */ + IxpFHdr hdr; + uint64_t offset; /* Tread, Twrite */ + uint32_t count; /* Tread, Twrite, Rread */ + char* data; /* Twrite, Rread */ }; struct IxpFRStat { - IxpFHdr hdr; - ushort nstat; - uchar* stat; + IxpFHdr hdr; + uint16_t nstat; + uchar* stat; }; struct IxpFTWStat { - IxpFHdr hdr; - IxpStat stat; + IxpFHdr hdr; + IxpStat stat; }; #if defined(IXP_NEEDAPI) && IXP_NEEDAPI <= 89 /* from fcall(3) in plan9port */ typedef struct IxpFcall IxpFcall; /* Deprecated */ struct IxpFcall { /* Deprecated */ - uchar type; - ushort tag; - ulong fid; + uint8_t type; + uint16_t tag; + uint32_t fid; UNION ( STRUCT ( /* Tversion, Rversion */ - ulong msize; + uint32_t msize; char *version; ) STRUCT ( /* Tflush */ - ushort oldtag; + uint16_t oldtag; ) STRUCT ( /* Rerror */ char *ename; ) STRUCT ( /* Ropen, Rcreate */ IxpQid qid; /* +Rattach */ - ulong iounit; + uint32_t iounit; ) STRUCT ( /* Rauth */ IxpQid aqid; ) STRUCT ( /* Tauth, Tattach */ - ulong afid; + uint32_t afid; char *uname; char *aname; ) STRUCT ( /* Tcreate */ - ulong perm; + uint32_t perm; char *name; - uchar mode; /* +Topen */ + uint8_t mode; /* +Topen */ ) STRUCT ( /* Twalk */ - ulong newfid; - ushort nwname; + uint32_t newfid; + uint16_t nwname; char *wname[IXP_MAX_WELEM]; ) STRUCT ( /* Rwalk */ - ushort nwqid; + uint16_t nwqid; IxpQid wqid[IXP_MAX_WELEM]; ) STRUCT ( - uvlong offset; /* Tread, Twrite */ - ulong count; /* Tread, Twrite, Rread */ + uint64_t offset; /* Tread, Twrite */ + uint32_t count; /* Tread, Twrite, Rread */ char *data; /* Twrite, Rread */ ) STRUCT ( /* Rstat */ - ushort nstat; + uint16_t nstat; uchar *stat; ) STRUCT ( /* Twstat */ @@ -437,7 +440,41 @@ struct IxpFcall { /* Deprecated */ ) }; #else -typedef union IxpFcall IxpFcall; +/** + * Type: IxpFcall + * Type: IxpFType + * Type: IxpFAttach + * Type: IxpFError + * Type: IxpFHdr + * Type: IxpFIO + * Type: IxpFRAuth + * Type: IxpFROpen + * Type: IxpFRStat + * Type: IxpFRWalk + * Type: IxpFTCreate + * Type: IxpFTFlush + * Type: IxpFTWStat + * Type: IxpFTWalk + * Type: IxpFVersion + * + * The IxpFcall structure represents a 9P protocol message. The + * P<hdr> element is common to all Fcall types, and may be used to + * determine the type and tag of the message. The IxpFcall type is + * used heavily in server applications, where it both presents a + * request to handler functions and returns a response to the + * client. + * + * Each member of the IxpFcall structure represents a certain + * message type, which can be discerned from the P<hdr.type> field. + * This value corresponds to one of the IxpFType constants. Types + * with significant overlap use the same structures, thus TRead and + * RWrite are both represented by IxpFIO and can be accessed via the + * P<io> member as well as P<tread> and P<rwrite> respectively. + * + * See also: + * T<Ixp9Srv>, T<Ixp9Req> + */ +typedef union IxpFcall IxpFcall; union IxpFcall { IxpFHdr hdr; IxpFVersion version; @@ -467,11 +504,11 @@ union IxpFcall { struct IxpConn { IxpServer* srv; - void* aux; - int fd; + void* aux; /* Arbitrary pointer, to be used by handlers. */ + int fd; /* The file descriptor of the connection. */ void (*read)(IxpConn *); void (*close)(IxpConn *); - char closed; + char closed; /* Non-zero when P<fd> has been closed. */ /* Private members */ IxpConn *next; @@ -523,12 +560,12 @@ struct IxpClient { }; struct IxpCFid { - uint fid; + uint32_t fid; IxpQid qid; - uchar mode; + uint8_t mode; uint open; uint iounit; - uvlong offset; + uint32_t offset; IxpClient* client; /* Private members */ @@ -536,13 +573,26 @@ struct IxpCFid { IxpMutex iolock; }; +/** + * Type: IxpFid + * + * Represents an open file for a 9P connection. The same + * structure persists as long as the file remains open, and is + * installed in the T<Ixp9Req> structure for any request Fcall + * which references it. Handlers may use the P<aux> member to + * store any data which must persist for the life of the open + * file. + * + * See also: + * T<Ixp9Req>, T<IxpQid>, T<IxpOMode> + */ struct IxpFid { - char* uid; - void* aux; - ulong fid; - IxpQid qid; - signed char omode; - uint iounit; + char* uid; /* The uid of the file opener. */ + void* aux; /* Arbitrary pointer, to be used by handlers. */ + uint32_t fid; /* The ID number of the fid. */ + IxpQid qid; /* The filesystem-unique QID of the file. */ + signed char omode; /* The open mode of the file. */ + uint iounit; /* The maximum size of any IO request. */ /* Private members */ Ixp9Conn* conn; @@ -551,12 +601,12 @@ struct IxpFid { struct Ixp9Req { Ixp9Srv* srv; - IxpFid* fid; - IxpFid* newfid; - Ixp9Req* oldreq; - IxpFcall ifcall; - IxpFcall ofcall; - void* aux; + IxpFid* fid; /* Fid structure corresponding to IxpFHdr.fid */ + IxpFid* newfid; /* Corresponds to IxpFTWStat.newfid */ + Ixp9Req* oldreq; /* For TFlush requests, the original request. */ + IxpFcall ifcall; /* The incoming request fcall. */ + IxpFcall ofcall; /* The response fcall, to be filled by handler. */ + void* aux; /* Arbitrary pointer, to be used by handlers. */ /* Private members */ Ixp9Conn *conn; @@ -564,22 +614,44 @@ struct Ixp9Req { struct Ixp9Srv { void* aux; - void (*attach)(Ixp9Req *r); - void (*clunk)(Ixp9Req *r); - void (*create)(Ixp9Req *r); - void (*flush)(Ixp9Req *r); - void (*open)(Ixp9Req *r); - void (*read)(Ixp9Req *r); - void (*remove)(Ixp9Req *r); - void (*stat)(Ixp9Req *r); - void (*walk)(Ixp9Req *r); - void (*write)(Ixp9Req *r); - void (*wstat)(Ixp9Req *r); - void (*freefid)(IxpFid *f); -}; - + void (*attach)(Ixp9Req*); + void (*clunk)(Ixp9Req*); + void (*create)(Ixp9Req*); + void (*flush)(Ixp9Req*); + void (*open)(Ixp9Req*); + void (*read)(Ixp9Req*); + void (*remove)(Ixp9Req*); + void (*stat)(Ixp9Req*); + void (*walk)(Ixp9Req*); + void (*write)(Ixp9Req*); + void (*wstat)(Ixp9Req*); + void (*freefid)(IxpFid*); +}; + +/** + * Type: IxpThread + * Type: IxpMutex + * Type: IxpRWLock + * Type: IxpRendez + * Variable: ixp_thread + * + * The IxpThread structure is used to adapt libixp to any of the + * myriad threading systems it may be used with. Before any + * other of libixp's functions is called, ixp_thread may be set + * to a structure filled with implementations of various locking + * primitives, along with primitive IO functions which may + * perform context switches until data is available. + * + * The names of the functions should be fairly self-explanitory. + * Read/write locks should allow multiple readers and a single + * writer of a shared resource, but should not allow new readers + * while a writer is waitng for a lock. Mutexes should allow + * only one accessor at a time. Rendezvous points are similar to + * pthread condition types. P<errbuf> should return a + * thread-local buffer or the size IXP_ERRMAX. + */ struct IxpThread { - /* RWLock */ + /* Read/write lock */ int (*initrwlock)(IxpRWLock*); void (*rlock)(IxpRWLock*); int (*canrlock)(IxpRWLock*); @@ -594,23 +666,23 @@ struct IxpThread { int (*canlock)(IxpMutex*); void (*unlock)(IxpMutex*); void (*mdestroy)(IxpMutex*); - /* Rendez */ + /* Rendezvous point */ int (*initrendez)(IxpRendez*); void (*sleep)(IxpRendez*); int (*wake)(IxpRendez*); int (*wakeall)(IxpRendez*); void (*rdestroy)(IxpRendez*); /* Other */ - char *(*errbuf)(void); + char* (*errbuf)(void); ssize_t (*read)(int, void*, size_t); ssize_t (*write)(int, const void*, size_t); int (*select)(int, fd_set*, fd_set*, fd_set*, struct timeval*); }; -extern IxpThread *ixp_thread; -extern int (*ixp_vsnprint)(char*, int, const char*, va_list); -extern char* (*ixp_vsmprint)(const char*, va_list); -extern void (*ixp_printfcall)(IxpFcall*); +extern IxpThread* ixp_thread; +extern int (*ixp_vsnprint)(char *buf, int nbuf, const char *fmt, va_list); +extern char* (*ixp_vsmprint)(const char *fmt, va_list); +extern void (*ixp_printfcall)(IxpFcall*); /* thread_*.c */ int ixp_taskinit(void); @@ -624,15 +696,15 @@ int ixp_pthread_init(void); #endif /* client.c */ -int ixp_close(IxpCFid*); -long ixp_pread(IxpCFid*, void*, long, vlong); -int ixp_print(IxpCFid*, const char*, ...); -long ixp_pwrite(IxpCFid*, const void*, long, vlong); -long ixp_read(IxpCFid*, void*, long); -int ixp_remove(IxpClient*, const char*); -void ixp_unmount(IxpClient*); -int ixp_vprint(IxpCFid*, const char*, va_list); -long ixp_write(IxpCFid*, const void*, long); +int ixp_close(IxpCFid*); +long ixp_pread(IxpCFid*, void*, long, int64_t); +int ixp_print(IxpCFid*, const char*, ...); +long ixp_pwrite(IxpCFid*, const void*, long, int64_t); +long ixp_read(IxpCFid*, void*, long); +int ixp_remove(IxpClient*, const char*); +void ixp_unmount(IxpClient*); +int ixp_vprint(IxpCFid*, const char*, va_list); +long ixp_write(IxpCFid*, const void*, long); IxpCFid* ixp_create(IxpClient*, const char*, uint perm, uchar mode); IxpStat* ixp_fstat(IxpCFid*); IxpClient* ixp_mount(const char*); @@ -642,15 +714,15 @@ IxpCFid* ixp_open(IxpClient*, const char*, uchar); IxpStat* ixp_stat(IxpClient*, const char*); /* convert.c */ -void ixp_pu8(IxpMsg*, uchar*); -void ixp_pu16(IxpMsg*, ushort*); -void ixp_pu32(IxpMsg*, ulong*); -void ixp_pu64(IxpMsg*, uvlong*); +void ixp_pu8(IxpMsg*, uint8_t*); +void ixp_pu16(IxpMsg*, uint16_t*); +void ixp_pu32(IxpMsg*, uint32_t*); +void ixp_pu64(IxpMsg*, uint64_t*); void ixp_pdata(IxpMsg*, char**, uint); void ixp_pstring(IxpMsg*, char**); -void ixp_pstrings(IxpMsg*, ushort*, char**); +void ixp_pstrings(IxpMsg*, uint16_t*, char**, uint); void ixp_pqid(IxpMsg*, IxpQid*); -void ixp_pqids(IxpMsg*, ushort*, IxpQid*); +void ixp_pqids(IxpMsg*, uint16_t*, IxpQid*, uint); void ixp_pstat(IxpMsg*, IxpStat*); void ixp_pfcall(IxpMsg*, IxpFcall*); @@ -661,11 +733,16 @@ void ixp_rerrstr(char*, int); void ixp_werrstr(const char*, ...); /* request.c */ -void respond(Ixp9Req*, const char *err); -void serve_9pcon(IxpConn*); +void ixp_respond(Ixp9Req*, const char *err); +void ixp_serve9conn(IxpConn*); + +#if defined(IXP_NEEDAPI) && IXP_NEEDAPI < 127 +# define respond ixp_respond +# define serve_9pcon ixp_serve9pconn +#endif /* message.c */ -ushort ixp_sizeof_stat(IxpStat*); +uint16_t ixp_sizeof_stat(IxpStat*); IxpMsg ixp_message(char*, uint len, uint mode); void ixp_freestat(IxpStat*); void ixp_freefcall(IxpFcall*); diff --git a/include/ixp_local.h b/include/ixp_local.h @@ -3,6 +3,16 @@ #include <ixp.h> #include <stdbool.h> +#undef ulong +#define ulong _ixpulong +typedef unsigned long ulong; + +#ifdef CPROTO +# undef bool +typedef int bool; +typedef char* va_list; +#endif + char *argv0; #define ARGBEGIN \ int _argtmp=0, _inargv=0; char *_argv=nil; \ @@ -66,20 +76,20 @@ struct IxpMap { }; struct IxpTimer { - Timer* link; - long msec; - long id; - void (*fn)(long, void*); - void* aux; + Timer* link; + uint32_t msec; + long id; + void (*fn)(long, void*); + void* aux; }; /* map.c */ -void ixp_mapfree(Map*, void(*)(void*)); -void ixp_mapexec(Map*, void(*)(void*, void*), void*); -void ixp_mapinit(Map*, MapEnt**, int); -bool ixp_mapinsert(Map*, ulong, void*, bool); -void* ixp_mapget(Map*, ulong); -void* ixp_maprm(Map*, ulong); +void ixp_mapfree(IxpMap*, void(*)(void*)); +void ixp_mapexec(IxpMap*, void(*)(void*, void*), void*); +void ixp_mapinit(IxpMap*, MapEnt**, int); +bool ixp_mapinsert(IxpMap*, ulong, void*, bool); +void* ixp_mapget(IxpMap*, ulong); +void* ixp_maprm(IxpMap*, ulong); /* mux.c */ void muxfree(IxpClient*); diff --git a/include/ixp_srvutil.h b/include/ixp_srvutil.h @@ -9,6 +9,7 @@ typedef struct IxpRequestLink IxpRequestLink; typedef IxpFileId* (*IxpLookupFn)(IxpFileId*, char*); struct IxpPendingLink { + /* Private members */ IxpPendingLink* next; IxpPendingLink* prev; IxpFid* fid; @@ -17,12 +18,14 @@ struct IxpPendingLink { }; struct IxpRequestLink { + /* Private members */ IxpRequestLink* next; IxpRequestLink* prev; Ixp9Req* req; }; struct IxpPending { + /* Private members */ IxpRequestLink req; IxpPendingLink fids; }; @@ -42,7 +45,7 @@ struct IxpFileId { uint id; uint index; IxpDirtab tab; - ushort nref; + uint nref; uchar volatil; }; diff --git a/lib/libixp/client.c b/lib/libixp/client.c @@ -504,7 +504,7 @@ ixp_fstat(IxpCFid *fid) { } static long -_pread(IxpCFid *f, char *buf, long count, vlong offset) { +_pread(IxpCFid *f, char *buf, long count, int64_t offset) { Fcall fcall; int n, len; @@ -567,7 +567,7 @@ ixp_read(IxpCFid *fid, void *buf, long count) { } long -ixp_pread(IxpCFid *fid, void *buf, long count, vlong offset) { +ixp_pread(IxpCFid *fid, void *buf, long count, int64_t offset) { int n; thread->lock(&fid->iolock); @@ -577,7 +577,7 @@ ixp_pread(IxpCFid *fid, void *buf, long count, vlong offset) { } static long -_pwrite(IxpCFid *f, const void *buf, long count, vlong offset) { +_pwrite(IxpCFid *f, const void *buf, long count, int64_t offset) { Fcall fcall; int n, len; @@ -638,7 +638,7 @@ ixp_write(IxpCFid *fid, const void *buf, long count) { } long -ixp_pwrite(IxpCFid *fid, const void *buf, long count, vlong offset) { +ixp_pwrite(IxpCFid *fid, const void *buf, long count, int64_t offset) { int n; thread->lock(&fid->iolock); @@ -648,8 +648,8 @@ ixp_pwrite(IxpCFid *fid, const void *buf, long count, vlong offset) { } /** - * Function: ixp_vprint * Function: ixp_print + * Function: ixp_vprint * Variable: ixp_vsmprint * * Params: @@ -666,10 +666,7 @@ ixp_pwrite(IxpCFid *fid, const void *buf, long count, vlong offset) { * V<ixp_vsmprint> may be set to a function which will * format its arguments and return a nul-terminated string * allocated by malloc(3). The default formats its arguments as - * printf(3). The function must format '%s' as a nul-terminated - * string and may not consume any arguments not specified by a - * %-prefixed format specifier, but may otherwise behave in any - * manner chosen by the user. + * printf(3). * * Returns: * These functions return the number of bytes written. diff --git a/lib/libixp/convert.c b/lib/libixp/convert.c @@ -14,7 +14,7 @@ enum { }; static void -ixp_puint(IxpMsg *msg, uint size, ulong *val) { +ixp_puint(IxpMsg *msg, uint size, uint32_t *val) { uchar *pos; int v; @@ -51,40 +51,80 @@ ixp_puint(IxpMsg *msg, uint size, ulong *val) { msg->pos += size; } +/** + * Function: ixp_pu8 + * Function: ixp_pu16 + * Function: ixp_pu32 + * Function: ixp_pu64 + * + * These functions pack or unpack an unsigned integer of the + * specified size. + * + * If P<msg>->mode is MsgPack, the value pointed to by P<val> is + * packed into the buffer at P<msg>->pos. If P<msg>->mode is + * MsgUnpack, the packed value at P<msg>->pos is loaded into the + * location pointed to by P<val>. In both cases, P<msg>->pos is + * advanced by the number of bytes read or written. If the call + * would advance P<msg>->pos beyond P<msg>->end, P<msg>->pos is + * advanced, but nothing is modified. + * + * See also: + * T<IxpMsg> + */ void -ixp_pu32(IxpMsg *msg, ulong *val) { +ixp_pu32(IxpMsg *msg, uint32_t *val) { ixp_puint(msg, SDWord, val); } void ixp_pu8(IxpMsg *msg, uchar *val) { - ulong v; + uint32_t v; v = *val; ixp_puint(msg, SByte, &v); *val = (uchar)v; } void -ixp_pu16(IxpMsg *msg, ushort *val) { - ulong v; +ixp_pu16(IxpMsg *msg, uint16_t *val) { + uint32_t v; v = *val; ixp_puint(msg, SWord, &v); - *val = (ushort)v; + *val = (uint16_t)v; } void -ixp_pu64(IxpMsg *msg, uvlong *val) { - ulong vl, vb; +ixp_pu64(IxpMsg *msg, uint64_t *val) { + uint32_t vl, vb; vl = (uint)*val; vb = (uint)(*val>>32); ixp_puint(msg, SDWord, &vl); ixp_puint(msg, SDWord, &vb); - *val = vl | ((uvlong)vb<<32); + *val = vl | ((uint64_t)vb<<32); } +/** + * Function: ixp_pstring + * + * Packs or unpacks a UTF-8 encoded string. The packed + * representation of the string consists of a 16-bit unsigned + * integer followed by the contents of the string. The unpacked + * representation is a nul-terminated character array. + * + * If P<msg>->mode is MsgPack, the string pointed to by P<s> is + * packed into the buffer at P<msg>->pos. If P<msg>->mode is + * MsgUnpack, the address pointed to by P<s> is loaded with a + * malloc(3) allocated, nul-terminated representation of the + * string packed at P<msg>->pos. In either case, P<msg>->pos is + * advanced by the number of bytes read or written. If the + * action would advance P<msg>->pos beyond P<msg>->end, + * P<msg>->pos is still advanced but no other action is taken. + * + * See also: + * T<IxpMsg>, F<ixp_pstrings>, F<ixp_pdata> + */ void ixp_pstring(IxpMsg *msg, char **s) { - ushort len; + uint16_t len; if(msg->mode == MsgPack) len = strlen(*s); @@ -101,14 +141,38 @@ ixp_pstring(IxpMsg *msg, char **s) { msg->pos += len; } +/** + * Function: ixp_pstrings + * + * Packs or unpacks an array of UTF-8 encoded strings. The packed + * representation consists of a 16-bit element count followed by + * an array of strings as packed by F<ixp_pstring>. The unpacked + * representation is an array of nul-terminated character arrays. + * + * If P<msg>->mode is MsgPack, P<*num> strings in the array + * pointed to by P<strings> are packed into the buffer at + * P<msg>->pos. If P<msg>->mode is MsgUnpack, P<*num> is loaded + * with the number of strings unpacked, the array at + * P<*strings> is loaded with pointers to the unpacked strings, + * and P<(*strings)[0]> must be freed by the user. In either + * case, P<msg>->pos is advanced by the number of bytes read or + * written. If the action would advance P<msg>->pos beyond + * P<msg>->end, P<msg>->pos is still advanced, but no other + * action is taken. If P<*num> is greater than P<max>, + * P<msg>->pos is set beyond P<msg>->end and no other action is + * taken. + * + * See also: + * P<IxpMsg>, P<ixp_pstring>, P<ixp_pdata> + */ void -ixp_pstrings(IxpMsg *msg, ushort *num, char *strings[]) { +ixp_pstrings(IxpMsg *msg, uint16_t *num, char *strings[], uint max) { char *s; uint i, size; - ushort len; + uint16_t len; ixp_pu16(msg, num); - if(*num > IXP_MAX_WELEM) { + if(*num > max) { msg->pos = msg->end+1; return; } @@ -145,6 +209,23 @@ ixp_pstrings(IxpMsg *msg, ushort *num, char *strings[]) { } } +/** + * Function: ixp_pdata + * + * Packs or unpacks a raw character buffer of size P<len>. + * + * If P<msg>->mode is MsgPack, buffer pointed to by P<data> is + * packed into the buffer at P<msg>->pos. If P<msg>->mode is + * MsgUnpack, the address pointed to by P<s> is loaded with a + * malloc(3) allocated buffer with the contents of the buffer at + * P<msg>->pos. In either case, P<msg>->pos is advanced by the + * number of bytes read or written. If the action would advance + * P<msg>->pos beyond P<msg>->end, P<msg>->pos is still advanced + * but no other action is taken. + * + * See also: + * T<IxpMsg>, F<ixp_pstring> + */ void ixp_pdata(IxpMsg *msg, char **data, uint len) { if(msg->pos + len <= msg->end) { @@ -157,19 +238,40 @@ ixp_pdata(IxpMsg *msg, char **data, uint len) { msg->pos += len; } +/** + * Function: ixp_pfcall + * Function: ixp_pqid + * Function: ixp_pqids + * Function: ixp_pstat + * Function: ixp_sizeof_stat + * + * These convenience functions pack or unpack the contents of + * libixp structures into their wire format. They behave as if + * F<ixp_pu8>, F<ixp_pu16>, F<ixp_pu32>, F<ixp_pu64>, and + * F<ixp_pstring> were called for each member of the structure + * in question. ixp_pqid is to ixp_pqid as F<ixp_pstrings> is to + * ixp_pstring. + * + * ixp_sizeof_stat returns the size of the packed represention + * of P<stat>. + * + * See also: + * T<IxpMsg>, F<ixp_pu8>, F<ixp_pu16>, F<ixp_pu32>, + * F<ixp_pu64>, F<ixp_pstring>, F<ixp_pstrings> + */ void -ixp_pqid(IxpMsg *msg, Qid *qid) { +ixp_pqid(IxpMsg *msg, IxpQid *qid) { ixp_pu8(msg, &qid->type); ixp_pu32(msg, &qid->version); ixp_pu64(msg, &qid->path); } void -ixp_pqids(IxpMsg *msg, ushort *num, Qid qid[]) { +ixp_pqids(IxpMsg *msg, uint16_t *num, IxpQid qid[], uint max) { int i; ixp_pu16(msg, num); - if(*num > IXP_MAX_WELEM) { + if(*num > max) { msg->pos = msg->end+1; return; } @@ -179,8 +281,8 @@ ixp_pqids(IxpMsg *msg, ushort *num, Qid qid[]) { } void -ixp_pstat(IxpMsg *msg, Stat *stat) { - ushort size; +ixp_pstat(IxpMsg *msg, IxpStat *stat) { + uint16_t size; if(msg->mode == MsgPack) size = ixp_sizeof_stat(stat) - 2; diff --git a/lib/libixp/error.c b/lib/libixp/error.c @@ -7,8 +7,8 @@ #include "ixp_local.h" static int -_vsnprint(char *buf, int n, const char *fmt, va_list ap) { - return vsnprintf(buf, n, fmt, ap); +_vsnprint(char *buf, int nbuf, const char *fmt, va_list ap) { + return vsnprintf(buf, nbuf, fmt, ap); } static char* @@ -40,10 +40,11 @@ enum { * Function: ixp_errstr * Function: ixp_rerrstr * Function: ixp_werrstr + * Variable: ixp_vsnprint * * Params: * buf: The buffer to read and/or fill. - * size: The size of the buffer. + * nbuf: The size of the buffer. * fmt: A format string with which to write the errstr. * ...: Arguments to P<fmt>. * @@ -56,12 +57,16 @@ enum { * the current thread's error buffer, while F<ixp_errstr> * exchanges P<buf>'s contents with those of the current * thread's error buffer. F<ixp_werrstr> formats the given - * format string, P<fmt>, via V<ixp_vsmprint> and writes it to + * format string, P<fmt>, via V<ixp_vsnprint> and writes it to * the error buffer. * - * Returns: - * F<ixp_errbuf> returns the current thread's error - * string buffer. + * V<ixp_vsnprint> may be set to a function which will format + * its arguments write the result to the P<nbuf> length buffer + * V<buf>. The default value is F<vsnprintf>. The function must + * format '%s' as a nul-terminated string and may not consume + * any arguments not indicated by a %-prefixed format specifier, + * but may otherwise behave in any manner chosen by the user. + * * See also: * V<ixp_vsmprint> */ @@ -78,18 +83,18 @@ ixp_errbuf() { } void -errstr(char *buf, int size) { +errstr(char *buf, int nbuf) { char tmp[IXP_ERRMAX]; strncpy(tmp, buf, sizeof tmp); - rerrstr(buf, size); + rerrstr(buf, nbuf); strncpy(thread->errbuf(), tmp, IXP_ERRMAX); errno = EPLAN9; } void -rerrstr(char *buf, int size) { - strncpy(buf, ixp_errbuf(), size); +rerrstr(char *buf, int nbuf) { + strncpy(buf, ixp_errbuf(), nbuf); } void diff --git a/lib/libixp/map.c b/lib/libixp/map.c @@ -26,7 +26,7 @@ insert(MapEnt **e, ulong val, const char *key) { } static MapEnt** -map_getp(Map *map, ulong val, bool create, bool *exists) { +map_getp(IxpMap *map, ulong val, bool create, bool *exists) { MapEnt **e; e = &map->bucket[val%map->nhash]; @@ -45,7 +45,7 @@ map_getp(Map *map, ulong val, bool create, bool *exists) { } void -ixp_mapfree(Map *map, void (*destroy)(void*)) { +ixp_mapfree(IxpMap *map, void (*destroy)(void*)) { int i; MapEnt *e; @@ -62,7 +62,7 @@ ixp_mapfree(Map *map, void (*destroy)(void*)) { } void -ixp_mapexec(Map *map, void (*run)(void*, void*), void *context) { +ixp_mapexec(IxpMap *map, void (*run)(void*, void*), void *context) { int i; MapEnt *e; @@ -74,7 +74,7 @@ ixp_mapexec(Map *map, void (*run)(void*, void*), void *context) { } void -ixp_mapinit(Map *map, MapEnt **buckets, int nbuckets) { +ixp_mapinit(IxpMap *map, MapEnt **buckets, int nbuckets) { map->bucket = buckets; map->nhash = nbuckets; @@ -83,7 +83,7 @@ ixp_mapinit(Map *map, MapEnt **buckets, int nbuckets) { } bool -ixp_mapinsert(Map *map, ulong key, void *val, bool overwrite) { +ixp_mapinsert(IxpMap *map, ulong key, void *val, bool overwrite) { MapEnt *e; bool existed, res; @@ -99,7 +99,7 @@ ixp_mapinsert(Map *map, ulong key, void *val, bool overwrite) { } void* -ixp_mapget(Map *map, ulong val) { +ixp_mapget(IxpMap *map, ulong val) { MapEnt *e; void *res; @@ -111,7 +111,7 @@ ixp_mapget(Map *map, ulong val) { } void* -ixp_maprm(Map *map, ulong val) { +ixp_maprm(IxpMap *map, ulong val) { MapEnt **e, *te; void *ret; diff --git a/lib/libixp/message.c b/lib/libixp/message.c @@ -18,6 +18,31 @@ enum { SQid = SByte + SDWord + SQWord, }; +/** + * Type: IxpMsg + * Type: IxpMsgMode + * Function: ixp_message + * + * The IxpMsg struct represents a binary message, and is used + * extensively by libixp for converting messages to and from + * wire format. The location and size of a buffer are stored in + * P<data> and P<size>, respectively. P<pos> points to the + * location in the message currently being packed or unpacked, + * while P<end> points to the end of the message. The packing + * functions advance P<pos> as they go, always ensuring that + * they don't read or write past P<end>. When a message is + * entirely packed or unpacked, P<pos> whould be less than or + * equal to P<end>. Any other state indicates error. + * + * ixp_message is a convenience function to pack a construct an + * IxpMsg from a buffer of a given P<length> and a given + * P<mode>. P<pos> and P<data> are set to P<data> and P<end> is + * set to P<data> + P<length>. + * + * See also: + * F<ixp_pu8>, F<ixp_pu16>, F<ixp_pu32>, F<ixp_pu64>, + * F<ixp_pstring>, F<ixp_pstrings> + */ IxpMsg ixp_message(char *data, uint length, uint mode) { IxpMsg m; @@ -30,8 +55,16 @@ ixp_message(char *data, uint length, uint mode) { return m; } +/** + * Function: ixp_freestat + * Function: ixp_freefcall + * + * These functions free malloc(3) allocated data in the members + * of the passed structures and set those members to nil. They + * do not free the structures themselves. + */ void -ixp_freestat(Stat *s) { +ixp_freestat(IxpStat *s) { free(s->name); free(s->uid); free(s->gid); @@ -40,7 +73,7 @@ ixp_freestat(Stat *s) { } void -ixp_freefcall(Fcall *fcall) { +ixp_freefcall(IxpFcall *fcall) { switch(fcall->hdr.type) { case RStat: free(fcall->rstat.stat); @@ -61,8 +94,8 @@ ixp_freefcall(Fcall *fcall) { } } -ushort -ixp_sizeof_stat(Stat * stat) { +uint16_t +ixp_sizeof_stat(IxpStat *stat) { return SWord /* size */ + SWord /* type */ + SDWord /* dev */ @@ -76,7 +109,7 @@ ixp_sizeof_stat(Stat * stat) { } void -ixp_pfcall(IxpMsg *msg, Fcall *fcall) { +ixp_pfcall(IxpMsg *msg, IxpFcall *fcall) { ixp_pu8(msg, &fcall->hdr.type); ixp_pu16(msg, &fcall->hdr.tag); @@ -112,10 +145,10 @@ ixp_pfcall(IxpMsg *msg, Fcall *fcall) { case TWalk: ixp_pu32(msg, &fcall->hdr.fid); ixp_pu32(msg, &fcall->twalk.newfid); - ixp_pstrings(msg, &fcall->twalk.nwname, fcall->twalk.wname); + ixp_pstrings(msg, &fcall->twalk.nwname, fcall->twalk.wname, nelem(fcall->twalk.wname)); break; case RWalk: - ixp_pqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid); + ixp_pqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid, nelem(fcall->rwalk.wqid)); break; case TOpen: ixp_pu32(msg, &fcall->hdr.fid); @@ -160,7 +193,7 @@ ixp_pfcall(IxpMsg *msg, Fcall *fcall) { ixp_pdata(msg, (char**)&fcall->rstat.stat, fcall->rstat.nstat); break; case TWStat: { - ushort size; + uint16_t size; ixp_pu32(msg, &fcall->hdr.fid); ixp_pu16(msg, &size); ixp_pstat(msg, &fcall->twstat.stat); @@ -169,9 +202,23 @@ ixp_pfcall(IxpMsg *msg, Fcall *fcall) { } } +/** + * Function: ixp_fcall2msg + * Function: ixp_msg2fcall + * + * These functions pack or unpack a 9P protocol message. The + * message is set to the appropriate mode and its position is + * set to the begining of its buffer. + * + * Returns: + * These functions return the size of the message on + * success and 0 on failure. + * See also: + * F<IxpMsg>, F<ixp_pfcall> + */ uint ixp_fcall2msg(IxpMsg *msg, Fcall *fcall) { - ulong size; + uint32_t size; msg->end = msg->data + msg->size; msg->pos = msg->data + SDWord; diff --git a/lib/libixp/request.c b/lib/libixp/request.c @@ -10,11 +10,18 @@ static void handlereq(Ixp9Req *r); -static void -_printfcall(Fcall *f) { - USED(f); -} -void (*ixp_printfcall)(Fcall*) = _printfcall; +/** + * Variable: ixp_printfcall + * + * When set to a non-null value, ixp_printfcall is called once for + * every incoming and outgoing Fcall. It is intended to simplify the + * writing of debugging code for clients, but may be used for any + * arbitrary purpose. + * + * See also: + * F<ixp_respond>, F<ixp_serve9conn> + */ +void (*ixp_printfcall)(Fcall*); static int min(int a, int b) { @@ -79,7 +86,7 @@ decref_p9conn(Ixp9Conn *p9conn) { static void* createfid(Map *map, int fid, Ixp9Conn *p9conn) { - Fid *f; + IxpFid *f; f = emallocz(sizeof *f); p9conn->ref++; @@ -95,7 +102,7 @@ createfid(Map *map, int fid, Ixp9Conn *p9conn) { static int destroyfid(Ixp9Conn *p9conn, ulong fid) { - Fid *f; + IxpFid *f; f = ixp_maprm(&p9conn->fidmap, fid); if(f == nil) @@ -132,7 +139,7 @@ handlefcall(IxpConn *c) { p9conn->conn = c; if(!ixp_mapinsert(&p9conn->tagmap, fcall.hdr.tag, req, false)) { - respond(req, Eduptag); + ixp_respond(req, Eduptag); return; } @@ -153,11 +160,12 @@ handlereq(Ixp9Req *r) { p9conn = r->conn; srv = p9conn->srv; - ixp_printfcall(&r->ifcall); + if(ixp_printfcall) + ixp_printfcall(&r->ifcall); switch(r->ifcall.hdr.type) { default: - respond(r, Enofunc); + ixp_respond(r, Enofunc); break; case TVersion: if(!strcmp(r->ifcall.version.version, "9P")) @@ -167,11 +175,11 @@ handlereq(Ixp9Req *r) { else r->ofcall.version.version = "unknown"; r->ofcall.version.msize = r->ifcall.version.msize; - respond(r, nil); + ixp_respond(r, nil); break; case TAttach: if(!(r->fid = createfid(&p9conn->fidmap, r->ifcall.hdr.fid, p9conn))) { - respond(r, Edupfid); + ixp_respond(r, Edupfid); return; } /* attach is a required function */ @@ -179,166 +187,166 @@ handlereq(Ixp9Req *r) { break; case TClunk: if(!(r->fid = ixp_mapget(&p9conn->fidmap, r->ifcall.hdr.fid))) { - respond(r, Enofid); + ixp_respond(r, Enofid); return; } if(!srv->clunk) { - respond(r, nil); + ixp_respond(r, nil); return; } srv->clunk(r); break; case TFlush: if(!(r->oldreq = ixp_mapget(&p9conn->tagmap, r->ifcall.tflush.oldtag))) { - respond(r, Enotag); + ixp_respond(r, Enotag); return; } if(!srv->flush) { - respond(r, Enofunc); + ixp_respond(r, Enofunc); return; } srv->flush(r); break; case TCreate: if(!(r->fid = ixp_mapget(&p9conn->fidmap, r->ifcall.hdr.fid))) { - respond(r, Enofid); + ixp_respond(r, Enofid); return; } if(r->fid->omode != -1) { - respond(r, Eopen); + ixp_respond(r, Eopen); return; } if(!(r->fid->qid.type&QTDIR)) { - respond(r, Enotdir); + ixp_respond(r, Enotdir); return; } if(!p9conn->srv->create) { - respond(r, Enofunc); + ixp_respond(r, Enofunc); return; } p9conn->srv->create(r); break; case TOpen: if(!(r->fid = ixp_mapget(&p9conn->fidmap, r->ifcall.hdr.fid))) { - respond(r, Enofid); + ixp_respond(r, Enofid); return; } if((r->fid->qid.type&QTDIR) && (r->ifcall.topen.mode|P9_ORCLOSE) != (P9_OREAD|P9_ORCLOSE)) { - respond(r, Eisdir); + ixp_respond(r, Eisdir); return; } r->ofcall.ropen.qid = r->fid->qid; if(!p9conn->srv->open) { - respond(r, Enofunc); + ixp_respond(r, Enofunc); return; } p9conn->srv->open(r); break; case TRead: if(!(r->fid = ixp_mapget(&p9conn->fidmap, r->ifcall.hdr.fid))) { - respond(r, Enofid); + ixp_respond(r, Enofid); return; } if(r->fid->omode == -1 || r->fid->omode == P9_OWRITE) { - respond(r, Enoread); + ixp_respond(r, Enoread); return; } if(!p9conn->srv->read) { - respond(r, Enofunc); + ixp_respond(r, Enofunc); return; } p9conn->srv->read(r); break; case TRemove: if(!(r->fid = ixp_mapget(&p9conn->fidmap, r->ifcall.hdr.fid))) { - respond(r, Enofid); + ixp_respond(r, Enofid); return; } if(!p9conn->srv->remove) { - respond(r, Enofunc); + ixp_respond(r, Enofunc); return; } p9conn->srv->remove(r); break; case TStat: if(!(r->fid = ixp_mapget(&p9conn->fidmap, r->ifcall.hdr.fid))) { - respond(r, Enofid); + ixp_respond(r, Enofid); return; } if(!p9conn->srv->stat) { - respond(r, Enofunc); + ixp_respond(r, Enofunc); return; } p9conn->srv->stat(r); break; case TWalk: if(!(r->fid = ixp_mapget(&p9conn->fidmap, r->ifcall.hdr.fid))) { - respond(r, Enofid); + ixp_respond(r, Enofid); return; } if(r->fid->omode != -1) { - respond(r, "cannot walk from an open fid"); + ixp_respond(r, "cannot walk from an open fid"); return; } if(r->ifcall.twalk.nwname && !(r->fid->qid.type&QTDIR)) { - respond(r, Enotdir); + ixp_respond(r, Enotdir); return; } if((r->ifcall.hdr.fid != r->ifcall.twalk.newfid)) { if(!(r->newfid = createfid(&p9conn->fidmap, r->ifcall.twalk.newfid, p9conn))) { - respond(r, Edupfid); + ixp_respond(r, Edupfid); return; } }else r->newfid = r->fid; if(!p9conn->srv->walk) { - respond(r, Enofunc); + ixp_respond(r, Enofunc); return; } p9conn->srv->walk(r); break; case TWrite: if(!(r->fid = ixp_mapget(&p9conn->fidmap, r->ifcall.hdr.fid))) { - respond(r, Enofid); + ixp_respond(r, Enofid); return; } if((r->fid->omode&3) != P9_OWRITE && (r->fid->omode&3) != P9_ORDWR) { - respond(r, "write on fid not opened for writing"); + ixp_respond(r, "write on fid not opened for writing"); return; } if(!p9conn->srv->write) { - respond(r, Enofunc); + ixp_respond(r, Enofunc); return; } p9conn->srv->write(r); break; case TWStat: if(!(r->fid = ixp_mapget(&p9conn->fidmap, r->ifcall.hdr.fid))) { - respond(r, Enofid); + ixp_respond(r, Enofid); return; } - if((ushort)~r->ifcall.twstat.stat.type) { - respond(r, "wstat of type"); + if(~r->ifcall.twstat.stat.type) { + ixp_respond(r, "wstat of type"); return; } - if((uint)~r->ifcall.twstat.stat.dev) { - respond(r, "wstat of dev"); + if(~r->ifcall.twstat.stat.dev) { + ixp_respond(r, "wstat of dev"); return; } - if((uchar)~r->ifcall.twstat.stat.qid.type || (ulong)~r->ifcall.twstat.stat.qid.version || (uvlong)~r->ifcall.twstat.stat.qid.path) { - respond(r, "wstat of qid"); + if(~r->ifcall.twstat.stat.qid.type || (ulong)~r->ifcall.twstat.stat.qid.version || ~r->ifcall.twstat.stat.qid.path) { + ixp_respond(r, "wstat of qid"); return; } if(r->ifcall.twstat.stat.muid && r->ifcall.twstat.stat.muid[0]) { - respond(r, "wstat of muid"); + ixp_respond(r, "wstat of muid"); return; } - if((ulong)~r->ifcall.twstat.stat.mode && ((r->ifcall.twstat.stat.mode&DMDIR)>>24) != r->fid->qid.type&QTDIR) { - respond(r, "wstat on DMDIR bit"); + if(~r->ifcall.twstat.stat.mode && ((r->ifcall.twstat.stat.mode&DMDIR)>>24) != r->fid->qid.type&QTDIR) { + ixp_respond(r, "wstat on DMDIR bit"); return; } if(!p9conn->srv->wstat) { - respond(r, Enofunc); + ixp_respond(r, Enofunc); return; } p9conn->srv->wstat(r); @@ -347,80 +355,93 @@ handlereq(Ixp9Req *r) { } } +/** + * Function: ixp_respond + * + * Sends a response to the given request. The response is + * constructed from the P<ofcall> member of the P<req> parameter, or + * from the P<error> parameter if it is non-null. In the latter + * case, the response is of type RError, while in any other case it + * is of the same type as P<req>->P<ofcall>, which must match the + * request type in P<req>->P<ifcall>. + * + * See also: + * T<Ixp9Req>, V<ixp_printfcall> + */ void -respond(Ixp9Req *r, const char *error) { +ixp_respond(Ixp9Req *req, const char *error) { Ixp9Conn *p9conn; int msize; - p9conn = r->conn; + p9conn = req->conn; - switch(r->ifcall.hdr.type) { + switch(req->ifcall.hdr.type) { default: if(!error) assert(!"Respond called on unsupported fcall type"); break; case TVersion: assert(error == nil); - free(r->ifcall.version.version); + free(req->ifcall.version.version); thread->lock(&p9conn->rlock); thread->lock(&p9conn->wlock); - msize = min(r->ofcall.version.msize, IXP_MAX_MSG); + msize = min(req->ofcall.version.msize, IXP_MAX_MSG); p9conn->rmsg.data = erealloc(p9conn->rmsg.data, msize); p9conn->wmsg.data = erealloc(p9conn->wmsg.data, msize); p9conn->rmsg.size = msize; p9conn->wmsg.size = msize; thread->unlock(&p9conn->wlock); thread->unlock(&p9conn->rlock); - r->ofcall.version.msize = msize; + req->ofcall.version.msize = msize; break; case TAttach: if(error) - destroyfid(p9conn, r->fid->fid); - free(r->ifcall.tattach.uname); - free(r->ifcall.tattach.aname); + destroyfid(p9conn, req->fid->fid); + free(req->ifcall.tattach.uname); + free(req->ifcall.tattach.aname); break; case TOpen: case TCreate: if(!error) { - r->ofcall.ropen.iounit = p9conn->rmsg.size - 24; - r->fid->iounit = r->ofcall.ropen.iounit; - r->fid->omode = r->ifcall.topen.mode; - r->fid->qid = r->ofcall.ropen.qid; + req->ofcall.ropen.iounit = p9conn->rmsg.size - 24; + req->fid->iounit = req->ofcall.ropen.iounit; + req->fid->omode = req->ifcall.topen.mode; + req->fid->qid = req->ofcall.ropen.qid; } - free(r->ifcall.tcreate.name); + free(req->ifcall.tcreate.name); break; case TWalk: - if(error || r->ofcall.rwalk.nwqid < r->ifcall.twalk.nwname) { - if(r->ifcall.hdr.fid != r->ifcall.twalk.newfid && r->newfid) - destroyfid(p9conn, r->newfid->fid); - if(!error && r->ofcall.rwalk.nwqid == 0) + if(error || req->ofcall.rwalk.nwqid < req->ifcall.twalk.nwname) { + if(req->ifcall.hdr.fid != req->ifcall.twalk.newfid && req->newfid) + destroyfid(p9conn, req->newfid->fid); + if(!error && req->ofcall.rwalk.nwqid == 0) error = Enofile; }else{ - if(r->ofcall.rwalk.nwqid == 0) - r->newfid->qid = r->fid->qid; + if(req->ofcall.rwalk.nwqid == 0) + req->newfid->qid = req->fid->qid; else - r->newfid->qid = r->ofcall.rwalk.wqid[r->ofcall.rwalk.nwqid-1]; + req->newfid->qid = req->ofcall.rwalk.wqid[req->ofcall.rwalk.nwqid-1]; } - free(*r->ifcall.twalk.wname); + free(*req->ifcall.twalk.wname); break; case TWrite: - free(r->ifcall.twrite.data); + free(req->ifcall.twrite.data); break; case TRemove: - if(r->fid) - destroyfid(p9conn, r->fid->fid); + if(req->fid) + destroyfid(p9conn, req->fid->fid); break; case TClunk: - if(r->fid) - destroyfid(p9conn, r->fid->fid); + if(req->fid) + destroyfid(p9conn, req->fid->fid); break; case TFlush: - if((r->oldreq = ixp_mapget(&p9conn->tagmap, r->ifcall.tflush.oldtag))) - respond(r->oldreq, Eintr); + if((req->oldreq = ixp_mapget(&p9conn->tagmap, req->ifcall.tflush.oldtag))) + ixp_respond(req->oldreq, Eintr); break; case TWStat: - ixp_freestat(&r->ifcall.twstat.stat); + ixp_freestat(&req->ifcall.twstat.stat); break; case TRead: case TStat: @@ -428,36 +449,37 @@ respond(Ixp9Req *r, const char *error) { /* Still to be implemented: auth */ } - r->ofcall.hdr.tag = r->ifcall.hdr.tag; + req->ofcall.hdr.tag = req->ifcall.hdr.tag; if(error == nil) - r->ofcall.hdr.type = r->ifcall.hdr.type + 1; + req->ofcall.hdr.type = req->ifcall.hdr.type + 1; else { - r->ofcall.hdr.type = RError; - r->ofcall.error.ename = (char*)error; + req->ofcall.hdr.type = RError; + req->ofcall.error.ename = (char*)error; } - ixp_printfcall(&r->ofcall); + if(ixp_printfcall) + ixp_printfcall(&req->ofcall); - ixp_maprm(&p9conn->tagmap, r->ifcall.hdr.tag);; + ixp_maprm(&p9conn->tagmap, req->ifcall.hdr.tag);; if(p9conn->conn) { thread->lock(&p9conn->wlock); - msize = ixp_fcall2msg(&p9conn->wmsg, &r->ofcall); + msize = ixp_fcall2msg(&p9conn->wmsg, &req->ofcall); if(ixp_sendmsg(p9conn->conn->fd, &p9conn->wmsg) != msize) ixp_hangup(p9conn->conn); thread->unlock(&p9conn->wlock); } - switch(r->ofcall.hdr.type) { + switch(req->ofcall.hdr.type) { case RStat: - free(r->ofcall.rstat.stat); + free(req->ofcall.rstat.stat); break; case RRead: - free(r->ofcall.rread.data); + free(req->ofcall.rread.data); break; } - free(r); + free(req); decref_p9conn(p9conn); } @@ -481,12 +503,12 @@ voidrequest(void *context, void *arg) { *(void**)context = flush_req; } -/* Clunk an open Fid */ +/* Clunk an open IxpFid */ static void voidfid(void *context, void *arg) { Ixp9Conn *p9conn; Ixp9Req *clunk_req; - Fid *fid; + IxpFid *fid; fid = arg; p9conn = fid->conn; @@ -524,8 +546,33 @@ cleanupconn(IxpConn *c) { } /* Handle incoming 9P connections */ +/** + * Type: Ixp9Srv + * Type: Ixp9Req + * Function: ixp_serve9conn + * + * The ixp_serve9conn handles incoming 9P connections. It is + * ordinarily passed as the P<read> member to F<ixp_listen> with an + * Ixp9Srv structure passed as the P<aux> member. The handlers + * defined in the Ixp9Srv structure are called whenever a matching + * Fcall type is received. The handlers are expected to call + * F<ixp_respond> at some point, whether before they return or at + * some undefined point in the future. Whenever a client + * disconnects, libixp generates whatever flush and clunk events are + * required to leave the connection in a clean state and waits for + * all responses before freeing the connections associated data + * structures. + * + * Whenever a file is closed and an T<IxpFid> is about to be freed, + * the P<freefid> member is called to perform any necessary cleanup + * and to free any associated resources. + * + * See also: + * F<ixp_listen>, F<ixp_respond>, F<ixp_printfcall>, + * F<IxpFcall>, F<IxpFid> + */ void -serve_9pcon(IxpConn *c) { +ixp_serve9conn(IxpConn *c) { Ixp9Conn *p9conn; int fd; diff --git a/lib/libixp/server.c b/lib/libixp/server.c @@ -17,19 +17,18 @@ * Params: * fs: The file descriptor on which to listen. * aux: A piece of data to store in the connection's - * S<IxpConn> data structure. - * read: The function to call when the connection has + * P<aux> member of the IxpConn data structure. + * read: The function called when the connection has * data available to read. - * close: A cleanup function to call when the + * close: A cleanup function called when the * connection is closed. * * Starts the server P<srv> listening on P<fd>. The optional - * callbacks are called as described, with the connections - * S<IxpConn> data structure as their arguments. + * P<read> and P<close> callbacks are called with the IxpConn + * structure for the connection as their sole argument. * * Returns: - * Returns the connection's new S<IxpConn> data - * structure. + * Returns the connection's new IxpConn data structure. */ IxpConn* ixp_listen(IxpServer *srv, int fd, void *aux, diff --git a/lib/libixp/srv_util.c b/lib/libixp/srv_util.c @@ -1,4 +1,4 @@ -/* Copyright ©2006-2010 Kris Maglione <fbsdaemon at gmail dot com> +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> * See LICENSE file for license details. */ #include <assert.h> @@ -24,14 +24,10 @@ struct IxpQueue { long len; }; -/* Macros */ -#define QID(t, i) (((vlong)((t)&0xFF)<<32)|((i)&0xFFFFFFFF)) +#define QID(t, i) (((int64_t)((t)&0xFF)<<32)|((i)&0xFFFFFFFF)) -/* Global Vars */ -/***************/ static IxpFileId* free_fileid; -/* Utility Functions */ /** * Function: ixp_srv_getfile * Type: IxpFileId @@ -104,6 +100,28 @@ ixp_srv_clonefiles(IxpFileId *fileid) { return r; } +/** + * Function: ixp_srv_readbuf + * Function: ixp_srv_writebuf + * + * Utility functions for handling TRead and TWrite requests for + * files backed by in-memory buffers. For both functions, P<buf> + * points to a buffer and P<len> specifies the length of the + * buffer. In the case of ixp_srv_writebuf, these values add a + * level of pointer indirection, and updates the values if they + * change. + * + * If P<max> has a value other than 0, ixp_srv_writebuf will + * truncate any writes to that point in the buffer. Otherwise, + * P<*buf> is assumed to be malloc(3) allocated, and is + * reallocated to fit the new data as necessary. The buffer is + * is always left nul-terminated. + * + * Bugs: + * ixp_srv_writebuf always truncates its buffer to the end + * of the most recent write. + */ + void ixp_srv_readbuf(Ixp9Req *req, char *buf, uint len) { @@ -176,6 +194,18 @@ ixp_srv_data2cstring(Ixp9Req *req) { req->ifcall.io.data = p; } +/** + * Function: ixp_srv_writectl + * + * This utility function is meant to simplify the writing of + * pseudo files to which single-lined commands are written. + * In order to use this function, the P<aux> member of + * P<req>->fid must be nul or an S<IxpFileId>. Each line of the + * written data is stripped of its trailing newline, + * nul-terminated, and stored in an S<IxpMsg>. For each line + * thus prepared, P<fn> is called with the IxpMsg pointer and + * the the P<p> member of the IxpFileId. + */ char* ixp_srv_writectl(Ixp9Req *req, char* (*fn)(void*, IxpMsg*)) { char *err, *s, *p, c; @@ -207,6 +237,41 @@ ixp_srv_writectl(Ixp9Req *req, char* (*fn)(void*, IxpMsg*)) { return err; } +/** + * Function: ixp_pending_write + * Function: ixp_pending_pushfid + * Function: ixp_pending_clunk + * Function: ixp_pending_flush + * Function: ixp_pending_respond + * Type: IxpPending + * + * These functions aid in writing virtual files used for + * broadcasting events or writing data when it becomes + * available. When a file to be used with these functions is + * opened, ixp_pending_pushfid should be called with its + * S<IxpFid> as an argument. This sets the IxpFid's P<pending> + * member to true. Thereafter, for each file with its + * P<pending> member set, ixp_pending_respond should be called + * for each TRead request, ixp_pending_clunk for each TClunk + * request, and ixp_pending_flush for each TFlush request. + * + * ixp_pending_write queues the data in P<dat> of length P<ndat> + * to be written to each currently pending fid in P<pending>. If + * there is a read request pending for a given fid, the data is + * written immediately. Otherwise, it is written the next time + * ixp_pending_respond is called. Likewise, if there is data + * queued when ixp_pending_respond is called, it is written + * immediately, otherwise the request is queued. + * + * The IxpPending data structure is opaque and should be + * initialized zeroed before using these functions for the first + * time. + * + * Returns: + * ixp_pending_clunk returns true if P<pending> has any + * more pending IxpFids. + */ + void ixp_pending_respond(Ixp9Req *req) { IxpFileId *file; @@ -228,7 +293,7 @@ ixp_pending_respond(Ixp9Req *req) { req_link->prev->next = req_link->next; free(req_link); } - respond(req, nil); + ixp_respond(req, nil); free(queue); }else { req_link = emallocz(sizeof *req_link); @@ -242,13 +307,13 @@ ixp_pending_respond(Ixp9Req *req) { } void -ixp_pending_write(IxpPending *pending, char *dat, long n) { +ixp_pending_write(IxpPending *pending, char *dat, long ndat) { IxpRequestLink req_link; IxpQueue **qp, *queue; IxpPendingLink *pp; IxpRequestLink *rp; - if(n == 0) + if(ndat == 0) return; if(pending->req.next == nil) { @@ -262,9 +327,9 @@ ixp_pending_write(IxpPending *pending, char *dat, long n) { for(qp=&pp->queue; *qp; qp=&qp[0]->link) ; queue = emallocz(sizeof *queue); - queue->dat = emalloc(n); - memcpy(queue->dat, dat, n); - queue->len = n; + queue->dat = emalloc(ndat); + memcpy(queue->dat, dat, ndat); + queue->len = ndat; *qp = queue; } @@ -348,7 +413,7 @@ ixp_pending_clunk(Ixp9Req *req) { req_link = req_link->next; if(r->fid == pend_link->fid) { pending_flush(r); - respond(r, "interrupted"); + ixp_respond(r, "interrupted"); } } @@ -362,10 +427,45 @@ ixp_pending_clunk(Ixp9Req *req) { } more = (pend_link->pending->fids.next == &pend_link->pending->fids); free(pend_link); - respond(req, nil); + ixp_respond(req, nil); return more; } +/** + * Function: ixp_srv_walkandclone + * Function: ixp_srv_readdir + * Function: ixp_srv_verifyfile + * Type: IxpLookupFn + * + * These convenience functions simplify the writing of basic and + * static file servers. They use a generic file lookup function + * to simplify the process of walking, cloning, and returning + * directory listings. Given the S<IxpFileId> of a directory and a + * filename name should return a new IxpFileId (allocated via + * F<ixp_srv_getfile>) for the matching directory entry, or null + * if there is no match. If the passed name is null, P<lookup> + * should return a linked list of IxpFileIds, one for each child + * directory entry. + * + * ixp_srv_walkandclone handles the moderately complex process + * of walking from a directory entry and cloning fids, and calls + * F<ixp_respond>. It should be called in response to a TWalk + * request. + * + * ixp_srv_readdir should be called to handle read requests on + * directories. It prepares a stat for each child of the + * directory, taking into account the requested offset, and + * calls F<ixp_respond>. The P<dostat> parameter must be a + * function which fills the passed S<IxpStat> pointer based on + * the contents of the passed IxpFileId. + * + * ixp_srv_verifyfile returns whether a file still exists in the + * filesystem, and should be used by filesystems that invalidate + * files once they have been deleted. + * + * See also: + * S<IxpFileId>, S<ixp_getfile>, S<ixp_freefile> + */ bool ixp_srv_verifyfile(IxpFileId *file, IxpLookupFn lookup) { IxpFileId *tfile; @@ -393,7 +493,7 @@ ixp_srv_readdir(Ixp9Req *req, IxpLookupFn lookup, void (*dostat)(IxpStat*, IxpFi IxpStat stat; char *buf; ulong size, n; - uvlong offset; + uint64_t offset; file = req->fid->aux; @@ -424,7 +524,7 @@ ixp_srv_readdir(Ixp9Req *req, IxpLookupFn lookup, void (*dostat)(IxpStat*, IxpFi } req->ofcall.io.count = msg.pos - msg.data; req->ofcall.io.data = msg.data; - respond(req, nil); + ixp_respond(req, nil); } void @@ -436,8 +536,8 @@ ixp_srv_walkandclone(Ixp9Req *req, IxpLookupFn lookup) { for(i=0; i < req->ifcall.twalk.nwname; i++) { if(!strcmp(req->ifcall.twalk.wname[i], "..")) { if(file->next) { - tfile=file; - file=file->next; + tfile = file; + file = file->next; ixp_srv_freefile(tfile); } }else{ @@ -459,7 +559,7 @@ ixp_srv_walkandclone(Ixp9Req *req, IxpLookupFn lookup) { file=file->next; ixp_srv_freefile(tfile); } - respond(req, Enofile); + ixp_respond(req, Enofile); return; } /* Remove refs for req->fid if no new fid */ @@ -473,6 +573,6 @@ ixp_srv_walkandclone(Ixp9Req *req, IxpLookupFn lookup) { }else req->newfid->aux = file; req->ofcall.rwalk.nwqid = i; - respond(req, nil); + ixp_respond(req, nil); } diff --git a/lib/libixp/timer.c b/lib/libixp/timer.c @@ -51,7 +51,7 @@ long ixp_settimer(IxpServer *srv, long msec, void (*fn)(long, void*), void *aux) { Timer **tp; Timer *t; - long time; + uint32_t time; time = ixp_msec(); if(time == -1) @@ -105,7 +105,7 @@ ixp_unsettimer(IxpServer *srv, long id) { return t != nil; } -/** +/* * Function: ixp_nexttimer * * Triggers any timers whose timeouts have ellapsed. This is @@ -121,7 +121,7 @@ ixp_unsettimer(IxpServer *srv, long id) { long ixp_nexttimer(IxpServer *srv) { Timer *t; - long time, ret; + uint32_t time, ret; SET(time); thread->lock(&srv->lk); diff --git a/lib/libixp/transport.c b/lib/libixp/transport.c @@ -49,6 +49,27 @@ readn(int fd, IxpMsg *msg, uint count) { return count - num; } +/** + * Function: ixp_sendmsg + * Function: ixp_recvmsg + * + * These functions read and write messages to and from the given + * file descriptors. + * + * ixp_sendmsg writes the data at P<msg>->pos upto P<msg>->end. + * If the call returns non-zero, all data is assured to have + * been written. + * + * ixp_recvmsg first reads a 32 bit, little-endian length from + * P<fd> and then reads a message of that length (including the + * 4 byte size specifier) into the buffer at P<msg>->data, so + * long as the size is less than P<msg>->size. + * + * Returns: + * These functions return the number of bytes read or + * written, or 0 on error. Errors are stored in + * F<ixp_errbuf>. + */ uint ixp_sendmsg(int fd, IxpMsg *msg) { int r; @@ -70,7 +91,7 @@ ixp_sendmsg(int fd, IxpMsg *msg) { uint ixp_recvmsg(int fd, IxpMsg *msg) { enum { SSize = 4 }; - ulong msize, size; + uint32_t msize, size; msg->mode = MsgUnpack; msg->pos = msg->data; diff --git a/lib/libixp/util.c b/lib/libixp/util.c @@ -11,6 +11,12 @@ #include <pwd.h> #include "ixp_local.h" +/** + * Function: ixp_smprint + * + * This function formats its arguments as F<printf> and returns + * a F<malloc> allocated string containing the result. + */ char* ixp_smprint(const char *fmt, ...) { va_list ap; @@ -125,8 +131,14 @@ ixp_namespace(void) { return namespace; } +/** + * Function: ixp_eprint + * + * libixp calls this function on error. It formats its arguments + * as F<printf> and exits the program. + */ void -eprint(const char *fmt, ...) { +ixp_eprint(const char *fmt, ...) { va_list ap; int err; @@ -170,8 +182,19 @@ mfatal(char *name, uint size) { exit(1); } +/** + * Function: ixp_emalloc + * Function: ixp_emallocz + * Function: ixp_erealloc + * Function: ixp_estrdup + * + * These functions act like their stdlib counterparts, but print + * an error message and exit the program if allocation fails. + * ixp_emallocz acts like ixp_emalloc but additionally zeros the + * result of the allocation. + */ void* -emalloc(uint size) { +ixp_emalloc(uint size) { void *ret = malloc(size); if(!ret) mfatal("malloc", size); @@ -179,14 +202,14 @@ emalloc(uint size) { } void* -emallocz(uint size) { +ixp_emallocz(uint size) { void *ret = emalloc(size); memset(ret, 0, size); return ret; } void* -erealloc(void *ptr, uint size) { +ixp_erealloc(void *ptr, uint size) { void *ret = realloc(ptr, size); if(!ret) mfatal("realloc", size); @@ -194,7 +217,7 @@ erealloc(void *ptr, uint size) { } char* -estrdup(const char *str) { +ixp_estrdup(const char *str) { void *ret = strdup(str); if(!ret) mfatal("strdup", strlen(str)); @@ -202,7 +225,7 @@ estrdup(const char *str) { } uint -tokenize(char *res[], uint reslen, char *str, char delim) { +ixp_tokenize(char *res[], uint reslen, char *str, char delim) { char *s; uint i; @@ -220,7 +243,7 @@ tokenize(char *res[], uint reslen, char *str, char delim) { } uint -strlcat(char *dst, const char *src, uint size) { +ixp_strlcat(char *dst, const char *src, uint size) { const char *s; char *d; int n, len; diff --git a/man/Ixp9Srv.3 b/man/Ixp9Srv.3 @@ -0,0 +1,72 @@ +.TH "IXP9SRV" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +Ixp9Srv, Ixp9Req, ixp_serve9conn + +.SH SYNOPSIS +.nf + #include <ixp.h> + + typedef struct Ixp9Srv Ixp9Srv; + struct Ixp9Srv { + void* aux; + void (*attach)(Ixp9Req*); + void (*clunk)(Ixp9Req*); + void (*create)(Ixp9Req*); + void (*flush)(Ixp9Req*); + void (*open)(Ixp9Req*); + void (*read)(Ixp9Req*); + void (*remove)(Ixp9Req*); + void (*stat)(Ixp9Req*); + void (*walk)(Ixp9Req*); + void (*write)(Ixp9Req*); + void (*wstat)(Ixp9Req*); + void (*freefid)(IxpFid*); + } + + typedef struct Ixp9Req Ixp9Req; + struct Ixp9Req { + Ixp9Srv* srv; + IxpFid* fid; /* Fid structure corresponding to IxpFHdr.fid */ + IxpFid* newfid; /* Corresponds to IxpFTWStat.newfid */ + Ixp9Req* oldreq; /* For TFlush requests, the original request. */ + IxpFcall ifcall; /* The incoming request fcall. */ + IxpFcall ofcall; /* The response fcall, to be filled by handler. */ + void* aux; /* Arbitrary pointer, to be used by handlers. */ + + /* Private members */ + ... + } + + void ixp_serve9conn(IxpConn *c); +.fi + +.SH DESCRIPTION +.P +The ixp_serve9conn handles incoming 9P connections. It is +ordinarily passed as the \fIread\fR member to \fBixp_listen(3)\fR with an +Ixp9Srv structure passed as the \fIaux\fR member. The handlers +defined in the Ixp9Srv structure are called whenever a matching +Fcall type is received. The handlers are expected to call +\fBixp_respond(3)\fR at some point, whether before they return or at +some undefined point in the future. Whenever a client +disconnects, libixp generates whatever flush and clunk events are +required to leave the connection in a clean state and waits for +all responses before freeing the connections associated data +structures. + +.P +Whenever a file is closed and an \fBIxpFid(3)\fR is about to be freed, +the \fIfreefid\fR member is called to perform any necessary cleanup +and to free any associated resources. + +.SH SEE ALSO +.P +ixp_listen(3), ixp_respond(3), ixp_printfcall(3), +IxpFcall(3), IxpFid(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- Ixp9Srv.man3 + diff --git a/man/IxpFcall.3 b/man/IxpFcall.3 @@ -0,0 +1,186 @@ +.TH "IXPFCALL" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +IxpFcall, IxpFType, IxpFAttach, IxpFError, IxpFHdr, IxpFIO, IxpFRAuth, IxpFROpen, IxpFRStat, IxpFRWalk, IxpFTCreate, IxpFTFlush, IxpFTWStat, IxpFTWalk, IxpFVersion + +.SH SYNOPSIS +.nf + #include <ixp.h> + + typedef struct IxpFcall IxpFcall; + typedef union IxpFcall IxpFcall; + union IxpFcall { + IxpFHdr hdr; + IxpFVersion version; + IxpFVersion tversion; + IxpFVersion rversion; + IxpFTFlush tflush; + IxpFROpen ropen; + IxpFROpen rcreate; + IxpFROpen rattach; + IxpFError error; + IxpFRAuth rauth; + IxpFAttach tattach; + IxpFAttach tauth; + IxpFTCreate tcreate; + IxpFTCreate topen; + IxpFTWalk twalk; + IxpFRWalk rwalk; + IxpFTWStat twstat; + IxpFRStat rstat; + IxpFIO twrite; + IxpFIO rwrite; + IxpFIO tread; + IxpFIO rread; + IxpFIO io; + } + + enum IxpFType { + P9_TVersion = 100, + P9_RVersion, + P9_TAuth = 102, + P9_RAuth, + P9_TAttach = 104, + P9_RAttach, + P9_TError = 106, /* illegal */ + P9_RError, + P9_TFlush = 108, + P9_RFlush, + P9_TWalk = 110, + P9_RWalk, + P9_TOpen = 112, + P9_ROpen, + P9_TCreate = 114, + P9_RCreate, + P9_TRead = 116, + P9_RRead, + P9_TWrite = 118, + P9_RWrite, + P9_TClunk = 120, + P9_RClunk, + P9_TRemove = 122, + P9_RRemove, + P9_TStat = 124, + P9_RStat, + P9_TWStat = 126, + P9_RWStat, + } + + typedef struct IxpFAttach IxpFAttach; + struct IxpFAttach { + IxpFHdr hdr; + uint32_t afid; + char* uname; + char* aname; + } + + typedef struct IxpFError IxpFError; + struct IxpFError { + IxpFHdr hdr; + char* ename; + } + + typedef struct IxpFHdr IxpFHdr; + struct IxpFHdr { + uint8_t type; + uint16_t tag; + uint32_t fid; + } + + typedef struct IxpFIO IxpFIO; + struct IxpFIO { + IxpFHdr hdr; + uint64_t offset; /* Tread, Twrite */ + uint32_t count; /* Tread, Twrite, Rread */ + char* data; /* Twrite, Rread */ + } + + typedef struct IxpFRAuth IxpFRAuth; + struct IxpFRAuth { + IxpFHdr hdr; + IxpQid aqid; + } + + typedef struct IxpFROpen IxpFROpen; + struct IxpFROpen { + IxpFHdr hdr; + IxpQid qid; /* +Rattach */ + uint32_t iounit; + } + + typedef struct IxpFRStat IxpFRStat; + struct IxpFRStat { + IxpFHdr hdr; + uint16_t nstat; + uchar* stat; + } + + typedef struct IxpFRWalk IxpFRWalk; + struct IxpFRWalk { + IxpFHdr hdr; + uint16_t nwqid; + IxpQid wqid\fI[IXP_MAX_WELEM]\fR; + } + + typedef struct IxpFTCreate IxpFTCreate; + struct IxpFTCreate { + IxpFHdr hdr; + uint32_t perm; + char* name; + uint8_t mode; /* +Topen */ + } + + typedef struct IxpFTFlush IxpFTFlush; + struct IxpFTFlush { + IxpFHdr hdr; + uint16_t oldtag; + } + + typedef struct IxpFTWStat IxpFTWStat; + struct IxpFTWStat { + IxpFHdr hdr; + IxpStat stat; + } + + typedef struct IxpFTWalk IxpFTWalk; + struct IxpFTWalk { + IxpFHdr hdr; + uint32_t newfid; + uint16_t nwname; + char* wname\fI[IXP_MAX_WELEM]\fR; + } + + typedef struct IxpFVersion IxpFVersion; + struct IxpFVersion { + IxpFHdr hdr; + uint32_t msize; + char* version; + } +.fi + +.SH DESCRIPTION +.P +The IxpFcall structure represents a 9P protocol message. The +\fIhdr\fR element is common to all Fcall types, and may be used to +determine the type and tag of the message. The IxpFcall type is +used heavily in server applications, where it both presents a +request to handler functions and returns a response to the +client. + +.P +Each member of the IxpFcall structure represents a certain +message type, which can be discerned from the \fIhdr.type\fR field. +This value corresponds to one of the IxpFType constants. Types +with significant overlap use the same structures, thus TRead and +RWrite are both represented by IxpFIO and can be accessed via the +\fIio\fR member as well as \fItread\fR and \fIrwrite\fR respectively. + +.SH SEE ALSO +.P +Ixp9Srv(3), Ixp9Req(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- IxpFcall.man3 + diff --git a/man/IxpFid.3 b/man/IxpFid.3 @@ -0,0 +1,41 @@ +.TH "IXPFID" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +IxpFid + +.SH SYNOPSIS +.nf + #include <ixp.h> + + typedef struct IxpFid IxpFid; + struct IxpFid { + char* uid; /* The uid of the file opener. */ + void* aux; /* Arbitrary pointer, to be used by handlers. */ + uint32_t fid; /* The ID number of the fid. */ + IxpQid qid; /* The filesystem-unique QID of the file. */ + signed char omode; /* The open mode of the file. */ + uint iounit; /* The maximum size of any IO request. */ + + /* Private members */ + ... + } +.fi + +.SH DESCRIPTION +.P +Represents an open file for a 9P connection. The same +structure persists as long as the file remains open, and is +installed in the \fBIxp9Req(3)\fR structure for any request Fcall +which references it. Handlers may use the \fIaux\fR member to +store any data which must persist for the life of the open +file. + +.SH SEE ALSO +.P +Ixp9Req(3), IxpQid(3), IxpOMode(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- IxpFid.man3 + diff --git a/man/IxpMsg.3 b/man/IxpMsg.3 @@ -0,0 +1,55 @@ +.TH "IXPMSG" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +IxpMsg, IxpMsgMode, ixp_message + +.SH SYNOPSIS +.nf + #include <ixp.h> + + typedef struct IxpMsg IxpMsg; + struct IxpMsg { + char* data; /* Begining of buffer. */ + char* pos; /* Current position in buffer. */ + char* end; /* End of message. */ + uint size; /* Size of buffer. */ + uint mode; /* MsgPack or MsgUnpack. */ + } + + enum IxpMsgMode { + MsgPack, + MsgUnpack, + } + + IxpMsg ixp_message(char *data, uint length, uint mode); +.fi + +.SH DESCRIPTION +.P +The IxpMsg struct represents a binary message, and is used +extensively by libixp for converting messages to and from +wire format. The location and size of a buffer are stored in +\fIdata\fR and \fIsize\fR, respectively. \fIpos\fR points to the +location in the message currently being packed or unpacked, +while \fIend\fR points to the end of the message. The packing +functions advance \fIpos\fR as they go, always ensuring that +they don't read or write past \fIend\fR. When a message is +entirely packed or unpacked, \fIpos\fR whould be less than or +equal to \fIend\fR. Any other state indicates error. + +.P +ixp_message is a convenience function to pack a construct an +IxpMsg from a buffer of a given \fIlength\fR and a given +\fImode\fR. \fIpos\fR and \fIdata\fR are set to \fIdata\fR and \fIend\fR is +set to \fIdata\fR + \fIlength\fR. + +.SH SEE ALSO +.P +ixp_pu8(3), ixp_pu16(3), ixp_pu32(3), ixp_pu64(3), +ixp_pstring(3), ixp_pstrings(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- IxpMsg.man3 + diff --git a/man/IxpThread.3 b/man/IxpThread.3 @@ -0,0 +1,81 @@ +.TH "IXPTHREAD" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +IxpThread, IxpMutex, IxpRWLock, IxpRendez, ixp_thread + +.SH SYNOPSIS +.nf + #include <ixp.h> + + typedef struct IxpThread IxpThread; + struct IxpThread { + /* Read/write lock */ + int (*initrwlock)(IxpRWLock*); + void (*rlock)(IxpRWLock*); + int (*canrlock)(IxpRWLock*); + void (*runlock)(IxpRWLock*); + void (*wlock)(IxpRWLock*); + int (*canwlock)(IxpRWLock*); + void (*wunlock)(IxpRWLock*); + void (*rwdestroy)(IxpRWLock*); + /* Mutex */ + int (*initmutex)(IxpMutex*); + void (*lock)(IxpMutex*); + int (*canlock)(IxpMutex*); + void (*unlock)(IxpMutex*); + void (*mdestroy)(IxpMutex*); + /* Rendezvous point */ + int (*initrendez)(IxpRendez*); + void (*sleep)(IxpRendez*); + int (*wake)(IxpRendez*); + int (*wakeall)(IxpRendez*); + void (*rdestroy)(IxpRendez*); + /* Other */ + char* (*errbuf)(void); + ssize_t (*read)(int, void*, size_t); + ssize_t (*write)(int, const void*, size_t); + int (*select)(int, fd_set*, fd_set*, fd_set*, struct timeval*); + } + + typedef struct IxpMutex IxpMutex; + struct IxpMutex { + void* aux; + } + + typedef struct IxpRWLock IxpRWLock; + struct IxpRWLock { + void* aux; + } + + typedef struct IxpRendez IxpRendez; + struct IxpRendez { + IxpMutex* mutex; + void* aux; + } + + IxpThread* ixp_thread; +.fi + +.SH DESCRIPTION +.P +The IxpThread structure is used to adapt libixp to any of the +myriad threading systems it may be used with. Before any +other of libixp's functions is called, ixp_thread may be set +to a structure filled with implementations of various locking +primitives, along with primitive IO functions which may +perform context switches until data is available. + +.P +The names of the functions should be fairly self\-explanitory. +Read/write locks should allow multiple readers and a single +writer of a shared resource, but should not allow new readers +while a writer is waitng for a lock. Mutexes should allow +only one accessor at a time. Rendezvous points are similar to +pthread condition types. \fIerrbuf\fR should return a +thread\-local buffer or the size IXP_ERRMAX. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- IxpThread.man3 + diff --git a/man/ixp_close.3 b/man/ixp_close.3 @@ -6,6 +6,8 @@ ixp_close .SH SYNOPSIS .nf + #include <ixp.h> + int ixp_close(IxpCFid *f); .fi diff --git a/man/ixp_dial.3 b/man/ixp_dial.3 @@ -6,6 +6,8 @@ ixp_dial, ixp_announce .SH SYNOPSIS .nf + #include <ixp.h> + int ixp_dial(const char *address); int ixp_announce(const char *address); diff --git a/man/ixp_emalloc.3 b/man/ixp_emalloc.3 @@ -0,0 +1,30 @@ +.TH "IXP_EMALLOC" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_emalloc, ixp_emallocz, ixp_erealloc, ixp_estrdup + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void *ixp_emalloc(uint size); + + void *ixp_emallocz(uint size); + + void *ixp_erealloc(void *ptr, uint size); + + char *ixp_estrdup(const char *str); +.fi + +.SH DESCRIPTION +.P +These functions act like their stdlib counterparts, but print +an error message and exit the program if allocation fails. +ixp_emallocz acts like ixp_emalloc but additionally zeros the +result of the allocation. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_emalloc.man3 + diff --git a/man/ixp_eprint.3 b/man/ixp_eprint.3 @@ -0,0 +1,22 @@ +.TH "IXP_EPRINT" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_eprint + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void ixp_eprint(const char *fmt, ...); +.fi + +.SH DESCRIPTION +.P +libixp calls this function on error. It formats its arguments +as \fBprintf(3)\fR and exits the program. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_eprint.man3 + diff --git a/man/ixp_errbuf.3 b/man/ixp_errbuf.3 @@ -2,17 +2,21 @@ .SH NAME .P -ixp_errbuf, ixp_errstr, ixp_rerrstr, ixp_werrstr +ixp_errbuf, ixp_errstr, ixp_rerrstr, ixp_werrstr, ixp_vsnprint .SH SYNOPSIS .nf + #include <ixp.h> + char *ixp_errbuf(void); - void ixp_errstr(char *buf, int size); + void ixp_errstr(char *buf, int nbuf); - void ixp_rerrstr(char *buf, int size); + void ixp_rerrstr(char *buf, int nbuf); void ixp_werrstr(const char *fmt, ...); + + int (*ixp_vsnprint)(char *buf, int nbuf, const char *fmt, va_list); .fi .SH PARAMETERS @@ -20,7 +24,7 @@ ixp_errbuf, ixp_errstr, ixp_rerrstr, ixp_werrstr buf The buffer to read and/or fill. .TP -size +nbuf The size of the buffer. .TP fmt @@ -41,13 +45,16 @@ thread. \fBixp_rerrstr(3)\fR fills \fIbuf\fR with the data from the current thread's error buffer, while \fBixp_errstr(3)\fR exchanges \fIbuf\fR's contents with those of the current thread's error buffer. \fBixp_werrstr(3)\fR formats the given -format string, \fIfmt\fR, via \fBixp_vsmprint(3)\fR and writes it to +format string, \fIfmt\fR, via \fBixp_vsnprint(3)\fR and writes it to the error buffer. -.SH RETURN VALUE .P -\fBixp_errbuf(3)\fR returns the current thread's error -string buffer. +\fBixp_vsnprint(3)\fR may be set to a function which will format +its arguments write the result to the \fInbuf\fR length buffer +\fBbuf(3)\fR. The default value is \fBvsnprintf(3)\fR. The function must +format '%s' as a nul\-terminated string and may not consume +any arguments not indicated by a %\-prefixed format specifier, +but may otherwise behave in any manner chosen by the user. .SH SEE ALSO .P diff --git a/man/ixp_fcall2msg.3 b/man/ixp_fcall2msg.3 @@ -0,0 +1,34 @@ +.TH "IXP_FCALL2MSG" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_fcall2msg, ixp_msg2fcall + +.SH SYNOPSIS +.nf + #include <ixp.h> + + uint ixp_fcall2msg(IxpMsg *msg, Fcall *fcall); + + uint ixp_msg2fcall(IxpMsg *msg, Fcall *fcall); +.fi + +.SH DESCRIPTION +.P +These functions pack or unpack a 9P protocol message. The +message is set to the appropriate mode and its position is +set to the begining of its buffer. + +.SH RETURN VALUE +.P +These functions return the size of the message on +success and 0 on failure. + +.SH SEE ALSO +.P +IxpMsg(3), ixp_pfcall(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_fcall2msg.man3 + diff --git a/man/ixp_freestat.3 b/man/ixp_freestat.3 @@ -0,0 +1,25 @@ +.TH "IXP_FREESTAT" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_freestat, ixp_freefcall + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void ixp_freestat(Stat *s); + + void ixp_freefcall(Fcall *fcall); +.fi + +.SH DESCRIPTION +.P +These functions free malloc(3) allocated data in the members +of the passed structures and set those members to nil. They +do not free the structures themselves. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_freestat.man3 + diff --git a/man/ixp_hangup.3 b/man/ixp_hangup.3 @@ -6,6 +6,8 @@ ixp_hangup, ixp_server_close .SH SYNOPSIS .nf + #include <ixp.h> + void ixp_hangup(IxpConn *c); void ixp_server_close(IxpServer *s); diff --git a/man/ixp_listen.3 b/man/ixp_listen.3 @@ -6,16 +6,18 @@ ixp_listen, IxpConn .SH SYNOPSIS .nf + #include <ixp.h> + IxpConn *ixp_listen(IxpServer *srv, int fd, void *aux, void (*read)(IxpConn *), void (*close)(IxpConn *)); typedef struct IxpConn IxpConn; struct IxpConn { IxpServer* srv; - void* aux; - int fd; + void* aux; /* Arbitrary pointer, to be used by handlers. */ + int fd; /* The file descriptor of the connection. */ void (*read)(IxpConn *); void (*close)(IxpConn *); - char closed; + char closed; /* Non-zero when //fd// has been closed. */ /* Private members */ ... @@ -29,26 +31,25 @@ The file descriptor on which to listen. .TP aux A piece of data to store in the connection's -\fBIxpConn(3)\fR data structure. +\fIaux\fR member of the IxpConn data structure. .TP read -The function to call when the connection has +The function called when the connection has data available to read. .TP close -A cleanup function to call when the +A cleanup function called when the connection is closed. .SH DESCRIPTION .P Starts the server \fIsrv\fR listening on \fIfd\fR. The optional -callbacks are called as described, with the connections -\fBIxpConn(3)\fR data structure as their arguments. +\fIread\fR and \fIclose\fR callbacks are called with the IxpConn +structure for the connection as their sole argument. .SH RETURN VALUE .P -Returns the connection's new \fBIxpConn(3)\fR data -structure. +Returns the connection's new IxpConn data structure. .\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) diff --git a/man/ixp_mount.3 b/man/ixp_mount.3 @@ -6,6 +6,8 @@ ixp_mount, ixp_mountfd, ixp_nsmount, IxpClient .SH SYNOPSIS .nf + #include <ixp.h> + IxpClient *ixp_mount(const char *address); IxpClient *ixp_mountfd(int fd); diff --git a/man/ixp_msec.3 b/man/ixp_msec.3 @@ -6,6 +6,8 @@ ixp_msec .SH SYNOPSIS .nf + #include <ixp.h> + long ixp_msec(void); .fi diff --git a/man/ixp_namespace.3 b/man/ixp_namespace.3 @@ -6,6 +6,8 @@ ixp_namespace .SH SYNOPSIS .nf + #include <ixp.h> + char *ixp_namespace(void); .fi diff --git a/man/ixp_nexttimer.3 b/man/ixp_nexttimer.3 @@ -1,30 +0,0 @@ -.TH "IXP_NEXTTIMER" 3 "2010 Jun" "libixp Manual" - -.SH NAME -.P -ixp_nexttimer - -.SH SYNOPSIS -.nf - long ixp_nexttimer(IxpServer *srv); -.fi - -.SH DESCRIPTION -.P -Triggers any timers whose timeouts have ellapsed. This is -primarily intended to be called from libixp's select -loop. - -.SH RETURN VALUE -.P -Returns the number of milliseconds until the next -timer's timeout. - -.SH SEE ALSO -.P -ixp_settimer(3), ixp_serverloop(3) - - -.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) -.\" cmdline: txt2tags -o- ixp_nexttimer.man3 - diff --git a/man/ixp_open.3 b/man/ixp_open.3 @@ -6,18 +6,20 @@ ixp_open, ixp_create, IxpCFid, IxpOMode .SH SYNOPSIS .nf + #include <ixp.h> + IxpCFid *ixp_open(IxpClient *c, const char *path, uchar mode); IxpCFid *ixp_create(IxpClient *c, const char *path, uint perm, uchar mode); typedef struct IxpCFid IxpCFid; struct IxpCFid { - uint fid; + uint32_t fid; IxpQid qid; - uchar mode; + uint8_t mode; uint open; uint iounit; - uvlong offset; + uint32_t offset; IxpClient* client; /* Private members */ diff --git a/man/ixp_pdata.3 b/man/ixp_pdata.3 @@ -0,0 +1,35 @@ +.TH "IXP_PDATA" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_pdata + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void ixp_pdata(IxpMsg *msg, char **data, uint len); +.fi + +.SH DESCRIPTION +.P +Packs or unpacks a raw character buffer of size \fIlen\fR. + +.P +If \fImsg\fR\->mode is MsgPack, buffer pointed to by \fIdata\fR is +packed into the buffer at \fImsg\fR\->pos. If \fImsg\fR\->mode is +MsgUnpack, the address pointed to by \fIs\fR is loaded with a +malloc(3) allocated buffer with the contents of the buffer at +\fImsg\fR\->pos. In either case, \fImsg\fR\->pos is advanced by the +number of bytes read or written. If the action would advance +\fImsg\fR\->pos beyond \fImsg\fR\->end, \fImsg\fR\->pos is still advanced +but no other action is taken. + +.SH SEE ALSO +.P +IxpMsg(3), ixp_pstring(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_pdata.man3 + diff --git a/man/ixp_pending_write.3 b/man/ixp_pending_write.3 @@ -0,0 +1,62 @@ +.TH "IXP_PENDING_WRITE" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_pending_write, ixp_pending_pushfid, ixp_pending_clunk, ixp_pending_flush, ixp_pending_respond, IxpPending + +.SH SYNOPSIS +.nf + #include <ixp_srvutil.h> + + void ixp_pending_write(IxpPending *pending, char *dat, long ndat); + + void ixp_pending_pushfid(IxpPending *pending, Fid *fid); + + bool ixp_pending_clunk(Ixp9Req *req); + + void ixp_pending_flush(Ixp9Req *req); + + void ixp_pending_respond(Ixp9Req *req); + + typedef struct IxpPending IxpPending; + struct IxpPending { + /* Private members */ + ... + } +.fi + +.SH DESCRIPTION +.P +These functions aid in writing virtual files used for +broadcasting events or writing data when it becomes +available. When a file to be used with these functions is +opened, ixp_pending_pushfid should be called with its +\fBIxpFid(3)\fR as an argument. This sets the IxpFid's \fIpending\fR +member to true. Thereafter, for each file with its +\fIpending\fR member set, ixp_pending_respond should be called +for each TRead request, ixp_pending_clunk for each TClunk +request, and ixp_pending_flush for each TFlush request. + +.P +ixp_pending_write queues the data in \fIdat\fR of length \fIndat\fR +to be written to each currently pending fid in \fIpending\fR. If +there is a read request pending for a given fid, the data is +written immediately. Otherwise, it is written the next time +ixp_pending_respond is called. Likewise, if there is data +queued when ixp_pending_respond is called, it is written +immediately, otherwise the request is queued. + +.P +The IxpPending data structure is opaque and should be +initialized zeroed before using these functions for the first +time. + +.SH RETURN VALUE +.P +ixp_pending_clunk returns true if \fIpending\fR has any +more pending IxpFids. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_pending_write.man3 + diff --git a/man/ixp_pfcall.3 b/man/ixp_pfcall.3 @@ -0,0 +1,43 @@ +.TH "IXP_PFCALL" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_pfcall, ixp_pqid, ixp_pqids, ixp_pstat, ixp_sizeof_stat + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void ixp_pfcall(IxpMsg *msg, Fcall *fcall); + + void ixp_pqid(IxpMsg *msg, Qid *qid); + + void ixp_pqids(IxpMsg *msg, uint16_t *num, Qid qid\fI[]\fR, uint max); + + void ixp_pstat(IxpMsg *msg, Stat *stat); + + uint16_t ixp_sizeof_stat(Stat *stat); +.fi + +.SH DESCRIPTION +.P +These convenience functions pack or unpack the contents of +libixp structures into their wire format. They behave as if +\fBixp_pu8(3)\fR, \fBixp_pu16(3)\fR, \fBixp_pu32(3)\fR, \fBixp_pu64(3)\fR, and +\fBixp_pstring(3)\fR were called for each member of the structure +in question. ixp_pqid is to ixp_pqid as \fBixp_pstrings(3)\fR is to +ixp_pstring. + +.P +ixp_sizeof_stat returns the size of the packed represention +of \fIstat\fR. + +.SH SEE ALSO +.P +IxpMsg(3), ixp_pu8(3), ixp_pu16(3), ixp_pu32(3), +ixp_pu64(3), ixp_pstring(3), ixp_pstrings(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_pfcall.man3 + diff --git a/man/ixp_print.3 b/man/ixp_print.3 @@ -0,0 +1,57 @@ +.TH "IXP_PRINT" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_print, ixp_vprint, ixp_vsmprint + +.SH SYNOPSIS +.nf + #include <ixp.h> + + int ixp_print(IxpCFid *fid, const char *fmt, ...); + + int ixp_vprint(IxpCFid *fid, const char *fmt, va_list args); + + char* (*ixp_vsmprint)(const char *fmt, va_list); +.fi + +.SH PARAMETERS +.TP +fid +An open IxpCFid to which to write the result. +.TP +fmt +The string with which to format the data. +.TP +args +A va_list holding the arguments to the format +string. +.TP +.RB ... +The arguments to the format string. + +.SH DESCRIPTION +.P +These functions act like the standard formatted IO +functions. They write the result of the formatting to the +file pointed to by C<fid>. + +.P +\fBixp_vsmprint(3)\fR may be set to a function which will +format its arguments and return a nul\-terminated string +allocated by malloc(3). The default formats its arguments as +printf(3). + +.SH RETURN VALUE +.P +These functions return the number of bytes written. +There is currently no way to detect failure. + +.SH SEE ALSO +.P +ixp_mount(3), ixp_open(3), printf(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_print.man3 + diff --git a/man/ixp_printfcall.3 b/man/ixp_printfcall.3 @@ -0,0 +1,28 @@ +.TH "IXP_PRINTFCALL" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_printfcall + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void (*ixp_printfcall)(IxpFcall*); +.fi + +.SH DESCRIPTION +.P +When set to a non\-null value, ixp_printfcall is called once for +every incoming and outgoing Fcall. It is intended to simplify the +writing of debugging code for clients, but may be used for any +arbitrary purpose. + +.SH SEE ALSO +.P +ixp_respond(3), ixp_serve9conn(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_printfcall.man3 + diff --git a/man/ixp_pstring.3 b/man/ixp_pstring.3 @@ -0,0 +1,38 @@ +.TH "IXP_PSTRING" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_pstring + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void ixp_pstring(IxpMsg *msg, char **s); +.fi + +.SH DESCRIPTION +.P +Packs or unpacks a UTF\-8 encoded string. The packed +representation of the string consists of a 16\-bit unsigned +integer followed by the contents of the string. The unpacked +representation is a nul\-terminated character array. + +.P +If \fImsg\fR\->mode is MsgPack, the string pointed to by \fIs\fR is +packed into the buffer at \fImsg\fR\->pos. If \fImsg\fR\->mode is +MsgUnpack, the address pointed to by \fIs\fR is loaded with a +malloc(3) allocated, nul\-terminated representation of the +string packed at \fImsg\fR\->pos. In either case, \fImsg\fR\->pos is +advanced by the number of bytes read or written. If the +action would advance \fImsg\fR\->pos beyond \fImsg\fR\->end, +\fImsg\fR\->pos is still advanced but no other action is taken. + +.SH SEE ALSO +.P +IxpMsg(3), ixp_pstrings(3), ixp_pdata(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_pstring.man3 + diff --git a/man/ixp_pstrings.3 b/man/ixp_pstrings.3 @@ -0,0 +1,42 @@ +.TH "IXP_PSTRINGS" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_pstrings + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void ixp_pstrings(IxpMsg *msg, uint16_t *num, char *strings\fI[]\fR, uint max); +.fi + +.SH DESCRIPTION +.P +Packs or unpacks an array of UTF\-8 encoded strings. The packed +representation consists of a 16\-bit element count followed by +an array of strings as packed by \fBixp_pstring(3)\fR. The unpacked +representation is an array of nul\-terminated character arrays. + +.P +If \fImsg\fR\->mode is MsgPack, \fI*num\fR strings in the array +pointed to by \fIstrings\fR are packed into the buffer at +\fImsg\fR\->pos. If \fImsg\fR\->mode is MsgUnpack, \fI*num\fR is loaded +with the number of strings unpacked, the array at +\fI*strings\fR is loaded with pointers to the unpacked strings, +and \fI(*strings)\fI[0]\fR\fR must be freed by the user. In either +case, \fImsg\fR\->pos is advanced by the number of bytes read or +written. If the action would advance \fImsg\fR\->pos beyond +\fImsg\fR\->end, \fImsg\fR\->pos is still advanced, but no other +action is taken. If \fI*num\fR is greater than \fImax\fR, +\fImsg\fR\->pos is set beyond \fImsg\fR\->end and no other action is +taken. + +.SH SEE ALSO +.P +\fIIxpMsg\fR, \fIixp_pstring\fR, \fIixp_pdata\fR + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_pstrings.man3 + diff --git a/man/ixp_pu8.3 b/man/ixp_pu8.3 @@ -0,0 +1,41 @@ +.TH "IXP_PU8" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_pu8, ixp_pu16, ixp_pu32, ixp_pu64 + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void ixp_pu8(IxpMsg *msg, uchar *val); + + void ixp_pu16(IxpMsg *msg, uint16_t *val); + + void ixp_pu32(IxpMsg *msg, uint32_t *val); + + void ixp_pu64(IxpMsg *msg, uint64_t *val); +.fi + +.SH DESCRIPTION +.P +These functions pack or unpack an unsigned integer of the +specified size. + +.P +If \fImsg\fR\->mode is MsgPack, the value pointed to by \fIval\fR is +packed into the buffer at \fImsg\fR\->pos. If \fImsg\fR\->mode is +MsgUnpack, the packed value at \fImsg\fR\->pos is loaded into the +location pointed to by \fIval\fR. In both cases, \fImsg\fR\->pos is +advanced by the number of bytes read or written. If the call +would advance \fImsg\fR\->pos beyond \fImsg\fR\->end, \fImsg\fR\->pos is +advanced, but nothing is modified. + +.SH SEE ALSO +.P +IxpMsg(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_pu8.man3 + diff --git a/man/ixp_read.3 b/man/ixp_read.3 @@ -6,9 +6,11 @@ ixp_read, ixp_pread .SH SYNOPSIS .nf + #include <ixp.h> + long ixp_read(IxpCFid *fid, void *buf, long count); - long ixp_pread(IxpCFid *fid, void *buf, long count, vlong offset); + long ixp_pread(IxpCFid *fid, void *buf, long count, int64_t offset); .fi .SH PARAMETERS diff --git a/man/ixp_remove.3 b/man/ixp_remove.3 @@ -6,6 +6,8 @@ ixp_remove .SH SYNOPSIS .nf + #include <ixp.h> + int ixp_remove(IxpClient *c, const char *path); .fi diff --git a/man/ixp_respond.3 b/man/ixp_respond.3 @@ -0,0 +1,30 @@ +.TH "IXP_RESPOND" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_respond + +.SH SYNOPSIS +.nf + #include <ixp.h> + + void ixp_respond(Ixp9Req *req, const char *error); +.fi + +.SH DESCRIPTION +.P +Sends a response to the given request. The response is +constructed from the \fIofcall\fR member of the \fIreq\fR parameter, or +from the \fIerror\fR parameter if it is non\-null. In the latter +case, the response is of type RError, while in any other case it +is of the same type as \fIreq\fR\->\fIofcall\fR, which must match the +request type in \fIreq\fR\->\fIifcall\fR. + +.SH SEE ALSO +.P +Ixp9Req(3), ixp_printfcall(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_respond.man3 + diff --git a/man/ixp_sendmsg.3 b/man/ixp_sendmsg.3 @@ -0,0 +1,41 @@ +.TH "IXP_SENDMSG" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_sendmsg, ixp_recvmsg + +.SH SYNOPSIS +.nf + #include <ixp.h> + + uint ixp_sendmsg(int fd, IxpMsg *msg); + + uint ixp_recvmsg(int fd, IxpMsg *msg); +.fi + +.SH DESCRIPTION +.P +These functions read and write messages to and from the given +file descriptors. + +.P +ixp_sendmsg writes the data at \fImsg\fR\->pos upto \fImsg\fR\->end. +If the call returns non\-zero, all data is assured to have +been written. + +.P +ixp_recvmsg first reads a 32 bit, little\-endian length from +\fIfd\fR and then reads a message of that length (including the +4 byte size specifier) into the buffer at \fImsg\fR\->data, so +long as the size is less than \fImsg\fR\->size. + +.SH RETURN VALUE +.P +These functions return the number of bytes read or +written, or 0 on error. Errors are stored in +\fBixp_errbuf(3)\fR. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_sendmsg.man3 + diff --git a/man/ixp_serverloop.3 b/man/ixp_serverloop.3 @@ -6,6 +6,8 @@ ixp_serverloop, IxpServer .SH SYNOPSIS .nf + #include <ixp.h> + int ixp_serverloop(IxpServer *srv); typedef struct IxpServer IxpServer; diff --git a/man/ixp_settimer.3 b/man/ixp_settimer.3 @@ -6,6 +6,8 @@ ixp_settimer .SH SYNOPSIS .nf + #include <ixp.h> + long ixp_settimer(IxpServer *srv, long msec, void (*fn)(long, void *), void *aux); .fi diff --git a/man/ixp_smprint.3 b/man/ixp_smprint.3 @@ -0,0 +1,22 @@ +.TH "IXP_SMPRINT" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_smprint + +.SH SYNOPSIS +.nf + #include <ixp.h> + + char *ixp_smprint(const char *fmt, ...); +.fi + +.SH DESCRIPTION +.P +This function formats its arguments as \fBprintf(3)\fR and returns +a \fBmalloc(3)\fR allocated string containing the result. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_smprint.man3 + diff --git a/man/ixp_srv_clonefiles.3 b/man/ixp_srv_clonefiles.3 @@ -6,6 +6,8 @@ ixp_srv_clonefiles .SH SYNOPSIS .nf + #include <ixp_srvutil.h> + IxpFileId *ixp_srv_clonefiles(IxpFileId *fileid); .fi diff --git a/man/ixp_srv_data2cstring.3 b/man/ixp_srv_data2cstring.3 @@ -6,6 +6,8 @@ ixp_srv_data2cstring .SH SYNOPSIS .nf + #include <ixp_srvutil.h> + void ixp_srv_data2cstring(Ixp9Req *req); .fi diff --git a/man/ixp_srv_freefile.3 b/man/ixp_srv_freefile.3 @@ -6,6 +6,8 @@ ixp_srv_freefile .SH SYNOPSIS .nf + #include <ixp_srvutil.h> + void ixp_srv_freefile(IxpFileId *fileid); .fi diff --git a/man/ixp_srv_getfile.3 b/man/ixp_srv_getfile.3 @@ -6,6 +6,8 @@ ixp_srv_getfile, IxpFileId .SH SYNOPSIS .nf + #include <ixp_srvutil.h> + IxpFileId *ixp_srv_getfile(void); typedef struct IxpFileId IxpFileId; @@ -16,7 +18,7 @@ ixp_srv_getfile, IxpFileId uint id; uint index; IxpDirtab tab; - ushort nref; + uint nref; uchar volatil; } .fi diff --git a/man/ixp_srv_readbuf.3 b/man/ixp_srv_readbuf.3 @@ -0,0 +1,40 @@ +.TH "IXP_SRV_READBUF" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_srv_readbuf, ixp_srv_writebuf + +.SH SYNOPSIS +.nf + #include <ixp_srvutil.h> + + void ixp_srv_readbuf(Ixp9Req *req, char *buf, uint len); + + void ixp_srv_writebuf(Ixp9Req *req, char **buf, uint *len, uint max); +.fi + +.SH DESCRIPTION +.P +Utility functions for handling TRead and TWrite requests for +files backed by in\-memory buffers. For both functions, \fIbuf\fR +points to a buffer and \fIlen\fR specifies the length of the +buffer. In the case of ixp_srv_writebuf, these values add a +level of pointer indirection, and updates the values if they +change. + +.P +If \fImax\fR has a value other than 0, ixp_srv_writebuf will +truncate any writes to that point in the buffer. Otherwise, +\fI*buf\fR is assumed to be malloc(3) allocated, and is +reallocated to fit the new data as necessary. The buffer is +is always left nul\-terminated. + +.SH BUGS +.P +ixp_srv_writebuf always truncates its buffer to the end +of the most recent write. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_srv_readbuf.man3 + diff --git a/man/ixp_srv_walkandclone.3 b/man/ixp_srv_walkandclone.3 @@ -0,0 +1,58 @@ +.TH "IXP_SRV_WALKANDCLONE" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_srv_walkandclone, ixp_srv_readdir, ixp_srv_verifyfile, IxpLookupFn + +.SH SYNOPSIS +.nf + #include <ixp_srvutil.h> + + void ixp_srv_walkandclone(Ixp9Req *req, IxpLookupFn lookup); + + void ixp_srv_readdir(Ixp9Req *req, IxpLookupFn lookup, void (*dostat)(Stat *, IxpFileId *)); + + bool ixp_srv_verifyfile(IxpFileId *file, IxpLookupFn lookup); + + typedef IxpFileId* (*IxpLookupFn)(IxpFileId*, char*); +.fi + +.SH DESCRIPTION +.P +These convenience functions simplify the writing of basic and +static file servers. They use a generic file lookup function +to simplify the process of walking, cloning, and returning +directory listings. Given the \fBIxpFileId(3)\fR of a directory and a +filename name should return a new IxpFileId (allocated via +\fBixp_srv_getfile(3)\fR) for the matching directory entry, or null +if there is no match. If the passed name is null, \fIlookup\fR +should return a linked list of IxpFileIds, one for each child +directory entry. + +.P +ixp_srv_walkandclone handles the moderately complex process +of walking from a directory entry and cloning fids, and calls +\fBixp_respond(3)\fR. It should be called in response to a TWalk +request. + +.P +ixp_srv_readdir should be called to handle read requests on +directories. It prepares a stat for each child of the +directory, taking into account the requested offset, and +calls \fBixp_respond(3)\fR. The \fIdostat\fR parameter must be a +function which fills the passed \fBIxpStat(3)\fR pointer based on +the contents of the passed IxpFileId. + +.P +ixp_srv_verifyfile returns whether a file still exists in the +filesystem, and should be used by filesystems that invalidate +files once they have been deleted. + +.SH SEE ALSO +.P +IxpFileId(3), ixp_getfile(3), ixp_freefile(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_srv_walkandclone.man3 + diff --git a/man/ixp_srv_writectl.3 b/man/ixp_srv_writectl.3 @@ -0,0 +1,28 @@ +.TH "IXP_SRV_WRITECTL" 3 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_srv_writectl + +.SH SYNOPSIS +.nf + #include <ixp_srvutil.h> + + char *ixp_srv_writectl(Ixp9Req *req, char *(*fn)(void *, IxpMsg *)); +.fi + +.SH DESCRIPTION +.P +This utility function is meant to simplify the writing of +pseudo files to which single\-lined commands are written. +In order to use this function, the \fIaux\fR member of +\fIreq\fR\->fid must be nul or an \fBIxpFileId(3)\fR. Each line of the +written data is stripped of its trailing newline, +nul\-terminated, and stored in an \fBIxpMsg(3)\fR. For each line +thus prepared, \fIfn\fR is called with the IxpMsg pointer and +the the \fIp\fR member of the IxpFileId. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_srv_writectl.man3 + diff --git a/man/ixp_stat.3 b/man/ixp_stat.3 @@ -6,19 +6,21 @@ ixp_stat, ixp_fstat, IxpStat, IxpQid, IxpQType, IxpDMode .SH SYNOPSIS .nf + #include <ixp.h> + Stat *ixp_stat(IxpClient *c, const char *path); Stat *ixp_fstat(IxpCFid *fid); typedef struct IxpStat IxpStat; struct IxpStat { - ushort type; - ulong dev; - IxpQid qid; - ulong mode; - ulong atime; - ulong mtime; - uvlong length; + uint16_t type; + uint32_t dev; + IxpQid qid; + uint32_t mode; + uint32_t atime; + uint32_t mtime; + uint64_t length; char* name; char* uid; char* gid; @@ -27,9 +29,9 @@ ixp_stat, ixp_fstat, IxpStat, IxpQid, IxpQType, IxpDMode typedef struct IxpQid IxpQid; struct IxpQid { - uchar type; - ulong version; - uvlong path; + uint8_t type; + uint32_t version; + uint64_t path; /* Private members */ ... } diff --git a/man/ixp_unmount.3 b/man/ixp_unmount.3 @@ -6,6 +6,8 @@ ixp_unmount .SH SYNOPSIS .nf + #include <ixp.h> + void ixp_unmount(IxpClient *client); .fi diff --git a/man/ixp_unsettimer.3 b/man/ixp_unsettimer.3 @@ -6,6 +6,8 @@ ixp_unsettimer .SH SYNOPSIS .nf + #include <ixp.h> + int ixp_unsettimer(IxpServer *srv, long id); .fi diff --git a/man/ixp_vprint.3 b/man/ixp_vprint.3 @@ -1,57 +0,0 @@ -.TH "IXP_VPRINT" 3 "2010 Jun" "libixp Manual" - -.SH NAME -.P -ixp_vprint, ixp_print, ixp_vsmprint - -.SH SYNOPSIS -.nf - ixp_vprint - - int ixp_print(IxpCFid *fid, const char *fmt, ...); - - ixp_vsmprint -.fi - -.SH PARAMETERS -.TP -fid -An open IxpCFid to which to write the result. -.TP -fmt -The string with which to format the data. -.TP -args -A va_list holding the arguments to the format -string. -.TP -.RB ... -The arguments to the format string. - -.SH DESCRIPTION -.P -These functions act like the standard formatted IO -functions. They write the result of the formatting to the -file pointed to by C<fid>. - -.P -\fBixp_vsmprint(3)\fR may be set to a function which will -format its arguments and return a nul\-terminated string -allocated by malloc(3). The default formats its arguments as -printf(3). The function must format '%s' as a nul\-terminated -string and may not consume any arguments not specified by a -manner chosen by the user. - -.SH RETURN VALUE -.P -These functions return the number of bytes written. -There is currently no way to detect failure. - -.SH SEE ALSO -.P -ixp_mount(3), ixp_open(3), printf(3) - - -.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) -.\" cmdline: txt2tags -o- ixp_vprint.man3 - diff --git a/man/ixp_write.3 b/man/ixp_write.3 @@ -6,9 +6,11 @@ ixp_write, ixp_pwrite .SH SYNOPSIS .nf + #include <ixp.h> + long ixp_write(IxpCFid *fid, const void *buf, long count); - long ixp_pwrite(IxpCFid *fid, const void *buf, long count, vlong offset); + long ixp_pwrite(IxpCFid *fid, const void *buf, long count, int64_t offset); .fi .SH PARAMETERS diff --git a/man/targets.mk b/man/targets.mk @@ -1,4 +1,7 @@ MANPAGES = \ + 'IxpFcall.3 IxpFType.3 IxpFAttach.3 IxpFError.3 IxpFHdr.3 IxpFIO.3 IxpFRAuth.3 IxpFROpen.3 IxpFRStat.3 IxpFRWalk.3 IxpFTCreate.3 IxpFTFlush.3 IxpFTWStat.3 IxpFTWalk.3 IxpFVersion.3' \ + 'IxpFid.3' \ + 'IxpThread.3 IxpMutex.3 IxpRWLock.3 IxpRendez.3 ixp_thread.3' \ 'ixp_unmount.3' \ 'ixp_mount.3 ixp_mountfd.3 ixp_nsmount.3 IxpClient.3' \ 'ixp_remove.3' \ @@ -7,8 +10,19 @@ MANPAGES = \ 'ixp_stat.3 ixp_fstat.3 IxpStat.3 IxpQid.3 IxpQType.3 IxpDMode.3' \ 'ixp_read.3 ixp_pread.3' \ 'ixp_write.3 ixp_pwrite.3' \ - 'ixp_vprint.3 ixp_print.3 ixp_vsmprint.3' \ - 'ixp_errbuf.3 ixp_errstr.3 ixp_rerrstr.3 ixp_werrstr.3' \ + 'ixp_print.3 ixp_vprint.3 ixp_vsmprint.3' \ + 'ixp_pu8.3 ixp_pu16.3 ixp_pu32.3 ixp_pu64.3' \ + 'ixp_pstring.3' \ + 'ixp_pstrings.3' \ + 'ixp_pdata.3' \ + 'ixp_pfcall.3 ixp_pqid.3 ixp_pqids.3 ixp_pstat.3 ixp_sizeof_stat.3' \ + 'ixp_errbuf.3 ixp_errstr.3 ixp_rerrstr.3 ixp_werrstr.3 ixp_vsnprint.3' \ + 'IxpMsg.3 IxpMsgMode.3 ixp_message.3' \ + 'ixp_freestat.3 ixp_freefcall.3' \ + 'ixp_fcall2msg.3 ixp_msg2fcall.3' \ + 'ixp_printfcall.3' \ + 'ixp_respond.3' \ + 'Ixp9Srv.3 Ixp9Req.3 ixp_serve9conn.3' \ 'ixp_listen.3 IxpConn.3' \ 'ixp_hangup.3 ixp_server_close.3' \ 'ixp_serverloop.3 IxpServer.3' \ @@ -16,9 +30,16 @@ MANPAGES = \ 'ixp_srv_getfile.3 IxpFileId.3' \ 'ixp_srv_freefile.3' \ 'ixp_srv_clonefiles.3' \ + 'ixp_srv_readbuf.3 ixp_srv_writebuf.3' \ 'ixp_srv_data2cstring.3' \ + 'ixp_srv_writectl.3' \ + 'ixp_pending_write.3 ixp_pending_pushfid.3 ixp_pending_clunk.3 ixp_pending_flush.3 ixp_pending_respond.3 IxpPending.3' \ + 'ixp_srv_walkandclone.3 ixp_srv_readdir.3 ixp_srv_verifyfile.3 IxpLookupFn.3' \ 'ixp_msec.3' \ 'ixp_settimer.3' \ 'ixp_unsettimer.3' \ - 'ixp_nexttimer.3' \ - 'ixp_namespace.3' + 'ixp_sendmsg.3 ixp_recvmsg.3' \ + 'ixp_smprint.3' \ + 'ixp_namespace.3' \ + 'ixp_eprint.3' \ + 'ixp_emalloc.3 ixp_emallocz.3 ixp_erealloc.3 ixp_estrdup.3' diff --git a/util/grepdoc b/util/grepdoc @@ -20,10 +20,11 @@ my @c = grep /\.c$/, @ARGV; my @h = grep /\.h$/, @ARGV; my %protos; +my %headers; open(my $stderr, '>&', \*STDERR); open STDERR, '>', '/dev/null'; -open my $fd, '-|', 'cproto', '-I./include', @c; +open my $fd, '-|', 'cproto', '-DCPROTO', '-I./include', @c, '/dev/null'; for(<$fd>) { chomp; s/\b_ixp//g; @@ -33,20 +34,41 @@ for(<$fd>) { } open STDERR, '>&', $stderr; -@ARGV = @h; -$_ = join "", map detab, <>; +my @txt; +@ARGV = (@h, '/dev/null'); +for my $f(@h) { + open my $fd, '<', $f; + $_ = join "", map detab, <$fd>; + push @txt, $_; -while(m/^typedef\b.*?(\w+);/gm) { - push @{$protos{$1}}, $& unless $& =~ m{\Q/* Deprecated */}; -} -while(m/^(?:enum|struct)\s+(\w+).*?^\}/gsm) { - my $proto = \@{$protos{$1}}; - push @$proto, subst {"$1$2$1..."} qr[(^ +)(\Q/* Private members */\E\n).*(?=\n\})]sm, $& - unless $& =~ m{\Q/* Deprecated */}; + $f =~ s|^(\./)?include/||; + + my $junk = qr/(?:\[.*\]|\)\(.*\))?/; + while(m/^extern\s+(.*\b(\w+)$junk;)$/gm) { + $headers{$2} = $f; + push @{$protos{$2}}, $1; + } + while(m/^(?!extern)[a-z][^(]+\b(\w+)\(/gmi) { + my $id = $1; + $headers{$id} = $f unless $& =~ m{^\s*(?:#|//|/\*|\*)}; + } + while(m/^typedef\b.*?\b(\w+)$junk;/gm) { + $headers{$1} = $f; + push @{$protos{$1}}, $& unless $& =~ m{\Q/* Deprecated */}; + } + while(m/^(?:enum|struct|union)\s+(\w+).*?^\}/gsm) { + $headers{$1} = $f; + my $proto = \@{$protos{$1}}; + push @$proto, subst {"$1$2$1..."} qr[(^ +)(\Q/* Private members */\E\n).*(?=\n\})]sm, $& + unless $& =~ m{\Q/* Deprecated */}; + } } -@ARGV = @c; -$_ .= join "", map detab, <>; +# print Data::Dumper->Dump([\%protos], ['%protos']); +# print Data::Dumper->Dump([\%headers], ['%headers']); + +@ARGV = (@c, '/dev/null'); +$_ = join "", @txt, map detab, <>; sub section($$) { my ($sect, $text) = @_; @@ -79,6 +101,10 @@ while(m{(?<=/\*\*\n)(?:[^*]|\*[^/])+}g) { next; } + my %hdrs = map {($headers{$_}, "")} @names; + my $includes = join "", map {"#include <$_>\n"} sort keys %hdrs; + $header = "$includes\n$header" if $includes; + sub despace { my ($space) = m/^(\s*)/; s/^$space//gm; diff --git a/util/link b/util/link @@ -27,7 +27,7 @@ echo LD "$($bin/cleanname ${BASE}$outfile)" [ -n "$noisycc" ] && echo $LD -o $outfile $ofiles $LDFLAGS $args $LD -o $outfile $ofiles $LDFLAGS $args >$xtmp 2>&1 status=$? -[ $status -eq 0 ] || $LD -o $outfile $ofiles $LDFLAGS $args >&2 +[ $status -eq 0 ] || echo $LD -o $outfile $ofiles $LDFLAGS $args >&2 sed 's/.*: In function `[^:]*: *//' $xtmp | egrep . | egrep -v 'is almost always misused|is dangerous, better use|in statically linked applications requires at runtime'