Class: GodObject::FilePermissions::ComplexMode

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/god_object/file_permissions/complex_mode.rb

Overview

An aggregate of Mode and SpecialMode to represent normal file permissions in a POSIX environment.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(numeric) ⇒ GodObject::FilePermissions::ComplexMode #initialize(enabled_digits) ⇒ GodObject::FilePermissions::ComplexMode

Returns a new instance of ComplexMode.

Overloads:

  • #initialize(numeric) ⇒ GodObject::FilePermissions::ComplexMode

    Returns a new ComplexMode object with the given numeric representation.

    Parameters:

    • numeric (Integer)

      a numeric representation

  • #initialize(enabled_digits) ⇒ GodObject::FilePermissions::ComplexMode

    Returns a new ComplexMode object with the given enabled digits

    Parameters:

    • enabled_digits (Array<:user_read, :user_write, :user_execute, :group_read, :group_write, :group_execute, :other_read, :other_write, :other_execute, :setuid, :setgid, :sticky>)

      a list of enabled digits



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
# File 'lib/god_object/file_permissions/complex_mode.rb', line 114

def initialize(*mode_components)
  sub_mode_components = Hash.new{|hash, key| hash[key] = Set.new }

  if mode_components.size == 1 && mode_components.first.respond_to?(:to_int)
    integer = mode_components.first

    [:other, :group, :user, :special].each do |mode|
      sub_mode_components[mode] = integer & 0b111
      integer = integer >> 3 unless mode == :special
    end
  else
    if mode_components.size == 1 && mode_components.first.is_a?(Enumerable)
      mode_components = mode_components.first
    end

    mode_components.flatten.each do |digit|
      case digit
      when /^user_(.*)$/
        sub_mode_components[:user] << $1.to_sym
      when /^group_(.*)$/
        sub_mode_components[:group] << $1.to_sym
      when /^other_(.*)$/
        sub_mode_components[:other] << $1.to_sym
      else
        sub_mode_components[:special] << digit
      end
    end
  end

  @user    = Mode.new(sub_mode_components[:user])
  @group   = Mode.new(sub_mode_components[:group])
  @other   = Mode.new(sub_mode_components[:other])
  @special = SpecialMode.new(sub_mode_components[:special])
end

Instance Attribute Details

#groupGodObject::FilePermissions::Mode

Returns permissions for the owning group.

Returns:



32
33
34
# File 'lib/god_object/file_permissions/complex_mode.rb', line 32

def group
  @group
end

#otherGodObject::FilePermissions::Mode

Returns permissions for everyone else.

Returns:



36
37
38
# File 'lib/god_object/file_permissions/complex_mode.rb', line 36

def other
  @other
end

#setgidObject (readonly)



254
# File 'lib/god_object/file_permissions/complex_mode.rb', line 254

def_delegators :@special, :setuid?, :setgid?, :sticky?

#setgid?true, false (readonly)

Returns the current state of the setgid digit.

Returns:

  • (true, false)

    the current state of the setgid digit



254
# File 'lib/god_object/file_permissions/complex_mode.rb', line 254

def_delegators :@special, :setuid?, :setgid?, :sticky?

#setuidObject (readonly)



254
# File 'lib/god_object/file_permissions/complex_mode.rb', line 254

def_delegators :@special, :setuid?, :setgid?, :sticky?

#setuid?true, false (readonly)

Returns the current state of the setuid digit.

Returns:

  • (true, false)

    the current state of the setuid digit



254
# File 'lib/god_object/file_permissions/complex_mode.rb', line 254

def_delegators :@special, :setuid?, :setgid?, :sticky?

#specialGodObject::FilePermissions::SpecialMode

Returns special file flags.

Returns:



39
40
41
# File 'lib/god_object/file_permissions/complex_mode.rb', line 39

def special
  @special
end

#stickyObject (readonly)



254
# File 'lib/god_object/file_permissions/complex_mode.rb', line 254

def_delegators :@special, :setuid?, :setgid?, :sticky?

#sticky?true, false (readonly)

Returns the current state of the sticky digit.

Returns:

  • (true, false)

    the current state of the sticky digit



254
# File 'lib/god_object/file_permissions/complex_mode.rb', line 254

