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 103 def initialize(vals) 104 unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode] 105 raise ArgumentError 106 end 107 108 vals[:mtime] ||= 0 109 vals[:checksum] ||= "" 110 vals[:typeflag] ||= "0" 111 vals[:magic] ||= "ustar" 112 vals[:version] ||= "00" 113 114 FIELDS.each do |field| 115 instance_variable_set("@#{field}", vals[field.intern]) 116 end 117 @empty = vals[:empty] 118 end
new_from_stream(stream, long_name = nil)
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, long_name = nil) 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 if typeflag == 'L' && name == '././@LongLink' 89 long_name = stream.read(512).rstrip 90 return new_from_stream(stream, long_name) 91 end 92 93 new(:name => long_name || name, 94 :mode => mode, :uid => uid, :gid => gid, 95 :size => size, :mtime => mtime, :checksum => checksum, 96 :typeflag => typeflag, :magic => magic, :version => version, 97 :uname => uname, :gname => gname, :devmajor => devmajor, 98 :devminor => devminor, :prefix => prefix, :empty => empty) 99 end
Public Instance Methods
empty?()
click to toggle source
# File lib/archive/tar/minitar.rb 120 def empty? 121 @empty 122 end
to_s()
click to toggle source
# File lib/archive/tar/minitar.rb 124 def to_s 125 update_checksum 126 header(@checksum) 127 end
update_checksum()
click to toggle source
Update the checksum field.
# File lib/archive/tar/minitar.rb 130 def update_checksum 131 hh = header(" " * 8) 132 @checksum = oct(calculate_checksum(hh), 6) 133 end
Private Instance Methods
calculate_checksum(hdr)
click to toggle source
# File lib/archive/tar/minitar.rb 144 def calculate_checksum(hdr) 145 hdr.unpack("C*").inject { |aa, bb| aa + bb } 146 end
header(chksum)
click to toggle source
# File lib/archive/tar/minitar.rb 148 def header(chksum) 149 arr = [name, oct(mode, 7), oct(uid, 7), oct(gid, 7), oct(size, 11), 150 oct(mtime, 11), chksum, " ", typeflag, linkname, magic, version, 151 uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix] 152 str = arr.pack(HEADER_PACK_FORMAT) 153 str + "\0" * ((512 - str.size) % 512) 154 end
oct(num, len)
click to toggle source
# File lib/archive/tar/minitar.rb 136 def oct(num, len) 137 if num.nil? 138 "\0" * (len + 1) 139 else 140 "%0#{len}o" % num 141 end 142 end