fusefs 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +11 -0
- data/API.txt +279 -0
- data/Changes.txt +63 -0
- data/LICENSE +20 -0
- data/README +46 -0
- data/Rakefile +56 -0
- data/TODO +11 -0
- data/VERSION +1 -0
- data/ext/MANIFEST +4 -0
- data/ext/extconf.rb +7 -0
- data/ext/fusefs_fuse.c +149 -0
- data/ext/fusefs_fuse.h +19 -0
- data/ext/fusefs_lib.c +1514 -0
- data/fusefs.gemspec +69 -0
- data/hello.sh +10 -0
- data/lib/fusefs.rb +244 -0
- data/sample/demo.rb +100 -0
- data/sample/dictfs.rb +84 -0
- data/sample/hello.rb +27 -0
- data/sample/openurifs.rb +53 -0
- data/sample/railsfs.rb +77 -0
- data/sample/sqlfs.rb +134 -0
- data/sample/yamlfs.rb +168 -0
- data/test/fusefs_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +83 -0
data/.document
ADDED
data/.gitignore
ADDED
data/API.txt
ADDED
@@ -0,0 +1,279 @@
|
|
1
|
+
FuseFS API DOCUMENT
|
2
|
+
===================
|
3
|
+
|
4
|
+
Last updated: 2005.09.19 by Greg Millam
|
5
|
+
|
6
|
+
WARNING
|
7
|
+
-------
|
8
|
+
|
9
|
+
Note: If you use DirLink (in demo.rb) or in any way access a FuseFS filesystem
|
10
|
+
from *within* the ruby script accessing the FuseFS, then FuseFS will hang, and
|
11
|
+
the only recourse is a kill -KILL.
|
12
|
+
|
13
|
+
Also: If there are any open files or shells with 'pwd's in your filesystem
|
14
|
+
when you exit your ruby script, fuse *might* not actually be unmounted. To
|
15
|
+
unmount a path yourself, run the command:
|
16
|
+
|
17
|
+
fusermount -u <path>
|
18
|
+
|
19
|
+
to unmount any FUSE filesystems mounted at <path>.
|
20
|
+
|
21
|
+
|
22
|
+
FuseFS API
|
23
|
+
----------
|
24
|
+
|
25
|
+
|
26
|
+
FuseFS provides a layer of abstraction to a programmer who wants to create a
|
27
|
+
virtual filesystem via FUSE.
|
28
|
+
|
29
|
+
FuseFS programs consist of two parts:
|
30
|
+
|
31
|
+
1) FuseFS, which is defined in 'fusefs.rb'
|
32
|
+
2) An object that defines a virtual directory. This must define a number of
|
33
|
+
methods (given below, in "Directory Methods" section) in order to be
|
34
|
+
usable.
|
35
|
+
|
36
|
+
To write a FuseFS program, you must:
|
37
|
+
|
38
|
+
* Define and create a Directory object that responds to the methods required
|
39
|
+
by FuseFS for its desired use.
|
40
|
+
|
41
|
+
* Call FuseFS.set_root <virtualdir> with the object defining your virtual
|
42
|
+
directory.
|
43
|
+
|
44
|
+
* Mount FuseFS under a real directory on your filesystem.
|
45
|
+
|
46
|
+
* Call FuseFS.run to start receiving and executing events.
|
47
|
+
|
48
|
+
Happy Filesystem Hacking!
|
49
|
+
|
50
|
+
|
51
|
+
Hello World FS
|
52
|
+
--------------
|
53
|
+
helloworld.rb
|
54
|
+
|
55
|
+
This creates a filesystem that contains exactly 1 file: "hello.txt" that, when
|
56
|
+
read, returns "Hello, World!"
|
57
|
+
|
58
|
+
This is not writable to, and contains no other files.
|
59
|
+
|
60
|
+
require 'fusefs'
|
61
|
+
|
62
|
+
class HelloDir
|
63
|
+
def contents(path)
|
64
|
+
['hello.txt']
|
65
|
+
end
|
66
|
+
def file?(path)
|
67
|
+
path -- '/hello.txt'
|
68
|
+
end
|
69
|
+
def read_file(path)
|
70
|
+
"Hello, World!\n"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
hellodir = HelloDir.new
|
75
|
+
FuseFS.set_root( hellodir )
|
76
|
+
|
77
|
+
# Mount under a directory given on the command line.
|
78
|
+
FuseFS.mount_under ARGV.shift
|
79
|
+
FuseFS.run
|
80
|
+
|
81
|
+
|
82
|
+
Directory Methods
|
83
|
+
-----------------
|
84
|
+
|
85
|
+
Without any methods defined, any object is by default a content-less,
|
86
|
+
file-less directory.
|
87
|
+
|
88
|
+
The following are necessary for most or all filesystems:
|
89
|
+
|
90
|
+
Directory listing and file type methods:
|
91
|
+
|
92
|
+
:contents(path) # Return an array of file and dirnames within <path>.
|
93
|
+
:directory?(path) # Return true if <path> is a directory.
|
94
|
+
:file?(path) # Return true if <path> is a file (not a directory).
|
95
|
+
:executable?(path) # Return true if <path> is an executable file.
|
96
|
+
:size(path) # Return the file size. Necessary for apache, xmms,
|
97
|
+
etc.
|
98
|
+
|
99
|
+
File reading:
|
100
|
+
|
101
|
+
:read_file(path) # Return the contents of the file at location <path>.
|
102
|
+
|
103
|
+
The following are only necessary if you want a filesystem that can be modified
|
104
|
+
by the user. Without defining any of the below, the contents of the filesystem
|
105
|
+
are automatically read-only.
|
106
|
+
|
107
|
+
File manipulation:
|
108
|
+
|
109
|
+
:can_write?(path) # Return true if the user can write to file at <path>.
|
110
|
+
:write_to(path,str) # Write the contents of <str> to file at <path>.
|
111
|
+
|
112
|
+
:can_delete?(path) # Return true if the user can delete file at <path>.
|
113
|
+
:delete(path) # Delete the file at <path>
|
114
|
+
|
115
|
+
Directory manipulation:
|
116
|
+
|
117
|
+
:can_mkdir?(path) # Return true if user can make a directory at <path>.
|
118
|
+
:mkdir(path) # Make a directory at path.
|
119
|
+
|
120
|
+
:can_rmdir?(path) # Return true if user can remove directory at <path>.
|
121
|
+
:rmdir(path) # Remove it.
|
122
|
+
|
123
|
+
Neat "toy":
|
124
|
+
|
125
|
+
:touch(path) # Called when a file is 'touch'd or otherwise has
|
126
|
+
their timestamps explicitly modified. I envision
|
127
|
+
this as a neat toy, maybe you can use it for a
|
128
|
+
push-button file?
|
129
|
+
"touch button" -> unmounts fusefs?
|
130
|
+
"touch musicfile.mp3" -> Play the mp3.
|
131
|
+
|
132
|
+
If you want a lower level control of your file, then you can use:
|
133
|
+
|
134
|
+
:raw_open(path,mode) # mode is "r" "w" or "rw", with "a" if the file
|
135
|
+
is opened for append. If raw_open returns true,
|
136
|
+
then the following calls are made:
|
137
|
+
:raw_read(path,off,sz) # Read sz bites from file at path starting at
|
138
|
+
offset off
|
139
|
+
:raw_write(path,off,sz,buf) # Write sz bites of buf to path starting at
|
140
|
+
offset off
|
141
|
+
:raw_close(path) # Close the file.
|
142
|
+
|
143
|
+
|
144
|
+
Method call flow
|
145
|
+
================
|
146
|
+
|
147
|
+
List contents:
|
148
|
+
:directory? will be checked before :contents
|
149
|
+
(Most 'ls' or 'dir' functions will go on next
|
150
|
+
to getattr() for all contents)
|
151
|
+
|
152
|
+
Read file:
|
153
|
+
:file? will be checked before :read_file
|
154
|
+
|
155
|
+
Getattr
|
156
|
+
:directory? will be checked first.
|
157
|
+
|
158
|
+
:file? will be checked before :can_write?
|
159
|
+
:file? will be checked before :executable?
|
160
|
+
|
161
|
+
Writing files:
|
162
|
+
* directory? is usually called on the directory
|
163
|
+
The FS wants to write a new file to, before this
|
164
|
+
can occur.
|
165
|
+
:can_write? will be checked before :write_to
|
166
|
+
|
167
|
+
Deleting files:
|
168
|
+
:file? will be checked before :can_delete?
|
169
|
+
:can_delete? will be checked before :delete
|
170
|
+
|
171
|
+
Creating dirs:
|
172
|
+
* directory? is usually called on the directory
|
173
|
+
The FS wants to make a new directory in, before
|
174
|
+
this can occur.
|
175
|
+
:directory? will be checked.
|
176
|
+
:can_mkdir? is called only if :directory? is false.
|
177
|
+
:can_mkdir? will be checked before :mkdir
|
178
|
+
|
179
|
+
Deleting dirs:
|
180
|
+
:directory? will be checked before :can_rmdir?
|
181
|
+
:can_rmdir? will be checked before :rmdir
|
182
|
+
|
183
|
+
|
184
|
+
module FuseFS
|
185
|
+
-------------
|
186
|
+
|
187
|
+
FuseFS methods:
|
188
|
+
|
189
|
+
FuseFS.set_root(object)
|
190
|
+
Set the root virtual directory to <object>. All queries for obtaining
|
191
|
+
file information is directed at object.
|
192
|
+
|
193
|
+
FuseFS.mount_under(path[,opt[,opt,...]])
|
194
|
+
This will cause FuseFS to virtually mount itself under the given path.
|
195
|
+
'path' is required to be a valid directory in your actual filesystem.
|
196
|
+
|
197
|
+
'opt's are FUSE options. Most likely, you will only want 'allow_other'
|
198
|
+
or 'allow_root'. The two are mutually exclusive in FUSE, but allow_other
|
199
|
+
will let other users, including root, access your filesystem. allow_root
|
200
|
+
will only allow root to access it.
|
201
|
+
|
202
|
+
Also available for FuseFS users are:
|
203
|
+
default_permissions, max_read=N, fsname=NAME.
|
204
|
+
|
205
|
+
For more information, look at FUSE.
|
206
|
+
|
207
|
+
(P.S: I know FUSE allows other options, but I don't think any of the
|
208
|
+
rest will do any good with FuseFS. If you think otherwise, please let me
|
209
|
+
know!)
|
210
|
+
|
211
|
+
FuseFS.run
|
212
|
+
This is the final step to make your virtual filesystem accessible. It is
|
213
|
+
recommended you run this as your main thread, but you can thread off to
|
214
|
+
run this.
|
215
|
+
|
216
|
+
FuseFS.handle_editor = bool (true by default)
|
217
|
+
If handle_editor is true, then FuseFS will attempt to capture all editor
|
218
|
+
files and prevent them from being passed to FuseRoot. It also prevents
|
219
|
+
created and unmodified files from being passed as well, as vim (among
|
220
|
+
others) will attempt to create and then remove a file that does not
|
221
|
+
exist.
|
222
|
+
|
223
|
+
FuseFS.reader_uid and FuseFS.reader_gid
|
224
|
+
When the filesystem is accessed, the accessor's uid or gid is returned
|
225
|
+
by FuseFS.reader_uid and FuseFS.reader_gid. You can use this in
|
226
|
+
determining your permissions, or even provide different files for
|
227
|
+
different users!
|
228
|
+
|
229
|
+
FuseFS.fuse_fd and FuseFS.process
|
230
|
+
These are not intended for use by the programmer. If you want to muck
|
231
|
+
with this, read the code to see what they do :D.
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
FuseDir
|
236
|
+
----------
|
237
|
+
|
238
|
+
FuseFS::FuseDir defines the methods "split_path" and "scan_path". You
|
239
|
+
should typically inherit from FuseDir in your own directory objects.
|
240
|
+
|
241
|
+
base, rest = split_path(path) # base is the file or directory in the
|
242
|
+
current context. rest is either nil,
|
243
|
+
or a path that is requested. If 'rest'
|
244
|
+
exists, then you should recurse the paths.
|
245
|
+
base, *rest = scan_path(path) # scan_path returns an array of all
|
246
|
+
directory and file elements given by
|
247
|
+
<path>. This is useful when you're
|
248
|
+
encapsulating an entire fs into one
|
249
|
+
object.
|
250
|
+
|
251
|
+
MetaDir
|
252
|
+
-------
|
253
|
+
|
254
|
+
MetaDir is a full filesystem defined with hashes. It is writable, and the user
|
255
|
+
can create and edit files within it, as well as the programmer.
|
256
|
+
|
257
|
+
Usage:
|
258
|
+
root = MetaDir.new
|
259
|
+
|
260
|
+
root.mkdir("/hello")
|
261
|
+
root.write_to("/hello/world","Hello, World!\n")
|
262
|
+
root.write_to("/hello/everybody","Hello, Everybody!\n")
|
263
|
+
|
264
|
+
FuseFS.set_root(root)
|
265
|
+
|
266
|
+
Because MetaDir is fully recursive, you can mount your own or other defined
|
267
|
+
directory structures under it. For example, to mount a dictionary filesystem
|
268
|
+
(as demonstrated in samples/dictfs.rb), use:
|
269
|
+
|
270
|
+
root.mkdir("/dict",DictFS.new)
|
271
|
+
|
272
|
+
Conclusion
|
273
|
+
----------
|
274
|
+
|
275
|
+
Happy Hacking! If you do anything neat with this, please let me know!
|
276
|
+
|
277
|
+
My email address is walker@deafcode.com
|
278
|
+
|
279
|
+
Thanks for using FuseFS!
|
data/Changes.txt
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
FuseFS 0.7
|
2
|
+
==========
|
3
|
+
|
4
|
+
* It's now a Rubygem on Github
|
5
|
+
|
6
|
+
FuseFS 0.6
|
7
|
+
==========
|
8
|
+
|
9
|
+
* FuseFS.mount_under() now takes FUSE options as optional arguments, such as
|
10
|
+
'allow_other' and 'allow_root'
|
11
|
+
* rmdir now works. (Whoops!)
|
12
|
+
|
13
|
+
FuseFS 0.5.1
|
14
|
+
============
|
15
|
+
|
16
|
+
* Bugfix for dealing with raw files (Thanks, Kent Sibilev)
|
17
|
+
|
18
|
+
FuseFS 0.5
|
19
|
+
==========
|
20
|
+
|
21
|
+
* Fixed for FUSE 2.4. direct_io turned from a mount option in 2.3 to a lib
|
22
|
+
option in 2.4.
|
23
|
+
* _why_the_lucky_stiff's railsfs.rb added to the samples/ dir.
|
24
|
+
* FuseRoot#raw_open is called with the path and "r" "w" "rw" for read or
|
25
|
+
write modes, along with "a" if it is called for appending.
|
26
|
+
* If raw_open returns true, FuseFS will call raw_read, raw_write, and
|
27
|
+
raw_close at necessary points. (See API.txt)
|
28
|
+
* FuseRoot#size is optionally called to determine file sizes, should the
|
29
|
+
user want a file size to be reported as anything other than 0.
|
30
|
+
|
31
|
+
FuseFS 0.4
|
32
|
+
==========
|
33
|
+
|
34
|
+
* Stronger and more robust handling of editor swap files, but still
|
35
|
+
incomplete.
|
36
|
+
* Peppered with debug statements.
|
37
|
+
* A bit cleaner method of calling ruby functions.
|
38
|
+
* rf_rename fixed. Whoops!
|
39
|
+
|
40
|
+
FuseFS 0.3
|
41
|
+
==========
|
42
|
+
|
43
|
+
* read_file borked FuseFS when a binary file was returned. Instead of using
|
44
|
+
strdup, it now mallocs according to the returned size, as appropriate.
|
45
|
+
* Addition of sample/openurifs.rb
|
46
|
+
* 'touch file' emptied a file, since it opened and then released without
|
47
|
+
writing. I added a 'modified' flag to fix this.
|
48
|
+
* 'touch' method call added, and called when a program attempts to modify
|
49
|
+
a file's time.
|
50
|
+
* 'executable?' check added in case programmer wants to the file to report
|
51
|
+
itself as executable to the filesystem.
|
52
|
+
* vim and emacs swap files are not passed to FuseFS =).
|
53
|
+
|
54
|
+
FuseFS 0.2
|
55
|
+
==========
|
56
|
+
|
57
|
+
* Fix call for deleting files from 'remove' to 'delete' to match API spec.
|
58
|
+
* Addition of sample/yamlfs.rb
|
59
|
+
|
60
|
+
FuseFS 0.1
|
61
|
+
==========
|
62
|
+
|
63
|
+
Initial import.
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2005 Greg Millam.
|
2
|
+
Copyright (c) 2009 Kyle Maxwell.
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
this software and associated documentation files (the "Software"), to deal in
|
6
|
+
the Software without restriction, including without limitation the rights to
|
7
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
8
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
9
|
+
so, subject to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
12
|
+
copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
20
|
+
SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
FuseFS README
|
2
|
+
============
|
3
|
+
|
4
|
+
FuseFS is a library aimed at allowing Ruby programmers to quickly and
|
5
|
+
easily create virtual filesystems with little more than a few lines of code.
|
6
|
+
|
7
|
+
A "hello world" file system equivalent to the one demonstrated on
|
8
|
+
fuse.sourceforge.org is just 20 lines of code!
|
9
|
+
|
10
|
+
FuseFS is *NOT* a full implementation of the FUSE api. rfuse
|
11
|
+
is designed for that.
|
12
|
+
|
13
|
+
|
14
|
+
Requirements
|
15
|
+
------------
|
16
|
+
|
17
|
+
* FUSE (http://fuse.sourceforge.org)
|
18
|
+
* Ruby (>= 1.8)
|
19
|
+
(* C compiler)
|
20
|
+
|
21
|
+
|
22
|
+
Install
|
23
|
+
-------
|
24
|
+
|
25
|
+
gem install fusefs
|
26
|
+
|
27
|
+
Usage
|
28
|
+
-----
|
29
|
+
|
30
|
+
Some sample ruby filesystems are listed in "sample/"
|
31
|
+
|
32
|
+
When you run a fusefs script, it will listen on a socket indefinitely, so
|
33
|
+
either background the script or open another terminal to mosey around in the
|
34
|
+
filesystem.
|
35
|
+
|
36
|
+
Also, check the API.txt file for more use.
|
37
|
+
|
38
|
+
|
39
|
+
License
|
40
|
+
-------
|
41
|
+
|
42
|
+
MIT license, in file "LICENSE"
|
43
|
+
|
44
|
+
|
45
|
+
Author: Greg Millam <walker@deafcode.com>.
|
46
|
+
Port/Maintainer: Shane <shane@duairc.com>
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "fusefs"
|
8
|
+
gem.summary = %Q{fusefs}
|
9
|
+
gem.description = %Q{Gemified}
|
10
|
+
gem.email = "shane@duairc.com"
|
11
|
+
gem.homepage = "http://github.com/duairc/fusefs"
|
12
|
+
gem.authors = ["Shane"]
|
13
|
+
gem.extensions = ["ext/extconf.rb"]
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/*_test.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/*_test.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
if File.exist?('VERSION')
|
47
|
+
version = File.read('VERSION')
|
48
|
+
else
|
49
|
+
version = ""
|
50
|
+
end
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "fusefs #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|