diff --git a/build.xml b/build.xml index aa06b0f5b..89ac6c475 100644 --- a/build.xml +++ b/build.xml @@ -384,14 +384,14 @@ basedir="${dist.name}/.." includes="${dist.name}/**" excludes="${dist.name}/lib/optional.jar"/> - + @@ -402,13 +402,13 @@ - + diff --git a/src/main/org/apache/tools/ant/taskdefs/Tar.java b/src/main/org/apache/tools/ant/taskdefs/Tar.java index ae80c097f..06adde55b 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Tar.java +++ b/src/main/org/apache/tools/ant/taskdefs/Tar.java @@ -68,9 +68,14 @@ import org.apache.tools.tar.*; public class Tar extends MatchingTask { + static public final String TRUNCATE = "truncate"; + static public final String GNU = "gnu"; + File tarFile; File baseDir; + String longFileMode = null; + /** * This is the name/location of where to create the tar file. */ @@ -84,6 +89,17 @@ public class Tar extends MatchingTask { public void setBasedir(File baseDir) { this.baseDir = baseDir; } + + /** + * Set how to handle long files. + * + * Allowable values are + * truncate + * gnu + */ + public void setLongfile(String method) { + this.longFileMode = method; + } public void execute() throws BuildException { if (tarFile == null) { @@ -115,6 +131,15 @@ public class Tar extends MatchingTask { try { tOut = new TarOutputStream(new FileOutputStream(tarFile)); tOut.setDebug(true); + if (longFileMode == null) { + tOut.setLongFileMode(TarOutputStream.LONGFILE_ERROR); + } + else if (longFileMode.equalsIgnoreCase(TRUNCATE)) { + tOut.setLongFileMode(TarOutputStream.LONGFILE_TRUNCATE); + } + else if (longFileMode.equalsIgnoreCase(GNU)) { + tOut.setLongFileMode(TarOutputStream.LONGFILE_GNU); + } for (int i = 0; i < files.length; i++) { File f = new File(baseDir,files[i]); diff --git a/src/main/org/apache/tools/tar/TarConstants.java b/src/main/org/apache/tools/tar/TarConstants.java index 37372590c..fe4a69959 100644 --- a/src/main/org/apache/tools/tar/TarConstants.java +++ b/src/main/org/apache/tools/tar/TarConstants.java @@ -179,4 +179,13 @@ public interface TarConstants { */ public static final String GNU_TMAGIC = "ustar "; + /** + * The namr of the GNU tar entry which contains a long name. + */ + public static final String GNU_LONGLINK = "././@LongLink"; + + /** + * Identifies the *next* file on the tape as having a long name. + */ + public static final byte LF_GNUTYPE_LONGNAME = (byte) 'L'; } diff --git a/src/main/org/apache/tools/tar/TarEntry.java b/src/main/org/apache/tools/tar/TarEntry.java index ef670417c..bc8cdc878 100644 --- a/src/main/org/apache/tools/tar/TarEntry.java +++ b/src/main/org/apache/tools/tar/TarEntry.java @@ -178,11 +178,14 @@ public class TarEntry implements TarConstants { this.devMajor = 0; this.devMinor = 0; - if (this.name.length() > NAMELEN) { - throw new RuntimeException("file name '" + this.name - + "' is too long ( > " - + NAMELEN + " bytes)"); - } + } + + /** + * Construct an entry with a name an a link flag. + */ + public TarEntry(String name, byte linkFlag) { + this(name); + this.linkFlag = linkFlag; } /** @@ -244,14 +247,6 @@ public class TarEntry implements TarConstants { this.linkFlag = LF_NORMAL; } - if (this.name.length() > NAMELEN) { - throw new RuntimeException("file name '" + this.name - + "' is too long ( > " - + NAMELEN + " bytes)"); - - // UNDONE When File lets us get the userName, use it! - } - this.size = file.length(); this.modTime = file.lastModified() / 1000; this.checkSum = 0; diff --git a/src/main/org/apache/tools/tar/TarOutputStream.java b/src/main/org/apache/tools/tar/TarOutputStream.java index 8d6f31d30..0d554fb00 100644 --- a/src/main/org/apache/tools/tar/TarOutputStream.java +++ b/src/main/org/apache/tools/tar/TarOutputStream.java @@ -69,6 +69,10 @@ import java.io.*; * @author Timothy Gerard Endres time@ice.com */ public class TarOutputStream extends FilterOutputStream { + static public final int LONGFILE_ERROR = 0; + static public final int LONGFILE_TRUNCATE = 1; + static public final int LONGFILE_GNU = 2; + protected boolean debug; protected int currSize; protected int currBytes; @@ -77,6 +81,7 @@ public class TarOutputStream extends FilterOutputStream { protected int assemLen; protected byte[] assemBuf; protected TarBuffer buffer; + protected int longFileMode = LONGFILE_ERROR; public TarOutputStream(OutputStream os) { this(os, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE); @@ -97,6 +102,11 @@ public class TarOutputStream extends FilterOutputStream { this.oneBuf = new byte[1]; } + public void setLongFileMode(int longFileMode) { + this.longFileMode = longFileMode; + } + + /** * Sets the debugging flag. * @@ -154,6 +164,27 @@ public class TarOutputStream extends FilterOutputStream { * @param entry The TarEntry to be written to the archive. */ public void putNextEntry(TarEntry entry) throws IOException { + if (entry.getName().length() > TarConstants.NAMELEN) { + + 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(entry.getName().length() + 1); + putNextEntry(longLinkEntry); + write(entry.getName().getBytes()); + write(0); + closeEntry(); + } + else if (longFileMode != LONGFILE_TRUNCATE) { + throw new RuntimeException("file name '" + entry.getName() + + "' is too long ( > " + + TarConstants.NAMELEN + " bytes)"); + } + } + entry.writeEntryHeader(this.recordBuf); this.buffer.writeRecord(this.recordBuf); @@ -210,7 +241,7 @@ public class TarOutputStream extends FilterOutputStream { /** * Writes bytes to the current tar archive entry. * - * This method simply calls read( byte[], int, int ). + * This method simply calls write( byte[], int, int ). * * @param wBuf The buffer to write to the archive. * @return The number of bytes read, or -1 at EOF. @@ -228,8 +259,6 @@ public class TarOutputStream extends FilterOutputStream { * that are not a multiple of recordsize in length, including * assembling records from small buffers. * - * This method simply calls read( byte[], int, int ). - * * @param wBuf The buffer to write to the archive. * @param wOffset The offset in the buffer from which to get bytes. * @param numToWrite The number of bytes to write.