Browse Source

port fix for COMPRESS-289 from Commons Compress

master
Stefan Bodewig 10 years ago
parent
commit
6d98fbb958
2 changed files with 27 additions and 7 deletions
  1. +5
    -0
      WHATSNEW
  2. +22
    -7
      src/main/org/apache/tools/tar/TarOutputStream.java

+ 5
- 0
WHATSNEW View File

@@ -32,6 +32,11 @@ Fixed bugs:
a NullPointerException when using FTP. a NullPointerException when using FTP.
Bugzilla Report 56873 Bugzilla Report 56873


* Long-Name and -link or PAX-header entries in TAR archives
always had the current time as last modfication time, creating
archives that are different at the byte level each time an
archive was built.

Other changes: Other changes:
-------------- --------------




+ 22
- 7
src/main/org/apache/tools/tar/TarOutputStream.java View File

@@ -28,6 +28,7 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.StringWriter; import java.io.StringWriter;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;


@@ -273,12 +274,12 @@ public class TarOutputStream extends FilterOutputStream {
} }
Map<String, String> paxHeaders = new HashMap<String, String>(); Map<String, String> paxHeaders = new HashMap<String, String>();
final String entryName = entry.getName(); final String entryName = entry.getName();
boolean paxHeaderContainsPath = handleLongName(entryName, paxHeaders, "path",
boolean paxHeaderContainsPath = handleLongName(entry, entryName, paxHeaders, "path",
TarConstants.LF_GNUTYPE_LONGNAME, "file name"); TarConstants.LF_GNUTYPE_LONGNAME, "file name");


final String linkName = entry.getLinkName(); final String linkName = entry.getLinkName();
boolean paxHeaderContainsLinkPath = linkName != null
&& handleLongName(linkName, paxHeaders, "linkpath",
boolean paxHeaderContainsLinkPath = linkName != null && linkName.length() > 0
&& handleLongName(entry, linkName, paxHeaders, "linkpath",
TarConstants.LF_GNUTYPE_LONGLINK, "link name"); TarConstants.LF_GNUTYPE_LONGLINK, "link name");


if (bigNumberMode == BIGNUMBER_POSIX) { if (bigNumberMode == BIGNUMBER_POSIX) {
@@ -299,7 +300,7 @@ public class TarOutputStream extends FilterOutputStream {
} }


if (paxHeaders.size() > 0) { if (paxHeaders.size() > 0) {
writePaxHeaders(entryName, paxHeaders);
writePaxHeaders(entry, entryName, paxHeaders);
} }


entry.writeEntryHeader(recordBuf, encoding, entry.writeEntryHeader(recordBuf, encoding,
@@ -465,7 +466,8 @@ public class TarOutputStream extends FilterOutputStream {
/** /**
* Writes a PAX extended header with the given map as contents. * Writes a PAX extended header with the given map as contents.
*/ */
void writePaxHeaders(String entryName,
void writePaxHeaders(TarEntry entry,
String entryName,
Map<String, String> headers) throws IOException { Map<String, String> headers) throws IOException {
String name = "./PaxHeaders.X/" + stripTo7Bits(entryName); String name = "./PaxHeaders.X/" + stripTo7Bits(entryName);
if (name.length() >= TarConstants.NAMELEN) { if (name.length() >= TarConstants.NAMELEN) {
@@ -478,6 +480,7 @@ public class TarOutputStream extends FilterOutputStream {
} }
TarEntry pex = new TarEntry(name, TarEntry pex = new TarEntry(name,
TarConstants.LF_PAX_EXTENDED_HEADER_LC); TarConstants.LF_PAX_EXTENDED_HEADER_LC);
transferModTime(entry, pex);


StringWriter w = new StringWriter(); StringWriter w = new StringWriter();
for (Map.Entry<String, String> h : headers.entrySet()) { for (Map.Entry<String, String> h : headers.entrySet()) {
@@ -537,7 +540,8 @@ public class TarOutputStream extends FilterOutputStream {
TarConstants.MAXSIZE); TarConstants.MAXSIZE);
addPaxHeaderForBigNumber(paxHeaders, "gid", entry.getGroupId(), addPaxHeaderForBigNumber(paxHeaders, "gid", entry.getGroupId(),
TarConstants.MAXID); TarConstants.MAXID);
addPaxHeaderForBigNumber(paxHeaders, "mtime", entry.getModTime().getTime() / 1000,
addPaxHeaderForBigNumber(paxHeaders, "mtime",
entry.getModTime().getTime() / 1000,
TarConstants.MAXSIZE); TarConstants.MAXSIZE);
addPaxHeaderForBigNumber(paxHeaders, "uid", entry.getUserId(), addPaxHeaderForBigNumber(paxHeaders, "uid", entry.getUserId(),
TarConstants.MAXID); TarConstants.MAXID);
@@ -594,6 +598,7 @@ public class TarOutputStream extends FilterOutputStream {
* <li>it truncates the name if longFileMode is TRUNCATE</li> * <li>it truncates the name if longFileMode is TRUNCATE</li>
* </ul></p> * </ul></p>
* *
* @param entry entry the name belongs to
* @param name the name to write * @param name the name to write
* @param paxHeaders current map of pax headers * @param paxHeaders current map of pax headers
* @param paxHeaderName name of the pax header to write * @param paxHeaderName name of the pax header to write
@@ -601,7 +606,7 @@ public class TarOutputStream extends FilterOutputStream {
* @param fieldName the name of the field * @param fieldName the name of the field
* @return whether a pax header has been written. * @return whether a pax header has been written.
*/ */
private boolean handleLongName(String name,
private boolean handleLongName(TarEntry entry , String name,
Map<String, String> paxHeaders, Map<String, String> paxHeaders,
String paxHeaderName, byte linkType, String fieldName) String paxHeaderName, byte linkType, String fieldName)
throws IOException { throws IOException {
@@ -619,6 +624,7 @@ public class TarOutputStream extends FilterOutputStream {
new TarEntry(TarConstants.GNU_LONGLINK, linkType); new TarEntry(TarConstants.GNU_LONGLINK, linkType);


longLinkEntry.setSize(len + 1); // +1 for NUL longLinkEntry.setSize(len + 1); // +1 for NUL
transferModTime(entry, longLinkEntry);
putNextEntry(longLinkEntry); putNextEntry(longLinkEntry);
write(encodedName.array(), encodedName.arrayOffset(), len); write(encodedName.array(), encodedName.arrayOffset(), len);
write(0); // NUL terminator write(0); // NUL terminator
@@ -631,4 +637,13 @@ public class TarOutputStream extends FilterOutputStream {
} }
return false; return false;
} }

private void transferModTime(TarEntry from, TarEntry to) {
Date fromModTime = from.getModTime();
long fromModTimeSeconds = fromModTime.getTime() / 1000;
if (fromModTimeSeconds < 0 || fromModTimeSeconds > TarConstants.MAXSIZE) {
fromModTime = new Date(0);
}
to.setModTime(fromModTime);
}
} }

Loading…
Cancel
Save