FCALL(2) FCALL(2)
NAME
Fcall, convS2M, convD2M, convM2S, convM2D, fcallfmt, dirfmt,
dirmodefmt, read9pmsg, statcheck, sizeS2M, sizeD2M -
interface to Plan 9 File protocol
SYNOPSIS
#include <u.h>
#include <libc.h>
#include <fcall.h>
uint convS2M(Fcall *f, uchar *ap, uint nap)
uint convD2M(Dir *d, uchar *ap, uint nap)
uint convM2S(uchar *ap, uint nap, Fcall *f)
uint convM2D(uchar *ap, uint nap, Dir *d, char *strs)
int dirfmt(Fmt*)
int fcallfmt(Fmt*)
int dirmodefmt(Fmt*)
int read9pmsg(int fd, void *buf, uint nbuf)
int statcheck(uchar *buf, uint nbuf)
uint sizeS2M(Fcall *f)
uint sizeD2M(Dir *d)
DESCRIPTION
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
typedef
struct Fcall
{
uchar type;
u32int fid;
ushort tag;
union {
struct {
u32int msize;/* Tversion, Rversion */
char *version; /* Tversion, Rversion */
};
Page 1 Plan 9 (printed 10/29/25)
FCALL(2) FCALL(2)
struct {
ushort oldtag;/* Tflush */
};
struct {
char *ename; /* Rerror */
};
struct {
Qid qid; /* Rattach, Ropen, Rcreate */
u32int iounit;/* Ropen, Rcreate */
};
struct {
Qid aqid; /* Rauth */
};
struct {
u32int afid;/* Tauth, Tattach */
char *uname; /* Tauth, Tattach */
char *aname; /* Tauth, Tattach */
};
struct {
u32int perm;/* Tcreate */
char *name; /* Tcreate */
uchar mode; /* Tcreate, Topen */
};
struct {
u32int newfid;/* Twalk */
ushort nwname;/* Twalk */
char *wname[MAXWELEM]; /* Twalk */
};
struct {
ushort nwqid;/* Rwalk */
Qid wqid[MAXWELEM]; /* Rwalk */
};
struct {
vlong offset; /* Tread, Twrite */
u32int count;/* Tread, Twrite, Rread */
char *data; /* Twrite, Rread */
};
struct {
ushort nstat;/* Twstat, Rstat */
uchar *stat; /* Twstat, Rstat */
};
};
} Fcall;
/* these are implemented as macros */
uchar GBIT8(uchar*)
ushort GBIT16(uchar*)
ulong GBIT32(uchar*)
vlong GBIT64(uchar*)
void PBIT8(uchar*, uchar)
Page 2 Plan 9 (printed 10/29/25)
FCALL(2) FCALL(2)
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 mes-
sages, 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 includ-
ing any data for Twrite and Rread messages is formatted
properly, the return value is the number of bytes the mes-
sage 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 mes-
sage starting at ap. The length of the resulting message is
returned. For Twrite and Rread messages, count bytes start-
ing 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 negoti-
ated 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; how-
ever, the return value still includes their length.
Page 3 Plan 9 (printed 10/29/25)
FCALL(2) FCALL(2)
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 the 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 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 letter `M'.
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.
SOURCE
/sys/src/libc/9sys
SEE ALSO
intro(2), 9p(2), stat(2), intro(5)
Page 4 Plan 9 (printed 10/29/25)