rfuse 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES.md +12 -3
- data/README.md +1 -1
- data/ext/rfuse/context.c +0 -1
- data/ext/rfuse/file_info.c +7 -6
- data/ext/rfuse/filler.c +5 -4
- data/ext/rfuse/helper.c +20 -16
- data/ext/rfuse/helper.h +2 -10
- data/ext/rfuse/intern_rfuse.c +5 -10
- data/ext/rfuse/rfuse.c +110 -188
- data/lib/rfuse/version.rb +1 -1
- data/lib/rfuse.rb +87 -3
- data/spec/basic_spec.rb +2 -28
- data/spec/fuse_file_info_spec.rb +41 -12
- data/spec/options_spec.rb +112 -0
- metadata +3 -2
data/lib/rfuse/version.rb
CHANGED
data/lib/rfuse.rb
CHANGED
@@ -19,6 +19,91 @@ module RFuse
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
# Parse mount arguments and options
|
23
|
+
#
|
24
|
+
# @param [Array<String>] argv
|
25
|
+
# normalised fuse options
|
26
|
+
#
|
27
|
+
# @param [Array<Symbol>] local_opts local options
|
28
|
+
# if these are found in the argv entry following "-o" they are removed
|
29
|
+
# from argv, ie so argv is a clean set of options that can be passed
|
30
|
+
# to {RFuse::Fuse} or {RFuse::FuseDelegator}
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# @return [Hash{Symbol => String,Boolean}]
|
34
|
+
# the extracted options
|
35
|
+
#
|
36
|
+
# @since 1.0.3
|
37
|
+
#
|
38
|
+
# Fuse itself will normalise arguments
|
39
|
+
#
|
40
|
+
# mount -t fuse </path/to/fs>#<device> mountpoint [options...]
|
41
|
+
# mount.fuse </path/to/fs>#<device> mountpoint [options...]
|
42
|
+
#
|
43
|
+
# both result in a call to /path/to/fs with arguments...
|
44
|
+
#
|
45
|
+
# [device] mountpoint [-h] [-o [opt,optkey=value,...]]
|
46
|
+
#
|
47
|
+
# which this method will parse into a Hash with the following special keys
|
48
|
+
#
|
49
|
+
# :device - the optional mount device, removed from argv if present
|
50
|
+
# :mountpoint - required mountpoint
|
51
|
+
# :help - true if -h was supplied
|
52
|
+
#
|
53
|
+
# and any other supplied options.
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# ARGV = [ "some/device", "/mnt/point", "-h", "-o", "debug,myfs=aValue" ]
|
57
|
+
# options = RFuse.parse_options(ARGV,:myfs)
|
58
|
+
#
|
59
|
+
# # options ==
|
60
|
+
# { :device => "some/device",
|
61
|
+
# :mountpoint => "/mnt/point",
|
62
|
+
# :help => true,
|
63
|
+
# :debug => true,
|
64
|
+
# :myfs => "aValue"
|
65
|
+
# }
|
66
|
+
# # and ARGV ==
|
67
|
+
# [ "/mnt/point","-h","-o","debug" ]
|
68
|
+
#
|
69
|
+
# fs = create_filesystem(options)
|
70
|
+
# fuse = RFuse::FuseDelegator.new(fs,*ARGV)
|
71
|
+
#
|
72
|
+
def self.parse_options(argv,*local_opts)
|
73
|
+
result = Hash.new(nil)
|
74
|
+
|
75
|
+
first_opt_index = (argv.find_index() { |opt| opt =~ /-.*/ } || argv.length )
|
76
|
+
|
77
|
+
result[:device] = argv.shift if first_opt_index > 1
|
78
|
+
result[:mountpoint] = argv[0] if argv.length > 0
|
79
|
+
|
80
|
+
if argv.include?("-h")
|
81
|
+
result[:help] = true
|
82
|
+
end
|
83
|
+
|
84
|
+
opt_index = ( argv.find_index("-o") || -1 ) + 1
|
85
|
+
|
86
|
+
if opt_index > 1 && opt_index < argv.length
|
87
|
+
options = argv[opt_index].split(",")
|
88
|
+
|
89
|
+
options.delete_if() do |opt|
|
90
|
+
opt.strip!
|
91
|
+
|
92
|
+
opt,value = opt.split("=",2)
|
93
|
+
value = true unless value
|
94
|
+
opt_sym = opt.to_sym
|
95
|
+
result[opt_sym] = value
|
96
|
+
|
97
|
+
#result of delete if
|
98
|
+
local_opts.include?(opt_sym)
|
99
|
+
end
|
100
|
+
|
101
|
+
argv[opt_index] = options.join(",")
|
102
|
+
end
|
103
|
+
|
104
|
+
result
|
105
|
+
end
|
106
|
+
|
22
107
|
class Fuse
|
23
108
|
|
24
109
|
# Main processing loop
|
@@ -40,7 +125,7 @@ module RFuse
|
|
40
125
|
ready, ignore, errors = IO.select([@fuse_io,@pr],[],[@fuse_io])
|
41
126
|
|
42
127
|
if ready.include?(@pr)
|
43
|
-
|
128
|
+
|
44
129
|
@pr.getc
|
45
130
|
@running = false
|
46
131
|
|
@@ -75,7 +160,7 @@ module RFuse
|
|
75
160
|
# afer the filesystem has been mounted successfully
|
76
161
|
def ruby_initialize
|
77
162
|
@pr,@pw = IO.pipe()
|
78
|
-
|
163
|
+
|
79
164
|
# The FD was created by FUSE so we don't want
|
80
165
|
# ruby to do anything with it during GC
|
81
166
|
@fuse_io = IO.for_fd(fd(),"r",:autoclose => false)
|
@@ -219,5 +304,4 @@ module RFuse
|
|
219
304
|
end
|
220
305
|
end
|
221
306
|
end
|
222
|
-
|
223
307
|
end #Module RFuse
|
data/spec/basic_spec.rb
CHANGED
@@ -9,32 +9,6 @@ describe RFuse::Fuse do
|
|
9
9
|
let!(:mockfs) { m = mock("fuse"); m.stub(:getattr).and_return(nil); m }
|
10
10
|
let(:mountpoint) { tempmount() }
|
11
11
|
|
12
|
-
context "mount options" do
|
13
|
-
it "should handle -h" do
|
14
|
-
fuse = RFuse::FuseDelegator.new(mockfs,mountpoint,"-h")
|
15
|
-
fuse.mounted?.should be_false
|
16
|
-
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should behave sensibly for bad mountpoint" do
|
20
|
-
fuse = RFuse::FuseDelegator.new(mockfs,"bad/mount/point")
|
21
|
-
fuse.mounted?.should be_false
|
22
|
-
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should behave sensibly for bad options" do
|
26
|
-
fuse = RFuse::FuseDelegator.new(mockfs,mountpoint,"-eviloption")
|
27
|
-
fuse.mounted?.should be_false
|
28
|
-
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should handle a Pathname as a mountpoint" do
|
32
|
-
fuse = RFuse::FuseDelegator.new(mockfs,Pathname.new(mountpoint))
|
33
|
-
fuse.mounted?.should be_true
|
34
|
-
fuse.unmount()
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
12
|
context "links" do
|
39
13
|
it "should create and resolve symbolic links"
|
40
14
|
|
@@ -175,13 +149,13 @@ describe RFuse::Fuse do
|
|
175
149
|
reads = 0
|
176
150
|
mockfs.stub(:read) { |ctx,path,size,offset,ffi|
|
177
151
|
reads += 2
|
178
|
-
"hello
|
152
|
+
"hello\000world"[offset,reads]
|
179
153
|
}
|
180
154
|
|
181
155
|
with_fuse(mountpoint,mockfs) do
|
182
156
|
File.open("#{mountpoint}/test") do |f|
|
183
157
|
val = f.gets
|
184
|
-
val.should == "hello
|
158
|
+
val.should == "hello\000world"
|
185
159
|
end
|
186
160
|
end
|
187
161
|
end
|
data/spec/fuse_file_info_spec.rb
CHANGED
@@ -1,21 +1,51 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe RFuse::Fuse do
|
4
|
+
|
5
|
+
let(:dir_stat) { RFuse::Stat.directory(0444) }
|
6
|
+
let(:file_stat) { RFuse::Stat.file(0444) }
|
7
|
+
let!(:mockfs) { m = mock("fuse"); m.stub(:getattr).and_return(nil); m }
|
8
|
+
let(:mountpoint) { tempmount() }
|
9
|
+
let(:open_files) { Hash.new() }
|
10
|
+
|
11
|
+
it "should pass fileinfo to #release" do
|
12
|
+
|
13
|
+
file_handle = Object.new()
|
14
|
+
stored_ffi = nil
|
15
|
+
captured_ex = nil
|
16
|
+
|
17
|
+
mockfs.stub(:getattr).with(anything(),"/ffirelease").and_return(file_stat)
|
18
|
+
|
19
|
+
mockfs.should_receive(:open).with(anything(),"/ffirelease",anything()) { |ctx,path,ffi|
|
20
|
+
stored_ffi = ffi
|
21
|
+
ffi.fh = file_handle
|
22
|
+
}
|
23
|
+
|
24
|
+
mockfs.should_receive(:release).with(anything(),"/ffirelease",anything()) { |ctx,path,ffi|
|
25
|
+
# the return value of release is ignore, so exceptions here are lost
|
26
|
+
begin
|
27
|
+
ffi.fh.should == file_handle
|
28
|
+
ffi.should == stored_ffi
|
29
|
+
rescue Exception => ex
|
30
|
+
captured_ex = ex
|
31
|
+
end
|
32
|
+
}
|
33
|
+
|
34
|
+
with_fuse(mountpoint,mockfs) do
|
35
|
+
f1 = File.new("#{mountpoint}/ffirelease")
|
36
|
+
f1.close()
|
37
|
+
end
|
38
|
+
|
39
|
+
raise captured_ex if captured_ex
|
40
|
+
end
|
41
|
+
|
4
42
|
context "file handles" do
|
5
43
|
it "should retain file handles over GC" do
|
6
|
-
mockfs = mock("fuse")
|
7
44
|
|
8
|
-
file_stat
|
45
|
+
file_stat.size = 11
|
9
46
|
|
10
|
-
mockfs.stub(:getattr)
|
11
|
-
|
12
|
-
when "/one","/two"
|
13
|
-
file_stat
|
14
|
-
else
|
15
|
-
nil
|
16
|
-
end
|
17
|
-
|
18
|
-
}
|
47
|
+
mockfs.stub(:getattr).with(anything(),"/one").and_return(file_stat)
|
48
|
+
mockfs.stub(:getattr).with(anything(),"/two").and_return(file_stat)
|
19
49
|
|
20
50
|
open_files = {}
|
21
51
|
mockfs.stub(:open) { |ctx,path,ffi|
|
@@ -29,7 +59,6 @@ describe RFuse::Fuse do
|
|
29
59
|
"hello world"
|
30
60
|
}
|
31
61
|
|
32
|
-
mountpoint = tempmount()
|
33
62
|
with_fuse(mountpoint,mockfs) do
|
34
63
|
f1 = File.new("#{mountpoint}/one")
|
35
64
|
f2 = File.new("#{mountpoint}/two")
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pathname'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
describe RFuse do
|
6
|
+
|
7
|
+
let(:dir_stat) { RFuse::Stat.directory(0444) }
|
8
|
+
let(:file_stat) { RFuse::Stat.file(0444) }
|
9
|
+
let!(:mockfs) { m = mock("fuse"); m.stub(:getattr).and_return(nil); m }
|
10
|
+
let(:mountpoint) { tempmount() }
|
11
|
+
|
12
|
+
context "mount options" do
|
13
|
+
it "should handle -h" do
|
14
|
+
fuse = RFuse::FuseDelegator.new(mockfs,mountpoint,"-h")
|
15
|
+
fuse.mounted?.should be_false
|
16
|
+
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should behave sensibly for bad mountpoint" do
|
20
|
+
fuse = RFuse::FuseDelegator.new(mockfs,"bad/mount/point")
|
21
|
+
fuse.mounted?.should be_false
|
22
|
+
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should behave sensibly for bad options" do
|
26
|
+
fuse = RFuse::FuseDelegator.new(mockfs,mountpoint,"-eviloption")
|
27
|
+
fuse.mounted?.should be_false
|
28
|
+
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should handle a Pathname as a mountpoint" do
|
32
|
+
fuse = RFuse::FuseDelegator.new(mockfs,Pathname.new(mountpoint))
|
33
|
+
fuse.mounted?.should be_true
|
34
|
+
fuse.unmount()
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "#parse_options" do
|
39
|
+
|
40
|
+
it "should detect -h" do
|
41
|
+
argv = [ "/mountpoint","-h" ]
|
42
|
+
result = RFuse.parse_options(argv)
|
43
|
+
|
44
|
+
result[:help].should be_true
|
45
|
+
result[:mountpoint].should == "/mountpoint"
|
46
|
+
result[:debug].should be_false
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should detect -h mixed with -o" do
|
50
|
+
argv = [ "/mountpoint","-h", "-o", "debug" ]
|
51
|
+
result = RFuse.parse_options(argv)
|
52
|
+
|
53
|
+
result[:help].should be_true
|
54
|
+
result[:mountpoint].should == "/mountpoint"
|
55
|
+
result[:debug].should be_true
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should detect debug" do
|
59
|
+
argv = [ "/mountpoint","-o","debug" ]
|
60
|
+
result = RFuse.parse_options(argv)
|
61
|
+
|
62
|
+
result[:debug].should be_true
|
63
|
+
result[:help].should be_false
|
64
|
+
|
65
|
+
argv = [ "/mountpoint","-o","default_permissions,debug" ]
|
66
|
+
result = RFuse.parse_options(argv)
|
67
|
+
result[:debug].should be_true
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should remove local options" do
|
71
|
+
argv = [ "/mountpoint","-o","debug,myoption" ]
|
72
|
+
|
73
|
+
result = RFuse.parse_options(argv,:myoption)
|
74
|
+
|
75
|
+
result[:debug].should be_true
|
76
|
+
result[:myoption].should be_true
|
77
|
+
|
78
|
+
argv[2].should == "debug"
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should parse values from options" do
|
82
|
+
argv = [ "/mountpoint", "-o", "debug,someopt=somevalue" ]
|
83
|
+
result = RFuse.parse_options(argv)
|
84
|
+
|
85
|
+
result[:someopt].should == "somevalue"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should parse values and remove local options" do
|
89
|
+
argv = [ "/mountpoint", "-o", "debug,someopt=somevalue" ]
|
90
|
+
result = RFuse.parse_options(argv,:someopt)
|
91
|
+
|
92
|
+
result[:someopt].should == "somevalue"
|
93
|
+
argv[2].should == "debug"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should parse and remove optional device" do
|
97
|
+
|
98
|
+
argv = [ "a device", "/mountpoint" , "-o", "rw,debug,default_permissions" ]
|
99
|
+
result = RFuse.parse_options(argv)
|
100
|
+
|
101
|
+
result[:device].should == "a device"
|
102
|
+
result[:mountpoint].should == "/mountpoint"
|
103
|
+
result[:rw].should be_true
|
104
|
+
result[:debug].should be_true
|
105
|
+
result[:default_permissions].should be_true
|
106
|
+
|
107
|
+
argv.length.should == 3
|
108
|
+
argv.join(" ").should == "/mountpoint -o rw,debug,default_permissions"
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rfuse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -135,6 +135,7 @@ files:
|
|
135
135
|
- sample/test-ruby.rb
|
136
136
|
- spec/basic_spec.rb
|
137
137
|
- spec/fuse_file_info_spec.rb
|
138
|
+
- spec/options_spec.rb
|
138
139
|
- spec/ruby_loop_spec.rb
|
139
140
|
- spec/spec_helper.rb
|
140
141
|
- spec/xattr_spec.rb
|