Skip to content

Instantly share code, notes, and snippets.

@sneakin
Created September 17, 2011 17:51
Show Gist options
  • Save sneakin/1224176 to your computer and use it in GitHub Desktop.
Save sneakin/1224176 to your computer and use it in GitHub Desktop.
A super basic RFuse file system.
#!/usr/bin/env ruby
#
# Minus the logging, this is the simplest file system that's most likely
# possible with RFuse-NG. It presents a single directory level that stores
# the contents of files in a Hash.
#
# This is in the public domain.
#
# Enjoy,
# sneakin
#
require 'rfuse_ng'
require 'ostruct'
class LoggedOStruct < OpenStruct
def method_missing(mid, *args, &block)
$stderr.puts "#{self}\t#{mid}\t#{args.inspect}" unless mid.to_s =~ /=$/
super
end
end
class MyFS < RFuse::Fuse
def initialize(mnt_pnt, options, libopt)
super(mnt_pnt, options, libopt)
@files = Hash.new
@files['hello.txt'] = "Hello world\n"
end
def readdir(ctx, path, filler, offset, ffi)
$stderr.puts "readdir: #{path} #{offset}"
if path == '/'
@files.each do |path, data|
filler.push(path, create_stat(false, data.length), 0)
end
else
raise Errno::ENOTDIR.new(path)
end
end
def getattr(ctx, path)
$stderr.puts "Getattr: #{path}\t#{@files.has_key?(File.basename(path))}"
if path == '/' || @files.has_key?(File.basename(path))
data = @files[File.basename(path)]
create_stat(path == '/', data ? data.length : 0 )
else
raise Errno::ENOENT.new
end
end
def read(ctx, path, size, offset, fi)
d = @files.fetch(File.basename(path)) { "" }
return d[offset..offset + size - 1]
end
def write(ctx, path, buf, offset, fi)
d = @files[File.basename(path)]
d[offset..offset + buf.length - 1] = buf
return buf.length
end
def mknod(ctx, path, mode, dev)
@files[File.basename(path)] = String.new
end
def unlink(ctx, path)
$stderr.puts "unlink\t#{path}"
@files.delete(File.basename(path))
end
def rename(ctx, path, as)
$stderr.puts "rename\t#{path}\t#{as}"
@files[File.basename(as)] = @files.delete(File.basename(path))
end
def truncate(ctx, path, offset)
$stderr.puts "truncate\t#{path}\t#{offset}"
@files[File.basename(path)] = @files[File.basename(path)][0..offset]
end
def statfs(ctx, path)
print "statfs: #{path}\n"
d = LoggedOStruct.new
d.f_bsize = 0
d.f_frsize = 0
d.f_blocks = 0
d.f_bfree = 0
d.f_bavail = 0
d.f_files = @files.size
d.f_ffree = 0
d.f_favail = 0
d.f_fsid = 0
d.f_flag = 0
d.f_namemax = 0
d
end
def init(ctx, conn_info)
print "Starting...\n"
end
private
def create_stat(is_dir = false, size = 0)
mode = 0666
if is_dir
mode = 0777
mode |= (4 << 12)
else
mode |= (8 << 12)
end
LoggedOStruct.new(:uid => 1, :gid => 1, :mode => mode, :size => size, :ctime => 0, :atime => Time.now.to_i, :mtime => 0, :dev => 0, :ino => 0, :nlink => is_dir ? 2 : 1, :rdev => 0, :blksize => 0, :blocks => 0)
end
end
if __FILE__ == $0
fo = MyFS.new(ARGV[0],["notparsed","-o notparsed,allow_other,volname=MyFS"],["debug"]);
#kernel: default_permissions,allow_other,kernel_cache,large_read,direct_io
# max_read=N,fsname=NAME
#library: debug,hard_remove
Signal.trap("TERM") do
fo.exit
fo.unmount
end
begin
fo.loop
rescue
print "Error:" + $!
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment