inspec/lib/vulcano/plugins/backend_stat.rb

91 lines
2.7 KiB
Ruby
Raw Normal View History

# encoding: utf-8
class Vulcano::Plugins::Backend
class Stat
TYPES = {
socket: 00140000,
symlink: 00120000,
file: 00100000,
block_device: 00060000,
directory: 00040000,
character_device: 00020000,
pipe: 00010000,
}
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)
type = TYPES.find { |_, mask| mask & tmask == mask }
type ||= [:unknown]
selinux = fields[8]
selinux = nil if selinux == '?' or selinux == '(null)'
{
type: type[0],
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)
type = TYPES.find { |_, mask| mask & tmask == mask }
type ||= [:unknown]
{
type: type[0],
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