class Minitar::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]; // 0 padded, octal, null a8 /A8 char gid[8]; // 0 padded, octal, null 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
is one of several known values.
POSIX indicates that “A POSIX-compliant implementation must treat any unrecognized typeflag value as a regular file.”
Constants
- BLOCK_SIZE
- FIELDS
All fields available in a POSIX tar(1) header.
- GNU_EXT_LONG_LINK
- HEADER_PACK_FORMAT
The pack format passed to Array#pack for encoding a header.
- HEADER_UNPACK_FORMAT
The unpack format passed to String#unpack for decoding a header.
- MAGIC_BYTES
- OPTIONAL_FIELDS
Fields that may be set in a POSIX tar(1) header.
- REQUIRED_FIELDS
Fields that must be set in a POSIX tar(1) header.
Attributes
The checksum of the file. Stored as an octal integer. Calculated before encoding the header as a string.
The major device ID. Not currently used.
The minor device ID. Not currently used.
The Unix owner group ID of the file. Stored as an octal integer.
The group name of the Unix owner of the file.
The name of the link stored. Not currently used.
Always “ustar0”.
The Unix file mode of the file. Stored as an octal integer. Required.
The modification time of the file in epoch seconds. Stored as an octal integer.
The name of the file. By default, limited to 100 bytes. Required. May be longer (up to BLOCK_SIZE
bytes) if using the GNU long name tar extension.
The prefix of the file; the path before name
. Limited to 155 bytes. Required.
The size of the file. Required.
The type of record in the file.
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.
The Unix owner user ID of the file. Stored as an octal integer.
The user name of the Unix owner of the file.
Always “00”
Public Class Methods
Creates a new PosixHeader
from a BLOCK_SIZE-byte data buffer.
# File lib/minitar/posix_header.rb, line 73 def from_data(data) fields = data.unpack(HEADER_UNPACK_FORMAT) name = fields.shift mode = fields.shift.oct uid = fields.shift.oct gid = fields.shift.oct size = strict_oct(fields.shift) 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.each_byte.any?(&:nonzero?) 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, linkname: linkname ) end
Creates a new PosixHeader
from a data stream.
# File lib/minitar/posix_header.rb, line 61 def from_stream(stream) from_data(stream.read(BLOCK_SIZE)) end
Creates a new PosixHeader
. A PosixHeader
cannot be created unless name
, size
, prefix
, and mode
are provided.
# File lib/minitar/posix_header.rb, line 125 def initialize(v) REQUIRED_FIELDS.each do |f| raise ArgumentError, "Field #{f} is required." unless v.key?(f) end v[:mtime] = v[:mtime].to_i v[:checksum] ||= "" v[:typeflag] ||= "0" v[:magic] ||= MAGIC_BYTES v[:version] ||= "00" FIELDS.each do |f| instance_variable_set(:"@#{f}", v[f]) end @empty = v[:empty] end
Creates a new PosixHeader
from a data stream. Deprecated; use PosixHeader.from_stream
instead.
# File lib/minitar/posix_header.rb, line 67 def new_from_stream(stream) warn "#{__method__} has been deprecated; use from_stream instead." from_stream(stream) end
Private Class Methods
# File lib/minitar/posix_header.rb, line 117 def strict_oct(string) return string.oct if /\A[0-7 ]*\z/.match?(string) raise ArgumentError, "#{string.inspect} is not a valid octal string" end
Public Instance Methods
Indicates if the header was an empty header.
# File lib/minitar/posix_header.rb, line 144 def empty? @empty end
Returns true
if the header is a long name special header which indicates that the next block of data is the filename.
# File lib/minitar/posix_header.rb, line 155 def long_name? typeflag == "L" && name == GNU_EXT_LONG_LINK end
A string representation of the header.
# File lib/minitar/posix_header.rb, line 160 def to_s update_checksum header(@checksum) end
Update the checksum field.
# File lib/minitar/posix_header.rb, line 167 def update_checksum hh = header(" " * 8) @checksum = oct(calculate_checksum(hh), 6) end
Indicates if the header has a valid magic value.
# File lib/minitar/posix_header.rb, line 149 def valid? empty? || @magic == MAGIC_BYTES end
Private Instance Methods
# File lib/minitar/posix_header.rb, line 182 def calculate_checksum(hdr) hdr.unpack("C*").inject { |a, e| a + e } end
# File lib/minitar/posix_header.rb, line 186 def header(chksum) arr = [name, oct(mode, 7), oct(uid, 7), oct(gid, 7), oct(size, 11), oct(mtime, 11), chksum, " ", typeflag, linkname, magic, version, uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix] str = arr.pack(HEADER_PACK_FORMAT) str + "\0" * ((BLOCK_SIZE - str.bytesize) % BLOCK_SIZE) end
# File lib/minitar/posix_header.rb, line 174 def oct(num, len) if num.nil? "\0" * (len + 1) else "%0#{len}o" % num end end