class Archive::Tar::PosixHeader

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.”

Constants

FIELDS
HEADER_PACK_FORMAT
HEADER_UNPACK_FORMAT

Public Class Methods

new(vals) click to toggle source

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

    # File lib/archive/tar/minitar.rb
 97 def initialize(vals)
 98   unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode]
 99     raise ArgumentError
100   end
101 
102   vals[:mtime]    ||= 0
103   vals[:checksum] ||= ""
104   vals[:typeflag] ||= "0"
105   vals[:magic]    ||= "ustar"
106   vals[:version]  ||= "00"
107 
108   FIELDS.each do |field|
109     instance_variable_set("@#{field}", vals[field.intern])
110   end
111   @empty = vals[:empty]
112 end
new_from_stream(stream) click to toggle source

Creates a new PosixHeader from a data stream.

   # File lib/archive/tar/minitar.rb
66 def self.new_from_stream(stream)
67   data = stream.read(512)
68   fields    = data.unpack(HEADER_UNPACK_FORMAT)
69   name      = fields.shift
70   mode      = fields.shift.oct
71   uid       = fields.shift.oct
72   gid       = fields.shift.oct
73   size      = fields.shift.oct
74   mtime     = fields.shift.oct
75   checksum  = fields.shift.oct
76   typeflag  = fields.shift
77   linkname  = fields.shift
78   magic     = fields.shift
79   version   = fields.shift.oct
80   uname     = fields.shift
81   gname     = fields.shift
82   devmajor  = fields.shift.oct
83   devminor  = fields.shift.oct
84   prefix    = fields.shift
85 
86   empty = (data == "\0" * 512)
87 
88   new(:name => name, :mode => mode, :uid => uid, :gid => gid,
89       :size => size, :mtime => mtime, :checksum => checksum,
90       :typeflag => typeflag, :magic => magic, :version => version,
91       :uname => uname, :gname => gname, :devmajor => devmajor,
92       :devminor => devminor, :prefix => prefix, :empty => empty)
93 end

Public Instance Methods

empty?() click to toggle source
    # File lib/archive/tar/minitar.rb
114 def empty?
115   @empty
116 end
to_s() click to toggle source
    # File lib/archive/tar/minitar.rb
118 def to_s
119   update_checksum
120   header(@checksum)
121 end
update_checksum() click to toggle source

Update the checksum field.

    # File lib/archive/tar/minitar.rb
124 def update_checksum
125   hh = header(" " * 8)
126   @checksum = oct(calculate_checksum(hh), 6)
127 end

Private Instance Methods

calculate_checksum(hdr) click to toggle source
    # File lib/archive/tar/minitar.rb
138 def calculate_checksum(hdr)
139   hdr.unpack("C*").inject { |aa, bb| aa + bb }
140 end
header(chksum) click to toggle source
    # File lib/archive/tar/minitar.rb
142 def header(chksum)
143   arr = [name, oct(mode, 7), oct(uid, 7), oct(gid, 7), oct(size, 11),
144   oct(mtime, 11), chksum, " ", typeflag, linkname, magic, version,
145   uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix]
146   str = arr.pack(HEADER_PACK_FORMAT)
147   str + "\0" * ((512 - str.size) % 512)
148 end
oct(num, len) click to toggle source
    # File lib/archive/tar/minitar.rb
130 def oct(num, len)
131   if num.nil?
132     "\0" * (len + 1)
133   else
134     "%0#{len}o" % num
135   end
136 end