|
| |
size[4] Tversion tag[2] msize[4] version[s]
size[4] Rversion tag[2] msize[4] version[s]
size[4] Tauth tag[2] afid[4] uname[s] aname[s]
size[4] Rauth tag[2] aqid[13]
size[4] Rerror tag[2] ename[s]
size[4] Tflush tag[2] oldtag[2]
size[4] Rflush tag[2]
size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s]
size[4] Rattach tag[2] qid[13]
size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s])
size[4] Rwalk tag[2] nwqid[2] nwqid*(wqid[13])
size[4] Topen tag[2] fid[4] mode[1]
size[4] Ropen tag[2] qid[13] iounit[4]
size[4] Tcreate tag[2] fid[4] name[s] perm[4] mode[1]
size[4] Rcreate tag[2] qid[13] iounit[4]
size[4] Tread tag[2] fid[4] offset[8] count[4]
size[4] Rread tag[2] count[4] data[count]
size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count]
size[4] Rwrite tag[2] count[4]
size[4] Tclunk tag[2] fid[4]
size[4] Rclunk tag[2]
size[4] Tremove tag[2] fid[4]
size[4] Rremove tag[2]
size[4] Tstat tag[2] fid[4]
size[4] Rstat tag[2] stat[n]
size[4] Twstat tag[2] fid[4] stat[n]
size[4] Rwstat tag[2]
|
Each T–message has a tag field, chosen and used by the client to
identify the message. The reply to the message will have the same
tag. Clients must arrange that no two outstanding messages on
the same connection have the same tag. An exception is the tag
NOTAG, defined as (ushort)~0 in <fcall.h>: the
client can use it, when establishing a connection, to override
tag matching in version messages.
The type of an R–message will either be one greater than the type
of the corresponding T–message or Rerror, indicating that the request
failed. In the latter case, the ename field contains a string
describing the reason for failure.
The version message identifies the version of the protocol and
indicates the maximum message size the system is prepared to handle.
It also initializes the connection and aborts all outstanding
I/O on the connection. The set of messages between version requests
is called a session.
Most T–messages contain a fid, a 32–bit unsigned integer that the
client uses to identify a ``current file'' on the server. Fids
are somewhat like file descriptors in a user process, but they
are not restricted to files open for I/O: directories being examined,
files being accessed by stat(2) calls, and so on -- all files being
manipulated by the operating system -- are identified by fids. Fids
are chosen by the client. All requests on a connection share the
same fid space; when several clients share a connection, the agent
managing the sharing must arrange that no two clients choose the
same fid.
The fid supplied in an attach message will be taken by the server
to refer to the root of the served file tree. The attach identifies
the user to the server and may specify a particular file tree
served by the server (for those that supply more than one).
Permission to attach to the service is proven by providing a special
fid, called afid, in the attach message. This afid is established
by exchanging auth messages and subsequently manipulated using
read and write messages to exchange authentication information
not defined explicitly by 9P. Once the
authentication protocol is complete, the afid is presented in
the attach to permit the user to access the service.
A walk message causes the server to change the current file associated
with a fid to be a file in the directory that is the old current
file, or one of its subdirectories. Walk returns a new fid that
refers to the resulting file. Usually, a client maintains a fid
for the root, and navigates by walks from the root fid.
A client can send multiple T–messages without waiting for the corresponding
R–messages, but all outstanding T–messages must specify different
tags. The server may delay the response to a request and respond
to later ones; this is sometimes necessary, for example when the
client reads from a file that the server
synthesizes from external events such as keyboard characters.
Replies (R–messages) to auth, attach, walk, open, and create requests
convey a qid field back to the client. The qid represents the
server's unique identification for the file being accessed: two
files on the same server hierarchy are the same if and only if
their qids are the same. (The client may have multiple
fids pointing to a single file on a server and hence having a
single qid.) The thirteen–byte qid fields hold a one–byte type,
specifying whether the file is a directory, append–only file, etc.,
and two unsigned integers: first the four–byte qid version, then
the eight–byte qid path. The path is an integer unique among all
files
in the hierarchy. If a file is deleted and recreated with the
same name in the same directory, the old and new path components
of the qids should be different. The version is a version number
for a file; typically, it is incremented every time the file is
modified.
An existing file can be opened, or a new file may be created in
the current (directory) file. I/O of a given number of bytes at
a given offset on an open file is done by read and write.
A client should clunk any fid that is no longer needed. The remove
transaction deletes files.
The stat transaction retrieves information about the file. The
stat field in the reply includes the file's name, access permissions
(read, write and execute for owner, group and public), access
and modification times, and owner and group identifications (see
stat(2)). The owner and group identifications are textual
names. The wstat transaction allows some of a file's properties
to be changed.
A request can be aborted with a flush request. When a server receives
a Tflush, it should not reply to the message with tag oldtag (unless
it has already replied), and it should immediately send an Rflush.
The client must wait until it gets the Rflush (even if the reply
to the original message arrives in the interim),
at which point oldtag may be reused.
Because the message size is negotiable and some elements of the
protocol are variable length, it is possible (although unlikely)
to have a situation where a valid message is too large to fit
within the negotiated size. For example, a very long file name
may cause a Rstat of the file or Rread of its directory entry
to be
too large to send. In most such cases, the server should generate
an error rather than modify the data to fit, such as by truncating
the file name. The exception is that a long error string in an
Rerror message should be truncated if necessary, since the string
is only advisory and in some sense arbitrary.
Most programs do not see the 9P protocol directly; instead calls
to library routines that access files are translated by the mount
driver, mnt(3), into 9P messages.
|