These routines convert messages in the machine–independent format
of the Plan 9 file protocol, 9P, to and from a more convenient
form, an Fcall structure:
#define MAXWELEM 16|
u32int msize; /* Tversion, Rversion */
char *version; /* Tversion, Rversion */
ushort oldtag; /* Tflush */
char *ename; /* Rerror */
Qid qid; /* Rattach, Ropen, Rcreate */
u32int iounit; /* Ropen, Rcreate */
Qid aqid; /* Rauth */
u32int afid; /* Tauth, Tattach */
char *uname; /* Tauth, Tattach */
char *aname; /* Tauth, Tattach */
u32int perm; /* Tcreate */
char *name; /* Tcreate */
uchar mode; /* Tcreate, Topen */
u32int newfid; /* Twalk */
ushort nwname; /* Twalk */
char *wname[MAXWELEM]; /* Twalk */
ushort nwqid; /* Rwalk */
Qid wqid[MAXWELEM]; /* Rwalk */
vlong offset; /* Tread, Twrite */
u32int count; /* Tread, Twrite, Rread */
char *data; /* Twrite, Rread */
ushort nstat; /* Twstat, Rstat */
uchar *stat; /* Twstat, Rstat */
/* these are implemented as macros */
void PBIT8(uchar*, uchar)
void PBIT16(uchar*, ushort)
void PBIT32(uchar*, ulong)
void PBIT64(uchar*, vlong)
#define BIT8SZ 1
#define BIT16SZ 2
#define BIT32SZ 4
#define BIT64SZ 8
This structure is defined in <fcall.h>. See section 5 for a full
description of 9P messages and their encoding. For all message
types, the type field of an Fcall holds one of Tversion, Rversion,
Tattach, Rattach, etc. (defined in an enumerated type in <fcall.h>).
Fid is used by most messages, and
tag is used by all messages. The other fields are used selectively
by the message types given in comments.
ConvM2S takes a 9P message at ap of length nap, and uses it to
fill in Fcall structure f. If the passed message including any
data for Twrite and Rread messages is formatted properly, the
return value is the number of bytes the message occupied in the
buffer ap, which will always be less than or equal to nap;
otherwise it is 0. For Twrite and Tread messages, data is set
to a pointer into the argument message, not a copy.
ConvS2M does the reverse conversion, turning f into a message
starting at ap. The length of the resulting message is returned.
For Twrite and Rread messages, count bytes starting at data are
copied into the message.
The constant IOHDRSZ is a suitable amount of buffer to reserve
for storing the 9P header; the data portion of a Twrite or Rread
will be no more than the buffer size negotiated in the Tversion/Rversion
exchange, minus IOHDRSZ.
The routine sizeS2M returns the number of bytes required to store
the machine–independent representation of the Fcall structure f,
including its initial 32–bit size field. In other words, it reports
the number of bytes produced by a successful call to convS2M.
Another structure is Dir, used by the routines described in stat(2).
ConvM2D converts the machine–independent form starting at ap into
d and returns the length of the machine–independent encoding. The
strings in the returned Dir structure are stored at successive
locations starting at strs. Usually strs will
point to storage immediately after the Dir itself. It can also
be a nil pointer, in which case the string pointers in the returned
Dir are all nil; however, the return value still includes their
ConvD2M does the reverse translation, also returning the length
of the encoding. If the buffer is too short, the return value
will be BIT16SZ and the correct size will be returned in the first
BIT16SZ bytes. (If the buffer is less that BIT16SZ, the return
value is zero; therefore a correct test for complete packing of
message is that the return value is greater than BIT16SZ). The
macro GBIT16 can be used to extract the correct value. The related
macros with different sizes retrieve the corresponding–sized quantities.
PBIT16 and its brethren place values in messages. With the exception
of handling short buffers in convD2M,
these macros are not usually needed except by internal routines.
Analogous to sizeS2M, sizeD2M returns the number of bytes required
to store the machine–independent representation of the Dir structure
d, including its initial 16–bit size field.
The routine statcheck checks whether the nbuf bytes of buf contain
a validly formatted machine–independent Dir entry suitable as an
argument, for example, for the wstat (see stat(2)) system call.
It checks that the sizes of all the elements of the the entry
sum to exactly nbuf, which is a simple but effective test
of validity. Nbuf and buf should include the second two–byte (16–bit)
length field that precedes the entry when formatted in a 9P message
(see stat(5)); in other words, nbuf is 2 plus the sum of the sizes
of the entry itself. Statcheck also verifies that the length field
has the correct value (that is, nbuf–2). It returns 0
for a valid entry and –1 for an incorrectly formatted entry.
Dirfmt, fcallfmt, and dirmodefmt are formatting routines, suitable
for fmtinstall(2). They convert Dir*, Fcall*, and long values
into string representations of the directory buffer, Fcall buffer,
or file mode value. Fcallfmt assumes that dirfmt has been installed
with format letter D and dirmodefmt with format
Read9pmsg calls read(2) multiple times, if necessary, to read
an entire 9P message into buf. The return value is 0 for end of
file, or –1 for error; it does not return partial messages.