source: project/wiki/9p @ 8118

Last change on this file since 8118 was 8118, checked in by sjamaan, 12 years ago

Add 9p egg documentation to the wiki

File size: 24.1 KB
Line 
1[[tags: egg]]
2
3== 9p
4
5[[toc:]]
6
7=== Description
8
9A pure Scheme implementation of the [[http://9p.cat-v.org|9p networked filesystem protocol]].
10
11=== Author
12
13[[Peter Bex]]
14
15=== Requirements
16
17Requires the [[http://www.call-with-current-continuation.org/eggs/iset|iset]] egg.
18
19=== Download
20
21[[http://www.call-with-current-continuation.org/eggs/9p.egg|9p.egg]]
22
23=== Documentation
24
259p is an implementation of the networked file system protocol known as 9P, specifically version 9P2000 which is also known as "Styx".
26This protocol is used by the [[http://cm.bell-labs.com/plan9|Plan 9 operating system]] and the [[http://wmii.suckless.org|wmii window manager]], among others.
27
28This implementation includes a low-level implementation of the protocol that is suitable both for writing clients and servers and a high-level client implementation.  There currently are no concrete plans for a high-level server implementation, but contributions are of course very welcome :)
29
30The low-level implementation is documented below under [[#9p-lolevel|9p-lolevel]] and the high-level client implementation under [[#9p-client|9p-client]].  The high-level client is discussed first, because this is the one you will most likely need.
31
32=== 9p-client
33
34The basic library was modeled after Chicken's [[Unit posix]] and a few choice other procedures that interact with the filesystem.  Most procedures from Unit posix are available under the same name, prefixed with {{9p:}}.  Where possible, the procedure's signature has been unmodified, except for an additional leading argument that specifies the connection with the 9p server.
35
36==== Usage
37
38  (use 9p-client)
39  (use utf8)
40
41It is highly recommended you require utf8 in your applications, as 9p is a utf8-aware protocol.  It is not a dependency of this egg because in some situations you might decide it's safe to leave it out, for performance or memory footprint reasons.
42
43==== Connection management
44
45===== 9p:client-connect
46
47Before doing anything else, you must establish a connection with the server.  This is done with the {{9p:client-connect}} procedure.
48
49    procedure: (9p:client-connect inport outport [user] [mountpoint])
50
51The {{inport}} and {{outport}} arguments are the ports you use to communicate to the server.  The {{user}} argument is the name of the user that creates the files.  It defaults to the empty string.  There is no support for authentication, so the user name is simply used for newly created files on servers that support usernames (wmii doesn't, for example).  The {{mountpoint}} also defaults to the empty string, which selects the "default mount point" on the server.  If the server has multiple mountpoints it exports, you can select with this argument.
52
53The procedure returns a connection object you must keep and use in all subsequent 9p procedure calls.
54
55You can use the following procedures to obtain some more information on the connection:
56
57  procedure: (9p:connection-outport connection)
58  procedure: (9p:connection-inport connection)
59
60Get back the underlying ports you passed to {{9p:client-connect}}.
61
62  procedure: (9p:connection-message-size connection)
63
64The maximum size of a low-level message as negotiated in the connection handshake.  Not very useful unless you would like to write some custom messages.  This ''includes'' the size of the tag (2 bytes) and the message type (1 byte).
65
66
67===== 9p:client-disconnect
68
69    procedure: (9p:client-disconnect connection)
70
71Disconnect from the server described by {{connection}}.  This clunks any fids that are still open (in Unix terms: closes any open file descriptors).
72
73===== 9p:connection?
74
75   procedure: (9p:connection? object)
76
77You can verify an object is a connection to a 9p server with this predicate.
78
79==== Files as ports
80
81===== 9p:with-output-to-file
82
83  procedure: (9p:with-output-to-file connection file thunk)
84
85Open {{file}} on the 9p connection {{connection}} and call {{thunk}} with the {{current-output-port}} set to a port that writes to the file. When the thunk finishes, the port is closed.
86
87===== 9p:call-with-output-file
88
89  procedure: (9p:call-with-output-file connection file procedure)
90
91Open {{file}} on the 9p connection {{connection}} and call {{procedure}} with an output-port that corresponds to the file. When the procedure finishes, the port is closed.  Procedure should accept one argument, the output-port.
92
93===== 9p:open-output-file
94
95  procedure: (9p:open-output-file connection file [mode])
96
97Create an output port that will write to the given {{file}} on the 9p connection {{connection}}.  If the file exists, it is truncated.  If it does not exist yet it will be created.  If the optional {{mode}} is given, it determines with what permissions the file will be created, if it is a new file.  See [[#Permission bits|below]] for the list of file permissions.
98
99Don't forget to close the output port (with {{close-output-port}}) when you finish writing to it!
100
101===== 9p:with-input-from-file
102
103  procedure: (9p:with-input-from-file connection file thunk)
104
105Open {{file}} on the 9p connection {{connection}} and call {{thunk}} with the {{current-input-port}} set to a port that reads from the file. When the thunk finishes, the port is closed.
106
107===== 9p:call-with-input-file
108
109  procedure: (9p:call-with-input-file connection file procedure)
110
111Open {{file}} on the 9p connection {{connection}} and call {{procedure}} with an input-port that corresponds to the file. When the procedure finishes, the port is closed.  Procedure should accept one argument, the input-port.
112
113===== 9p:open-input-file
114
115  procedure: (9p:open-input-file connection file)
116
117Create an input port that will read from the given {{file}} on the 9p connection {{connection}}.
118
119Don't forget to close the input port (with {{close-input-port}} when you finish reading from it!
120
121==== Directories
122
123===== 9p:directory?
124
125  procedure: (9p:directory? connection path)
126
127Returns {{#t}} if the given {{path}} on the {{connection}} is a directory, {{#f}} if not.
128
129===== 9p:create-directory
130
131  procedure: (9p:create-directory connection path permissions)
132
133Create a directory on the {{connection}} with the given {{path}}.  It will have the specified {{permissions}}, see [[#Permission bits|below]] for the available permissions.
134
135===== 9p:directory
136
137  procedure: (9p:directory connection directory [show-dotfiles?])
138
139Returns a list with the contents of the {{directory}} on the {{connection}}. Files beginning with {{.}} are included only if {{show-dotfiles?}} is given and not #f.
140
141==== Files
142
143===== 9p:regular-file?
144
145  procedure: (9p:regular-file? connection path)
146
147Returns {{#t}} if the given {{path}} on the {{connection}} is a regular file, {{#f}} if not.  9p does not support symlinks or FIFOs, so this is the same as {{(not (9p:directory? connection path))}}, even if the underlying FS is a Unix FS (the 9p egg currently does not (and probably will never) support [[http://v9fs.sourceforge.net/rfc/9p2000.u.html|9P2000.u]]).
148
149===== 9p:delete-file
150
151  procedure: (9p:delete-file connection path)
152
153Delete the file indicated by {{path}} on the {{connection}}. If the file does not exist or you do not have permission to delete it, an error is signaled.
154
155===== 9p:file-stat
156
157  procedure: (9p:file-stat connection path)
158
159Returns a 9-element vector which contains information about the file indicated by {{path}} on the {{connection}}.  It has the following contents:
160
161* The QID of the file (The qid can be queried with the [[#QIDs|QID procedures]] from 9p-lolevel.
162* The permission mode (See [[#Permission bits|the permission bits section]] for a description)
163* The access time of the file.  This is an integer which indicates the server-time when the file was last accessed.  There is no way to determine what the server's time is using the 9p protocol, so you can only use this for comparing timestamps of files on the same server unless you use an additional protocol to find out about the server's current time and zone.
164* The modification time of the file.  This is an integer which indicates the server-time when the file was last modified.
165* The file's size in bytes.
166* The filename of the file.
167* The user who owns the file (a string, not a uid, because Plan9 has only user and group names, not numerical ids).
168* The group who owns the file (a string)
169* The user who last modified the file (a string)
170
171===== 9p:file-permissions
172
173  procedure: (9p:file-permissions connection path)
174
175Returns the permissions of the file indicated by {{path}} on the {{connection}}. See [[#Permission bits|the permission bits section]] for a description of the possible bits.
176
177===== 9p:file-access-time
178
179  procedure: (9p:file-access-time connection path)
180
181Returns the access time of the file indicated by {{path}} on the {{connection}}.  See the notes under [[9p:file-stat]].
182
183
184===== 9p:file-modification-time
185
186  procedure: (9p:file-modification-time connection path)
187
188Returns the modification time of the file indicated by {{path}} on the {{connection}}.  See the notes under [[9p:file-stat]].
189
190===== 9p:file-size
191
192  procedure: (9p:file-size connection path)
193
194Returns the size, in bytes, of the file indicated by {{path}} on the {{connection}}.
195
196===== 9p:file-owner
197
198  procedure: (9p:file-owner connection path)
199
200Returns the name of the owner, as a string, of the file indicated by {{path}} on the {{connection}}.
201
202===== 9p:file-group
203
204  procedure: (9p:file-group connection path)
205
206Returns the name of the owning group, as a string, of the file indicated by {{path}} on the {{connection}}.
207
208===== 9p:file-last-modified-by
209
210  procedure: (9p:file-last-modified-by connection path)
211
212Returns the name of the user, as a string, who last changed the file indicated by {{path}} on the {{connection}}.
213
214==== File handles and low-level calls
215
216These calls are not on the protocol level, as the [[9p-lolevel]] library procedures, but they are more low-level than the other procedures in the [[9p-client]] library because they allow you to work on the file handle level.
217
218===== 9p:file-open
219
220  procedure: (9p:file-open connection path mode)
221
222Opens the file indicated by {{path}} on the {{connection}} with the given {{mode}} and returns an opaque handle object which you can use for the other procedures described in this section.  For bit flags that the {{mode}} can take, see [[#Open flags|the open flags section]].
223
224===== 9p:file-create
225
226  procedure: (9p:file-create connection path permissions mode)
227
228Creates and opens the file indicated by {{path}} on the {{connection}} with the given {{permission}} and {{mode}} and returns an opaque handle object which you can use for the other procedures described in this section.  For bit flags that the {{mode}} can take, see [[#Open flags|the open flags section]].  For bit flags that the {{permission}} can take, see [[#Permission bits|the permission bits section]].
229
230
231===== 9p:file-close
232
233  procedure: (9p:file-close handle)
234
235Close the file indicated by {{handle}}.  It is not an error to close a file more than once.
236
237===== 9p:file-read
238
239  procedure: (9p:file-read handle size)
240
241Read {{size}} bytes from the file with the given {{handle}}.  This procedure returns a list with two values: the buffer containing the data and the number of bytes read.
242
243===== 9p:file-write
244
245  procedure: (9p:file-write handle buffer [size])
246
247Writes the contents of the string or bytevector {{buffer}} into the file with the given {{handle}}. If the optional argument {{size}} is given, then only the specified number of bytes are written.
248
249===== 9p:set-file-position!
250
251  procedure: (9p:set-file-position! handle position [whence])
252
253Sets the current read/write position of {{handle}} to {{position}}, which should be an exact integer. {{whence}} specifies how the position is to interpreted and should be one of the values {{seek/set}}, {{seek/cur}} and {{seek/end}}. It defaults to {{seek/set}}.
254
255===== 9p:file-position
256
257  procedure: (9p:file-position handle)
258
259Returns the current read/write position of the {{handle}}.
260
261===== 9p:handle-stat
262
263  procedure: (9p:handle-stat handle)
264
265Just like [[9p:file-stat]], except it works on a handle instead of on a connection with a filename.
266
267===== Low-level handle access
268
269If you want to get really dirty and low-level you can modify file handles with the following procedures.  This is not recommended, but sometimes required if you want to do some custom things just above the protocol level and extend the client library instead of writing your own.
270
271====== 9p:path-walk
272
273  procedure: (9p:path-walk connection path [starting-point])
274
275Obtain a handle for the file identified by {{path}} on the {{connection}} ''without opening it''.  You must not forget to clunk the handle's FID (or just call {{9p:file-close}} on the handle).
276
277====== 9p:with-handle-to
278
279If all you need is a temporary handle/FID for a message to the server, you can use this utility procedure:
280
281  procedure: (9p:with-handle-to connection path procedure)
282
283This will call {{procedure}} with one argument: a temporary handle which represents the {{path}} on the {{connection}}.  After the procedure returns, the handle will be deallocated and the FID will no longer be valid.  This returns whatever {{procedure}} returned.  If a condition is signaled, the handle will be deallocated properly and the FID clunked.
284
285====== 9p:alloc-handle
286
287The 9p-client library keeps track of FIDs for you so you do not have to remember numbers.  If you wish to send low-level messages yourself you should allocate and release FIDs through the library so your FIDs can't clash with the FIDs the library uses:
288
289  procedure: (9p:alloc-handle connection)
290
291Allocate a handle on the connection.  This returns a handle object which you can query with the following procedures:
292
293  9p:handle-connection
294  9p:handle-fid
295  9p:handle-position
296  9p:handle-iounit
297
298The fid is allocated from an internal pool of free fids.  The position is initialized to 0, and used as an offset for read/write procedures (the server does not keep track of this for us in the 9p protocol).
299
300The iounit defaults to {{#f}} and you are expected to set it manually (normally, [[9p:file-open]] and [[9p:file-create]] do this for you). is returned as part of the Ropen and Rcreate replies and is the maximum size of a data transfer (either read or write).  If the server returns 0, the iounit should default to the size returned by {{9p:connection-message-size}} minus 24.
301
302
303====== 9p:release-handle
304
305Once you are done with a handle, you must either pass the handle to [[9p:file-close]] (or just disconnect with [[9p:client-disconnect]]) or call {{9p:release-handle}}:
306
307  procedure: (9p:release-handle handle)
308
309'''important''': be sure to clunk the handle's fid first.  {{9p:release-handle}} does ''not'' clunk the fid.
310
311
312===== Sending messages
313
314A code using 9p-client normally never needs to send raw messages, but in case it does, there is one convenience procedure that does just a bit more than the raw [[9p-lolevel]] procedures do:
315
316  procedure: (9p:request connection type . args)
317
318This creates a new {{9p:message}} object (see below) with a tag and the given {{type}}.  {{args}} are the message-contents.  It then sends this request to the server and awaits a response.  The response should match the request (a {{Twhatever}} should result in a {{Rwhatever}} message), or a condition of type {{(exn 9p-response-error)}} is signaled.  If the server returns an error (via {{Rerror}}), a condition of type {{(exn 9p-server-error)}} is signaled.  The response object (a 9p:message object) is returned.
319
320=== 9p-lolevel
321
322This library allows you to build your own client or server abstraction library.  This documentation will not make a lot of sense if you haven't read the [[http://9p.cat-v.org/documentation|9p protocol documentation]].
323
324==== Usage
325
326  (use 9p-lolevel)
327  (use utf8)
328
329Again, utf8 is highly recommended but not strictly required.
330
331==== Messages
332
333Messages are main concept in the 9p protocol.  They can be created as follows:
334
335  procedure: (make-9p:message type tag contents)
336
337The type is a symbol, one of
338  Tversion Rversion
339  Tauth Rauth
340  Tattach Rattach
341  Rerror
342  Tflush Rflush
343  Twalk Rwalk
344  Topen Ropen
345  Tcreate Rcreate
346  Tread Rread
347  Twrite Rwrite
348  Tclunk Rclunk
349  Tremove Rremove
350  Tstat Rstat
351  Twstat Rwstat
352
353As you can see, all messages (except Rerror) come in pairs: there is a transmit message (that starts with a T) and a response message (that starts with an R).  The client sends transmit messages and the server sends response message in return.  It must either send the matching response message or Rerror.  It is not allowed to return a different message, nor is it allowed for the client to send a response message or the server to send a transmit message.
354
355The tag is a unique identifier that allows the client to keep track of what it sent and what responses belong to what transmissions.  The client sends a message with a given tag and the server will respond with the matching response message bearing the same tag.  This allows a client to send messages ''asynchronously'', as long as they all have a different tag.  Then the responses can come in any order and be handled at any time and still be understood if the client keeps a list of sent tags and what transmissions belonged to them.  The [[9p-client]] library always sends messages synchronously, waiting for replies before sending new transmissions.  This allows it to use a constant tag all the time.
356
357The contents are a list whose contents differ per message type.  For instance, a Tversion message's contents consist of an {{msize}} (a maximum message size) and a {{string}} which indicates the protocol version.  Currently the 9p-lolevel implicitly assumes the 9P2000 version of the protocol because of the way it is constructed.  If it turns out to be useful to support different versions, the egg's API will most likely change in order to allow for more flexibility.
358
359You can of course query and modify the message objects with the following procedures:
360  9p:message?
361  9p:message-type
362  9p:message-type-set!
363  9p:message-tag
364  9p:message-tag-set!
365  9p:message-contents
366  9p:message-contents-set!
367
368===== 9p:send-message
369
370  procedure: (9p:send-message outport message)
371
372Sends the {{message}} on the output-port {{outport}}.
373
374===== 9p:receive-message
375
376  procedure: (9p:receive-message inport)
377
378Waits for a message on input-port {{inport}} and returns a 9p message-object.
379 
380==== QIDs
381
382A QID is an unique identifier for a file on the server; two QIDs are the same iff they point to the same file.  A QID has three fields which can be queried with the following procedures:
383
384  procedure: (9p:qid-type)
385  procedure: (9p:qid-version)
386  procedure: (9p:qid-path)
387
388You can create a QID using the {{make-9p:qid}} procedure:
389
390  procedure: (make-9p:qid type version path)
391
392Finally, you can check if an object is a QID object with the {{9p:qid?}} predicate:
393
394  procedure: (9p:qid? object)
395
396The fields of the QID will be described next.
397
398First, the type of a QID is a bitwise field which consists of several of the following constants ORed together:
399
400  9p:qtfile
401 
402{{9p:qtfile}} indicates that the file is, in fact, a file.  Because everything in Plan9 is a file, this is always true, even for directories.  It does ''not'' mean that the file is a regular file.
403 
404  9p:qtdir
405
406{{9p:qtdir}} indicates that the file is a directory.
407
408  9p:qtappend
409
410{{9p:qtappend}} indicates that the file is an append-only file.
411
412  9p:qtexcl
413
414{{9p:qtexcl}} indicates that the file is marked for exclusive-use.  This means that only one client can have this file open at any time.
415
416  9p:qtauth
417
418{{9p:qtauth}} indicates that the file is an authentication file established by AUTH messages.
419 
420  9p:qttmp
421
422{{9p:qttmp}} indicates that the file is a "temporary file".  In practice this means that the file is not included in nightly backups.
423
424The version of a QID is a version number for the file which is incremented every time the file is modified.
425
426The path of a QID is an integer that is unique among all files in the file hierarchy (ie, this uniquely identifies the file in the FS).
427
428==== Permission bits
429
430The permissions below can be ORed together bitwise to produce the desired permission mode.  When creating new files, the execute bit is ignored by the server unless you're creating a directory, so it is safe to always include it.
431
432'''Note:''' The 9p protocol documentation is not very consistent in naming these.  Sometimes it refers to permissions as ''mode'', and sometimes as ''perm'' or ''permission''.  On other occasions, it refers to the [[#Open flags|open flags]] as ''mode''.  Read carefully and check the context!
433
434   9p:perm/irusr
435   9p:perm/iwusr
436   9p:perm/ixusr
437
438These constants determine the permissions for the user who owns the file: read, write and execute, respectively.
439
440   9p:perm/irgrp
441   9p:perm/iwgrp
442   9p:perm/ixgrp
443   
444These constants determine the permissions for the group that owns the file: read, write and execute, respectively.
445
446   9p:perm/iroth
447   9p:perm/iwoth
448   9p:perm/ixoth
449
450These constants determine the permissions for others: read, write and execute, respectively.
451
452There are some additional "permissions" that can be used on {{Tcreate}} messages, which are not really permissions but rather modes that change the way the file behaves (hence the inconsistence of the docs).  These are like the 'special' bits in Unix like sticky/setuid etc.  These are the following:
453
454  9p:dmdir
455
456This is used to create directories instead of files with {{Tcreate}}.
457
458  9p:dmappend
459
460The file can only be appended to.
461
462  9p:dmexcl
463
464The file is 'exclusive', it can only be opened by one client at a time.
465
466  9p:dmauth
467
468The file is an authentication file, as established by AUTH messages.
469
470  9p:dmtmp
471
472The file is to be considered "temporary".  In practice this means that it is not included in nightly backups.
473
474==== Open flags
475
476These flags are useful when opening a new file (for use in the {{Topen}}/{{Tcreate}} messages).  These can be ORed together bitwise to produce the desired mode.
477
478   9p:open/rdonly
479
480The file is to be opened only for reading.
481
482   9p:open/wronly
483
484The file is to be opened only for writing.
485
486   9p:open/rdwr
487
488The file is to be opened both for reading and writing.
489
490   9p:open/trunc
491
492The file is to be truncated on opening.
493
494   9p:open/rclose
495
496The file is to be removed upon closing (ie, when the FID is clunked).
497
498==== Utility procedures
499
500===== 9p:data->directory-listing
501
502  procedure: (9p:data->directory-listing data show-dotfiles?)
503
504Because the 9p protocol requires you to use the {{Tread}}/{{Rread}} messages to read both from files and directories, the {{Rread}} response can be considered to be a polymorphic type.  In case of files, the data is simply a bytestream, but in case of directories, the data will be structured.  This means the data needs to be decoded.
505
506This procedures decodes the {{data}} obtained from the {{Rread}} message and returns a list of filenames which are the directory listing for the directory that was read.  If {{show-dotfiles?}} is {{#f}} files starting with a dot are excluded from the list.
507
508Note: The converse procedure, {{9p:directory-listing->data}}, is currently not implemented.
509
510=== Changelog
511
5120.1 Initial release
513
514
515=== License
516
517  Copyright (c) 2008, Peter Bex
518  All rights reserved.
519 
520  Redistribution and use in source and binary forms, with or without
521  modification, are permitted provided that the following conditions are
522  met:
523 
524  Redistributions of source code must retain the above copyright
525  notice, this list of conditions and the following disclaimer.
526 
527  Redistributions in binary form must reproduce the above copyright
528  notice, this list of conditions and the following disclaimer in the
529  documentation and/or other materials provided with the distribution.
530 
531  Neither the name of the author nor the names of its contributors may
532  be used to endorse or promote products derived from this software
533  without specific prior written permission.
534 
535  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
536  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
537  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
538  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
539  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
540  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
541  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
542  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
543  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
544  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
545  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
546  OF THE POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.