Skip to content

Commit a74a385

Browse files
committed
Z-1647 Added handling of Tar formats for files over 8GB such as Posix and Pax
1 parent 500dbba commit a74a385

1 file changed

Lines changed: 36 additions & 9 deletions

File tree

src/Tar/TarHeader.cs

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
// obligated to do so. If you do not wish to do so, delete this
3434
// exception statement from your version.
3535

36+
// HISTORY
37+
// 27-07-2012 Z-1647 Added handling of Tar formats for files over 8GB such as Posix and Pax
3638

3739
/* The tar format and its POSIX successor PAX have a long history which makes for compatability
3840
issues when creating and reading files.
@@ -584,8 +586,8 @@ public void ParseBuffer(byte[] header)
584586

585587
GroupId = (int)TarHeader.ParseOctal(header, offset, TarHeader.GIDLEN);
586588
offset += TarHeader.GIDLEN;
587-
588-
Size = TarHeader.ParseOctal(header, offset, TarHeader.SIZELEN);
589+
590+
Size = TarHeader.ParseBinaryOrOctal(header, offset, TarHeader.SIZELEN);
589591
offset += TarHeader.SIZELEN;
590592

591593
ModTime = GetDateTimeFromCTime(TarHeader.ParseOctal(header, offset, TarHeader.MODTIMELEN));
@@ -638,10 +640,10 @@ public void WriteHeader(byte[] outBuffer)
638640
offset = GetOctalBytes(mode, outBuffer, offset, MODELEN);
639641
offset = GetOctalBytes(UserId, outBuffer, offset, UIDLEN);
640642
offset = GetOctalBytes(GroupId, outBuffer, offset, GIDLEN);
641-
642-
offset = GetLongOctalBytes(Size, outBuffer, offset, SIZELEN);
643-
offset = GetLongOctalBytes(GetCTime(ModTime), outBuffer, offset, MODTIMELEN);
644-
643+
644+
offset = GetBinaryOrOctalBytes(Size, outBuffer, offset, SIZELEN);
645+
offset = GetOctalBytes(GetCTime(ModTime), outBuffer, offset, MODTIMELEN);
646+
645647
int csOffset = offset;
646648
for (int c = 0; c < CHKSUMLEN; ++c)
647649
{
@@ -740,6 +742,21 @@ static internal void RestoreSetValues()
740742
defaultGroupName = groupNameAsSet;
741743
}
742744

745+
// Return value that may be stored in octal or binary. Length must exceed 8.
746+
//
747+
static private long ParseBinaryOrOctal(byte[] header, int offset, int length) {
748+
if (header[offset] >= 128) {
749+
// File sizes over 8GB are stored in 8 right-justified bytes of binary indicated by setting the high-order bit of the leftmost byte of a numeric field.
750+
int pos = length - 8;
751+
long result = 0;
752+
while (pos < length) {
753+
result = result << 8 | header[offset + pos++];
754+
}
755+
return result;
756+
}
757+
return ParseOctal(header, offset, length);
758+
}
759+
743760
/// <summary>
744761
/// Parse an octal string from a header buffer.
745762
/// </summary>
@@ -1017,15 +1034,25 @@ public static int GetOctalBytes(long value, byte[] buffer, int offset, int lengt
10171034
}
10181035

10191036
/// <summary>
1020-
/// Put an octal representation of a value into a buffer
1037+
/// Put an octal or binary representation of a value into a buffer
10211038
/// </summary>
10221039
/// <param name = "value">Value to be convert to octal</param>
10231040
/// <param name = "buffer">The buffer to update</param>
10241041
/// <param name = "offset">The offset into the buffer to store the value</param>
1025-
/// <param name = "length">The length of the octal string</param>
1042+
/// <param name = "length">The length of the octal string. Must be 12.</param>
10261043
/// <returns>Index of next byte</returns>
1027-
public static int GetLongOctalBytes(long value, byte[] buffer, int offset, int length)
1044+
private static int GetBinaryOrOctalBytes(long value, byte[] buffer, int offset, int length)
10281045
{
1046+
if (value > 0x1FFFFFFFF) { // Octal 77777777777 (11 digits)
1047+
// Put value as binary, right-justified into the buffer. Set high order bit of left-most byte.
1048+
int pos = length - 1;
1049+
while (pos > 0) {
1050+
buffer[offset + pos--] = (byte)value;
1051+
value = value >> 8;
1052+
}
1053+
buffer[offset] = 128;
1054+
return offset + length;
1055+
}
10291056
return GetOctalBytes(value, buffer, offset, length);
10301057
}
10311058

0 commit comments

Comments
 (0)