Class: Gem::Package::TarHeader

Inherits:
Object
  • Object
show all
Defined in:
lib/rubygems/package/tar_header.rb

Overview

– struct tarfile_entry_posix

char name[100];     # ASCII + (Z unless filled)
char mode[8];       # 0 padded, octal, null
char uid[8];        # ditto
char gid[8];        # ditto
char size[12];      # 0 padded, octal, null
char mtime[12];     # 0 padded, octal, null
char checksum[8];   # 0 padded, octal, null, space
char typeflag[1];   # file: "0"  dir: "5"
char linkname[100]; # ASCII + (Z unless filled)
char magic[6];      # "ustar\0"
char version[2];    # "00"
char uname[32];     # ASCIIZ
char gname[32];     # ASCIIZ
char devmajor[8];   # 0 padded, octal, null
char devminor[8];   # o padded, octal, null
char prefix[155];   # ASCII + (Z unless filled)

; ++ A header for a tar file

Constant Summary collapse

FIELDS =

Fields in the tar header

[
  :checksum,
  :devmajor,
  :devminor,
  :gid,
  :gname,
  :linkname,
  :magic,
  :mode,
  :mtime,
  :name,
  :prefix,
  :size,
  :typeflag,
  :uid,
  :uname,
  :version,
].freeze
PACK_FORMAT =

Pack format for a tar header

"a100" + # name
"a8"   + # mode
"a8"   + # uid
"a8"   + # gid
"a12"  + # size
"a12"  + # mtime
"a7a"  + # chksum
"a"    + # typeflag
"a100" + # linkname
"a6"   + # magic
"a2"   + # version
"a32"  + # uname
"a32"  + # gname
"a8"   + # devmajor
"a8"   + # devminor
"a155"
UNPACK_FORMAT =

Unpack format for a tar header

"A100" + # name
"A8"   + # mode
"A8"   + # uid
"A8"   + # gid
"A12"  + # size
"A12"  + # mtime
"A8"   + # checksum
"A"    + # typeflag
"A100" + # linkname
"A6"   + # magic
"A2"   + # version
"A32"  + # uname
"A32"  + # gname
"A8"   + # devmajor
"A8"   + # devminor
"A155"
EMPTY_HEADER =

:nodoc:

("\0" * 512).b.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(vals) ⇒ TarHeader

Creates a new TarHeader using vals



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rubygems/package/tar_header.rb', line 149

def initialize(vals)
  unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode]
    raise ArgumentError, ":name, :size, :prefix and :mode required"
  end

  @checksum = vals[:checksum] || ""
  @devmajor = vals[:devmajor] || 0
  @devminor = vals[:devminor] || 0
  @gid = vals[:gid] || 0
  @gname = vals[:gname] || "wheel"
  @linkname = vals[:linkname]
  @magic = vals[:magic] || "ustar"
  @mode = vals[:mode]
  @mtime = vals[:mtime] || 0
  @name = vals[:name]
  @prefix = vals[:prefix]
  @size = vals[:size]
  @typeflag = vals[:typeflag]
  @typeflag = "0" if @typeflag.nil? || @typeflag.empty?
  @uid = vals[:uid] || 0
  @uname = vals[:uname] || "wheel"
  @version = vals[:version] || "00"

  @empty = vals[:empty]
end

Class Method Details

.from(stream) ⇒ Object

Creates a tar header from IO stream



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/rubygems/package/tar_header.rb', line 103

def self.from(stream)
  header = stream.read 512
  return EMPTY if header == EMPTY_HEADER

  fields = header.unpack UNPACK_FORMAT

  new name: fields.shift,
      mode: strict_oct(fields.shift),
      uid: oct_or_256based(fields.shift),
      gid: oct_or_256based(fields.shift),
      size: strict_oct(fields.shift),
      mtime: strict_oct(fields.shift),
      checksum: strict_oct(fields.shift),
      typeflag: fields.shift,
      linkname: fields.shift,
      magic: fields.shift,
      version: strict_oct(fields.shift),
      uname: fields.shift,
      gname: fields.shift,
      devmajor: strict_oct(fields.shift),
      devminor: strict_oct(fields.shift),
      prefix: fields.shift,

      empty: false
end

.oct_or_256based(str) ⇒ Object



136
137
138
139
140
141
142
143
144
# File 'lib/rubygems/package/tar_header.rb', line 136

def self.oct_or_256based(str)
  # \x80 flags a positive 256-based number
  # \ff flags a negative 256-based number
  # In case we have a match, parse it as a signed binary value
  # in big-endian order, except that the high-order bit is ignored.

  return str.unpack1("@4N") if /\A[\x80\xff]/n.match?(str)
  strict_oct(str)
end

.strict_oct(str) ⇒ Object

Raises:

  • (ArgumentError)


129
130
131
132
133
134
# File 'lib/rubygems/package/tar_header.rb', line 129

def self.strict_oct(str)
  str.strip!
  return str.oct if /\A[0-7]*\z/.match?(str)

  raise ArgumentError, "#{str.inspect} is not an octal string"
end

Instance Method Details

#==(other) ⇒ Object

:nodoc:



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/rubygems/package/tar_header.rb', line 198

def ==(other) # :nodoc:
  self.class === other &&
    @checksum == other.checksum &&
    @devmajor == other.devmajor &&
    @devminor == other.devminor &&
    @gid      == other.gid      &&
    @gname    == other.gname    &&
    @linkname == other.linkname &&
    @magic    == other.magic    &&
    @mode     == other.mode     &&
    @mtime    == other.mtime    &&
    @name     == other.name     &&
    @prefix   == other.prefix   &&
    @size     == other.size     &&
    @typeflag == other.typeflag &&
    @uid      == other.uid      &&
    @uname    == other.uname    &&
    @version  == other.version
end

#empty?Boolean

Is the tar entry empty?

Returns:

  • (Boolean)


194
195
196
# File 'lib/rubygems/package/tar_header.rb', line 194

def empty?
  @empty
end

#full_nameObject

Header’s full name, including prefix



234
235
236
237
238
239
240
# File 'lib/rubygems/package/tar_header.rb', line 234

def full_name
  if prefix != ""
    File.join prefix, name
  else
    name
  end
end

#to_sObject

:nodoc:



218
219
220
221
# File 'lib/rubygems/package/tar_header.rb', line 218

def to_s # :nodoc:
  update_checksum
  header
end

#update_checksumObject

Updates the TarHeader’s checksum



226
227
228
229
# File 'lib/rubygems/package/tar_header.rb', line 226

def update_checksum
  header = header " " * 8
  @checksum = oct calculate_checksum(header), 6
end