rfusefs 1.0.0 → 1.0.1.RC0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/.travis.yml +8 -0
- data/README.rdoc +13 -21
- data/Rakefile +1 -0
- data/lib/fuse/fusedir.rb +15 -0
- data/lib/fuse/rfusefs-fuse.rb +26 -8
- data/lib/fusefs/metadir.rb +2 -1
- data/lib/fusefs/pathmapper.rb +185 -56
- data/lib/fusefs/sqlitemapper.rb +125 -0
- data/lib/rfusefs/version.rb +1 -1
- data/lib/rfusefs.rb +55 -1
- data/rfusefs.gemspec +30 -0
- data/spec/metadir_spec.rb +24 -24
- data/spec/mount_unmount_spec.rb +21 -0
- data/spec/pathmapper_spec.rb +143 -53
- data/spec/rfusefs_spec.rb +23 -1
- data/spec/sample_spec.rb +9 -9
- data/spec/spec_helper.rb +0 -5
- data/spec/sqlitemapper_spec.rb +135 -0
- metadata +49 -9
data/lib/rfusefs.rb
CHANGED
@@ -8,6 +8,59 @@ require 'rfusefs/version'
|
|
8
8
|
module FuseFS
|
9
9
|
@mounts = { }
|
10
10
|
|
11
|
+
# Convenience method to launch a FuseFS filesystem with nice error messages
|
12
|
+
#
|
13
|
+
# @param [Array<String>] argv command line arguments
|
14
|
+
# @param [Array<Symbol>] options list of additional options
|
15
|
+
# @param [String] option_usage describing additional option usage
|
16
|
+
# @param [String] device a description of the device field
|
17
|
+
# @param [String] exec the executable file
|
18
|
+
#
|
19
|
+
# @yieldparam [Hash<Symbol,String>] options
|
20
|
+
# options parsed from ARGV including...
|
21
|
+
# * :device - the optional mount device
|
22
|
+
# * :mountpoint - required mountpoint
|
23
|
+
# * :help - true if -h was supplied
|
24
|
+
#
|
25
|
+
# @yieldreturn [FuseDir] an RFuseFS filesystem
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# MY_OPTIONS = [ :myfs ]
|
29
|
+
# OPTION_USAGE = " -o myfs=VAL how to use the myfs option"
|
30
|
+
#
|
31
|
+
# # Normally from the command line...
|
32
|
+
# ARGV = [ "some/device", "/mnt/point", "-h", "-o", "debug,myfs=aValue" ]
|
33
|
+
#
|
34
|
+
# FuseFS.main(ARGV, MY_OPTIONS, OPTION_USAGE, "/path/to/somedevice", $0) do |options|
|
35
|
+
#
|
36
|
+
# # options ==
|
37
|
+
# { :device => "some/device",
|
38
|
+
# :mountpoint => "/mnt/point",
|
39
|
+
# :help => true,
|
40
|
+
# :debug => true,
|
41
|
+
# :myfs => "aValue"
|
42
|
+
# }
|
43
|
+
#
|
44
|
+
# fs = MyFS.new(options)
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
def FuseFS.main(argv=ARGV,options=[],option_usage="",device=nil,exec=File.basename($0))
|
48
|
+
options = RFuse.parse_options(argv,*options)
|
49
|
+
|
50
|
+
if options[:mountpoint]
|
51
|
+
fs = yield options
|
52
|
+
|
53
|
+
puts RFuse.usage(device,exec) if options[:help] || !fs
|
54
|
+
puts "Options:\n" if options[:help]
|
55
|
+
|
56
|
+
FuseFS.start(fs,*argv) if fs || options[:help]
|
57
|
+
|
58
|
+
puts option_usage if options[:help]
|
59
|
+
else
|
60
|
+
puts "rfusefs: failed, no mountpoint provided",RFuse.usage(device,exec)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
11
64
|
# Start the FuseFS root at mountpoint with opts.
|
12
65
|
# @param [Object] root see {set_root}
|
13
66
|
# @param mountpoint [String] {mount_under}
|
@@ -15,7 +68,6 @@ module FuseFS
|
|
15
68
|
# @note RFuseFS extension
|
16
69
|
# @return [void]
|
17
70
|
def FuseFS.start(root,mountpoint,*opts)
|
18
|
-
print "Starting FuseFS #{root} at #{mountpoint} with #{opts}\n"
|
19
71
|
Signal.trap("TERM") { FuseFS.exit() }
|
20
72
|
Signal.trap("INT") { FuseFS.exit() }
|
21
73
|
FuseFS.set_root(root)
|
@@ -89,7 +141,9 @@ module FuseFS
|
|
89
141
|
# you cannot access your filesystem using ruby File operations.
|
90
142
|
# @note RFuseFS extension
|
91
143
|
def FuseFS.run
|
144
|
+
@fs.mounted()
|
92
145
|
@fuse.loop if @fuse.mounted?
|
146
|
+
@fs.unmounted()
|
93
147
|
end
|
94
148
|
|
95
149
|
# Exit the run loop and teardown FUSE
|
data/rfusefs.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rfusefs/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rfusefs"
|
7
|
+
s.version = RFuseFS::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Grant Gardner"]
|
10
|
+
s.email = ["grant@lastweekend.com.au"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/rfusefs"
|
12
|
+
s.summary = %q{Filesystem in Ruby Userspace}
|
13
|
+
s.description = %q{A more Ruby like way to write FUSE filesystems - inspired by (compatible with) FuseFS, implemented over RFuse}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,spec-fusefs}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.has_rdoc = 'yard'
|
21
|
+
s_extra_rdoc_files = 'History.rdoc'
|
22
|
+
|
23
|
+
s.add_dependency("rfuse", ">= 1.0.4RC0")
|
24
|
+
s.add_development_dependency("rake")
|
25
|
+
s.add_development_dependency("rspec")
|
26
|
+
s.add_development_dependency("yard")
|
27
|
+
s.add_development_dependency("redcarpet")
|
28
|
+
s.add_development_dependency("sqlite3")
|
29
|
+
s.add_development_dependency("rb-inotify")
|
30
|
+
end
|
data/spec/metadir_spec.rb
CHANGED
@@ -220,44 +220,44 @@ describe FuseFS::MetaDir do
|
|
220
220
|
|
221
221
|
end
|
222
222
|
context "in a mounted FUSE filesystem" do
|
223
|
+
|
224
|
+
let(:mountpoint) { Pathname.new(Dir.mktmpdir(["rfusefs","metadir"])) }
|
225
|
+
let(:metadir) { FuseFS::MetaDir.new() }
|
226
|
+
let(:testdir) { mountpoint + "test" }
|
227
|
+
let(:testfile) { testdir + "hello.txt" }
|
228
|
+
|
223
229
|
before(:all) do
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
puts "#{@mountpoint}"
|
228
|
-
@mountpoint.mkdir unless @mountpoint.directory?
|
229
|
-
@metadir = FuseFS::MetaDir.new()
|
230
|
-
@metadir.mkdir("/test")
|
231
|
-
@metadir.write_to("/test/hello.txt","Hello World!\n")
|
232
|
-
FuseFS.mount(@metadir,@mountpoint)
|
233
|
-
@testdir = (@mountpoint + "test")
|
234
|
-
@testfile = (@testdir + "hello.txt")
|
230
|
+
metadir.mkdir("/test")
|
231
|
+
metadir.write_to("/test/hello.txt","Hello World!\n")
|
232
|
+
FuseFS.mount(metadir,mountpoint)
|
235
233
|
#Give FUSE some time to get started
|
236
|
-
sleep(
|
234
|
+
sleep(0.5)
|
237
235
|
end
|
238
236
|
|
239
237
|
after(:all) do
|
240
|
-
FuseFS.unmount(
|
238
|
+
FuseFS.unmount(mountpoint)
|
239
|
+
sleep(0.5)
|
240
|
+
FileUtils.rm_r(mountpoint)
|
241
241
|
end
|
242
242
|
|
243
243
|
it "should list directory contents" do
|
244
|
-
|
244
|
+
testdir.entries().should =~ pathnames(".","..","hello.txt")
|
245
245
|
end
|
246
246
|
|
247
247
|
it "should read files" do
|
248
|
-
|
249
|
-
|
248
|
+
testfile.file?.should be_true
|
249
|
+
testfile.read().should == "Hello World!\n"
|
250
250
|
end
|
251
251
|
|
252
252
|
it "should create directories" do
|
253
|
-
newdir =
|
253
|
+
newdir = testdir + "newdir"
|
254
254
|
newdir.mkdir()
|
255
255
|
newdir.directory?.should be_true
|
256
|
-
|
256
|
+
testdir.entries().should =~ pathnames(".","..","hello.txt","newdir")
|
257
257
|
end
|
258
258
|
|
259
259
|
it "should create files" do
|
260
|
-
newfile =
|
260
|
+
newfile = testdir + "newfile"
|
261
261
|
newfile.open("w") do |file|
|
262
262
|
file << "A new file\n"
|
263
263
|
end
|
@@ -265,14 +265,14 @@ describe FuseFS::MetaDir do
|
|
265
265
|
end
|
266
266
|
|
267
267
|
it "should move directories" do
|
268
|
-
fromdir =
|
268
|
+
fromdir = testdir + "fromdir"
|
269
269
|
fromdir.mkdir()
|
270
270
|
subfile = fromdir + "afile"
|
271
271
|
subfile.open("w") do |file|
|
272
272
|
file << "testfile\n"
|
273
273
|
end
|
274
274
|
|
275
|
-
movedir = (
|
275
|
+
movedir = (mountpoint + "movedir")
|
276
276
|
movedir.directory?.should be_false
|
277
277
|
fromdir.rename(movedir)
|
278
278
|
movedir.directory?.should be_true
|
@@ -283,10 +283,10 @@ describe FuseFS::MetaDir do
|
|
283
283
|
end
|
284
284
|
|
285
285
|
it "should move files" do
|
286
|
-
movefile = (
|
286
|
+
movefile = (mountpoint + "moved.txt")
|
287
287
|
movefile.file?.should be_false
|
288
|
-
|
289
|
-
|
288
|
+
testfile.should be_true
|
289
|
+
testfile.rename(movefile)
|
290
290
|
movefile.read.should == "Hello World!\n"
|
291
291
|
end
|
292
292
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rfusefs'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
describe "a mounted FuseFS" do
|
7
|
+
let(:mountpoint) { Pathname.new(Dir.mktmpdir("rfusefs_mount_unmount")) }
|
8
|
+
|
9
|
+
after(:each) { FileUtils.rmdir mountpoint }
|
10
|
+
|
11
|
+
it "should get mounted and unmounted callbacks" do
|
12
|
+
mock_fs = FuseFS::FuseDir.new()
|
13
|
+
mock_fs.should_receive(:mounted)
|
14
|
+
mock_fs.should_receive(:unmounted)
|
15
|
+
|
16
|
+
t = Thread.new { sleep 0.5 ; puts "exiting" ; FuseFS.exit }
|
17
|
+
FuseFS.start(mock_fs,mountpoint)
|
18
|
+
t.join
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/spec/pathmapper_spec.rb
CHANGED
@@ -1,112 +1,202 @@
|
|
1
1
|
#Pathmapper is hard to test because it is difficult to mock Dir/Pathname/File etc...
|
2
2
|
require "spec_helper"
|
3
3
|
require "fusefs/pathmapper"
|
4
|
+
require 'tmpdir'
|
5
|
+
require 'pathname'
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
class PMFixture
|
8
|
+
attr_reader :tmpdir
|
9
|
+
|
10
|
+
def initialize()
|
11
|
+
@tmpdir = Pathname.new(Dir.mktmpdir("rfusefs_pathmapper"))
|
12
|
+
pathmap(@tmpdir + "hello.txt","/textfiles/hello")
|
13
|
+
pathmap(@tmpdir + "mysong.mp3","/artist/album/mysong.mp3")
|
14
|
+
pathmap(@tmpdir + "apicture.jpeg","/pictures/201103/apicture.jpg")
|
15
|
+
end
|
16
|
+
|
17
|
+
def pathmap(real_file,mapped_path)
|
18
|
+
File.open(real_file.to_s,"w") do |f|
|
19
|
+
f << mapped_path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def fs
|
24
|
+
@fs ||= FuseFS::PathMapperFS.create(@tmpdir) do |file|
|
13
25
|
File.file?(file) ? IO.read(file.to_s) : nil
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def mount()
|
30
|
+
return @mountpoint if @mountpoint
|
31
|
+
@mountpoint = Pathname.new(Dir.mktmpdir("rfusefs_pathmapper_mnt"))
|
32
|
+
FuseFS.mount(fs,@mountpoint)
|
33
|
+
sleep(0.5)
|
34
|
+
@mountpoint
|
35
|
+
end
|
36
|
+
|
37
|
+
def cleanup
|
38
|
+
if @mountpoint
|
39
|
+
FuseFS.unmount(@mountpoint)
|
40
|
+
sleep(0.5)
|
41
|
+
FileUtils.rmdir(@mountpoint)
|
42
|
+
end
|
43
|
+
FileUtils.rm_r(@tmpdir)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
describe FuseFS::PathMapperFS do
|
49
|
+
before(:each) do
|
50
|
+
@fixture = PMFixture.new
|
51
|
+
@tmpdir = @fixture.tmpdir
|
52
|
+
@pathmapFS = @fixture.fs
|
53
|
+
end
|
54
|
+
|
55
|
+
after(:each) do
|
56
|
+
@fixture.cleanup
|
57
|
+
end
|
58
|
+
|
59
|
+
context "fusefs api" do
|
60
|
+
|
61
|
+
it "maps files and directories" do
|
22
62
|
@pathmapFS.directory?("/").should be_true
|
23
63
|
@pathmapFS.directory?("/textfiles").should be_true
|
24
64
|
@pathmapFS.directory?("/pictures/201103").should be_true
|
25
65
|
@pathmapFS.file?("/textfiles/hello").should be_true
|
66
|
+
@pathmapFS.directory?("/textfiles/hello").should be_false
|
26
67
|
@pathmapFS.file?("/artist/album/mysong.mp3").should be_true
|
68
|
+
@pathmapFS.directory?("/artist/album/mysong.mp3").should be_false
|
69
|
+
@pathmapFS.file?("/some/unknown/path").should be_false
|
70
|
+
@pathmapFS.directory?("/some/unknown/path").should be_false
|
27
71
|
end
|
28
|
-
|
29
|
-
it "
|
72
|
+
|
73
|
+
it "lists the mapped contents of directories" do
|
30
74
|
@pathmapFS.contents("/").should =~ [ "textfiles","artist","pictures" ]
|
31
75
|
@pathmapFS.contents("/artist").should =~ [ "album" ]
|
32
76
|
@pathmapFS.contents("/textfiles").should =~ [ "hello" ]
|
33
77
|
end
|
34
78
|
|
35
|
-
it "
|
79
|
+
it "reports the size of a file" do
|
36
80
|
@pathmapFS.size("/textfiles/hello").should == 16
|
37
81
|
end
|
38
82
|
|
39
|
-
it "
|
83
|
+
it "reads the contents of a file" do
|
84
|
+
@pathmapFS.read_file("/textfiles/hello").should == "/textfiles/hello"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "does not allow writes" do
|
88
|
+
@pathmapFS.can_write?("/textfiles/hello").should be_false
|
89
|
+
end
|
90
|
+
|
91
|
+
it "reports the atime,mtime and ctime of the mapped file" do
|
40
92
|
atime,mtime,ctime = @pathmapFS.times("/pictures/201103/apicture.jpg")
|
41
93
|
picture = @tmpdir + "apicture.jpeg"
|
42
94
|
atime.should == picture.atime()
|
43
95
|
mtime.should == picture.mtime()
|
44
96
|
ctime.should == picture.ctime()
|
45
97
|
end
|
46
|
-
end
|
47
98
|
|
48
|
-
|
49
|
-
|
99
|
+
it "reports filesystem statistics"
|
100
|
+
|
101
|
+
context "writing to a pathmapped FS" do
|
102
|
+
before(:each) do
|
103
|
+
@pathmapFS.allow_write=true
|
104
|
+
@pathmapFS.write_to("textfiles/hello","updated content")
|
105
|
+
end
|
106
|
+
|
107
|
+
it "updates the contents of the real file" do
|
108
|
+
hello_path = @tmpdir + "hello.txt"
|
109
|
+
hello_path.read.should == "updated content"
|
110
|
+
end
|
111
|
+
|
112
|
+
it "updates the contents of the mapped file" do
|
113
|
+
@pathmapFS.read_file("textfiles/hello").should == "updated content"
|
114
|
+
end
|
115
|
+
|
116
|
+
it "changes the reported file size" do
|
117
|
+
@pathmapFS.size("textfiles/hello").should == 15
|
118
|
+
end
|
119
|
+
|
120
|
+
it "changes the filesystem statistics"
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
50
124
|
|
51
125
|
context "a real Fuse mounted filesystem" do
|
52
|
-
before(:
|
53
|
-
|
54
|
-
|
55
|
-
@pathmapFS.use_raw_file_access = true
|
56
|
-
FuseFS.mount(@pathmapFS,@mountpoint)
|
57
|
-
sleep(1)
|
126
|
+
before(:each) do
|
127
|
+
@pathmapFS.allow_write=true
|
128
|
+
@mountpoint = @fixture.mount
|
58
129
|
end
|
59
130
|
|
60
|
-
it "
|
131
|
+
it "maps files and directories" do
|
61
132
|
(@mountpoint + "textfiles").directory?.should be_true
|
62
|
-
(@mountpoint + "pictures/201103").directory?.should be_true
|
63
133
|
(@mountpoint + "textfiles/hello").file?.should be_true
|
64
|
-
(@mountpoint + "artist/album/mysong.mp3").file?.should be_true
|
65
134
|
end
|
66
135
|
|
67
|
-
it "
|
68
|
-
|
136
|
+
it "lists the mapped contents of directories" do
|
137
|
+
(@mountpoint + "textfiles").entries.should =~ pathnames(".","..","hello")
|
69
138
|
end
|
70
139
|
|
71
|
-
it "
|
140
|
+
it "represents the stat information of the underlying files" do
|
72
141
|
hellopath=(@mountpoint + "textfiles/hello")
|
73
142
|
realpath=(@tmpdir + "hello.txt")
|
74
143
|
mappedstat = hellopath.stat
|
75
144
|
realstat = realpath.stat
|
76
145
|
mappedstat.size.should == realstat.size
|
77
|
-
puts "#{realstat.atime.to_f},#{mappedstat.atime.to_f}"
|
78
146
|
mappedstat.atime.should == realstat.atime
|
79
147
|
mappedstat.mtime.should == realstat.mtime
|
80
148
|
mappedstat.ctime.should == realstat.ctime
|
81
149
|
end
|
82
150
|
|
83
|
-
it "
|
84
|
-
hellopath
|
151
|
+
it "reads the files" do
|
152
|
+
hellopath= @mountpoint + "textfiles/hello"
|
85
153
|
hellopath.read.should == "/textfiles/hello"
|
86
|
-
|
154
|
+
end
|
155
|
+
|
156
|
+
it "writes the files" do
|
157
|
+
hellopath= @mountpoint + "textfiles/hello"
|
158
|
+
real_path = @tmpdir + "hello.txt"
|
159
|
+
hellopath.open("w") do |f|
|
160
|
+
f.print "updated content"
|
161
|
+
end
|
162
|
+
hellopath.read.should == "updated content"
|
163
|
+
real_path.read.should == "updated content"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context "a real Fuse mount with raw file access" do
|
168
|
+
|
169
|
+
before(:each) do
|
170
|
+
@pathmapFS.use_raw_file_access = true
|
171
|
+
@pathmapFS.allow_write = true
|
172
|
+
@mountpoint = @fixture.mount
|
173
|
+
end
|
174
|
+
|
175
|
+
it "reads files" do
|
176
|
+
hello_path = (@mountpoint + "textfiles/hello")
|
177
|
+
hello_path.open do |f|
|
87
178
|
f.seek(2)
|
88
179
|
f.read(3).should == "ext"
|
89
180
|
end
|
90
|
-
|
181
|
+
|
182
|
+
hello_path.sysopen do |f|
|
91
183
|
f.sysseek(1)
|
92
184
|
f.sysread(3).should == "tex"
|
93
185
|
end
|
94
186
|
end
|
95
187
|
|
96
|
-
|
97
|
-
|
98
|
-
|
188
|
+
it "writes files" do
|
189
|
+
hello_path = (@mountpoint + "textfiles/hello")
|
190
|
+
real_path = @tmpdir + "hello.txt"
|
191
|
+
hello_path.open("r+") do |f|
|
192
|
+
f.sysseek(2)
|
193
|
+
f.syswrite("zzz")
|
194
|
+
f.sysseek(0)
|
195
|
+
f.sysread(6).should == "/tzzzf"
|
196
|
+
end
|
197
|
+
|
198
|
+
real_path.read.should == "/tzzzfiles/hello"
|
99
199
|
end
|
100
200
|
|
101
201
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
after(:all) do
|
108
|
-
FileUtils.rm_rf(@tmpdir.to_s)
|
109
|
-
end
|
110
|
-
|
111
|
-
|
112
202
|
end
|
data/spec/rfusefs_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FuseFS do
|
4
|
+
|
4
5
|
TEST_FILE = "/aPath/aFile"
|
5
6
|
TEST_DIR = "/aPath"
|
6
7
|
ROOT_PATH = "/"
|
@@ -41,7 +42,7 @@ describe FuseFS do
|
|
41
42
|
@mock_fuse = FuseFS::FuseDir.new()
|
42
43
|
@fuse = FuseFS::RFuseFS.new(@mock_fuse)
|
43
44
|
end
|
44
|
-
|
45
|
+
|
45
46
|
describe :readdir do
|
46
47
|
before(:each) do
|
47
48
|
@mock_fuse.should_receive(:contents).with("/apath").and_return(["afile"])
|
@@ -390,7 +391,28 @@ describe FuseFS do
|
|
390
391
|
end
|
391
392
|
|
392
393
|
end
|
394
|
+
context "extended attributes" do
|
395
|
+
|
396
|
+
let(:xattr) { {} }
|
397
|
+
before(:each) { @mock_fuse.stub!(:xattr).with(TEST_FILE).and_return(xattr) }
|
398
|
+
|
399
|
+
it "should get, set and list attributes" do
|
400
|
+
xattr["user.one"] = "xattr one"
|
401
|
+
|
402
|
+
@fuse.getxattr(nil,TEST_FILE,"user.one").should == "xattr one"
|
403
|
+
@fuse.setxattr(nil,TEST_FILE,"user.two","xattr two")
|
404
|
+
xattr["user.two"].should == "xattr two"
|
405
|
+
@fuse.listxattr(nil,TEST_FILE).should =~ [ "user.one", "user.two" ]
|
406
|
+
@fuse.removexattr(nil,TEST_FILE,"user.two")
|
407
|
+
xattr.keys.should =~ [ "user.one" ]
|
408
|
+
end
|
409
|
+
|
410
|
+
it "should raise ENODATA is no attribute is available" do
|
411
|
+
lambda{@fuse.getxattr(nil,TEST_FILE,"user.xxxx") }.should raise_error(Errno::ENODATA)
|
412
|
+
end
|
393
413
|
|
414
|
+
|
415
|
+
end
|
394
416
|
end
|
395
417
|
|
396
418
|
describe "a FuseFS filesystem with gid/uid specific behaviour" do
|
data/spec/sample_spec.rb
CHANGED
@@ -5,26 +5,26 @@ require 'pathname'
|
|
5
5
|
require 'hello'
|
6
6
|
|
7
7
|
describe "Access Hello World sample from Ruby file operations" do
|
8
|
+
let(:mountpoint) { Pathname.new(Dir.mktmpdir("rfusefs_sample")) }
|
9
|
+
|
8
10
|
before(:all) do
|
9
|
-
tmpdir = Pathname.new(Dir.tmpdir) + "rfusefs"
|
10
|
-
tmpdir.mkdir unless tmpdir.directory?
|
11
|
-
@mountpoint = tmpdir + "sample_spec"
|
12
|
-
@mountpoint.mkdir unless @mountpoint.directory?
|
13
11
|
hello = HelloDir.new()
|
14
|
-
FuseFS.mount(hello
|
12
|
+
FuseFS.mount(hello,mountpoint)
|
15
13
|
#Give FUSE some time to get started
|
16
|
-
sleep(
|
14
|
+
sleep(0.5)
|
17
15
|
end
|
18
16
|
|
19
17
|
after(:all) do
|
20
|
-
FuseFS.unmount(
|
18
|
+
FuseFS.unmount(mountpoint)
|
19
|
+
sleep(0.5)
|
20
|
+
FileUtils.rmdir(mountpoint)
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should list expected root directory contents" do
|
24
|
-
Dir.entries(
|
24
|
+
Dir.entries(mountpoint.to_s).should =~ [".","..","hello.txt"]
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should output the expected sample contents" do
|
28
|
-
(
|
28
|
+
(mountpoint + "hello.txt").read().should == "Hello, World!\n"
|
29
29
|
end
|
30
30
|
end
|
data/spec/spec_helper.rb
CHANGED