class Solaris::Prototype

Class to represent Solaris package file prototypes. A prototype line contains information regarding file type, location, ownership, permisions.

See Solaris’ prototype(4) man-page for information on attributes.

This class does not support special lines (those beginning with !), pathname variable substitution or prototype parts.

Constants

DEFAULT_INSTALL_CLASS

Install class to use if not specified.

DEFAULT_PART

Part to use if not specified. Solaris 10 documentation for prototype(4) states that no part given implies “part 1”.

RE_FTYPE

Regular expression for filetype.

RE_GROUP

Regular expression for group name.

RE_INSTALL_CLASS

Regular expression for install class.

RE_MAJOR

Regular expression for major device mode.

RE_MINOR

Regular expression for minor device mode.

RE_MODE

Regular expression for octal file mode.

RE_OWNER

Regular expression for user name.

RE_PATH

Regular expression for path.

Attributes

ftype[RW]

The file type. One of :b, :c, :d, :e, :f, :p, :v, :x, :i, :l, :s.

group[RW]

The file’s group (string).

install_class[RW]

The installation class. Defaults to DEFAULT_INSTALL_CLASS.

major[RW]

The major mode (integer), for device files (ftype :b or :c).

minor[RW]

The minor mode (integer), for device files (ftype :b or :c).

mode[RW]

The mode of the file, as an integer. This is often presented as an octal number.

owner[RW]

The file user (string).

part[RW]

The prototype part (string).

path[RW]

The path of the file.

rpath[RW]

The target path for links.

Public Class Methods

from_line(line) click to toggle source

Create a Prototype object from a line from a prototype(4) file.

# File lib/solaris/prototype.rb, line 82
def self.from_line(line)
  ftype = $1.to_sym if line =~ %r^#{RE_FTYPE} /
  re = case ftype
       when :b, :c
         %r^#{ftype} #{RE_INSTALL_CLASS} #{RE_PATH} #{RE_MAJOR} #{RE_MINOR} #{RE_MODE} #{RE_OWNER} #{RE_GROUP}$/
       when :d, :e, :f, :p, :v, :x
         %r^#{ftype} #{RE_INSTALL_CLASS} #{RE_PATH} #{RE_MODE} #{RE_OWNER} #{RE_GROUP}$/
       when :i
         %r^#{ftype} #{RE_PATH}/ # perhaps not really path
       when :l, :s
         %r^#{ftype} #{RE_INSTALL_CLASS} #{RE_PATH}=#{RE_PATH}/
       else
         raise ArgumentError, 'Unknown filetype'
       end
  if line =~ re
    proto = self.new
    proto.ftype = ftype
    case ftype
    when :b, :c
      proto.install_class = $1
      proto.path =$2
      proto.major = $3.to_i
      proto.minor = $4.to_i
      proto.mode = $5 == '?' ? $5 : $5.to_i( 8 )
      proto.owner = $6
      proto.group = $7
    when :d, :e, :f, :p, :v, :x
      proto.install_class = $1
      proto.path = $2
      proto.mode = $3 == '?' ? $3 : $3.to_i( 8 )
      proto.owner = $4
      proto.group = $5
    when :i
      proto.path = $1
    when :l, :s
      proto.install_class = $1
      proto.path = $2
      proto.rpath = $3
    end
  else
    if line =~ %r^!/
      raise ArgumentError, "Prototype commands not supported #{line.inspect}"
    else
      raise ArgumentError, "Could not parse line #{line.inspect}"
    end
  end
  proto
end
from_path(path, actual=nil) click to toggle source

Create a Prototype from the file at the path on the local filesystem.

If actual is provided then this is the path that is used for the object’s path property although all other properties are created from the path argument. The process must be able to stat(2) the file at path to determine these properties.

If this object is to be fed to pkgmk(1M) to be installed at real_location and the file that will be used to construct the package currently lives at current_location then the second argument should take the form real_location=current_location. The first argument (path) is always the file from which the Prototype’s properties only (eg. owner, mode) are created.

For example, to take the object attributes from the already installed file in /opt/MYpkg/foo, but to subsequently package the file ./foo in that same location using pkgmk(1M) call:

from_path( '/opt/MYpkg/foo', '/opt/MYpkg/foo=./foo' )
# File lib/solaris/prototype.rb, line 150
def self.from_path(path, actual=nil)
  proto = self.new
  proto.part = DEFAULT_PART
  # Use #lstat since we are always interested in the link source,
  # not the target.
  stat = File.lstat( path )
  raise RuntimeError, 'Unknown file type' if stat.ftype == 'unknown'
  # Stat returns "link" for symlink, not "symlink"
  proto.ftype = stat.symlink? ? :s : stat.ftype[0].to_sym
  proto.path = actual || path
  proto.part = nil
  proto.install_class = DEFAULT_INSTALL_CLASS
  if [ :b, :c ].include?( proto.ftype )
    proto.major = stat.dev_major
    proto.minor = stat.dev_minor
  end
  proto.mode = stat.mode & 07777
  proto.owner = Etc.getpwuid( stat.uid ).name
  proto.group = Etc.getgrgid( stat.gid ).name
  proto
end
new() click to toggle source

Create a new Solaris::Prototype object.

# File lib/solaris/prototype.rb, line 173
def initialize
end

Public Instance Methods

relocatable?() click to toggle source

Relocatable files have a non-absolute path.

# File lib/solaris/prototype.rb, line 177
def relocatable?
  @path !~ %r^\//
end
to_s() click to toggle source

Convert the object to a prototype(4) line (string).

# File lib/solaris/prototype.rb, line 182
def to_s
  ( ( @part ? [ @part ] : [] ) +
   case @ftype
   when :b, :c
     [ @ftype, @install_class, @path, @major, @minor, mode_s, @owner, @group ]
   when :d, :e, :f, :p, :v, :x
     [ @ftype, @install_class, @path, mode_s, @owner, @group ]
   when :i
     [ @ftype, @path ]
   when :l, :s
     [ @ftype, @install_class, "#{@path}=#{@rpath}" ]
   else
     raise RuntimeError, "Unknown ftype #{@ftype.inspect}"
   end ).join( ' ' )
end
valid?() click to toggle source

Returns true if the object is a valid prototype specification, false otherwise.

# File lib/solaris/prototype.rb, line 200
def valid?
  begin
    self.class.from_line( to_s )
  rescue ArgumentError, RuntimeError
    false
  else
    true
  end

end

Private Instance Methods

mode_s() click to toggle source

String to represent the mode attribute. If the mode is to be set explicitly then return its 4-digit octal representation as a string. If the mode is to be “unchanged” then return “?”.

# File lib/solaris/prototype.rb, line 216
def mode_s
  @mode == '?' ? '?' : ( '%04o' % @mode )
end