Class: RubySMB::Server::Share::Provider::VirtualDisk::VirtualPathname

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb

Overview

This object emulates Ruby's builtin Pathname object but uses a virtual file system instead of the real local one.

Since:

  • 3.1.1

Constant Summary collapse

SEPARATOR =

Since:

  • 3.1.1

File::SEPARATOR

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(disk, path, **kwargs) ⇒ VirtualPathname

Returns a new instance of VirtualPathname.

Parameters:

  • disk (Hash)

    The mapping of paths to objects representing the virtual file system.

  • path (String)

    The path of this entry.

  • exist? (Boolean)

    Whether or not this entry represents an existing entry in the virtual file system.

  • stat (File::Stat)

    An explicit stat that represents this object. A default VirtualStat will be created unless specified.

Since:

  • 3.1.1



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 46

def initialize(disk, path, **kwargs)
  @virtual_disk = disk
  @path = path

  if kwargs.fetch(:exist?, true)
    if kwargs[:stat]
      if kwargs[:stat].is_a?(Hash)
        @stat = VirtualStat.new(**kwargs[:stat])
      else
        @stat = kwargs[:stat]
      end
    else
      @stat = VirtualStat.new
    end
  else
    raise ArgumentError.new('can not specify a stat object when exist? is false') if kwargs[:stat]
    @stat = nil
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object (private)

Raises:

  • (NoMethodError)

Since:

  • 3.1.1



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 168

def method_missing(symbol, *args)
  # should we forward to one of the stat methods
  if STAT_METHODS.include?(symbol)
    # if we have a stat object then forward it
    return stat.send(symbol, *args) if exist?
    # if we don't have a stat object, emulate what Pathname does when it does not exist

    # these two methods return nil
    return nil if %i[ world_readable? world_writable? ].include?(symbol)

    # any of the other ?-suffixed methods return false
    return false if symbol.to_s.end_with?('?')

    # any other method raises a Errno::ENOENT exception
    raise Errno::ENOENT.new('No such file or directory')
  end

  raise NoMethodError, "undefined method `#{symbol}' for #{self.class}"
end

Instance Attribute Details

#virtual_diskObject

Since:

  • 3.1.1



39
40
41
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 39

def virtual_disk
  @virtual_disk
end

Class Method Details

.basename(*args) ⇒ Object

Since:

  • 3.1.1



111
112
113
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 111

def self.basename(*args)
  File.basename(*args)
end

.cleanpath(path) ⇒ Object

Since:

  • 3.1.1



147
148
149
150
151
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 147

def self.cleanpath(path)
  # per the docs this Pathname#cleanpath doesn't touch the file system
  # see: https://ruby-doc.org/stdlib-3.1.1/libdoc/pathname/rdoc/Pathname.html#class-Pathname-label-Core+methods
  Pathname.new(path).cleanpath.to_s
end

.dirname(*args) ⇒ Object

Since:

  • 3.1.1



119
120
121
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 119

def self.dirname(*args)
  File.dirname(*args)
end

Instance Method Details

#<=>(other) ⇒ Object

Since:

  • 3.1.1



70
71
72
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 70

def <=>(other)
  to_s <=> other.to_s
end

#==(other) ⇒ Object

Since:

  • 3.1.1



66
67
68
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 66

def ==(other)
  other.is_a?(self.class) && other.to_s == to_s
end

#absolute?Boolean

Returns:

  • (Boolean)

Since:

  • 3.1.1



99
100
101
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 99

def absolute?
  to_s.start_with?(SEPARATOR)
end

#basenameObject

Since:

  • 3.1.1



107
108
109
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 107

def basename
  lookup_or_create(self.class.basename(to_s))
end

#children(with_directory = true) ⇒ Object

Raises:

  • (Errno::ENOTDIR)

Since:

  • 3.1.1



133
134
135
136
137
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 133

def children(with_directory=true)
  raise Errno::ENOTDIR.new("Not a directory @ dir_initialize - #{to_s}") unless directory?

  @virtual_disk.each_value.select { |dent| dent.dirname == self && dent != self }.map { |dent| with_directory ? dent : dent.basename }
end

#cleanpath(consider_symlink = false) ⇒ Object

Since:

  • 3.1.1



143
144
145
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 143

def cleanpath(consider_symlink=false)
  lookup_or_create(self.class.cleanpath(to_s), stat: (exist? ? stat : nil))
end

#dirnameObject Also known as: parent

Since:

  • 3.1.1



115
116
117
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 115

def dirname
  lookup_or_create(self.class.dirname(to_s))
end

#entriesObject

Since:

  • 3.1.1



139
140
141
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 139

def entries
  children(false)
end

#exist?Boolean

Returns:

  • (Boolean)

Since:

  • 3.1.1



74
75
76
77
78
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 74

def exist?
  !@stat.nil?
rescue Errno::ENOENT
  false
end

#extnameObject

Since:

  • 3.1.1



123
124
125
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 123

def extname
  File.extname(to_s)
end

#join(other) ⇒ Object Also known as: +, /

Since:

  • 3.1.1



86
87
88
89
90
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 86

def join(other)
  # per the docs this Pathname#join doesn't touch the file system
  # see: https://ruby-doc.org/stdlib-3.1.1/libdoc/pathname/rdoc/Pathname.html#class-Pathname-label-Core+methods
  lookup_or_create(Pathname.new(to_s).join(other).to_s)
end

#relative?Boolean

Returns:

  • (Boolean)

Since:

  • 3.1.1



103
104
105
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 103

def relative?
  !absolute?
end

#splitObject

Since:

  • 3.1.1



127
128
129
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 127

def split
  [dirname, basename]
end

#statObject

Raises:

  • (Errno::ENOENT)

Since:

  • 3.1.1



80
81
82
83
84
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 80

def stat
  raise Errno::ENOENT.new('No such file or directory') unless exist? && (@stat.file? || @stat.directory?)

  @stat
end

#to_sObject

Since:

  • 3.1.1



95
96
97
# File 'lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb', line 95

def to_s
  @path
end