.\" Copyright (c) 2021 Omar Polo .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate: July 30 2021 $ .Dt 9P 7 .Os .Sh NAME .Nm 9P .Nd Simple Distributed File System .Sh DESCRIPTION .Nm is a protocol that implements a distributed file systems. It provides primitives to manage .Pq create, read, write and delete sets of files remotely. These files don't necessarily need to be actually stored on a disk, they may be, for example, synthesise on demand from external sources. .Pp A client transmits requests .Pq T-messages to a server, which returns replies .Pq R-messages to the client. The combined acts of transmitting a request of a particular type and receiving a reply is called a transaction of that type. .Pp Each message consists of a sequence of bytes mostly grouped in one, two or four integer fields transmitted in little-endian order .Pq least significant byte first . Data items of larger or variable lengths are represented by a two-byte field specifying the length followed by the actual data. The only exception to this rule are QIDs, thirteen byte long objects, that are sent as-is. .Pp Text strings are represented with a two-byte count and the sequence of UNICODE codepoints encoded in UTF-8. Text strings in 9p are not NUL-terminated. The NUL-terminator is illegal in all text strings and thus excluded from paths, user names and so on. .Pp Fields are hereafter denoted as .Bd -literal -offset indent type[1] tag[2] fid[4] .Ed .Pp to indicate that type is one byte long, tag two and fid four. Strings are denoted as name[s] and are sent on the wire as .Bd -literal -offset indent length[2] string[length] .Ed .Pp A qid, described later, is a 13-byte value that is sent on the wire as .Bd -literal -offset indent type[1] version[4] path[8] .Ed .Sh MESSAGE STRUCTURE Every message has a header with the following fields: .Bd -literal -offset indent len[4] type[1] tag[2] .Ed .Pp where len indicates the overall length of the message, including itself; type is one byte indicating the type of the message and the tag is a number choosen by the client that indicate uniquely the request. Then follows an optional body whose structure depends on the type of the message. .Pp The message types are as follows: .Pq the header is omitted for brevity .Bl -tag -width versionxx .It Ic version Negotiate the version and maximum message size. .Bd -literal msize[4] version[s] msize[4] version[s] .Ed .Pp The .Ic version request must be the first message sent, and the client cannot issue further requests until receiving the Rversion reply. .Ar tag should be .Dv NOTAG .Pq \-1 or 255 . The client suggest a .Ar msize .Pq the maximum size for packets and the protocol version used, the server replies with a .Ar msize smaller or equal to the one proposed by the client. The version string must always begin with the two character .Dq 9P . If the server don't understand the client required version, should reply with a Rversion using the version string .Dq unknown and not use a Rerror. .It Ic attach Populate the namespace .Bd -literal fid[4] afid[4] uname[s] aname[s] qid[13] .Ed .Pp The .Ic attach message binds the given .Ar fid to the root of the file tree identified by .Ar aname . .Ar uname identifies the user and .Ar afid specifies a fid previously established by an auth message, or the special .Dv NOFID value .Pq defined as (u32int_t)~0 if the authentication is not required. .It Ic clunk Close fids. .Bd -literal fid[4] .Aq empty response .Ed .Pp Once a fid has been clunked .Pq closed it becomes .Dq free and the same value can be used for subsequential .Ic walk or .Ic attach requests. .Pp The actual file on the disk is not removed unless it was opened with the .Dv ORCLOSE flag. .It Ic error Return an error string. .Bd -literal .Aq no request ename[s] .Ed .Pp The Rerror message is used to return an error string describing the failure of a request. The .Ar tag indicates the failed request. .Pp Note that there isn't a .Ic Terror request for obvious reason and it's not possible for a server to reply to a .Ic Tversion or .Ic Tflush using .Ic Rerror . .It Ic flush Abort an ongoing operation. .Bd -literal oldtag[2] .Aq empty response .Ed .Pp Given the asynchronous nature of the protocol, the server may respond to the pending request before responding to the .Ic Tflush and is possible for a client to send multiple .Ic Tflush for the same operation. The client must wait to receive a corresponding .Ic Rflush before reusing .Ar oldtag for subsequent messages. .Pp If a response for .Ar oldtag is received before the .Ic Rflush reply, the client must assume that the operation was completed with success .Pq fid allocated, files created, ... If no response is received before the .Ic Rflush then the transaction is considered to have been successfully cancelled. .Pp Note that the tag of this request and the corresponding reply is NOT .Ar oldtag but a new tag value. .It Ic walk Traverse a file tree. .Bd -literal fid[4] newfid[4] nwname[2] nwname*(wname[s]) nwqid[2] nwqid*(qid[13]) .Ed .Pp The .Ar nwname components are walked in order starting from .Ar fid .Pq which must point to a directory and, if successful, .Ar newfid is associated to the reached file. .Pp It is possible for .Ar fid and .Ar newfid to be equal, in this case the fid is .Dq mutated , otherwise .Ar newfid must be unused. As a special case, a walk of zero components duplicates the fid. .Pp If the first element cannot be walked for any reason an .Ic Rerror is returned. Otherwise, .Ic Rwalk is returned with a number of qids equal to the file viside by the walk. A client can thus detect a walk when that the replied .Ar nwqid number is not equal to the .Ar nwname field in the request. Only when walk return successfully .Ar newfid will be affected. .Pp A maximum of 16 component can be used per walk request. .It Ic open Prepare a fid for I/O. .Bd -literal fid[4] mode[1] qid[13] iounit[4] .Ed .Pp .Ar mode determines the type of I/O: .Bl -tag -width Ds -offset indent -compact .It 0x00 Pq Dv OREAD Open the file for reading. .It 0x01 Pq Dv OWRITE Open the file for writing. .It 0x02 Pq Dv ORDWD Open the file for both reading and writing. .It 0x03 Pq Dv OEXEC Open for exec. .El .Pp Additionally, the following flags can be or'ed to .Ar mode : .Bl -tag -width Ds -offset indent -compact .It 0x10 Pq Dv OTRUNC Truncate the file before opening .It 0x40 Pq Dv ORCLOSE Remove the file upon .Ic clunk . .El .Pp The returned .Ar iounit is the optimal blocksize for I/O. .It Ic create Create a file .Bd -literal fid[4] name[s] perm[4] mode[1] qid[13] iounit[4] .Ed .Pp The call attempts to create a file named .Ar name in the directory identified by .Ar fid according to .Ar perm and then to open it with .Ar mode into the given .Ar fid . .Pp It is illegal to use an already opened .Ar fid or to attempt to create the .Dq \&. or .Dq .. entries. .It Ic read Read data at offset .Bd -literal fid[4] offset[8] count[4] count[4] data[count] .Ed .Pp .Ar fid must have been prepared for I/O with a previous .Ic open call. The returned .Ar count is zero when reaching end-of-file and may be lesser than what requested. .Pp Directories are a stream of stat structures, as described in .Ic stat , and for them the read request message must have offset equal to zero or the value of .Ar offset in the previous read on the directory plus the number of bytes returned in the previous read. Thus, is not possible to seek into directories except for rewinding. .It Ic write Write data at offset .Bd -literal fid[4] offset[8] count[4] data[count] count[4] .Ed .Pp .Ar fid must have been prepared for I/O with a previous .Ic open or .Ic create call. The returned .Ar count is the amount of data actually written and may differ from the one in the request. .It Ic stat Get file status .Bd -literal fid[4] stat[n] .Ed .Pp The stat structure is made by the following fields: .Bl -tag -width tenletters -compact .It size[2] total byte count of the following data .It type[2] for kernel use .It dev[4] for kernel use .It qid[13] server unique identifier of the file .It mode[4] permissions and flags .It atime[4] last access time .It mtime[4] last modification time .It length[8] length of file in bytes .It name[s] file name (must be .Dq / if the file is the root directory of the server) .It uid[s] owner name .It gid[s] group name .It muid[s] name of the user who last modified the file. .El .Pp Note that the .Ar size is always present, even in the .Ic wstat call. While it may be considered redundant, it's kept to simplify the parsing of the stat entries in a directory. .It Ic wstat Change file attributes .Bd -literal fid[4] stat[n] .Aq empty response .Ed .Pp .Ar fid must have been prepared for writing with a previous .Ic open or .Ic create call. .Pp The .Ar stat structure is the same described in .Ic stat . .Pp The .Ar stat structure sent reflect what changes the client wishes to make to the given fid. To leave some fields as unchanged, use empty string or the maximum allowed value for integral fields. For example, to avoid changing the permission of the fid use 0xFFFFFFFF, or (uint32_t)-1. .It Ic remove Remove and clunk fid .Bd -literal fid[4] .Aq empty response .Ed .Pp After a .Ic remove call, even if an error is returned, the .Ar fid is closed. .El .\" .Sh 9P2000.L EXTENSIONS .\" .Xr kamid 8 .\" supports also a subset of the .\" .Sq 9P2000.L .\" dialect. .\" The supported messages are .\" .Bl -tag -width readdir .\" .It Ic readdir .\" Read directory entries .\" .Bd -literal .\" fid[4] offset[8] count[4] .\" count[4] data[count] .\" .Ed .\" .Pp .\" Each directory entry is described by a variable-length record: .\" .Ql qid[13] offset[8] type[1] name[s] . .\" Offset is zero upon the first call. .\" If the .\" .Ar count .\" field in the .\" .Ic Rreaddir .\" response is not zero then more data is available. .\" .Pp .\" .Ar count .\" is allowed to be zero in the request. .\" .El .Sh SEE ALSO .Xr utf8 7 , .Xr kamid 8