def_delegators :@special, :setuid?, :setgid?, :sticky?

#userGodObject::FilePermissions::Mode

Returns permissions for the owner.

Returns:



28
29
30
# File 'lib/god_object/file_permissions/complex_mode.rb', line 28

def user
  @user
end

Class Method Details

.build(complex_mode) ⇒ GodObject::FilePermissions::ComplexMode .build(numeric) ⇒ GodObject::FilePermissions::ComplexMode .build(enabled_digits) ⇒ GodObject::FilePermissions::ComplexMode

Overloads:



70
71
72
73
74
75
76
# File 'lib/god_object/file_permissions/complex_mode.rb', line 70

def build(mode)
  if mode.kind_of?(self)
    mode
  else
    new(mode)
  end
end

.from_file(path, symlink_handling = :resolve_symlinks) ⇒ Object

Creates a new complex mode from filesystem object given by path.

Parameters:

  • path (Pathname, String)

    path of the source filesystem object

  • symlink_handling (:resolve_symlinks, :target_symlinks) (defaults to: :resolve_symlinks)

    if set to :target_symlinks and the target is a symlink, the symlink will not be resolved but is itself used as source. By default, the symlink will be resolved



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/god_object/file_permissions/complex_mode.rb', line 85

def from_file(path, symlink_handling = :resolve_symlinks)
  file = to_pathname(path)

  case symlink_handling
  when :resolve_symlinks
    new(file.stat.mode)
  when :target_symlinks
    new(file.lstat.mode)
  else
    raise ArgumentError, "Invalid symlink handling: #{symlink_handling.inspect}"
  end
end

Instance Method Details

#assign_to_file(path, symlink_handling = :resolve_symlinks) ⇒ Object

Assigns the mode to a filesystem object given by path.

Parameters:

  • path (Pathname, String)

    path of the target filesystem object

  • symlink_handling (:resolve_symlinks, :target_symlinks) (defaults to: :resolve_symlinks)

    if set to :target_symlinks and the target is a symlink, the symlink will not be resolved but is itself used as target. By default, the symlink will be resolved



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/god_object/file_permissions/complex_mode.rb', line 156

def assign_to_file(path, symlink_handling = :resolve_symlinks)
  file = to_pathname(path)

  case symlink_handling
  when :resolve_symlinks
    file.chmod(to_i)
  when :target_symlinks
    begin
      file.lchmod(to_i)
    rescue ::NotImplementedError, Errno::ENOSYS
      raise NotImplementedError, "lchmod function is not available in current OS or Ruby environment"
    end
  else
    raise ArgumentError, "Invalid symlink handling: #{symlink_handling.inspect}"
  end
end

#inspectString

Represents the ComplexMode as String for debugging.

Returns:

  • (String)

    a String representation for debugging



176
177
178
# File 'lib/god_object/file_permissions/complex_mode.rb', line 176

def inspect
  "#<#{self.class}: #{to_s.inspect}>"
end

#to_iInteger

Converts the ComplexMode to a four-digit octal representation

Returns:

  • (Integer)

    four-digit octal representation



221
222
223
224
225
226
227
228
229
# File 'lib/god_object/file_permissions/complex_mode.rb', line 221

def to_i
  result = 0

  [@special, @user, @group, @other].each do |mode|
    result = (result << 3) | mode.to_i
  end

  result
end

#to_sString

Represents the ComplexMode as String.

Uses the format used by the ls utility.

Returns:

  • (String)

    a String representation



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
# File 'lib/god_object/file_permissions/complex_mode.rb', line 185

def to_s
  string = ''

  string << case [@special.setuid?, @user.execute?]
            when [true, true]
              @user.to_s[0..1] << 's'
            when [true, false]
              @user.to_s[0..1] << 'S'
            else
              @user.to_s
            end

  string << case [@special.setgid?, @group.execute?]
            when [true, true]
              @group.to_s[0..1] << 's'
            when [true, false]
              @group.to_s[0..1] << 'S'
            else
              @group.to_s
            end

  string << case [@special.sticky?, @other.execute?]
            when [true, true]
              @other.to_s[0..1] << 't'
            when [true, false]
              @other.to_s[0..1] << 'T'
            else
              @other.to_s
            end

  string
end