Browse Source

merge TAR long link handling fix by Emmanuel Bourg

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@1512171 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 12 years ago
parent
commit
18e098d81f
2 changed files with 61 additions and 27 deletions
  1. +2
    -0
      WHATSNEW
  2. +59
    -27
      src/main/org/apache/tools/tar/TarOutputStream.java

+ 2
- 0
WHATSNEW View File

@@ -14,6 +14,8 @@ Other changes:

* Documentation fix for if/unless attributes. PR 55359.

* tar entries with long link names are now handled the same way as
entries with long names.

Changes from Ant 1.9.1 TO Ant 1.9.2
===================================


+ 59
- 27
src/main/org/apache/tools/tar/TarOutputStream.java View File

@@ -273,31 +273,13 @@ public class TarOutputStream extends FilterOutputStream {
}
Map<String, String> paxHeaders = new HashMap<String, String>();
final String entryName = entry.getName();
final ByteBuffer encodedName = encoding.encode(entryName);
final int nameLen = encodedName.limit() - encodedName.position();
boolean paxHeaderContainsPath = false;
if (nameLen >= TarConstants.NAMELEN) {
boolean paxHeaderContainsPath = handleLongName(entryName, paxHeaders, "path",
TarConstants.LF_GNUTYPE_LONGNAME);

if (longFileMode == LONGFILE_POSIX) {
paxHeaders.put("path", entryName);
paxHeaderContainsPath = true;
} else if (longFileMode == LONGFILE_GNU) {
// create a TarEntry for the LongLink, the contents
// of which are the entry's name
TarEntry longLinkEntry = new TarEntry(TarConstants.GNU_LONGLINK,
TarConstants.LF_GNUTYPE_LONGNAME);

longLinkEntry.setSize(nameLen + 1); // +1 for NUL
putNextEntry(longLinkEntry);
write(encodedName.array(), encodedName.arrayOffset(), nameLen);
write(0); // NUL terminator
closeEntry();
} else if (longFileMode != LONGFILE_TRUNCATE) {
throw new RuntimeException("file name '" + entryName
+ "' is too long ( > "
+ TarConstants.NAMELEN + " bytes)");
}
}
final String linkName = entry.getLinkName();
boolean paxHeaderContainsLinkPath = linkName != null
&& handleLongName(linkName, paxHeaders, "linkpath",
TarConstants.LF_GNUTYPE_LONGLINK);

if (bigNumberMode == BIGNUMBER_POSIX) {
addPaxHeadersForBigNumbers(paxHeaders, entry);
@@ -310,10 +292,10 @@ public class TarOutputStream extends FilterOutputStream {
paxHeaders.put("path", entryName);
}

if (addPaxHeadersForNonAsciiNames
if (addPaxHeadersForNonAsciiNames && !paxHeaderContainsLinkPath
&& (entry.isLink() || entry.isSymbolicLink())
&& !ASCII.canEncode(entry.getLinkName())) {
paxHeaders.put("linkpath", entry.getLinkName());
&& !ASCII.canEncode(linkName)) {
paxHeaders.put("linkpath", linkName);
}

if (paxHeaders.size() > 0) {
@@ -596,4 +578,54 @@ public class TarOutputStream extends FilterOutputStream {
+ maxValue + " )");
}
}

/**
* Handles long file or link names according to the longFileMode setting.
*
* <p>I.e. if the given name is too long to be written to a plain
* tar header then
* <ul>
* <li>it creates a pax header who's name is given by the
* paxHeaderName parameter if longFileMode is POSIX</li>
* <li>it creates a GNU longlink entry who's type is given by
* the linkType parameter if longFileMode is GNU</li>
* <li>throws an exception othewise.</li>
* </ul></p>
*
* @param name the name to write
* @param paxHeaders current map of pax headers
* @param paxHeaderName name of the pax header to write
* @param linkType type of the GNU entry to write
* @return whether a pax header has been written.
*/
private boolean handleLongName(String name,
Map<String, String> paxHeaders,
String paxHeaderName, byte linkType)
throws IOException {
final ByteBuffer encodedName = encoding.encode(name);
final int len = encodedName.limit() - encodedName.position();
if (len >= TarConstants.NAMELEN) {

if (longFileMode == LONGFILE_POSIX) {
paxHeaders.put(paxHeaderName, name);
return true;
} else if (longFileMode == LONGFILE_GNU) {
// create a TarEntry for the LongLink, the contents
// of which are the link's name
TarEntry longLinkEntry =
new TarEntry(TarConstants.GNU_LONGLINK, linkType);

longLinkEntry.setSize(len + 1); // +1 for NUL
putNextEntry(longLinkEntry);
write(encodedName.array(), encodedName.arrayOffset(), len);
write(0); // NUL terminator
closeEntry();
} else if (longFileMode != LONGFILE_TRUNCATE) {
throw new RuntimeException(paxHeaderName + " '" + name
+ "' is too long ( > "
+ TarConstants.NAMELEN + " bytes)");
}
}
return false;
}
}

Loading…
Cancel
Save