9P (Plan 9 Filesystem Protocol) VFS

20060322 -- I have started work on a VFS to transparently access file servers via 9P [L1 ], the Plan 9 [L2 ] [L3 ] filesystem protocol. Technically, we support the 9P2000 'version' of 9P.

The code is based on the python 9P implementation by Tim Newsham [L4 ].

The current version of the (work in progress/proof of concept) code can be accessed here: http://plan9.bell-labs.com/sources/contrib/axel/tcl/9pvfs/

Requirements on Tcl version:

  • 64bit int support (Tcl 8.4)
  • chan create subcommand (Tcl 8.5).

Currently the code makes it easy to use 9P as a client in tcl.

Initially the access was readonly, 20060621 support was added to write/create/delete files and create and delete directories.

The intention is to also provide support to easily create (simple) 'synthetic' (virtual) file servers that can be accessed via 9P. That would allow tcl programs to offer access to their resources via 9P.

I'm not sure what the link could be (would be, should be) with something like tclvfs -- ideally there would be one way to define (describe, code, make) a (synthetic) file server in tcl. And then there should be a way to 'ask' any such synthetic file server to talk 9P, either over a given chan, or over a freshly created new chan.

I'll think out loud a bit about creation of synthetic 9P servers at the bottom of this page. Once there has been sufficient thinking I'll start experimenting with code.

To do:

  • make sure that we use the right mechanisms to report errors (we use vfs::filesystem posixerror and error)
  • rethink the Mount arguments a bit, also (in particular) when using authentication.
  • package it properly
  • better naming for dynamically created global variables
  • use better random number generator for auth
  • add support for creation of 9P (synthetic) file servers
  • ...

I could probably use some help regarding the naming for dynamically created global variables and maybe also with packaging and/or proper use of namespaces to make the code conform to current tcl standards. I have tried to use namespaces to structure the code, but my experience with namespaces is limited.

Right now there is code to mount a file system over 9P and transparently access it -- code that allows one to use 9P as a client.

The file "main-no-auth.tcl" [L5 ] there mounts the public Plan 9 source repository as user none (without authenticating, like anonymous ftp access) and then accesses it:

 source 9pvfs.tcl

 set fs [socket sources.cs.bell-labs.com 564]
 fconfigure $fs -translation  binary

 # mount as user none on /tmp
 vfs::9p::Mount $fs none /tmp

 puts [glob [file join /tmp *]]

 set f [open /tmp/plan9/NOTICE r]
 puts [read $f]
 close $f
 cd /tmp/patch
 puts [glob ./*]

 cd ../plan9

 set f [open LICENSE r]
 puts [read $f]
 close $f
 set f1 [open /tmp/plan9/NOTICE r]
 set f2 [open LICENSE r]
 set f3 [open /tmp/plan9/NOTICE r]
 puts [read $f2]
 puts [read $f1]
 puts [read $f3]
 close $f1
 close $f3
 close $f2
 foreach fn [list /tmp/plan9/NOTICE /tmp / plan9/LICENSE] {
   file stat $fn X
   foreach e [array names X] {
     puts "file stat $fn  $e $X($e)"

The file"main-auth.tcl" [L6 ] accesses the same repository as a different user, for which authentication is needed. This will fail unless you have an account there. The authentication mechanism uses DES, and hence it requires tclDES.

 lappend auto_path tclDES-0.8
 source 9pvfs.tcl
 source p9sk1.tcl

 set fs [socket sources.cs.bell-labs.com 564]
 fconfigure $fs -translation  binary

 # mount on /tmp using username name and password secret
 # using authentication server sources.cs.bell-labs.com
 # to verify username and password
 # (have to do this better)
 vfs::9p::Mount $fs name /tmp sources.cs.bell-labs.com secret

 puts [glob [file join /tmp *]]

Regarding creation of synthetic 9P file servers: (just thinking out loud)

20060322 -- Initial idea:

It might prove interesting to implement a synthetic 9P file server also as a (user created) tcl channel, using chan create.

Why? Because, essentially, all that 9P needs is a reliable byte stream, and in that respect the chan is as general as we can get. Also, it allows us to access synthetic tcl 9P servers in exactly the same way as we treat real remote 9P file servers that we access over the network (using socket in the examples above).

Open questions:

  • can we multiplex the access to a single tcl chan? (to have multiple clients accessing a single server)
  • can we export a chan via tcp? (can we open a listen socket and connect all incoming connections to the open synthetic file server chan?)
  • can we create something like Plan 9 /srv where servers can post (show, publish) an open chan that clients can then use to access them?

20060323 -- thinking a bit more:

Probably a synthetic file server should not have a single chan on which it is accessable via 9P, but multiple. That would deal with the first two open questions above.

Assuming that we have a way to create a (9P) synthetic file server, and that we have an 'object' (or command) to access it. Then we should be able to do two things:

  • give this object (or command) an open file descriptor (chan) and ask it to serve its files via 9P on that
  • ask this object (or command) to create a fresh open file descriptor (chan) and serve its files via 9P on that

The first thing allows us to separately create the 'transport' over which the client accesses the server (for example: the channel created for an incoming connection of a listen socket). The second thing takes care of the simple case where we don't care about the underlying transport but just want to access the synthetic file server.

Axel Belinfante