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

Reply via email to