Class: FuseFS::MetaDir
- Inherits:
-
Object
- Object
- FuseFS::MetaDir
- Defined in:
- lib/fusefs/metadir.rb
Overview
A full in-memory filesystem defined with hashes. It is writable to the user that mounted it may 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 Everyone!\n")
FuseFS.start(mntpath,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 (see samples/dictfs.rb), use:
root.mkdir("/dict",DictFS.new())
Constant Summary collapse
- DEFAULT_FS =
FuseDir.new()
Instance Attribute Summary collapse
-
#stats ⇒ StatsHelper
readonly
Helper for filesystem accounting (df etc).
Instance Method Summary collapse
-
#can_delete?(path) ⇒ Boolean
Delete a file.
-
#can_mkdir?(path) ⇒ Boolean
mkdir - does not make intermediate dirs!.
-
#can_rmdir?(path) ⇒ Boolean
Delete an existing directory make sure it is not empty.
-
#can_write?(path) ⇒ Boolean
can_write only applies to files…
-
#contents(path) ⇒ Object
List directory contents.
- #delete(path) ⇒ Object
- #directory?(path) ⇒ Boolean
- #file?(path) ⇒ Boolean
-
#initialize(stats = nil) ⇒ MetaDir
constructor
A new instance of MetaDir.
- #mkdir(path, dir = nil) ⇒ Object
- #read_file(path) ⇒ Object
- #rename(from_path, to_path, to_fusefs = self) ⇒ Object
- #rmdir(path) ⇒ Object
- #scan_path ⇒ Object
- #size(path) ⇒ Object
- #split_path(path) ⇒ Object
-
#statistics(path) ⇒ Object
path is ignored? - recursively calculate for all subdirs - but cache and then rely on fuse to keep count.
- #write_to(path, contents) ⇒ Object
-
#xattr(path) ⇒ Object
Extended attributes.
Constructor Details
#initialize(stats = nil) ⇒ MetaDir
Returns a new instance of MetaDir.
27 28 29 30 31 32 33 |
# File 'lib/fusefs/metadir.rb', line 27 def initialize(stats = nil) @subdirs = Hash.new(nil) @files = Hash.new(nil) @xattr = Hash.new() { |h,k| h[k] = Hash.new } @stats = stats || StatsHelper.new() @stats.adjust(0,1) end |
Instance Attribute Details
#stats ⇒ StatsHelper (readonly)
Returns helper for filesystem accounting (df etc).
25 26 27 |
# File 'lib/fusefs/metadir.rb', line 25 def stats @stats end |
Instance Method Details
#can_delete?(path) ⇒ Boolean
Delete a file
107 108 109 110 111 |
# File 'lib/fusefs/metadir.rb', line 107 def can_delete?(path) pathmethod(:can_delete?,path) do |filename| return mount_user? end end |
#can_mkdir?(path) ⇒ Boolean
mkdir - does not make intermediate dirs!
121 122 123 124 125 |
# File 'lib/fusefs/metadir.rb', line 121 def can_mkdir?(path) pathmethod(:can_mkdir?,path) do |dirname| return mount_user? end end |
#can_rmdir?(path) ⇒ Boolean
Delete an existing directory make sure it is not empty
135 136 137 138 139 |
# File 'lib/fusefs/metadir.rb', line 135 def can_rmdir?(path) pathmethod(:can_rmdir?,path) do |dirname| return mount_user? && @subdirs.has_key?(dirname) && @subdirs[dirname].contents("/").empty? end end |
#can_write?(path) ⇒ Boolean
can_write only applies to files… see can_mkdir for directories…
86 87 88 89 90 |
# File 'lib/fusefs/metadir.rb', line 86 def can_write?(path) pathmethod(:can_write?,path) do |filename| return mount_user? end end |
#contents(path) ⇒ Object
List directory contents
56 57 58 59 60 61 62 63 64 |
# File 'lib/fusefs/metadir.rb', line 56 def contents(path) pathmethod(:contents,path) do | filename | if !filename (@files.keys + @subdirs.keys).sort.uniq else @subdirs[filename].contents("/") end end end |
#delete(path) ⇒ Object
113 114 115 116 117 118 |
# File 'lib/fusefs/metadir.rb', line 113 def delete(path) pathmethod(:delete,path) do |filename| contents = @files.delete(filename) @stats.adjust(-contents.to_s.length,-1) end end |
#directory?(path) ⇒ Boolean
43 44 45 46 47 |
# File 'lib/fusefs/metadir.rb', line 43 def directory?(path) pathmethod(:directory?,path) do |filename| !filename || filename == "/" || @subdirs.has_key?(filename) end end |
#file?(path) ⇒ Boolean
49 50 51 52 53 |
# File 'lib/fusefs/metadir.rb', line 49 def file?(path) pathmethod(:file?,path) do |filename| @files.has_key?(filename) end end |
#mkdir(path, dir = nil) ⇒ Object
127 128 129 130 131 132 |
# File 'lib/fusefs/metadir.rb', line 127 def mkdir(path,dir=nil) pathmethod(:mkdir,path,dir) do | dirname,dirobj | dirobj ||= MetaDir.new(@stats) @subdirs[dirname] = dirobj end end |
#read_file(path) ⇒ Object
73 74 75 76 77 |
# File 'lib/fusefs/metadir.rb', line 73 def read_file(path) pathmethod(:read_file,path) do |filename| @files[filename].to_s end end |
#rename(from_path, to_path, to_fusefs = self) ⇒ Object
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 |
# File 'lib/fusefs/metadir.rb', line 148 def rename(from_path,to_path,to_fusefs = self) from_base,from_rest = split_path(from_path) case when !from_base # Shouldn't ever happen. raise Errno::EACCES.new("Can't move root") when !from_rest # So now we have a file or directory to move if @files.has_key?(from_base) return false unless can_delete?(from_base) && to_fusefs.can_write?(to_path) to_fusefs.write_to(to_path,@files[from_base]) to_fusefs.xattr(to_path).merge!(@xattr[from_base]) @xattr.delete(from_base) @files.delete(from_base) elsif @subdirs.has_key?(from_base) # we don't check can_rmdir? because that would prevent us # moving non empty directories return false unless mount_user? && to_fusefs.can_mkdir?(to_path) begin to_fusefs.mkdir(to_path,@subdirs[from_base]) to_fusefs.xattr(to_path).merge!(@xattr[from_base]) @xattr.delete(from_base) @subdirs.delete(from_base) @stats.adjust(0,-1) return true rescue ArgumentError # to_rest does not support mkdir with an arbitrary object return false end else #We shouldn't get this either return false end when @subdirs.has_key?(from_base) begin if to_fusefs != self #just keep recursing.. return @subdirs[from_base].rename(from_rest,to_path,to_fusefs) else to_base,to_rest = split_path(to_path) if from_base == to_base #mv within a subdir, just pass it on return @subdirs[from_base].rename(from_rest,to_rest) else #OK, this is the tricky part, we want to move something further down #our tree into something in another part of the tree. #from this point on we keep a reference to the fusefs that owns #to_path (ie us) and pass it down, but only if the eventual path #is writable anyway! if (file?(to_path)) return false unless can_write?(to_path) else return false unless can_mkdir?(to_path) end return @subdirs[from_base].rename(from_rest,to_path,self) end end rescue NoMethodError #sub dir doesn't support rename return false rescue ArgumentError #sub dir doesn't support rename with additional to_fusefs argument return false end else return false end end |
#rmdir(path) ⇒ Object
141 142 143 144 145 146 |
# File 'lib/fusefs/metadir.rb', line 141 def rmdir(path) pathmethod(:rmdir,path) do |dirname| @subdirs.delete(dirname) @stats.adjust(0,-1) end end |
#scan_path ⇒ Object
39 40 41 |
# File 'lib/fusefs/metadir.rb', line 39 def scan_path DEFAULT_FS.scan_path(path) end |
#size(path) ⇒ Object
79 80 81 82 83 |
# File 'lib/fusefs/metadir.rb', line 79 def size(path) pathmethod(:size,path) do | filename | return @files[filename].to_s.length end end |
#split_path(path) ⇒ Object
35 36 37 |
# File 'lib/fusefs/metadir.rb', line 35 def split_path(path) DEFAULT_FS.split_path(path) end |
#statistics(path) ⇒ Object
path is ignored? - recursively calculate for all subdirs - but cache and then rely on fuse to keep count
221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/fusefs/metadir.rb', line 221 def statistics(path) pathmethod(:statistics,path) do |stats_path| if @subdirs.has_key?(stats_path) #unlike all the other functions where this metadir applies #the function to @subdirs - we need to pass it on @subdirs[stats_path].statistics("/") else @stats.to_statistics end end end |
#write_to(path, contents) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/fusefs/metadir.rb', line 92 def write_to(path,contents) pathmethod(:write_to,path,contents) do |filename, filecontents | adj_size = filecontents.to_s.length adj_nodes = 1 if @files.has_key?(filename) adj_size = adj_size - @files[filename].to_s.length adj_nodes = 0 end @stats.adjust(adj_size,adj_nodes) @files[filename] = filecontents end end |
#xattr(path) ⇒ Object
Extended attributes
67 68 69 70 71 |
# File 'lib/fusefs/metadir.rb', line 67 def xattr(path) pathmethod(:xattr,path) do | path | @xattr[path] end end |