Class: Omnizip::Formats::Zip::UnixExtraField

Inherits:
Object
  • Object
show all
Defined in:
lib/omnizip/formats/zip/unix_extra_field.rb

Overview

Info-ZIP Unix extra field (tag 0x7875) Stores Unix-specific metadata including symbolic link targets

Constant Summary collapse

UNIX_EXTRA_FIELD_TAG =
0x7875

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(version: 1, uid: nil, gid: nil, link_target: nil) ⇒ UnixExtraField

Returns a new instance of UnixExtraField.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 13

def initialize(
  version: 1,
  uid: nil,
  gid: nil,
  link_target: nil
)
  @version = version
  @uid = uid
  @gid = gid
  @link_target = link_target

  # Calculate sizes
  @uid_size = uid ? [uid].pack("V").bytesize : 0
  @gid_size = gid ? [gid].pack("V").bytesize : 0
end

Instance Attribute Details

#gidObject

Returns the value of attribute gid.



11
12
13
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 11

def gid
  @gid
end

#gid_sizeObject

Returns the value of attribute gid_size.



11
12
13
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 11

def gid_size
  @gid_size
end

Returns the value of attribute link_target.



11
12
13
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 11

def link_target
  @link_target
end

#uidObject

Returns the value of attribute uid.



11
12
13
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 11

def uid
  @uid
end

#uid_sizeObject

Returns the value of attribute uid_size.



11
12
13
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 11

def uid_size
  @uid_size
end

#versionObject

Returns the value of attribute version.



11
12
13
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 11

def version
  @version
end

Class Method Details

.find_in_extra_field(extra_field_data) ⇒ Object

Parse extra field from complete extra field data



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 97

def self.find_in_extra_field(extra_field_data)
  return nil if extra_field_data.nil? || extra_field_data.empty?

  offset = 0
  while offset < extra_field_data.bytesize - 4
    tag, size = extra_field_data[offset, 4].unpack("vv")

    if tag == UNIX_EXTRA_FIELD_TAG
      field_data = extra_field_data[offset + 4, size]
      return from_binary(field_data)
    end

    offset += 4 + size
  end

  nil
end

Create a Unix extra field for a hard link



126
127
128
129
130
131
132
133
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 126

def self.for_hardlink(uid: nil, gid: nil)
  new(
    version: 1,
    uid: uid,
    gid: gid,
    link_target: nil,
  )
end

Create a Unix extra field for a symbolic link



116
117
118
119
120
121
122
123
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 116

def self.for_symlink(target, uid: nil, gid: nil)
  new(
    version: 1,
    uid: uid,
    gid: gid,
    link_target: target,
  )
end

.from_binary(data) ⇒ Object

Parse from binary data



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 65

def self.from_binary(data)
  return nil if data.nil? || data.bytesize < 3

  version = data.unpack1("C")
  offset = 1

  # Read UID
  uid_size = data[offset].unpack1("C")
  offset += 1
  uid = (data[offset, uid_size].unpack1("V") if uid_size.positive?)
  offset += uid_size

  # Read GID
  gid_size = data[offset].unpack1("C")
  offset += 1
  gid = (data[offset, gid_size].unpack1("V") if gid_size.positive?)
  offset += gid_size

  # Read link target if present
  link_target = if offset < data.bytesize
                  data[offset..].force_encoding("UTF-8")
                end

  new(
    version: version,
    uid: uid,
    gid: gid,
    link_target: link_target,
  )
end

Instance Method Details

#sizeObject

Get the size of this extra field in bytes



136
137
138
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 136

def size
  to_binary.bytesize
end

#symlink?Boolean

Check if this field contains a symbolic link target

Returns:

  • (Boolean)


30
31
32
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 30

def symlink?
  !@link_target.nil? && !@link_target.empty?
end

#to_binaryObject

Serialize to binary format



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 35

def to_binary
  data = [version].pack("C")

  # Add UID if present
  if @uid
    data << [@uid_size].pack("C")
    data << [@uid].pack("V")[0, @uid_size]
  else
    data << [0].pack("C")
  end

  # Add GID if present
  if @gid
    data << [@gid_size].pack("C")
    data << [@gid].pack("V")[0, @gid_size]
  else
    data << [0].pack("C")
  end

  # Add link target if present (for symbolic links)
  data << @link_target.b if @link_target

  # Return with tag and size
  [
    UNIX_EXTRA_FIELD_TAG,
    data.bytesize,
  ].pack("vv") + data
end

#to_hObject

Convert to hash representation



141
142
143
144
145
146
147
148
149
# File 'lib/omnizip/formats/zip/unix_extra_field.rb', line 141

def to_h
  {
    tag: UNIX_EXTRA_FIELD_TAG,
    version: @version,
    uid: @uid,
    gid: @gid,
    link_target: @link_target,
  }
end