2015-09-29 17:18:48 +00:00
|
|
|
# encoding: utf-8
|
|
|
|
|
2015-09-29 23:42:04 +00:00
|
|
|
class Vulcano::Plugins::Backend::FileCommon
|
2015-09-29 17:18:48 +00:00
|
|
|
class Stat
|
2015-09-30 00:20:47 +00:00
|
|
|
TYPES = {
|
2015-09-29 17:18:48 +00:00
|
|
|
socket: 00140000,
|
|
|
|
symlink: 00120000,
|
|
|
|
file: 00100000,
|
|
|
|
block_device: 00060000,
|
|
|
|
directory: 00040000,
|
|
|
|
character_device: 00020000,
|
|
|
|
pipe: 00010000,
|
|
|
|
}
|
|
|
|
|
2015-09-29 23:42:04 +00:00
|
|
|
def self.find_type(mode)
|
2015-09-30 00:20:47 +00:00
|
|
|
res = TYPES.find { |_, mask| mask & mode == mask }
|
2015-09-29 23:42:04 +00:00
|
|
|
res.nil? ? :unknown : res[0]
|
|
|
|
end
|
|
|
|
|
2015-09-29 17:18:48 +00:00
|
|
|
def self.stat(shell_escaped_path, backend)
|
|
|
|
return bsd_stat(shell_escaped_path, backend) if backend.os.bsd?
|
|
|
|
return linux_stat(shell_escaped_path, backend) if backend.os.unix?
|
|
|
|
# all other cases we don't handle
|
|
|
|
# TODO: print an error if we get here, as it shouldn't be invoked
|
|
|
|
# on non-unix
|
|
|
|
{}
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.linux_stat(shell_escaped_path, backend)
|
|
|
|
res = backend.run_command("stat #{shell_escaped_path} 2>/dev/null --printf '%s\n%f\n%U\n%u\n%G\n%g\n%X\n%Y\n%C'")
|
|
|
|
|
|
|
|
# ignore the exit_code: it is != 0 if selinux labels are not supported
|
|
|
|
# on the system.
|
|
|
|
|
|
|
|
fields = res.stdout.split("\n")
|
|
|
|
return {} if fields.length != 9
|
|
|
|
|
|
|
|
tmask = fields[1].to_i(16)
|
|
|
|
selinux = fields[8]
|
|
|
|
selinux = nil if selinux == '?' or selinux == '(null)'
|
|
|
|
|
|
|
|
{
|
2015-09-29 23:42:04 +00:00
|
|
|
type: find_type(tmask),
|
2015-09-29 17:18:48 +00:00
|
|
|
mode: tmask & 00777,
|
|
|
|
owner: fields[2],
|
|
|
|
group: fields[4],
|
|
|
|
mtime: fields[7].to_i,
|
|
|
|
size: fields[0].to_i,
|
|
|
|
selinux_label: selinux,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.bsd_stat(shell_escaped_path, backend)
|
|
|
|
# From stat man page on FreeBSD:
|
|
|
|
# z The size of file in bytes (st_size).
|
|
|
|
# p File type and permissions (st_mode).
|
|
|
|
# u, g User ID and group ID of file's owner (st_uid, st_gid).
|
|
|
|
# a, m, c, B
|
|
|
|
# The time file was last accessed or modified, or when the
|
|
|
|
# inode was last changed, or the birth time of the inode
|
|
|
|
# (st_atime, st_mtime, st_ctime, st_birthtime).
|
|
|
|
#
|
|
|
|
# The special output specifier S may be used to indicate that the
|
|
|
|
# output, if applicable, should be in string format. May be used
|
|
|
|
# in combination with:
|
|
|
|
# ...
|
|
|
|
# gu Display group or user name.
|
|
|
|
res = backend.run_command(
|
|
|
|
"stat -f '%z\n%p\n%Su\n%u\n%Sg\n%g\n%a\n%m' "\
|
|
|
|
"#{shell_escaped_path}")
|
|
|
|
|
|
|
|
return {} if res.exit_status != 0
|
|
|
|
|
|
|
|
fields = res.stdout.split("\n")
|
|
|
|
return {} if fields.length != 8
|
|
|
|
|
|
|
|
tmask = fields[1].to_i(8)
|
|
|
|
|
|
|
|
{
|
2015-09-29 23:42:04 +00:00
|
|
|
type: find_type(tmask),
|
2015-09-29 17:18:48 +00:00
|
|
|
mode: tmask & 00777,
|
|
|
|
owner: fields[2],
|
|
|
|
group: fields[4],
|
|
|
|
mtime: fields[7].to_i,
|
|
|
|
size: fields[0].to_i,
|
|
|
|
selinux_label: fields[8],
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|