Class TarUtils
- java.lang.Object
-
- org.apache.commons.compress.archivers.tar.TarUtils
-
public class TarUtils extends java.lang.Object
This class provides static utility methods to work with byte streams.
-
-
Field Summary
Fields Modifier and Type Field Description private static int
BYTE_MASK
(package private) static ZipEncoding
DEFAULT_ENCODING
(package private) static ZipEncoding
FALLBACK_ENCODING
Encapsulates the algorithms used up to Commons Compress 1.3 as ZipEncoding.
-
Constructor Summary
Constructors Modifier Constructor Description private
TarUtils()
Prevents instantiation.
-
Method Summary
All Methods Static Methods Concrete Methods Deprecated Methods Modifier and Type Method Description static long
computeCheckSum(byte[] buf)
Computes the checksum of a tar entry header.private static java.lang.String
exceptionMessage(byte[] buffer, int offset, int length, int current, byte currentByte)
private static void
formatBigIntegerBinary(long value, byte[] buf, int offset, int length, boolean negative)
static int
formatCheckSumOctalBytes(long value, byte[] buf, int offset, int length)
Writes an octal value into a buffer.private static void
formatLongBinary(long value, byte[] buf, int offset, int length, boolean negative)
static int
formatLongOctalBytes(long value, byte[] buf, int offset, int length)
Writes an octal long integer into a buffer.static int
formatLongOctalOrBinaryBytes(long value, byte[] buf, int offset, int length)
Writes a long integer into a buffer as an octal string if this will fit, or as a binary number otherwise.static int
formatNameBytes(java.lang.String name, byte[] buf, int offset, int length)
Copies a name into a buffer.static int
formatNameBytes(java.lang.String name, byte[] buf, int offset, int length, ZipEncoding encoding)
Copies a name into a buffer.static int
formatOctalBytes(long value, byte[] buf, int offset, int length)
Writes an octal integer into a buffer.static void
formatUnsignedOctalString(long value, byte[] buffer, int offset, int length)
Fills a buffer with unsigned octal number, padded with leading zeroes.private static long
parseBinaryBigInteger(byte[] buffer, int offset, int length, boolean negative)
private static long
parseBinaryLong(byte[] buffer, int offset, int length, boolean negative)
static boolean
parseBoolean(byte[] buffer, int offset)
Parses a boolean byte from a buffer.protected static java.util.List<TarArchiveStructSparse>
parseFromPAX01SparseHeaders(java.lang.String sparseMap)
For PAX Format 0.1, the sparse headers are stored in a single variable : GNU.sparse.map GNU.sparse.map Map of non-null data chunks.static java.lang.String
parseName(byte[] buffer, int offset, int length)
Parses an entry name from a buffer.static java.lang.String
parseName(byte[] buffer, int offset, int length, ZipEncoding encoding)
Parses an entry name from a buffer.static long
parseOctal(byte[] buffer, int offset, int length)
Parses an octal string from a buffer.static long
parseOctalOrBinary(byte[] buffer, int offset, int length)
Computes the value contained in a byte buffer.protected static java.util.List<TarArchiveStructSparse>
parsePAX01SparseHeaders(java.lang.String sparseMap)
Deprecated.use #parseFromPAX01SparseHeaders insteadprotected static java.util.List<TarArchiveStructSparse>
parsePAX1XSparseHeaders(java.io.InputStream inputStream, int recordSize)
For PAX Format 1.X: The sparse map itself is stored in the file data block, preceding the actual file data.protected static java.util.Map<java.lang.String,java.lang.String>
parsePaxHeaders(java.io.InputStream inputStream, java.util.List<TarArchiveStructSparse> sparseHeaders, java.util.Map<java.lang.String,java.lang.String> globalPaxHeaders)
Deprecated.use the four-arg version insteadprotected static java.util.Map<java.lang.String,java.lang.String>
parsePaxHeaders(java.io.InputStream inputStream, java.util.List<TarArchiveStructSparse> sparseHeaders, java.util.Map<java.lang.String,java.lang.String> globalPaxHeaders, long headerSize)
For PAX Format 0.0, the sparse headers(GNU.sparse.offset and GNU.sparse.numbytes) may appear multi times, and they look like:static TarArchiveStructSparse
parseSparse(byte[] buffer, int offset)
Parses the content of a PAX 1.0 sparse block.private static long[]
readLineOfNumberForPax1X(java.io.InputStream inputStream)
For 1.X PAX Format, the sparse headers are stored in the file data block, preceding the actual file data.(package private) static java.util.List<TarArchiveStructSparse>
readSparseStructs(byte[] buffer, int offset, int entries)
static boolean
verifyCheckSum(byte[] header)
Wikipedia says: The checksum is calculated by taking the sum of the unsigned byte values of the header block with the eight checksum bytes taken to be ASCII spaces (decimal value 32).
-
-
-
Field Detail
-
BYTE_MASK
private static final int BYTE_MASK
- See Also:
- Constant Field Values
-
DEFAULT_ENCODING
static final ZipEncoding DEFAULT_ENCODING
-
FALLBACK_ENCODING
static final ZipEncoding FALLBACK_ENCODING
Encapsulates the algorithms used up to Commons Compress 1.3 as ZipEncoding.
-
-
Method Detail
-
computeCheckSum
public static long computeCheckSum(byte[] buf)
Computes the checksum of a tar entry header.- Parameters:
buf
- The tar entry's header buffer.- Returns:
- The computed checksum.
-
exceptionMessage
private static java.lang.String exceptionMessage(byte[] buffer, int offset, int length, int current, byte currentByte)
-
formatBigIntegerBinary
private static void formatBigIntegerBinary(long value, byte[] buf, int offset, int length, boolean negative)
-
formatCheckSumOctalBytes
public static int formatCheckSumOctalBytes(long value, byte[] buf, int offset, int length)
Writes an octal value into a buffer. UsesformatUnsignedOctalString(long, byte[], int, int)
to format the value as an octal string with leading zeros. The converted number is followed by NUL and then space.- Parameters:
value
- The value to convertbuf
- The destination bufferoffset
- The starting offset into the buffer.length
- The size of the buffer.- Returns:
- The updated value of offset, i.e. offset+length
- Throws:
java.lang.IllegalArgumentException
- if the value (and trailer) will not fit in the buffer
-
formatLongBinary
private static void formatLongBinary(long value, byte[] buf, int offset, int length, boolean negative)
-
formatLongOctalBytes
public static int formatLongOctalBytes(long value, byte[] buf, int offset, int length)
Writes an octal long integer into a buffer. UsesformatUnsignedOctalString(long, byte[], int, int)
to format the value as an octal string with leading zeros. The converted number is followed by a space.- Parameters:
value
- The value to write as octalbuf
- The destinationbuffer.offset
- The starting offset into the buffer.length
- The length of the buffer- Returns:
- The updated offset
- Throws:
java.lang.IllegalArgumentException
- if the value (and trailer) will not fit in the buffer
-
formatLongOctalOrBinaryBytes
public static int formatLongOctalOrBinaryBytes(long value, byte[] buf, int offset, int length)
Writes a long integer into a buffer as an octal string if this will fit, or as a binary number otherwise. UsesformatUnsignedOctalString(long, byte[], int, int)
to format the value as an octal string with leading zeros. The converted number is followed by a space.- Parameters:
value
- The value to write into the buffer.buf
- The destination buffer.offset
- The starting offset into the buffer.length
- The length of the buffer.- Returns:
- The updated offset.
- Throws:
java.lang.IllegalArgumentException
- if the value (and trailer) will not fit in the buffer.- Since:
- 1.4
-
formatNameBytes
public static int formatNameBytes(java.lang.String name, byte[] buf, int offset, int length)
Copies a name into a buffer. Copies characters from the name into the buffer starting at the specified offset. If the buffer is longer than the name, the buffer is filled with trailing NULs. If the name is longer than the buffer, the output is truncated.- Parameters:
name
- The header name from which to copy the characters.buf
- The buffer where the name is to be stored.offset
- The starting offset into the bufferlength
- The maximum number of header bytes to copy.- Returns:
- The updated offset, i.e. offset + length
-
formatNameBytes
public static int formatNameBytes(java.lang.String name, byte[] buf, int offset, int length, ZipEncoding encoding) throws java.io.IOException
Copies a name into a buffer. Copies characters from the name into the buffer starting at the specified offset. If the buffer is longer than the name, the buffer is filled with trailing NULs. If the name is longer than the buffer, the output is truncated.- Parameters:
name
- The header name from which to copy the characters.buf
- The buffer where the name is to be stored.offset
- The starting offset into the bufferlength
- The maximum number of header bytes to copy.encoding
- name of the encoding to use for file names- Returns:
- The updated offset, i.e. offset + length
- Throws:
java.io.IOException
- on error- Since:
- 1.4
-
formatOctalBytes
public static int formatOctalBytes(long value, byte[] buf, int offset, int length)
Writes an octal integer into a buffer. UsesformatUnsignedOctalString(long, byte[], int, int)
to format the value as an octal string with leading zeros. The converted number is followed by space and NUL- Parameters:
value
- The value to writebuf
- The buffer to receive the outputoffset
- The starting offset into the bufferlength
- The size of the output buffer- Returns:
- The updated offset, i.e. offset+length
- Throws:
java.lang.IllegalArgumentException
- if the value (and trailer) will not fit in the buffer
-
formatUnsignedOctalString
public static void formatUnsignedOctalString(long value, byte[] buffer, int offset, int length)
Fills a buffer with unsigned octal number, padded with leading zeroes.- Parameters:
value
- number to convert to octal - treated as unsignedbuffer
- destination bufferoffset
- starting offset in bufferlength
- length of buffer to fill- Throws:
java.lang.IllegalArgumentException
- if the value will not fit in the buffer
-
parseBinaryBigInteger
private static long parseBinaryBigInteger(byte[] buffer, int offset, int length, boolean negative)
-
parseBinaryLong
private static long parseBinaryLong(byte[] buffer, int offset, int length, boolean negative)
-
parseBoolean
public static boolean parseBoolean(byte[] buffer, int offset)
Parses a boolean byte from a buffer. Leading spaces and NUL are ignored. The buffer may contain trailing spaces or NULs.- Parameters:
buffer
- The buffer from which to parse.offset
- The offset into the buffer from which to parse.- Returns:
- The boolean value of the bytes.
- Throws:
java.lang.IllegalArgumentException
- if an invalid byte is detected.
-
parseFromPAX01SparseHeaders
protected static java.util.List<TarArchiveStructSparse> parseFromPAX01SparseHeaders(java.lang.String sparseMap) throws java.io.IOException
For PAX Format 0.1, the sparse headers are stored in a single variable : GNU.sparse.map GNU.sparse.map Map of non-null data chunks. It is a string consisting of comma-separated values "offset,size[,offset-1,size-1...]"- Parameters:
sparseMap
- the sparse map string consisting of comma-separated values "offset,size[,offset-1,size-1...]"- Returns:
- unmodifiable list of sparse headers parsed from sparse map
- Throws:
java.io.IOException
- Corrupted TAR archive.- Since:
- 1.21
-
parseName
public static java.lang.String parseName(byte[] buffer, int offset, int length)
Parses an entry name from a buffer. Parsing stops when a NUL is found or the buffer length is reached.- Parameters:
buffer
- The buffer from which to parse.offset
- The offset into the buffer from which to parse.length
- The maximum number of bytes to parse.- Returns:
- The entry name.
-
parseName
public static java.lang.String parseName(byte[] buffer, int offset, int length, ZipEncoding encoding) throws java.io.IOException
Parses an entry name from a buffer. Parsing stops when a NUL is found or the buffer length is reached.- Parameters:
buffer
- The buffer from which to parse.offset
- The offset into the buffer from which to parse.length
- The maximum number of bytes to parse.encoding
- name of the encoding to use for file names- Returns:
- The entry name.
- Throws:
java.io.IOException
- on error- Since:
- 1.4
-
parseOctal
public static long parseOctal(byte[] buffer, int offset, int length)
Parses an octal string from a buffer.Leading spaces are ignored. The buffer must contain a trailing space or NUL, and may contain an additional trailing space or NUL.
The input buffer is allowed to contain all NULs, in which case the method returns 0L (this allows for missing fields).
To work-around some tar implementations that insert a leading NUL this method returns 0 if it detects a leading NUL since Commons Compress 1.4.
- Parameters:
buffer
- The buffer from which to parse.offset
- The offset into the buffer from which to parse.length
- The maximum number of bytes to parse - must be at least 2 bytes.- Returns:
- The long value of the octal string.
- Throws:
java.lang.IllegalArgumentException
- if the trailing space/NUL is missing or if an invalid byte is detected.
-
parseOctalOrBinary
public static long parseOctalOrBinary(byte[] buffer, int offset, int length)
Computes the value contained in a byte buffer. If the most significant bit of the first byte in the buffer is set, this bit is ignored and the rest of the buffer is interpreted as a binary number. Otherwise, the buffer is interpreted as an octal number as per the parseOctal function above.- Parameters:
buffer
- The buffer from which to parse.offset
- The offset into the buffer from which to parse.length
- The maximum number of bytes to parse.- Returns:
- The long value of the octal or binary string.
- Throws:
java.lang.IllegalArgumentException
- if the trailing space/NUL is missing or an invalid byte is detected in an octal number, or if a binary number would exceed the size of a signed long 64-bit integer.- Since:
- 1.4
-
parsePAX01SparseHeaders
@Deprecated protected static java.util.List<TarArchiveStructSparse> parsePAX01SparseHeaders(java.lang.String sparseMap)
Deprecated.use #parseFromPAX01SparseHeaders insteadFor PAX Format 0.1, the sparse headers are stored in a single variable : GNU.sparse.mapGNU.sparse.map: Map of non-null data chunks. It is a string consisting of comma-separated values "offset,size[,offset-1,size-1...]"
Will internally invoke
parseFromPAX01SparseHeaders(java.lang.String)
and map IOExceptions to a RzuntimeException, You should useparseFromPAX01SparseHeaders(java.lang.String)
directly instead.- Parameters:
sparseMap
- the sparse map string consisting of comma-separated values "offset,size[,offset-1,size-1...]"- Returns:
- sparse headers parsed from sparse map
-
parsePAX1XSparseHeaders
protected static java.util.List<TarArchiveStructSparse> parsePAX1XSparseHeaders(java.io.InputStream inputStream, int recordSize) throws java.io.IOException
For PAX Format 1.X: The sparse map itself is stored in the file data block, preceding the actual file data. It consists of a series of decimal numbers delimited by newlines. The map is padded with nulls to the nearest block boundary. The first number gives the number of entries in the map. Following are map entries, each one consisting of two numbers giving the offset and size of the data block it describes.- Parameters:
inputStream
- parsing source.recordSize
- The size the TAR header- Returns:
- sparse headers
- Throws:
java.io.IOException
- if an I/O error occurs.
-
parsePaxHeaders
@Deprecated protected static java.util.Map<java.lang.String,java.lang.String> parsePaxHeaders(java.io.InputStream inputStream, java.util.List<TarArchiveStructSparse> sparseHeaders, java.util.Map<java.lang.String,java.lang.String> globalPaxHeaders) throws java.io.IOException
Deprecated.use the four-arg version insteadFor PAX Format 0.0, the sparse headers(GNU.sparse.offset and GNU.sparse.numbytes) may appear multi times, and they look like:GNU.sparse.size=size GNU.sparse.numblocks=numblocks repeat numblocks times GNU.sparse.offset=offset GNU.sparse.numbytes=numbytes end repeat
For PAX Format 0.1, the sparse headers are stored in a single variable: GNU.sparse.map
GNU.sparse.map: Map of non-null data chunks. It is a string consisting of comma-separated values "offset,size[,offset-1,size-1...]"
- Parameters:
inputStream
- input stream to read keys and valuessparseHeaders
- used in PAX Format 0.0 & 0.1, as it may appear multiple times, the sparse headers need to be stored in an array, not a mapglobalPaxHeaders
- global PAX headers of the tar archive- Returns:
- map of PAX headers values found inside the current (local or global) PAX headers tar entry.
- Throws:
java.io.IOException
- if an I/O error occurs.
-
parsePaxHeaders
protected static java.util.Map<java.lang.String,java.lang.String> parsePaxHeaders(java.io.InputStream inputStream, java.util.List<TarArchiveStructSparse> sparseHeaders, java.util.Map<java.lang.String,java.lang.String> globalPaxHeaders, long headerSize) throws java.io.IOException
For PAX Format 0.0, the sparse headers(GNU.sparse.offset and GNU.sparse.numbytes) may appear multi times, and they look like:GNU.sparse.size=size GNU.sparse.numblocks=numblocks repeat numblocks times GNU.sparse.offset=offset GNU.sparse.numbytes=numbytes end repeat
For PAX Format 0.1, the sparse headers are stored in a single variable : GNU.sparse.map
GNU.sparse.map: Map of non-null data chunks. It is a string consisting of comma-separated values "offset,size[,offset-1,size-1...]"
- Parameters:
inputStream
- input stream to read keys and valuessparseHeaders
- used in PAX Format 0.0 & 0.1, as it may appear multiple times, the sparse headers need to be stored in an array, not a mapglobalPaxHeaders
- global PAX headers of the tar archiveheaderSize
- total size of the PAX header, will be ignored if negative- Returns:
- map of PAX headers values found inside the current (local or global) PAX headers tar entry.
- Throws:
java.io.IOException
- if an I/O error occurs.- Since:
- 1.21
-
parseSparse
public static TarArchiveStructSparse parseSparse(byte[] buffer, int offset)
Parses the content of a PAX 1.0 sparse block.- Parameters:
buffer
- The buffer from which to parse.offset
- The offset into the buffer from which to parse.- Returns:
- a parsed sparse struct
- Since:
- 1.20
-
readLineOfNumberForPax1X
private static long[] readLineOfNumberForPax1X(java.io.InputStream inputStream) throws java.io.IOException
For 1.X PAX Format, the sparse headers are stored in the file data block, preceding the actual file data. It consists of a series of decimal numbers delimited by newlines.- Parameters:
inputStream
- the input stream of the tar file- Returns:
- the decimal number delimited by '\n', and the bytes read from input stream
- Throws:
java.io.IOException
-
readSparseStructs
static java.util.List<TarArchiveStructSparse> readSparseStructs(byte[] buffer, int offset, int entries) throws java.io.IOException
- Throws:
java.io.IOException
- Since:
- 1.21
-
verifyCheckSum
public static boolean verifyCheckSum(byte[] header)
Wikipedia says:The checksum is calculated by taking the sum of the unsigned byte values of the header block with the eight checksum bytes taken to be ASCII spaces (decimal value 32). It is stored as a six digit octal number with leading zeroes followed by a NUL and then a space. Various implementations do not adhere to this format. For better compatibility, ignore leading and trailing whitespace, and get the first six digits. In addition, some historic tar implementations treated bytes as signed. Implementations typically calculate the checksum both ways, and treat it as good if either the signed or unsigned sum matches the included checksum.
The return value of this method should be treated as a best-effort heuristic rather than an absolute and final truth. The checksum verification logic may well evolve over time as more special cases are encountered.
- Parameters:
header
- tar header- Returns:
- whether the checksum is reasonably good
- Since:
- 1.5
- See Also:
- COMPRESS-191
-
-