fusefs 0.7.0
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/.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
|