On Jan 14, 2008, at 3:10 PM, roger peppe wrote:
i agree that it's too hard to create servers for simple filesystems.
i've been wondering on and off for years what a "low-bar-to-entry"
filesystem
creating library might look like, and my current thoughts go
something like:
I've been playing around with my own implementation of 9P in Ruby in
an effort to explore this problem space and to better understand 9P.
I don't know how many people on this list are familiar with ruby but
it is pretty readable so I'll throw out some examples of my code and
see what you think. The example below does everything locally, but
I've got facilities for connecting and serving via TCP and the 9P-
wire protocol.
I'd appreciate comments/feedback.
class Example < Device
class Root < Directory
root :mode => 0555
child 'readonly', :mode => 0600
child 'text', :mode => 0600, :contents => 'some text to
start with'
child 'subdir/' :mode => 0700 do
child 'subfile' :mode => 0555
end
child 'bob' :mode => 0600, :uid => 'bob'
child 'all' :mode => 0444
# Lets define a Pipe resource
class Pipe < Resource
# incoming write requests get forwarded to aux object
def write(fid, offset, data)
aux.write(data)
end
# incoming read requests get forwarded to aux object
def read(fid, offset, count)
aux.read(count)
end
end
# Everytime the Device gets instantiated construct
# a unix domain socketpair, attach the ends to two
# new Pipe resources and then put the Pipe resources
# in the device namespace.
child 'pipe/' :mode => 0700 do
data, data1 = *UNIXSocket.socketpair
child 'data', Pipe, :mode => 0600, :aux => data
child 'data1', Pipe, :mode => 0600, :aux => data1
end
end
end
# Everytime Example is instantiated we'll get a hiearchy like:
# /readonly
# /text
# /subdir
# /subdir/subfile
# /bob
# /all
# /pipe
# /pipe/data data/data1 connected via Unix pipe
# /pipe/data1
# Access the device via 9P API
device = Example.new
device.version # Tversion
a = device.auth # Tauth
r = device.attach(a) # Tattach
data = r.walk('pipe', 'data').open(ORDWR)
data.write('some text')
data1 = r.walk('pipe', 'data1').open
puts data1.read # read until EOF (0 byte read)
# Now construct a Plan 9-like namespace for access
ns = NS.attach(Device.new) # start with memory fs device mounted
at '/'
ns.mkdir '/d1'
ns.mkdir '/d2'
ns['/d1'].mount Example.new # instantiate Example and mount
ns['/d2'].mount Example.new # again but on a different directory
d = ns['/d1/pipe/data'].open(ORDWR)
d.write('some txt')
puts ns['/d1/pipe/data1'].open.read # read from the other end