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. * 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 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>(); Map<String, String> paxHeaders = new HashMap<String, String>();
final String entryName = entry.getName(); 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) { if (bigNumberMode == BIGNUMBER_POSIX) {
addPaxHeadersForBigNumbers(paxHeaders, entry); addPaxHeadersForBigNumbers(paxHeaders, entry);
@@ -310,10 +292,10 @@ public class TarOutputStream extends FilterOutputStream {
paxHeaders.put("path", entryName); paxHeaders.put("path", entryName);
} }


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


if (paxHeaders.size() > 0) { if (paxHeaders.size() > 0) {
@@ -596,4 +578,54 @@ public class TarOutputStream extends FilterOutputStream {
+ maxValue + " )"); + 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