Class: Archive::Tar::PosixHeader

Inherits:
Object
  • Object
show all
Defined in:
lib/folio/minitar.rb

Overview

Archive::Tar::PosixHeader

Implements the POSIX tar header as a Ruby class. The structure of the POSIX tar header is:

struct tarfile_entry_posix
{                      //                               pack/unpack
   char name[100];     // ASCII (+ Z unless filled)     a100/Z100
   char mode[8];       // 0 padded, octal, null         a8  /A8
   char uid[8];        // ditto                         a8  /A8
   char gid[8];        // ditto                         a8  /A8
   char size[12];      // 0 padded, octal, null         a12 /A12
   char mtime[12];     // 0 padded, octal, null         a12 /A12
   char checksum[8];   // 0 padded, octal, null, space  a8  /A8
   char typeflag[1];   // see below                     a   /a
   char linkname[100]; // ASCII + (Z unless filled)     a100/Z100
   char magic[6];      // "ustar\0"                     a6  /A6
   char version[2];    // "00"                          a2  /A2
   char uname[32];     // ASCIIZ                        a32 /Z32
   char gname[32];     // ASCIIZ                        a32 /Z32
   char devmajor[8];   // 0 padded, octal, null         a8  /A8
   char devminor[8];   // 0 padded, octal, null         a8  /A8
   char prefix[155];   // ASCII (+ Z unless filled)     a155/Z155
};

The typeflag may be one of the following known values:

"0"

Regular file. NULL should be treated as a synonym, for compatibility purposes.

"1"

Hard link.

"2"

Symbolic link.

"3"

Character device node.

"4"

Block device node.

"5"

Directory.

"6"

FIFO node.

"7"

Reserved.

POSIX indicates that “A POSIX-compliant implementation must treat any unrecognized typeflag value as a regular file.”

Constant Summary collapse

FIELDS =

:nodoc:

%w(name mode uid gid size mtime checksum typeflag linkname) +
%w(magic version uname gname devmajor devminor prefix)
HEADER_PACK_FORMAT =
"a100a8a8a8a12a12a7aaa100a6a2a32a32a8a8a155"
HEADER_UNPACK_FORMAT =
"Z100A8A8A8A12A12A8aZ100A6A2Z32Z32A8A8Z155"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(vals) ⇒ PosixHeader

Creates a new PosixHeader. A PosixHeader cannot be created unless the #name, #size, #prefix, and #mode are provided.



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/folio/minitar.rb', line 173

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

  vals[:mtime]    ||= 0
  vals[:checksum] ||= ""
  vals[:typeflag] ||= "0"
  vals[:magic]    ||= "ustar"
  vals[:version]  ||= "00"

  FIELDS.each do |field|
    instance_variable_set("@#{field}", vals[field.intern])
  end
  @empty = vals[:empty]
end

Class Method Details

.new_from_stream(stream) ⇒ Object

Creates a new PosixHeader from a data stream.



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/folio/minitar.rb', line 142

def self.new_from_stream(stream)
  data = stream.read(512)
  fields    = data.unpack(HEADER_UNPACK_FORMAT)
  name      = fields.shift
  mode      = fields.shift.oct
  uid       = fields.shift.oct
  gid       = fields.shift.oct
  size      = fields.shift.oct
  mtime     = fields.shift.oct
  checksum  = fields.shift.oct
  typeflag  = fields.shift
  linkname  = fields.shift
  magic     = fields.shift
  version   = fields.shift.oct
  uname     = fields.shift
  gname     = fields.shift
  devmajor  = fields.shift.oct
  devminor  = fields.shift.oct
  prefix    = fields.shift

  empty = (data == "\0" * 512)

  new(:name => name, :mode => mode, :uid => uid, :gid => gid,
      :size => size, :mtime => mtime, :checksum => checksum,
      :typeflag => typeflag, :magic => magic, :version => version,
      :uname => uname, :gname => gname, :devmajor => devmajor,
      :devminor => devminor, :prefix => prefix, :empty => empty)
end

Instance Method Details

#empty?Boolean

Returns:

  • (Boolean)


190
191
192
# File 'lib/folio/minitar.rb', line 190

def empty?
  @empty
end

#to_sObject



194
195
196
197
# File 'lib/folio/minitar.rb', line 194

def to_s
  update_checksum
  header(@checksum)
end

#update_checksumObject

Update the checksum field.



200
201
202
203
# File 'lib/folio/minitar.rb', line 200

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