lib/wright/util/file_permissions.rb
require 'wright/util/file'
require 'wright/util/user'
module Wright
module Util
# Helper class to manage file permissions.
class FilePermissions
# Creates a FilePermissions object from a
# {Wright::Resource::File} or {Wright::Resource::Directory}.
#
# @param resource [Wright::Resource::File,
# Wright::Resource::Directory] the resource object
# @param filetype [Symbol] the file's type (+:file+ or +:directory+)
#
# @return [Wright::Util::FilePermissions] the FilePermissions
# object
# @raise [ArgumentError] if the user or group are invalid
def self.create_from_resource(resource, filetype)
filepath = ::File.expand_path(resource.name)
p = Wright::Util::FilePermissions.new(filepath, filetype)
p.uid = Wright::Util::User.user_to_uid(resource.owner)
p.gid = Wright::Util::User.group_to_gid(resource.group)
p.mode = resource.mode
p
end
# @return [String] the filename
attr_accessor :filename
# @return [Integer] the file's intended uid
attr_accessor :uid
# @return [Integer] the file's intended gid
attr_accessor :gid
# @return [Integer] the file's intended mode
attr_reader :mode
VALID_FILETYPES = [:file, :directory].freeze
private_constant :VALID_FILETYPES
# Initializes a FilePermissions object.
#
# @param filename [String] the file's name
# @param filetype [Symbol] the file's type (+:file+ or +:directory+)
def initialize(filename, filetype)
unless VALID_FILETYPES.include?(filetype)
raise ArgumentError, "Invalid filetype '#{filetype}'"
end
@filename = filename
@filetype = filetype
end
# @return [Integer] the file's target mode
def mode=(mode)
if mode.nil?
@mode = nil
return
end
mode_i = File.numeric_mode_to_i(mode)
unless mode_i
base_mode_i = ::File.exist?(filename) ? current_mode : default_mode
mode_i = File.symbolic_mode_to_i(mode, base_mode_i, filetype)
end
@mode = mode_i
end
# Checks if the file's uid, gid and mode are up-to-date
# @return [Bool] +true+ if the file is up to date, +false+
# otherwise
def uptodate?
if ::File.exist?(filename)
uid_uptodate? && gid_uptodate? && mode_uptodate?
else
false
end
end
# Updates the file's uid, gid and mode.
#
# @return [void]
def update
::File.chmod(mode, filename) if mode
::File.chown(uid, gid, filename) if uid || gid
end
# @return [Integer] the file's current mode
def current_mode
Wright::Util::File.file_mode(filename)
end
# @return [Integer] the file's current owner's uid
def current_uid
Wright::Util::File.file_owner(filename)
end
# @return [Integer] the file's current group's gid
def current_gid
Wright::Util::File.file_group(filename)
end
private
attr_reader :filetype
def uid_uptodate?
uid.nil? || current_uid == uid
end
def gid_uptodate?
gid.nil? || current_gid == gid
end
def mode_uptodate?
mode.nil? || current_mode == mode
end
def default_mode
case filetype
when :file
~::File.umask & 0o666
when :directory
~::File.umask & 0o777
end
end
end
end
end