Blob


1 .\" Copyright (c) 2021 Omar Polo <op@omarpolo.com>
2 .\"
3 .\" Permission to use, copy, modify, and distribute this software for any
4 .\" purpose with or without fee is hereby granted, provided that the above
5 .\" copyright notice and this permission notice appear in all copies.
6 .\"
7 .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 .\"
15 .Dd $Mdocdate: July 30 2021 $
16 .Dt 9P 7
17 .Os
18 .Sh NAME
19 .Nm 9P
20 .Nd Simple Distributed File System
21 .Sh DESCRIPTION
22 .Nm
23 is a protocol that implements a distributed file systems.
24 It provides primitives to manage
25 .Pq create, read, write and delete
26 sets of files remotely.
27 These files don't necessarily need to be actually stored on a disk,
28 they may be, for example, synthesise on demand from external sources.
29 .Pp
30 A client transmits requests
31 .Pq T-messages
32 to a server, which returns replies
33 .Pq R-messages
34 to the client.
35 The combined acts of transmitting a request of a particular type and
36 receiving a reply is called a transaction of that type.
37 .Pp
38 Each message consists of a sequence of bytes mostly grouped in one,
39 two or four integer fields transmitted in little-endian order
40 .Pq least significant byte first .
41 Data items of larger or variable lengths are represented by a two-byte
42 field specifying the length followed by the actual data.
43 The only exception to this rule are QIDs, thirteen byte long
44 objects, that are sent as-is.
45 .Pp
46 Text strings are represented with a two-byte count and the sequence of
47 UNICODE codepoints encoded in UTF-8.
48 Text strings in 9p are not NUL-terminated.
49 The NUL-terminator is illegal in all text strings and thus excluded
50 from paths, user names and so on.
51 .Pp
52 Fields are hereafter denoted as
53 .Bd -literal -offset indent
54 type[1] tag[2] fid[4]
55 .Ed
56 .Pp
57 to indicate that type is one byte long, tag two and fid four.
58 Strings are denoted as name[s] and are sent on the wire as
59 .Bd -literal -offset indent
60 length[2] string[length]
61 .Ed
62 .Pp
63 A qid, described later, is a 13-byte value that is sent on the wire as
64 .Bd -literal -offset indent
65 type[1] version[4] path[8]
66 .Ed
67 .Sh MESSAGE STRUCTURE
68 Every message has a header with the following fields:
69 .Bd -literal -offset indent
70 len[4] type[1] tag[2]
71 .Ed
72 .Pp
73 where len indicates the overall length of the message, including
74 itself; type is one byte indicating the type of the message and the
75 tag is a number choosen by the client that indicate uniquely the
76 request.
77 Then follows an optional body whose structure depends on the type of
78 the message.
79 .Pp
80 The message types are as follows:
81 .Pq the header is omitted for brevity
82 .Bl -tag -width versionxx
83 .It Ic version
84 Negotiate the version and maximum message size.
85 .Bd -literal
86 msize[4] version[s]
87 msize[4] version[s]
88 .Ed
89 .Pp
90 The
91 .Ic version
92 request must be the first message sent, and the client cannot issue
93 further requests until receiving the Rversion reply.
94 .Cm tag
95 should be
96 .Dv NOTAG
97 .Pq \-1 or 255 .
98 The client suggest a
99 .Cm msize
100 .Pq the maximum size for packets
101 and the protocol version used, the server replies with a
102 .Cm msize
103 smaller or equal to the one proposed by the client.
104 The version string must always begin with the two character
105 .Dq 9P .
106 If the server don't understand the client required version, should
107 reply with a Rversion using the version string
108 .Dq unknown
109 and not use a Rerror.
110 .It Ic attach
111 Populate the namespace
112 .Bd -literal
113 fid[4] afid[4] uname[s] aname[s]
114 qid[13]
115 .Ed
116 .Pp
117 The
118 .Ic attach
119 message binds the given
120 .Ar fid
121 to the root of the file tree identified by
122 .Ar aname .
123 .Ar uname
124 identifies the user and
125 .Ar afid
126 specifies a fid previously established by an auth message, or the
127 special
128 .Dv NOFID
129 value
130 .Pq defined as (u32int)~0
131 if the authentication is not required.
132 .It Ic clunk
133 Close fids.
134 .Bd -literal
135 fid[4]
136 .Aq empty response
137 .Ed
138 .Pp
139 Once a fid has been clunked
140 .Pq closed
141 it becomes
142 .Dq free
143 and the same value can be used for subsequential
144 .Ic walk
145 or
146 .Ic attach
147 requests.
148 .Pp
149 The actual file on the disk is not remove unless it was opened with the
150 .Dv ORCLOSE
151 flag.
152 .It Ic error
153 Return an error string.
154 .Bd -literal
155 ename[s]
156 .Ed
157 .Pp
158 The Rerror message is used to return an error string describing the
159 failure of a request.
160 The
161 .Cm tag
162 indicates the failed request.
163 .Pp
164 Note that there isn't a
165 .Ic Terror
166 request for obvious reason and it's not possible for a server to reply to
168 .Ic Tversion
169 or
170 .Ic Tflush
171 using
172 .Ic Rerror .
173 .It Ic flush
174 Abort an ongoing operation.
175 .Bd -literal
176 oldtag[2]
177 .Aq empty response
178 .Ed
179 .Pp
180 Given the asynchronous nature of the protocol, the server may respond to
181 the pending request before responding to the
182 .Ic Tflush
183 and is possible for a client to send multiple
184 .Ic Tflush
185 for the same operation.
186 The client must wait to receive a corresponding
187 .Ic Rflush
188 before reusing
189 .Ar oldtag
190 for subsequent messages.
191 .Pp
192 If a response for
193 .Ar oldtag
194 is received before the
195 .Ic Rflush
196 reply, the client must assume that the operation was completed with success
197 .Pq fid allocated, files created, ...
198 If no response is received before the
199 .Ic Rflush
200 then the transaction is considered to have been successfully cancelled.
201 .Pp
202 Note that the tag of this request and the corresponding reply is NOT
203 .Ar oldtag
204 but a new tag value.
205 .It Ic walk
206 Traverse a file tree.
207 .Bd -literal
208 fid[4] newfid[4] nwname[2] nwname*(wname[s])
209 nwqid[2] nwqid*(qid[13])
210 .Ed
211 .Pp
212 The
213 .Ar nwname
214 components are walked in order starting from
215 .Ar fid
216 .Pq which must point to a directory
217 and, if successful,
218 .Ar newfid
219 is associated to the reached file.
220 .Pp
221 It is possible for
222 .Ar fid
223 and
224 .Ar newfid
225 to be equal, in this case the fid is
226 .Dq mutated ,
227 otherwise
228 .Ar newfid
229 must be unused.
230 As a special case, a walk of zero components duplicates the fid.
231 .Pp
232 If the first element cannot be walked for any reason an
233 .Ic Rerror
234 is returned.
235 Otherwise,
236 .Ic Rwalk
237 is returned with a number of qids equal to the file viside by the walk.
238 A client can thus detect a walk when that the replied
239 .Ar nwqid
240 number is not equal to the
241 .Ar nwname
242 field in the request.
243 Only when walk return successfully
244 .Ar newfid
245 will be affected.
246 .Pp
247 A maximum of 16 component can be used per walk request.
248 .It Ic open
249 Prepare a fid for I/O.
250 .Bd -literal
251 fid[4] mode[1]
252 qid[13] iounit[4]
253 .Ed
254 .Pp
255 .Ar mode
256 determines the type of I/O:
257 .Bl -tag -width Ds -offset indent -compact
258 .It 0 Dv OREAD
259 .It 1 Dv OWRITE
260 .It 2 Dv ORDWD
261 .It 3 Dv OEXEC
262 .El
263 .Pp
264 The returned
265 .Ar iounit
266 is the optimal blocksize for I/O.
267 .It Ic create
268 Create a file
269 .Bd -literal
270 fid[4] name[s] perm[4] mode[1]
271 qid[13] iounit[4]
272 .Ed
273 .Pp
274 The call attempts to create a file named
275 .Ar name
276 in the directory identified by
277 .Ar fid
278 according to
279 .Ar perm
280 and then to open it with
281 .Ar mode
282 into the given
283 .Ar fid .
284 .Pp
285 It is illegal to use an already opened
286 .Ar fid
287 or to attempt to create the
288 .Dq \&.
289 or
290 .Dq ..
291 entries.
292 .It Ic read
293 Read data at offset from file
294 .Bd -literal
295 fid[4] offset[8] count[4]
296 count[4] data[count]
297 .Ed
298 .Pp
299 .Ar fid
300 must have been prepared for I/O with a previous
301 .Ic open
302 call.
303 The returned
304 .Ar count
305 is zero when reaching end-of-file and may be lesser than what requested.
306 .Pp
307 Directories are a stream of stat structures, as described in
308 .Ic stat ,
309 and for them the read request message must have offset equal to zero or
310 the value of
311 .Ar offset
312 in the previous read on the directory plus the number of bytes returned
313 in the previous read.
314 Thus, is not possible to seek into directories except for rewinding.
315 .It Ic write
316 Write data at offset
317 .Bd -literal
318 fid[4] offset[8] count[4] data[count]
319 count[4]
320 .Ed
321 .It Ic stat
322 get file status
323 .Bd -literal
324 fid[4]
325 stat[n]
326 .Ed
327 .Pp
328 The stat structure is made by the following fields:
329 .Bl -tag -width twelveletters -compact
330 .It size[2]
331 total byte count of the following data
332 .It type[2]
333 for kernel use
334 .It dev[4]
335 for kernel use
336 .It qid[13]
337 server unique identifier of the file
338 .It mode[4]
339 permissions and flags
340 .It atime[4]
341 last access time
342 .It mtime[4]
343 last modification time
344 .It length[8]
345 length of file in bytes
346 .It name[s]
347 file name
348 (must be
349 .Dq /
350 if the file is the root directory of the server)
351 .It uid[s]
352 owner name
353 .It gid[s]
354 group name
355 .It muid[s]
356 name of the user who last modified the file.
357 .El
358 .It Ic remove
359 Remove a file
360 .Bd -literal
361 fid[4]
362 .Aq empty response
363 .Ed
364 .El
365 .\" .Sh 9P2000.L EXTENSIONS
366 .\" .Xr kamid 8
367 .\" supports also a subset of the
368 .\" .Sq 9P2000.L
369 .\" dialect.
370 .\" The supported messages are
371 .\" .Bl -tag -width readdir
372 .\" .It Ic readdir
373 .\" Read directory entries
374 .\" .Bd -literal
375 .\" fid[4] offset[8] count[4]
376 .\" count[4] data[count]
377 .\" .Ed
378 .\" .Pp
379 .\" Each directory entry is described by a variable-length record:
380 .\" .Ql qid[13] offset[8] type[1] name[s] .
381 .\" Offset is zero upon the first call.
382 .\" If the
383 .\" .Ar count
384 .\" field in the
385 .\" .Ic Rreaddir
386 .\" response is not zero then more data is available.
387 .\" .Pp
388 .\" .Ar count
389 .\" is allowed to be zero in the request.
390 .\" .El
391 .Sh SEE ALSO
392 .Xr utf8 7 ,
393 .Xr kamid 8