class Zip::ExtraField::NTFS

PKWARE NTFS Extra Field (0x000a) Only Tag 0x0001 is supported

Constants

HEADER_ID
SEC_TO_UNIX_EPOCH
WINDOWS_TICK

Attributes

atime[RW]
ctime[RW]
mtime[RW]

Public Class Methods

new(binstr = nil) click to toggle source
# File lib/zip/extra_field/ntfs.rb, line 11
def initialize(binstr = nil)
  @ctime = nil
  @mtime = nil
  @atime = nil
  binstr && merge(binstr)
end

Public Instance Methods

==(other) click to toggle source
# File lib/zip/extra_field/ntfs.rb, line 36
def ==(other)
  @mtime == other.mtime &&
    @atime == other.atime &&
    @ctime == other.ctime
end
merge(binstr) click to toggle source
# File lib/zip/extra_field/ntfs.rb, line 20
def merge(binstr)
  return if binstr.empty?
  size, content = initial_parse(binstr)
  (size && content) || return

  content = content[4..-1]
  tags = parse_tags(content)

  tag1 = tags[1]
  return unless tag1
  ntfs_mtime, ntfs_atime, ntfs_ctime = tag1.unpack('Q<Q<Q<')
  ntfs_mtime && @mtime ||= from_ntfs_time(ntfs_mtime)
  ntfs_atime && @atime ||= from_ntfs_time(ntfs_atime)
  ntfs_ctime && @ctime ||= from_ntfs_time(ntfs_ctime)
end
pack_for_c_dir() click to toggle source

But 7-zip for Windows only stores at central dir

# File lib/zip/extra_field/ntfs.rb, line 48
def pack_for_c_dir
  # reserved 0 and tag 1
  s = [0, 1].pack('Vv')

  tag1 = ''.force_encoding(Encoding::BINARY)
  if @mtime
    tag1 << [to_ntfs_time(@mtime)].pack('Q<')
    if @atime
      tag1 << [to_ntfs_time(@atime)].pack('Q<')
      tag1 << [to_ntfs_time(@ctime)].pack('Q<') if @ctime
    end
  end
  s << [tag1.bytesize].pack('v') << tag1
  s
end
pack_for_local() click to toggle source

Info-ZIP note states this extra field is stored at local header

# File lib/zip/extra_field/ntfs.rb, line 43
def pack_for_local
  pack_for_c_dir
end

Private Instance Methods

from_ntfs_time(ntfs_time) click to toggle source
# File lib/zip/extra_field/ntfs.rb, line 82
def from_ntfs_time(ntfs_time)
  ::Zip::DOSTime.at(ntfs_time / WINDOWS_TICK - SEC_TO_UNIX_EPOCH)
end
parse_tags(content) click to toggle source
# File lib/zip/extra_field/ntfs.rb, line 66
def parse_tags(content)
  return {} if content.nil?
  tags = {}
  i = 0
  while i < content.bytesize
    tag, size = content[i, 4].unpack('vv')
    i += 4
    break unless tag && size
    value = content[i, size]
    i += size
    tags[tag] = value
  end

  tags
end
to_ntfs_time(time) click to toggle source
# File lib/zip/extra_field/ntfs.rb, line 86
def to_ntfs_time(time)
  ((time.to_f + SEC_TO_UNIX_EPOCH) * WINDOWS_TICK).to_i
end