class Archive::Entry

Constants

BLOCK_DEVICE
CHARACTER_DEVICE
DIRECTORY
FIFO
FILE
SOCKET
S_IFBLK
S_IFCHR
S_IFDIR
S_IFIFO
S_IFLNK
S_IFMT

region File-type Constants

S_IFREG
S_IFSOCK

Attributes

entry[R]

@return [FFI::Pointer]

Public Class Methods

file_types() click to toggle source
# File lib/ffi_libarchive/entry.rb, line 24
def self.file_types
  @file_types ||= Hash[constants.reject { |k| k =~ /^S_/ }.map { |k| [k.downcase, const_get(k)] }]
end
from_pointer(entry) click to toggle source

@param [FFI::Pointer] @return [Entry]

# File lib/ffi_libarchive/entry.rb, line 32
def self.from_pointer(entry)
  new entry
end
new(entry = nil) { |self| ... } click to toggle source

@param [FFI::Pointer] entry

# File lib/ffi_libarchive/entry.rb, line 37
def initialize(entry = nil)
  if entry
    @entry = entry
  else
    @entry = C.archive_entry_new
    raise Error, 'No entry object' unless @entry
  end

  if block_given?
    begin
      yield self
    ensure
      close
    end
  else
    ObjectSpace.define_finalizer(self, method(:close).to_proc)
  end
end

Protected Class Methods

attach_attribute(api, opts = {}) click to toggle source

@param [Symbol] api API method @param [Hash] opts @option opts [#to_sym] :name Method name @option opts [Boolean] :maybe Skip undefined method? @option opts [#call] :post The result transformer @option opts [#call] :pre The arguments processor

# File lib/ffi_libarchive/entry.rb, line 75
def attach_attribute(api, opts = {})
  opts[:name] ||= api.to_s.sub(/^archive_entry_/, '').sub(/_is_.*$/, '\0?')

  define_method(opts[:name].to_sym) do |*args|
    opts[:pre].call(args) if opts[:pre].respond_to?(:call)

    result = C.respond_to?(api) || !opts[:maybe] ? C.send(api, *args.unshift(entry)) : nil
    opts[:post].respond_to?(:call) ? opts[:post].call(result) : result
  end
end
proc_2_args_to_i() click to toggle source
# File lib/ffi_libarchive/entry.rb, line 90
def proc_2_args_to_i
  @proc_2_args_to_i ||= proc { |args| args.fill(0, args.size..1).map!(&:to_i) }
end
proc_is_nonzero() click to toggle source
# File lib/ffi_libarchive/entry.rb, line 94
def proc_is_nonzero
  @proc_is_nonzero ||= 0.method(:!=)
end
proc_read_wide_string() click to toggle source
# File lib/ffi_libarchive/entry.rb, line 98
def proc_read_wide_string
  @proc_read_wide_string ||= Utils.method(:read_wide_string)
end
proc_string_arg_to_wide() click to toggle source
# File lib/ffi_libarchive/entry.rb, line 102
def proc_string_arg_to_wide
  @proc_string_arg_to_wide ||= proc { |args| args.map! { |s| Utils.to_wide_string s } }
end
proc_time_at() click to toggle source
# File lib/ffi_libarchive/entry.rb, line 86
def proc_time_at
  @proc_time_at ||= Time.method(:at)
end

Public Instance Methods

close() click to toggle source
# File lib/ffi_libarchive/entry.rb, line 56
def close
  # TODO: do we need synchronization here?
  C.archive_entry_free(@entry) if @entry
ensure
  @entry = nil
end
copy_lstat(filename) click to toggle source

@param [String, FFI::Pointer] filename

# File lib/ffi_libarchive/entry.rb, line 228
def copy_lstat(filename)
  copy_stat_from(filename.is_a?(String) ? File.lstat(filename) : filename)
end
copy_stat(filename) click to toggle source

@param [String, FFI::Pointer] filename

# File lib/ffi_libarchive/entry.rb, line 233
def copy_stat(filename)
  copy_stat_from(filename.is_a?(String) ? File.stat(filename) : filename)
end
copy_stat_from(stat) click to toggle source

@private @param [FFI::Pointer, File::Stat] stat

# File lib/ffi_libarchive/entry.rb, line 239
def copy_stat_from(stat)
  if stat.respond_to?(:null?) && !stat.null?
    C.archive_entry_copy_stat(entry, stat)

  elsif stat.is_a?(File::Stat)
    %w[dev gid uid ino nlink rdev size mode].each do |fn|
      # @type [Integer]
      f = stat.send(fn)
      send "#{fn}=", f if f
    end

    %w[atime ctime mtime birthtime].each do |fn|
      # @type [Time]
      f = stat.respond_to?(fn) ? stat.send(fn) : nil
      send "set_#{fn}", f, f.tv_nsec if f
    end
  else
    raise ArgumentError, "Copying stat for #{stat.class} is not supported"
  end
end
fflags() click to toggle source

region File flags/attributes (see lsattr) @return [Array<Integer>] of [:set, :clear]

# File lib/ffi_libarchive/entry.rb, line 290
def fflags
  set   = FFI::MemoryPointer.new :ulong
  clear = FFI::MemoryPointer.new :ulong
  C.archive_entry_fflags(entry, set, clear)

  [set.get_ulong(0), clear.get_ulong(0)]
end
filetype_s() click to toggle source

@return [Symbol]

# File lib/ffi_libarchive/entry.rb, line 215
def filetype_s
  self.class.file_types.key(filetype & S_IFMT)
end
xattr_add_entry(name, value) click to toggle source

@param [String] name @param [String] value

# File lib/ffi_libarchive/entry.rb, line 540
def xattr_add_entry(name, value)
  raise ArgumentError, 'value is not a String' unless value.is_a?(String)

  C.archive_entry_xattr_add_entry(entry, name, Utils.get_memory_ptr(value), value.bytesize)
end
xattr_next() click to toggle source

@return [Array<String>] of [:name, :value]

# File lib/ffi_libarchive/entry.rb, line 554
def xattr_next
  name  = FFI::MemoryPointer.new :pointer
  value = FFI::MemoryPointer.new :pointer
  size  = FFI::MemoryPointer.new :size_t
  return nil if C.archive_entry_xattr_next(entry, name, value, size) != C::OK

  name  = name.get_pointer(0) unless name.null?
  value = value.get_pointer(0) unless value.null?
  # Someday size.get(:size_t) could work
  [
    name.null? ? nil : name.get_string(0),
    value.null? ? nil : value.get_bytes(0, size.send("get_uint#{FFI.type_size(:size_t) * 8}", 0))
  ]
end