-
Notifications
You must be signed in to change notification settings - Fork 10
/
API.txt
279 lines (195 loc) · 8.73 KB
/
API.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
FuseFS API DOCUMENT
===================
Last updated: 2005.09.19 by Greg Millam
WARNING
-------
Note: If you use DirLink (in demo.rb) or in any way access a FuseFS filesystem
from *within* the ruby script accessing the FuseFS, then FuseFS will hang, and
the only recourse is a kill -KILL.
Also: If there are any open files or shells with 'pwd's in your filesystem
when you exit your ruby script, fuse *might* not actually be unmounted. To
unmount a path yourself, run the command:
fusermount -u <path>
to unmount any FUSE filesystems mounted at <path>.
FuseFS API
----------
FuseFS provides a layer of abstraction to a programmer who wants to create a
virtual filesystem via FUSE.
FuseFS programs consist of two parts:
1) FuseFS, which is defined in 'fusefs.rb'
2) An object that defines a virtual directory. This must define a number of
methods (given below, in "Directory Methods" section) in order to be
usable.
To write a FuseFS program, you must:
* Define and create a Directory object that responds to the methods required
by FuseFS for its desired use.
* Call FuseFS.set_root <virtualdir> with the object defining your virtual
directory.
* Mount FuseFS under a real directory on your filesystem.
* Call FuseFS.run to start receiving and executing events.
Happy Filesystem Hacking!
Hello World FS
--------------
helloworld.rb
This creates a filesystem that contains exactly 1 file: "hello.txt" that, when
read, returns "Hello, World!"
This is not writable to, and contains no other files.
require 'fusefs'
class HelloDir
def contents(path)
['hello.txt']
end
def file?(path)
path -- '/hello.txt'
end
def read_file(path)
"Hello, World!\n"
end
end
hellodir = HelloDir.new
FuseFS.set_root( hellodir )
# Mount under a directory given on the command line.
FuseFS.mount_under ARGV.shift
FuseFS.run
Directory Methods
-----------------
Without any methods defined, any object is by default a content-less,
file-less directory.
The following are necessary for most or all filesystems:
Directory listing and file type methods:
:contents(path) # Return an array of file and dirnames within <path>.
:directory?(path) # Return true if <path> is a directory.
:file?(path) # Return true if <path> is a file (not a directory).
:executable?(path) # Return true if <path> is an executable file.
:size(path) # Return the file size. Necessary for apache, xmms,
etc.
File reading:
:read_file(path) # Return the contents of the file at location <path>.
The following are only necessary if you want a filesystem that can be modified
by the user. Without defining any of the below, the contents of the filesystem
are automatically read-only.
File manipulation:
:can_write?(path) # Return true if the user can write to file at <path>.
:write_to(path,str) # Write the contents of <str> to file at <path>.
:can_delete?(path) # Return true if the user can delete file at <path>.
:delete(path) # Delete the file at <path>
Directory manipulation:
:can_mkdir?(path) # Return true if user can make a directory at <path>.
:mkdir(path) # Make a directory at path.
:can_rmdir?(path) # Return true if user can remove directory at <path>.
:rmdir(path) # Remove it.
Neat "toy":
:touch(path) # Called when a file is 'touch'd or otherwise has
their timestamps explicitly modified. I envision
this as a neat toy, maybe you can use it for a
push-button file?
"touch button" -> unmounts fusefs?
"touch musicfile.mp3" -> Play the mp3.
If you want a lower level control of your file, then you can use:
:raw_open(path,mode) # mode is "r" "w" or "rw", with "a" if the file
is opened for append. If raw_open returns true,
then the following calls are made:
:raw_read(path,off,sz) # Read sz bites from file at path starting at
offset off
:raw_write(path,off,sz,buf) # Write sz bites of buf to path starting at
offset off
:raw_close(path) # Close the file.
Method call flow
================
List contents:
:directory? will be checked before :contents
(Most 'ls' or 'dir' functions will go on next
to getattr() for all contents)
Read file:
:file? will be checked before :read_file
Getattr
:directory? will be checked first.
:file? will be checked before :can_write?
:file? will be checked before :executable?
Writing files:
* directory? is usually called on the directory
The FS wants to write a new file to, before this
can occur.
:can_write? will be checked before :write_to
Deleting files:
:file? will be checked before :can_delete?
:can_delete? will be checked before :delete
Creating dirs:
* directory? is usually called on the directory
The FS wants to make a new directory in, before
this can occur.
:directory? will be checked.
:can_mkdir? is called only if :directory? is false.
:can_mkdir? will be checked before :mkdir
Deleting dirs:
:directory? will be checked before :can_rmdir?
:can_rmdir? will be checked before :rmdir
module FuseFS
-------------
FuseFS methods:
FuseFS.set_root(object)
Set the root virtual directory to <object>. All queries for obtaining
file information is directed at object.
FuseFS.mount_under(path[,opt[,opt,...]])
This will cause FuseFS to virtually mount itself under the given path.
'path' is required to be a valid directory in your actual filesystem.
'opt's are FUSE options. Most likely, you will only want 'allow_other'
or 'allow_root'. The two are mutually exclusive in FUSE, but allow_other
will let other users, including root, access your filesystem. allow_root
will only allow root to access it.
Also available for FuseFS users are:
default_permissions, max_read=N, fsname=NAME.
For more information, look at FUSE.
(P.S: I know FUSE allows other options, but I don't think any of the
rest will do any good with FuseFS. If you think otherwise, please let me
know!)
FuseFS.run
This is the final step to make your virtual filesystem accessible. It is
recommended you run this as your main thread, but you can thread off to
run this.
FuseFS.handle_editor = bool (true by default)
If handle_editor is true, then FuseFS will attempt to capture all editor
files and prevent them from being passed to FuseRoot. It also prevents
created and unmodified files from being passed as well, as vim (among
others) will attempt to create and then remove a file that does not
exist.
FuseFS.reader_uid and FuseFS.reader_gid
When the filesystem is accessed, the accessor's uid or gid is returned
by FuseFS.reader_uid and FuseFS.reader_gid. You can use this in
determining your permissions, or even provide different files for
different users!
FuseFS.fuse_fd and FuseFS.process
These are not intended for use by the programmer. If you want to muck
with this, read the code to see what they do :D.
FuseDir
----------
FuseFS::FuseDir defines the methods "split_path" and "scan_path". You
should typically inherit from FuseDir in your own directory objects.
base, rest = split_path(path) # base is the file or directory in the
current context. rest is either nil,
or a path that is requested. If 'rest'
exists, then you should recurse the paths.
base, *rest = scan_path(path) # scan_path returns an array of all
directory and file elements given by
<path>. This is useful when you're
encapsulating an entire fs into one
object.
MetaDir
-------
MetaDir is a full filesystem defined with hashes. It is writable, and the user
can create and edit files within it, as well as the programmer.
Usage:
root = MetaDir.new
root.mkdir("/hello")
root.write_to("/hello/world","Hello, World!\n")
root.write_to("/hello/everybody","Hello, Everybody!\n")
FuseFS.set_root(root)
Because MetaDir is fully recursive, you can mount your own or other defined
directory structures under it. For example, to mount a dictionary filesystem
(as demonstrated in samples/dictfs.rb), use:
root.mkdir("/dict",DictFS.new)
Conclusion
----------
Happy Hacking! If you do anything neat with this, please let me know!
My email address is walker@deafcode.com
Thanks for using FuseFS!