Module: RFuse

Defined in:
lib/rfuse.rb,
lib/rfuse/version.rb,
ext/rfuse/filler.c,
ext/rfuse/context.c,
ext/rfuse/file_info.c,
ext/rfuse/rfuse_mod.c

Overview

Ruby FUSE (Filesystem in USErspace) binding

Defined Under Namespace

Classes: Context, Error, FileInfo, Filler, Fuse, FuseDelegator, Stat, StatVfs

Constant Summary collapse

VERSION =
"1.2.3"
FUSE_MAJOR_VERSION =

The underlying FUSE library major version

INT2FIX(FUSE_MAJOR_VERSION)
FUSE_MINOR_VERSION =

The underlyfing FUSE library minor versoin

INT2FIX(FUSE_MINOR_VERSION)

Class Method Summary collapse

Class Method Details

.main(argv = ARGV, extra_options = [], extra_options_usage = nil, device = nil, exec = File.basename($0)) {|options, argv| ... } ⇒ Object

Convenience method to launch a fuse filesystem, with nice usage messages and default signal traps

Examples:


class MyFuse < Fuse
   def initialize(myfs,*argv)
      @myfs = myfs # my filesystem local option value
      super(*argv)
   end
   # ... implementations for filesystem methods ...
end

class MyFSClass  # not a subclass of Fuse, FuseDelegator used
   def initialize(myfs)
    @myfs = myfs # my filesystem local option value
   end
   # ...
end

MY_OPTIONS = [ :myfs ]
OPTION_USAGE = "  -o myfs=VAL how to use the myfs option"
DEVICE_USAGE = "how to use device arg"

# Normally from the command line...
ARGV = [ "some/device", "/mnt/point", "-h", "-o", "debug,myfs=aValue" ]

RFuse.main(ARGV, MY_OPTIONS, OPTION_USAGE, DEVICE_USAGE, $0) do |options, argv|

    # options ==
       { :device => "some/device",
         :mountpoint => "/mnt/point",
         :help => true,
         :debug => true,
         :myfs => "aValue"
       }

    # ... validate options...
    raise RFuse::Error, "Bad option" unless options[:myfs]

    # return the filesystem class to be initialised by RFuse
    MyFuse
    # or
    MyFSClass

    # OR take full control over initialisation yourself and return the object
    MyFuse.new(options[:myfs],*argv)
    # or
    MyFSClass.new(options[:myfs])

end

Parameters:

  • argv (Array<String>) (defaults to: ARGV)

    command line arguments

  • extra_options (Array<Symbol>) (defaults to: [])

    list of additional options

  • extra_options_usage (String) (defaults to: nil)

    describing additional option usage

  • device (String) (defaults to: nil)

    a description of the device field

  • exec (String) (defaults to: File.basename($0))

    the executable file

Yield Parameters:

Yield Returns:

  • (Class<Fuse>)

    a subclass of Fuse that implements your filesystem. Will receive .new(*extra_options,*argv)

  • (Class)

    a class that implements RFuse::FuseDelegator::FUSE_METHODS. Will receive .new(*extra_options) and the resulting instance sent with *argv to FuseDelegator

  • (Fuse)

    Your initialised (and therefore already mounted) filesystem

  • (Object)

    An object that implements the Fuse methods, to be passed with *argv to FuseDelegator

  • (Error)

    raise Error with appropriate message for invalid options

Since:

  • 1.1.0



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/rfuse.rb', line 204

