module Wright::Util::File

Various file methods.

Constants

MODE_MAP
USER_MAP

Public Class Methods

expand_tilde_path(path) click to toggle source

Expands tilde symbols in file paths. Path elements other than the first one are left alone.

@param path [String] the file path

@example

Wright::Util::File.expand_tilde_path('~root/foo')
# => "/root/foo"

Wright::Util::File.expand_tilde_path('~root/foo/..')
# => "/root/foo/.."

Wright::Util::File.expand_tilde_path('../foo/bar')
# => "../foo/bar"

@return [String] the expanded path

# File lib/wright/util/file.rb, line 228
def self.expand_tilde_path(path)
  return path unless path.start_with?('~')

  first, *rest = path.split(::File::SEPARATOR)
  ::File.join(::File.expand_path(first), rest)
end
file_group(path) click to toggle source

Returns a file's owner.

@param path [String] the file's path

@example

FileUtils.touch('foo')
FileUtils.chown(0, 0, 'foo')
Wright::Util::File.file_group('foo')
# => 0

Wright::Util::File.file_group('nonexistent')
# => nil

@return [Integer] the file owner's uid or nil if the file does

not exist.
# File lib/wright/util/file.rb, line 208
def self.file_group(path)
  ::File.exist?(path) ? ::File.stat(path).gid : nil
end
file_mode(path) click to toggle source

Returns a file's current mode.

@param path [String] the file's path

@example

FileUtils.touch('foo')
FileUtils.chmod(0644, 'foo')
Wright::Util::File.file_mode('foo').to_s(8)
# => "644"

@return [Integer] the file mode as an integer or nil if the

file does not exist
# File lib/wright/util/file.rb, line 170
def self.file_mode(path)
  ::File.exist?(path) ? (::File.stat(path).mode & 07777) : nil
end
file_owner(path) click to toggle source

Returns a file's owner.

@param path [String] the file's path

@example

FileUtils.touch('foo')
FileUtils.chown(0, 0, 'foo')
Wright::Util::File.file_owner('foo')
# => 0

Wright::Util::File.file_owner('nonexistent')
# => nil

@return [Integer] the file owner's uid or nil if the file

does not exist
# File lib/wright/util/file.rb, line 189
def self.file_owner(path)
  ::File.exist?(path) ? ::File.stat(path).uid : nil
end
ln_sfn(target, link_name) click to toggle source

Creates symlinks without descending into directories.

If the file denoted by link_name is a symlink to a directory, {ln_sfn} does not descend into it. Behaves similar to GNU ln(1) or OpenBSD ln(1) when using +ln -sfn target link_name+.

@param target [String] the link target @param link_name [String] the link name

@return [void]

# File lib/wright/util/file.rb, line 245
def self.ln_sfn(target, link_name)
  if ::File.symlink?(link_name) && ::File.directory?(link_name)
    FileUtils.rm(link_name)
  end
  FileUtils.ln_sf(target, link_name)
end
numeric_mode_to_i(mode) click to toggle source

Converts a numeric mode string to an integer mode.

@param mode [String, to_i] the numeric mode string

@example

Wright::Util::File.numeric_mode_to_i('0600').to_s(8)
# => "600"

Wright::Util::File.numeric_mode_to_i('644').to_s(8)
# => "644"

Wright::Util::File.numeric_mode_to_i(0644).to_s(8)
# => "644"

Wright::Util::File.numeric_mode_to_i('invalid_mode').to_s(8)
# => nil

@return [Integer] the mode in integer form or nil if the

mode could not be converted
# File lib/wright/util/file.rb, line 145
def self.numeric_mode_to_i(mode)
  return mode.to_i unless mode.is_a?(String)
  mode =~ /\A[0-7]{3,4}\Z/ ? mode.to_i(8) : nil
end
symbolic_mode_to_i(mode, base_mode, filetype = :file) click to toggle source

Converts a symbolic mode string to an integer mode value.

@param mode [String] the symbolic mode string @param base_mode [Integer] the base mode @param filetype [Symbol] the filetype

@example

Wright::Util::File.symbolic_mode_to_i('u=rw,go=r', 0400).to_s(8)
# => "644"

Wright::Util::File.symbolic_mode_to_i('u=rw,g+r', 0200).to_s(8)
# => "640"

@return [Integer] the integer mode

# File lib/wright/util/file.rb, line 76
def self.symbolic_mode_to_i(mode, base_mode, filetype = :file)
  is_directory = (filetype == :directory)
  unless symbolic_mode?(mode)
    fail ArgumentError, "Invalid file mode \"#{mode}\""
  end
  mode_i = base_mode
  mode.split(/,/).each do |mode_clause|
    mode_i = mode_clause_to_i(mode_clause, mode_i, is_directory)
  end
  mode_i
end

Private Class Methods

apply_user_mode_masks(base_mode_i, user_mask, op, mode_mask) click to toggle source
# File lib/wright/util/file.rb, line 114
def self.apply_user_mode_masks(base_mode_i, user_mask, op, mode_mask)
  case op
  when '='
    (base_mode_i & ~user_mask) | (user_mask & mode_mask)
  when '+'
    base_mode_i | (user_mask & mode_mask)
  when '-'
    base_mode_i & ~(user_mask & mode_mask)
  end
end
mode_clause_to_i(mode_clause, base_mode_i, is_directory) click to toggle source

Converts a single symbolic mode clause to an integer mode value.

@param mode_clause [String] the symbolic mode clause @param base_mode_i [Integer] the integer base mode @param is_directory [Bool] denotes whether the mode_clause

should be treated as a symbolic directory mode clause

@example

Wright::Util::File.mode_clause_to_i('g+r', 0600, false).to_s(8)
# => "640"

Wright::Util::File.mode_clause_to_i('+rw', 0600, false).to_s(8)
# => "666"

@return [Integer] the mode clause as an integer

# File lib/wright/util/file.rb, line 104
def self.mode_clause_to_i(mode_clause, base_mode_i, is_directory)
  mode_clause = "a#{mode_clause}" if mode_clause =~ /\A[+-=]/
  who, op, perm = mode_clause.split(/([+-=])/)
  perm ||= ''
  user_mask = user_mask(who)
  mode_mask = mode_mask(perm, is_directory)
  apply_user_mode_masks(base_mode_i, user_mask, op, mode_mask)
end
mode_mask(mode, is_directory) click to toggle source
# File lib/wright/util/file.rb, line 56
def self.mode_mask(mode, is_directory)
  mode.tr!('X', 'x') if is_directory
  mode.chars.reduce(0) { |a, e| a | MODE_MAP[e].to_i }
end
symbolic_mode?(mode_str) click to toggle source
# File lib/wright/util/file.rb, line 150
def self.symbolic_mode?(mode_str)
  return true if mode_str.empty?
  mode_fragment = /([augo]*[+-=][rwxXst]*)/
  mode_re = /\A#{mode_fragment}(,#{mode_fragment})*\Z/
  !(mode_str =~ mode_re).nil?
end
user_mask(target) click to toggle source
# File lib/wright/util/file.rb, line 42
def self.user_mask(target)
  target.chars.reduce(0) { |a, e| a | USER_MAP[e] }
end