COMPRESS-179 TarUtils.formatLongOctalOrBinaryBytes() assumes the field will be 12 bytes long
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/compress/trunk@1292596 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index f29ce0b..1eca3da 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -46,6 +46,9 @@
<body>
<release version="1.4" date="unreleased"
description="Release 1.4">
+ <action issue="COMPRESS-179" type="fix" date="2012-02-23">
+ TarUtils.formatLongOctalOrBinaryBytes() assumes the field will be 12 bytes long
+ </action>
<action issue="COMPRESS-175" type="fix" date="2012-02-22">
GNU Tar sometimes uses binary encoding for UID and GID
</action>
diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/TarConstants.java b/src/main/java/org/apache/commons/compress/archivers/tar/TarConstants.java
index e77ce97..ad84490 100644
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarConstants.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarConstants.java
@@ -58,6 +58,13 @@
int GIDLEN = 8;
/**
+ * The maximum value of gid/uid in a tar archive which can
+ * be expressed in octal char notation (that's 7 sevens, octal).
+ * @since 1.4
+ */
+ long MAXID = 07777777L;
+
+ /**
* The length of the checksum field in a header buffer.
*/
int CHKSUMLEN = 8;
@@ -69,7 +76,8 @@
int SIZELEN = 12;
/**
- * The maximum size of a file in a tar archive (That's 11 sevens, octal).
+ * The maximum size of a file in a tar archive
+ * which can be expressed in octal char notation (that's 11 sevens, octal).
*/
long MAXSIZE = 077777777777L;
diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java b/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
index 674fd22..7afe0d3 100644
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
@@ -324,7 +324,10 @@
public static int formatLongOctalOrBinaryBytes(
final long value, byte[] buf, final int offset, final int length) {
- if (value < TarConstants.MAXSIZE + 1) {
+ // Check whether we are dealing with UID/GID or SIZE field
+ final long maxAsOctalChar = length == TarConstants.UIDLEN ? TarConstants.MAXID : TarConstants.MAXSIZE;
+
+ if (value <= maxAsOctalChar) { // OK to store as octal chars
return formatLongOctalBytes(value, buf, offset, length);
}
diff --git a/src/test/java/org/apache/commons/compress/archivers/tar/TarUtilsTest.java b/src/test/java/org/apache/commons/compress/archivers/tar/TarUtilsTest.java
index 9e48128..9397767 100644
--- a/src/test/java/org/apache/commons/compress/archivers/tar/TarUtilsTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/tar/TarUtilsTest.java
@@ -110,20 +110,43 @@
}
}
- private void checkRoundTripOctal(final long value) {
- byte [] buffer = new byte[12];
+ private void checkRoundTripOctal(final long value, final int bufsize) {
+ byte [] buffer = new byte[bufsize];
long parseValue;
TarUtils.formatLongOctalBytes(value, buffer, 0, buffer.length);
parseValue = TarUtils.parseOctal(buffer,0, buffer.length);
assertEquals(value,parseValue);
}
+ private void checkRoundTripOctal(final long value) {
+ checkRoundTripOctal(value, TarConstants.SIZELEN);
+ }
+
public void testRoundTripOctal() {
checkRoundTripOctal(0);
checkRoundTripOctal(1);
// checkRoundTripOctal(-1); // TODO What should this do?
- checkRoundTripOctal(077777777777L);
+ checkRoundTripOctal(TarConstants.MAXSIZE);
// checkRoundTripOctal(0100000000000L); // TODO What should this do?
+
+ checkRoundTripOctal(0, TarConstants.UIDLEN);
+ checkRoundTripOctal(1, TarConstants.UIDLEN);
+ checkRoundTripOctal(TarConstants.MAXID, 8);
+ }
+
+ private void checkRoundTripOctalOrBinary(final long value, final int bufsize) {
+ byte [] buffer = new byte[bufsize];
+ long parseValue;
+ TarUtils.formatLongOctalOrBinaryBytes(value, buffer, 0, buffer.length);
+ parseValue = TarUtils.parseOctalOrBinary(buffer,0, buffer.length);
+ assertEquals(value,parseValue);
+ }
+
+ public void testRoundTripOctalOrBinary() {
+ checkRoundTripOctalOrBinary(0, 8);
+ checkRoundTripOctalOrBinary(1, 8);
+ checkRoundTripOctalOrBinary(Long.MAX_VALUE, 8); // [0x7f ff ff ff ff ff ff ff
+ checkRoundTripOctalOrBinary(TarConstants.MAXSIZE, 8); // will need binary format
}
// Check correct trailing bytes are generated