def self.main(argv=ARGV,extra_options=[],extra_options_usage=nil,device=nil,exec=File.basename($0))

    options = parse_options(argv,*extra_options)

    unless options[:mountpoint]
        $stderr.puts "rfuse: failed, no mountpoint provided"
        puts usage(device,exec)
        return nil
    end

    if options[:help]
        puts usage(device,exec)
        # TODO: In Fuse 3.0 this looks like it will move to $stdout
        help_io = STDERR
        help_io.puts "Fuse options: (#{FUSE_MAJOR_VERSION}.#{FUSE_MINOR_VERSION})"
        help_io.puts "    -h                     help - print this help output"
        help_io.puts "    -d |-o debug           enable internal FUSE debug output"
        help_io.puts ""
        help_io.flush()

        # Cause Fuse kernel Options to print, but don't actually start a filesystem
        Fuse.new(*argv)

        if extra_options_usage
            help_io.puts "Filesystem options:"
            help_io.puts extra_options_usage
        end

        return nil
    end

    begin
        fs = yield options,argv

        raise Error, "no filesystem provided" unless fs

        fuse = create(fs,argv,options,extra_options)

        raise Error, "filesystem #{fs} not mounted" unless fuse && fuse.mounted?

        fuse.run
    rescue Error => fuse_ex
        # These errors are produced generally because the user passed bad arguments etc..
        puts usage(device,exec) unless options[:help]
        $stderr.puts "rfuse failed: #{fuse_ex.message}"
        return nil
    rescue => ex
        # These are other errors related the yield block
        $stderr.puts ex.message
        $stderr.puts ex.backtrace.join("\n")
    end

end

.parse_options(argv, *local_opts) ⇒ Hash<Symbol,String|Boolean>

Parse mount arguments and options

Fuse itself will normalise arguments

mount -t fuse </path/to/fs.rb>#<device> mountpoint [options...]
mount.fuse </path/to/fs.rb>#<device> mountpoint [options...]

both result in the following command execution

/path/to/fs.rb [device] mountpoint [-h] [-d] [-o [opt,optkey=value,...]]

which this method will parse into a Hash with the following special keys

  • :device - the optional mount device, removed from argv if present
  • :mountpoint - required mountpoint
  • :help - if -h was supplied - will print help text (and not mount the filesystem!)
  • :debug - if -d (or -o debug) was supplied - will print debug output from the underlying FUSE library

and any other supplied options.

Examples:

ARGV = [ "some/device", "/mnt/point", "-h", "-o", "debug,myfs=aValue" ]
options = RFuse.parse_options(ARGV,:myfs)

# options ==
{ :device => "some/device",
  :mountpoint => "/mnt/point",
  :help => true,
  :debug => true,
  :myfs => "aValue"
}
# and ARGV ==
[ "/mnt/point","-h","-o","debug" ]

fs = create_filesystem(options)
fuse = RFuse::FuseDelegator.new(fs,*ARGV)

Parameters:

  • argv (Array<String>)

    normalised fuse options

  • local_opts (Array<Symbol>)

    local options if these are found in the argv entry following "-o" they are removed from argv, ie so argv is a clean set of options that can be passed to Fuse or FuseDelegator

Returns:

  • (Hash<Symbol,String|Boolean>)

    the extracted options

Since:

  • 1.0.3



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/rfuse.rb', line 74

def self.parse_options(argv,*local_opts)
    result = Hash.new(nil)

    first_opt_index = (argv.find_index() { |opt| opt =~ /^-.*/ } || argv.length )

    result[:device] = argv.shift if first_opt_index > 1
    result[:mountpoint] = argv[0] if argv.length > 0

    if argv.include?("-h")
        result[:help]  =  true
    end

    if argv.include?("-d")
        result[:debug] = true
    end

    opt_index = ( argv.find_index("-o") || -1 ) + 1

    if opt_index > 1 && opt_index < argv.length
        options = argv[opt_index].split(",")

        options.delete_if() do |opt|
            opt.strip!

            opt,value = opt.split("=",2)
            value = true unless value
            opt_sym = opt.to_sym
            result[opt_sym] = value

            #result of delete if
            local_opts.include?(opt_sym)
        end

        if options.empty?
            argv.slice!(opt_index - 1,2)
        else
            argv[opt_index] = options.join(",")
        end
    end

    result
end

.usage(device = nil, exec = File.basename($0)) ⇒ String

Generate a usage string

Parameters:

  • device (String) (defaults to: nil)

    a description of how the device field should be used

  • exec (String) (defaults to: File.basename($0))

    the executable

Returns:

  • (String)

    the usage string



122
123
124
# File 'lib/rfuse.rb', line 122

def self.usage(device=nil,exec=File.basename($0))
    "Usage:\n     #{exec} #{device} mountpoint [-h] [-d] [-o [opt,optkey=value,...]]\n"
end