class Train::Extras::Stat

Constants

TYPES

Public Class Methods

aix_stat(shell_escaped_path, backend, follow_symlink) click to toggle source
# File lib/train/extras/stat.rb, line 103
    def self.aix_stat(shell_escaped_path, backend, follow_symlink)
      # Perl here b/c it is default on AIX
      lstat = follow_symlink ? 'lstat' : 'stat'
      stat_cmd = <<-EOP
      perl -e '
      @a = #{lstat}(shift) or exit 2;
      $u = getpwuid($a[4]);
      $g = getgrgid($a[5]);
      printf("0%o\\n%s\\n%d\\n%s\\n%d\\n%d\\n%d\\n", $a[2], $u, $a[4], $u, $a[5], $a[9], $a[7])
      ' #{shell_escaped_path}
      EOP

      res = backend.run_command(stat_cmd)
      return {} if res.exit_status != 0
      fields = res.stdout.split("\n")
      return {} if fields.length != 7
      tmask  = fields[0].to_i(8)
      {
        type:  find_type(tmask),
        mode:  tmask & 07777,
        owner: fields[1],
        uid:   fields[2].to_i,
        group: fields[3],
        gid:   fields[4].to_i,
        mtime: fields[5].to_i,
        size:  fields[6].to_i,
        selinux_label: nil,
      }
    end
bsd_stat(shell_escaped_path, backend, follow_symlink) click to toggle source
# File lib/train/extras/stat.rb, line 63
def self.bsd_stat(shell_escaped_path, backend, follow_symlink)
  # 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.
  lstat = follow_symlink ? ' -L' : ''
  res = backend.run_command(
    "stat#{lstat} -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:  find_type(tmask),
    mode:  tmask & 07777,
    owner: fields[2],
    uid:   fields[3].to_i,
    group: fields[4],
    gid:   fields[5].to_i,
    mtime: fields[7].to_i,
    size:  fields[0].to_i,
    selinux_label: fields[8],
  }
end
find_type(mode) click to toggle source
# File lib/train/extras/stat.rb, line 17
def self.find_type(mode)
  res = TYPES.find { |_, mask| mask & mode == mask }
  res.nil? ? :unknown : res[0]
end
linux_stat(shell_escaped_path, backend, follow_symlink) click to toggle source
# File lib/train/extras/stat.rb, line 36
def self.linux_stat(shell_escaped_path, backend, follow_symlink)
  lstat = follow_symlink ? ' -L' : ''
  res = backend.run_command("stat#{lstat} #{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)'

  {
    type:  find_type(tmask),
    mode:  tmask & 07777,
    owner: fields[2],
    uid:   fields[3].to_i,
    group: fields[4],
    gid:   fields[5].to_i,
    mtime: fields[7].to_i,
    size:  fields[0].to_i,
    selinux_label: selinux,
  }
end
stat(shell_escaped_path, backend, follow_symlink) click to toggle source
# File lib/train/extras/stat.rb, line 22
def self.stat(shell_escaped_path, backend, follow_symlink)
  # use perl scripts for aix and solaris 10
  if backend.os.aix? || (backend.os.solaris? && backend.os[:release].to_i < 11) || backend.os.hpux?
    return aix_stat(shell_escaped_path, backend, follow_symlink)
  end
  return bsd_stat(shell_escaped_path, backend, follow_symlink) if backend.os.bsd?
  # linux and solaris 11 will use standard linux stats
  return linux_stat(shell_escaped_path, backend, follow_symlink) 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