rfusefs 0.8.0 → 1.0.0.RC0
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/.gitignore +9 -0
- data/Gemfile +4 -0
- data/History.rdoc +20 -0
- data/README.rdoc +20 -15
- data/Rakefile +10 -17
- data/TODO.txt +1 -2
- data/lib/fuse/fusedir.rb +202 -0
- data/lib/fuse/rfusefs-fuse.rb +402 -482
- data/lib/fusefs/dirlink.rb +1 -1
- data/lib/fusefs/metadir.rb +240 -240
- data/lib/fusefs/pathmapper.rb +189 -188
- data/lib/rfusefs/version.rb +3 -0
- data/lib/rfusefs.rb +109 -301
- data/samples/demo.rb +9 -14
- data/samples/dictfs.rb +4 -14
- data/samples/hello.rb +1 -2
- data/spec/metadir_spec.rb +295 -0
- data/spec/pathmapper_spec.rb +112 -0
- data/spec/rfusefs_spec.rb +77 -76
- data/spec/sample_spec.rb +3 -2
- data/spec/spec_helper.rb +7 -1
- metadata +112 -124
- data/.gemtest +0 -0
- data/History.txt +0 -9
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -1
data/.gitignore
ADDED
data/Gemfile
ADDED
data/History.rdoc
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
=== 1.0.0 / 2012-08-07
|
4
|
+
|
5
|
+
* Depend on new rfuse 1.0.0, Ruby 1.9
|
6
|
+
|
7
|
+
* API breaking changes
|
8
|
+
|
9
|
+
* order of arguments to {FuseFS.mount}, {FuseFS.start} changed
|
10
|
+
to account for better option handling in RFuse
|
11
|
+
|
12
|
+
=== 0.8.0 / 2011-02-19
|
13
|
+
|
14
|
+
* Initial port from fusefs
|
15
|
+
|
16
|
+
* Improved raw methods
|
17
|
+
* new "times" api for including atime,mtime,ctime in stat results
|
18
|
+
* metadir allow mv directories
|
19
|
+
* includes PathMapperFS
|
20
|
+
|
data/README.rdoc
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
= rfusefs
|
2
2
|
|
3
|
+
* https://rubygems.org/gems/rfusefs
|
3
4
|
* https://github.com/lwoggardner/rfusefs
|
4
5
|
|
5
6
|
== DESCRIPTION
|
6
7
|
|
7
|
-
RFuseFS is a port of the FuseFS[http://
|
8
|
+
RFuseFS is a port of the FuseFS[http://rubygems.org/gems/fusefs/]
|
8
9
|
library aimed at allowing Ruby programmers to quickly and easily create
|
9
10
|
virtual filesystems with little more than a few lines of code.
|
10
11
|
|
11
|
-
RFuseFS is api compatible with
|
12
|
+
RFuseFS is api compatible with FuseFS (0.7.0)
|
12
13
|
|
13
14
|
== SYNOPSIS
|
14
15
|
|
@@ -18,20 +19,23 @@ virtual filesystem via FUSE.
|
|
18
19
|
FuseFS programs consist of two parts:
|
19
20
|
|
20
21
|
1. FuseFS, which is defined in 'rfusefs.rb'
|
21
|
-
2. An object that defines a virtual directory by
|
22
|
-
subset of the {FuseFS::API}
|
22
|
+
2. An object that defines a virtual directory by subclassing {FuseFS::FuseDir}
|
23
23
|
|
24
24
|
To write a FuseFS program, you must:
|
25
25
|
|
26
26
|
* Define and create a Directory object that responds to the methods required
|
27
27
|
by FuseFS for its desired use.
|
28
28
|
|
29
|
-
* Call
|
30
|
-
|
31
|
-
|
29
|
+
* Call
|
30
|
+
|
31
|
+
FuseFS.start <virtualdir> <mountpoint> [mount_options]
|
32
|
+
|
33
|
+
where <virtualdir> with an object defining your virtual directory.
|
34
|
+
and <mountpoint> is a real directory on your filesystem
|
32
35
|
|
33
36
|
See samples under /samples and also the following starter classes
|
34
37
|
|
38
|
+
* {FuseFS::FuseDir}
|
35
39
|
* {FuseFS::MetaDir}
|
36
40
|
* {FuseFS::DirLink}
|
37
41
|
* {FuseFS::PathMapperFS}
|
@@ -58,14 +62,15 @@ Happy Filesystem Hacking!
|
|
58
62
|
end
|
59
63
|
|
60
64
|
hellodir = HelloDir.new
|
61
|
-
|
62
|
-
|
65
|
+
|
66
|
+
# Usage: #{$0} mountpoint [mount_options]
|
67
|
+
FuseFS.start(hellodir,*ARGV)
|
63
68
|
|
64
69
|
== REQUIREMENTS:
|
65
70
|
|
66
71
|
* FUSE (http://fuse.sourceforge.org)
|
67
|
-
* Ruby (>=1.
|
68
|
-
*
|
72
|
+
* Ruby (>=1.9)
|
73
|
+
* rfuse (~> 1.0)
|
69
74
|
|
70
75
|
== INSTALL:
|
71
76
|
|
@@ -75,10 +80,10 @@ Happy Filesystem Hacking!
|
|
75
80
|
|
76
81
|
After checking out the source, run:
|
77
82
|
|
78
|
-
$
|
83
|
+
$ bundle install # install dependencies
|
84
|
+
$ rake spec # run tests
|
85
|
+
$ rake yard # generate docs
|
79
86
|
|
80
|
-
This task will install any missing dependencies, run the tests/specs,
|
81
|
-
and generate the RDoc.
|
82
87
|
|
83
88
|
== LICENSE:
|
84
89
|
|
@@ -86,7 +91,7 @@ and generate the RDoc.
|
|
86
91
|
|
87
92
|
* Copyright (c) 2005 Greg Millam. (FuseFS)
|
88
93
|
* Copyright (c) 2009 Kyle Maxwell. (FuseFS)
|
89
|
-
* Copyright (c)
|
94
|
+
* Copyright (c) 2012 Grant Gardner. (RFuseFS)
|
90
95
|
|
91
96
|
Permission is hereby granted, free of charge, to any person obtaining
|
92
97
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,24 +1,17 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require 'yard'
|
4
|
+
require 'rspec/core/rake_task'
|
2
5
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
# Hoe.plugin :compiler
|
7
|
-
# Hoe.plugin :gem_prelude_sucks
|
8
|
-
# Hoe.plugin :inline
|
9
|
-
# Hoe.plugin :racc
|
10
|
-
# Hoe.plugin :rubyforge
|
11
|
-
Hoe.plugin :yard
|
12
|
-
Hoe.plugin :git
|
13
|
-
|
14
|
-
Hoe.spec 'rfusefs' do
|
15
|
-
self.readme_file="README.rdoc"
|
16
|
-
developer('Grant Gardner', 'grant@lastweekend.com.au')
|
17
|
-
extra_deps << [ 'rfuse-ng' , '>= 0.5.3' ]
|
6
|
+
YARD::Rake::YardocTask.new do |t|
|
7
|
+
# Need this because YardocTask does not read the gemspec
|
8
|
+
t.files = ['lib/**/*.rb', '-','History.rdoc'] # optional
|
18
9
|
end
|
19
10
|
|
20
|
-
|
21
|
-
|
11
|
+
RSpec::Core::RakeTask.new(:spec)
|
12
|
+
|
13
|
+
desc "FuseFS compatibility specs"
|
14
|
+
RSpec::Core::RakeTask.new("spec:fusefs") do |t|
|
22
15
|
t.pattern = 'spec-fusefs/**/*_spec.rb'
|
23
16
|
end
|
24
17
|
|
data/TODO.txt
CHANGED
data/lib/fuse/fusedir.rb
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
module FuseFS
|
2
|
+
|
3
|
+
# This class is equivalent to using Object.new() as the virtual directory
|
4
|
+
# for target for {FuseFS.start}. It exists primarily to document the API
|
5
|
+
# but can also be used as a superclass for your filesystem
|
6
|
+
#
|
7
|
+
# == Method call sequences
|
8
|
+
#
|
9
|
+
# === Stat (getattr)
|
10
|
+
#
|
11
|
+
# FUSE itself will generally stat referenced files and validate the results
|
12
|
+
# before performing any file/directory operations so this sequence is called
|
13
|
+
# very often
|
14
|
+
#
|
15
|
+
# 1. {#directory?} is checked first
|
16
|
+
# * {#can_write?} OR {#can_mkdir?} with .\_rfusefs_check\_ to determine write permissions
|
17
|
+
# * {#times} is called to determine atime,mtime,ctime info for the directory
|
18
|
+
#
|
19
|
+
# 2. {#file?} is checked next
|
20
|
+
# * {#can_write?}, {#executable?}, {#size}, {#times} are called to fill out the details
|
21
|
+
#
|
22
|
+
# 3. otherwise we tell FUSE that the path does not exist
|
23
|
+
#
|
24
|
+
# === List directory
|
25
|
+
#
|
26
|
+
# FUSE confirms the path is a directory (via stat above) before we call {#contents}
|
27
|
+
#
|
28
|
+
# FUSE will generally go on to stat each directory entry in the results
|
29
|
+
#
|
30
|
+
# === Reading files
|
31
|
+
#
|
32
|
+
# FUSE confirms path is a file before we call {#read_file}
|
33
|
+
#
|
34
|
+
# For fine control of file access see {#raw_open}, {#raw_read}, {#raw_close}
|
35
|
+
#
|
36
|
+
# === Writing files
|
37
|
+
#
|
38
|
+
# FUSE confirms path for the new file is a directory
|
39
|
+
#
|
40
|
+
# * {#can_write?} is checked at file open
|
41
|
+
# * {#write_to} is called when the file is flushed or closed
|
42
|
+
#
|
43
|
+
# See also {#raw_open}, {#raw_truncate}, {#raw_write}, {#raw_close}
|
44
|
+
#
|
45
|
+
# === Deleting files
|
46
|
+
#
|
47
|
+
# FUSE confirms path is a file before we call {#can_delete?} then {#delete}
|
48
|
+
#
|
49
|
+
# === Creating directories
|
50
|
+
#
|
51
|
+
# FUSE confirms parent is a directory before we call {#can_mkdir?} then {#mkdir}
|
52
|
+
#
|
53
|
+
# === Deleting directories
|
54
|
+
#
|
55
|
+
# FUSE confirms path is a directory before we call {#can_rmdir?} then {#rmdir}
|
56
|
+
#
|
57
|
+
# === Renaming files and directories
|
58
|
+
#
|
59
|
+
# FUSE confirms the rename is valid (eg. not renaming a directory to a file)
|
60
|
+
#
|
61
|
+
# * Try {#rename} to see if the virtual directory wants to handle this itself
|
62
|
+
# * If rename returns false/nil then we try to copy/delete (files only) ie.
|
63
|
+
# * {#file?}(from), {#can_write?}(to), {#can_delete?}(from) and if all true
|
64
|
+
# * {#read_file}(from), {#write_to}(to), {#delete}(from)
|
65
|
+
# * otherwise reject the rename
|
66
|
+
class FuseDir
|
67
|
+
INIT_TIMES = Array.new(3,0)
|
68
|
+
|
69
|
+
# base,rest = split_path(path)
|
70
|
+
# @return [Array<String,String>] base,rest. base is the first directory in
|
71
|
+
# path, and rest is nil> or the remaining path.
|
72
|
+
# Typically if rest is not nil? you should
|
73
|
+
# recurse the paths
|
74
|
+
def split_path(path)
|
75
|
+
cur, *rest = path.scan(/[^\/]+/)
|
76
|
+
if rest.empty?
|
77
|
+
[ cur, nil ]
|
78
|
+
else
|
79
|
+
[ cur, File::SEPARATOR + File.join(rest) ]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# base,*rest = scan_path(path)
|
84
|
+
# @return [Array<String>] all directory and file elements in path. Useful
|
85
|
+
# when encapsulating an entire fs into one object
|
86
|
+
def scan_path(path)
|
87
|
+
path.scan(/[^\/]+/)
|
88
|
+
end
|
89
|
+
|
90
|
+
# @abstract FuseFS api
|
91
|
+
# @return [Boolean] true if path is a directory
|
92
|
+
def directory?(path);return false;end
|
93
|
+
|
94
|
+
# @abstract FuseFS api
|
95
|
+
# @return [Boolean] true if path is a file
|
96
|
+
def file?(path);end
|
97
|
+
|
98
|
+
# @abstract FuseFS api
|
99
|
+
# @return [Array<String>] array of file and directory names within path
|
100
|
+
def contents(path);return [];end
|
101
|
+
|
102
|
+
# @abstract FuseFS api
|
103
|
+
# @return [Boolean] true if path is an executable file
|
104
|
+
def executable?(path);return false;end
|
105
|
+
|
106
|
+
# File size
|
107
|
+
# @abstract FuseFS api
|
108
|
+
# @return [Fixnum] the size in byte of a file (lots of applications rely on this being accurate )
|
109
|
+
def size(path);return 0;end
|
110
|
+
|
111
|
+
# File time information. RFuseFS extension.
|
112
|
+
# @abstract FuseFS api
|
113
|
+
# @return [Array<Fixnum, Time>] a 3 element array [ atime, mtime. ctime ] (good for rsync etc)
|
114
|
+
def times(path);return INIT_TIMES;end
|
115
|
+
|
116
|
+
# @abstract FuseFS api
|
117
|
+
# @return [String] the contents of the file at path
|
118
|
+
def read_file(path);return "";end
|
119
|
+
|
120
|
+
# @abstract FuseFS api
|
121
|
+
# @return [Boolean] true if the user can write to file at path
|
122
|
+
def can_write?(path);return false;end
|
123
|
+
|
124
|
+
# Write the contents of str to file at path
|
125
|
+
# @abstract FuseFS api
|
126
|
+
def write_to(path,str);end
|
127
|
+
|
128
|
+
# @abstract FuseFS api
|
129
|
+
# @return [Boolean] true if the user can delete the file at path
|
130
|
+
def can_delete?(path);return false;end
|
131
|
+
|
132
|
+
# Delete the file at path
|
133
|
+
# @abstract FuseFS api
|
134
|
+
def delete(path);end
|
135
|
+
|
136
|
+
# @abstract FuseFS api
|
137
|
+
# @return [Boolean] true if user can make a directory at path
|
138
|
+
def can_mkdir?(path);return false;end
|
139
|
+
|
140
|
+
# Make a directory at path
|
141
|
+
# @abstract FuseFS api
|
142
|
+
def mkdir(path);end
|
143
|
+
|
144
|
+
# @abstract FuseFS api
|
145
|
+
# @return [Boolean] true if user can remove a directory at path
|
146
|
+
def can_rmdir?(path);return false;end
|
147
|
+
|
148
|
+
# Remove the directory at path
|
149
|
+
# @abstract FuseFS api
|
150
|
+
def rmdir(path);end
|
151
|
+
|
152
|
+
# Neat toy. Called when a file is touched or has its timestamp explicitly modified
|
153
|
+
# @abstract FuseFS api
|
154
|
+
def touch(path,modtime);end
|
155
|
+
|
156
|
+
# Move a file or directory.
|
157
|
+
# @abstract FuseFS api
|
158
|
+
# @return [Object] non nil/false to indicate the rename has been handled,
|
159
|
+
# otherwise will fallback to copy/delete
|
160
|
+
def rename(from_path,to_path);end
|
161
|
+
|
162
|
+
# Raw file access
|
163
|
+
# @abstract FuseFS api
|
164
|
+
# @param mode [String] "r","w" or "rw", with "a" if file is opened for append
|
165
|
+
# @param rfusefs [Boolean] will be "true" if RFuseFS extensions are available
|
166
|
+
# @return [Object] a non nil object if you want lower level control of file operations
|
167
|
+
# Under RFuseFS this object will be passed back in to the other raw
|
168
|
+
# methods as the optional parameter _raw_
|
169
|
+
#
|
170
|
+
def raw_open(path,mode,rfusefs = nil);end
|
171
|
+
|
172
|
+
# RFuseFS extension.
|
173
|
+
#
|
174
|
+
# Truncate file at path (or filehandle raw) to offset bytes. Called immediately after a file is opened
|
175
|
+
# for write without append.
|
176
|
+
#
|
177
|
+
# This method can also be invoked (without raw) outside of an open file context. See
|
178
|
+
# FUSE documentation on truncate() vs ftruncate()
|
179
|
+
# @abstract FuseFS api
|
180
|
+
def raw_truncate(path,off,raw=nil);end
|
181
|
+
|
182
|
+
# Read _sz_ bytes from file at path (or filehandle raw) starting at offset off
|
183
|
+
#
|
184
|
+
# @param [String] path
|
185
|
+
# @param [Fixnum] offset
|
186
|
+
# @param [Fixnum] size
|
187
|
+
# @param [Object] raw the filehandle returned by {#raw_open}
|
188
|
+
# @abstract FuseFS api
|
189
|
+
def raw_read(path,offset,size,raw=nil);end
|
190
|
+
|
191
|
+
# Write _sz_ bytes from file at path (or filehandle raw) starting at offset off
|
192
|
+
# @abstract FuseFS api
|
193
|
+
def raw_write(path,off,sz,buf,raw=nil);end
|
194
|
+
|
195
|
+
# Close the file previously opened at path (or filehandle raw)
|
196
|
+
# @abstract FuseFS api
|
197
|
+
def raw_close(path,raw=nil);end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
DEFAULT_FS = FuseDir.new()
|
202
|
+
end
|