Class: VirtFS::Context
- Inherits:
-
Object
- Object
- VirtFS::Context
- Defined in:
- lib/virtfs/context.rb
Overview
FS-specific state under which FS calls occur.
VirtFS maps an independent context instance to each Ruby thread group, and internally switches to it before dispatching target FS calls from that thread. This class implements the core functionality behind the FS context
Instance Attribute Summary collapse
-
#key ⇒ Object
Returns the value of attribute key.
Instance Method Summary collapse
-
#chdir(dir) ⇒ Object
Change virtual filesystem working directory.
-
#chroot(dir) ⇒ Object
Change virtual file system root, after which all root calls to mount point will be mapped to specified dir.
-
#cwd_root ⇒ Object
private
Helper to change virtual filesystem working directory to filesystem root.
-
#dir_exist?(dir) ⇒ Boolean
Indicating if specified dir exists.
-
#expand_links(p, include_last = true) ⇒ Object
private
Expand symbolic links in the path.
- #fs_on(mount_point) ⇒ Object
-
#getwd ⇒ String
Current filesystem working directory.
-
#initialize ⇒ Context
constructor
A new instance of Context.
-
#mount(fs_instance, mount_point) ⇒ Object
Mount the specified FS instance at the specified mount point.
-
#mount_points ⇒ Array<String>
Array of mount points.
-
#mounted?(mount_point) ⇒ Boolean
Indicating if mount point is mounted.
-
#path_lookup(path, raise_full_path = false, include_last = true) ⇒ Object
private
Expand symbolic links and perform mount indirection look up.
- #restore_cwd_root(cwd, root) ⇒ Object
-
#umount(mount_point) ⇒ Object
Unmount the FS mounted at the specified mount point.
-
#with_root(dir) ⇒ Object
Invoke block with the specified root, restoring before returning.
Constructor Details
#initialize ⇒ Context
Returns a new instance of Context.
11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/virtfs/context.rb', line 11 def initialize @mount_points = [] @fs_lookup = {} @mount_mutex = Mutex.new @dir_mutex = Mutex.new @saved_root = nil @saved_cwd = nil @root = VfsRealFile::SEPARATOR @cwd = @root @key = nil end |
Instance Attribute Details
#key ⇒ Object
Returns the value of attribute key.
9 10 11 |
# File 'lib/virtfs/context.rb', line 9 def key @key end |
Instance Method Details
#chdir(dir) ⇒ Object
Change virtual filesystem working directory
161 162 163 164 165 166 167 168 169 |
# File 'lib/virtfs/context.rb', line 161 def chdir(dir) fs = path = nil @dir_mutex.synchronize do nwd = remove_root(local_path(dir, @cwd, @root), @root) fs, path = mount_lookup(nwd) @cwd = nwd end fs.dir_chdir(path) if fs.respond_to?(:dir_chdir) end |
#chroot(dir) ⇒ Object
Change virtual file system root, after which all root calls to mount point will be mapped to specified dir
115 116 117 118 119 120 121 122 |
# File 'lib/virtfs/context.rb', line 115 def chroot(dir) raise SystemCallError.new(dir, Errno::ENOENT::Errno) unless dir_exist?(dir) @dir_mutex.synchronize do @root = full_path(dir, true, @cwd, @root) @cwd = VfsRealFile::SEPARATOR end 0 end |
#cwd_root ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Helper to change virtual filesystem working directory to filesystem root
236 237 238 239 240 |
# File 'lib/virtfs/context.rb', line 236 def cwd_root @dir_mutex.synchronize do return @cwd, @root end end |
#dir_exist?(dir) ⇒ Boolean
Returns indicating if specified dir exists.
149 150 151 152 153 154 155 156 |
# File 'lib/virtfs/context.rb', line 149 def dir_exist?(dir) begin fs, p = path_lookup(dir) rescue Errno::ENOENT return false end VirtFS.fs_call(fs) { dir_exist?(p) } end |
#expand_links(p, include_last = true) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Expand symbolic links in the path. This must be done here, because a symlink in one file system can point to a file in another filesystem.
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 |
# File 'lib/virtfs/context.rb', line 204 def (p, include_last = true) cp = VfsRealFile::SEPARATOR components = p.split(VfsRealFile::SEPARATOR) components.shift if components[0] == "" # root last_component = components.pop unless include_last # # For each component of the path, check to see # if it's a symbolic link. If so, expand it # relative to its base directory. # components.each do |c| ncp = VfsRealFile.join(cp, c) # # Each file system knows how to check for, # and read, its own links. # fs, lp = mount_lookup(ncp) if fs.file_symlink?(lp) sl = fs.file_readlink(lp) cp = sl[0, 1] == VfsRealFile::SEPARATOR ? sl : VfsRealFile.join(cp, sl) else cp = ncp end end return cp if include_last VfsRealFile.join(cp, last_component.to_s) end |
#fs_on(mount_point) ⇒ Object
97 98 99 100 101 102 103 |
# File 'lib/virtfs/context.rb', line 97 def fs_on(mount_point) mp = full_path(mount_point, true, *cwd_root) mp += VfsRealFile::SEPARATOR unless mp.end_with?(VfsRealFile::SEPARATOR) @mount_mutex.synchronize do @fs_lookup[mp] end end |
#getwd ⇒ String
Returns current filesystem working directory.
172 173 174 |
# File 'lib/virtfs/context.rb', line 172 def getwd @cwd end |
#mount(fs_instance, mount_point) ⇒ Object
Mount the specified FS instance at the specified mount point. This registers specified fs to be accessed through the specified mount point via internal mechanisms. After this point any calls to this mount point through VirtFS under this context will be mapped through the specified fs instance
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/virtfs/context.rb', line 46 def mount(fs_instance, mount_point) mp_display = mount_point raise "mount: invalid filesystem object #{fs_instance.class.name}" unless fs_instance.respond_to?(:mount_point) raise "mount: filesystem is busy" if fs_instance.mount_point begin mount_point = full_path(mount_point, true, *cwd_root) rescue Errno::ENOENT raise SystemCallError.new(mp_display, Errno::ENOENT::Errno) end mount_point += VfsRealFile::SEPARATOR unless mount_point.end_with?(VfsRealFile::SEPARATOR) @mount_mutex.synchronize do raise "mount: mount point #{mp_display} is busy" if @fs_lookup[mount_point] fs_instance.mount_point = mount_point @fs_lookup[mount_point] = fs_instance @mount_points.push(mount_point).sort_by!(&:length).reverse! end nil end |
#mount_points ⇒ Array<String>
Returns array of mount points.
85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/virtfs/context.rb', line 85 def mount_points @mount_mutex.synchronize do @mount_points.collect do |p| if p == VfsRealFile::SEPARATOR VfsRealFile::SEPARATOR else p.chomp(VfsRealFile::SEPARATOR) end end end end |
#mounted?(mount_point) ⇒ Boolean
Returns indicating if mount point is mounted.
106 107 108 |
# File 'lib/virtfs/context.rb', line 106 def mounted?(mount_point) !fs_on(mount_point).nil? end |
#path_lookup(path, raise_full_path = false, include_last = true) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Expand symbolic links and perform mount indirection look up.
189 190 191 192 193 194 195 |
# File 'lib/virtfs/context.rb', line 189 def path_lookup(path, raise_full_path = false, include_last = true) mount_lookup(full_path(path, include_last, *cwd_root)) rescue Errno::ENOENT raise if raise_full_path # so we report the original path. raise SystemCallError.new(path, Errno::ENOENT::Errno) end |
#restore_cwd_root(cwd, root) ⇒ Object
242 243 244 245 246 247 |
# File 'lib/virtfs/context.rb', line 242 def restore_cwd_root(cwd, root) @dir_mutex.synchronize do @cwd = cwd if cwd @root = root if root end end |
#umount(mount_point) ⇒ Object
Unmount the FS mounted at the specified mount point
72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/virtfs/context.rb', line 72 def umount(mount_point) mount_point = full_path(mount_point, true, *cwd_root) @mount_mutex.synchronize do mp_display = mount_point mount_point += VfsRealFile::SEPARATOR unless mount_point.end_with?(VfsRealFile::SEPARATOR) raise "umount: nothing mounted on #{mp_display}" unless @fs_lookup[mount_point] @fs_lookup.delete(mount_point).umount @mount_points.delete(mount_point) end nil end |
#with_root(dir) ⇒ Object
Invoke block with the specified root, restoring before returning
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/virtfs/context.rb', line 127 def with_root(dir) raise SystemCallError.new(dir, Errno::ENOENT::Errno) unless dir_exist?(dir) @dir_mutex.synchronize do raise "Cannot nest with_root blocks" unless @saved_root.nil? @saved_root = @root @saved_cwd = @cwd @root = full_path(dir, true, @cwd, @root) @cwd = VfsRealFile::SEPARATOR end begin yield ensure @dir_mutex.synchronize do @root = @saved_root @cwd = @saved_cwd @saved_root = nil @saved_cwd = nil end end end |