blob: 26d8fe05d4d3e8daecc1cc2d76d66c92a1160cd5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.commons.compress.archivers.tar;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import org.apache.commons.compress.AbstractTestCase;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.utils.CharsetNames;
public class TarArchiveOutputStreamTest extends AbstractTestCase {
public void testCount() throws Exception {
File f = File.createTempFile("commons-compress-tarcount", ".tar");
f.deleteOnExit();
FileOutputStream fos = new FileOutputStream(f);
ArchiveOutputStream tarOut = new ArchiveStreamFactory()
.createArchiveOutputStream(ArchiveStreamFactory.TAR, fos);
File file1 = getFile("test1.xml");
TarArchiveEntry sEntry = new TarArchiveEntry(file1);
tarOut.putArchiveEntry(sEntry);
FileInputStream in = new FileInputStream(file1);
byte[] buf = new byte[8192];
int read = 0;
while ((read = in.read(buf)) > 0) {
tarOut.write(buf, 0, read);
}
in.close();
tarOut.closeArchiveEntry();
tarOut.close();
assertEquals(f.length(), tarOut.getBytesWritten());
}
public void testMaxFileSizeError() throws Exception {
TarArchiveEntry t = new TarArchiveEntry("foo");
t.setSize(077777777777L);
TarArchiveOutputStream tos =
new TarArchiveOutputStream(new ByteArrayOutputStream());
tos.putArchiveEntry(t);
t.setSize(0100000000000L);
tos = new TarArchiveOutputStream(new ByteArrayOutputStream());
try {
tos.putArchiveEntry(t);
fail("Should have generated RuntimeException");
} catch (RuntimeException expected) {
}
}
public void testBigNumberStarMode() throws Exception {
TarArchiveEntry t = new TarArchiveEntry("foo");
t.setSize(0100000000000L);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR);
tos.putArchiveEntry(t);
// make sure header is written to byte array
tos.write(new byte[10 * 1024]);
byte[] data = bos.toByteArray();
assertEquals(0x80,
((int) data[TarConstants.NAMELEN
+ TarConstants.MODELEN
+ TarConstants.UIDLEN
+ TarConstants.GIDLEN]
) & 0x80);
TarArchiveInputStream tin =
new TarArchiveInputStream(new ByteArrayInputStream(data));
TarArchiveEntry e = tin.getNextTarEntry();
assertEquals(0100000000000L, e.getSize());
}
public void testBigNumberPosixMode() throws Exception {
TarArchiveEntry t = new TarArchiveEntry("foo");
t.setSize(0100000000000L);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
tos.putArchiveEntry(t);
// make sure header is written to byte array
tos.write(new byte[10 * 1024]);
byte[] data = bos.toByteArray();
assertEquals("00000000000 ",
new String(data,
1024 + TarConstants.NAMELEN
+ TarConstants.MODELEN
+ TarConstants.UIDLEN
+ TarConstants.GIDLEN, 12,
CharsetNames.UTF_8));
TarArchiveInputStream tin =
new TarArchiveInputStream(new ByteArrayInputStream(data));
TarArchiveEntry e = tin.getNextTarEntry();
assertEquals(0100000000000L, e.getSize());
}
public void testWriteSimplePaxHeaders() throws Exception {
Map<String, String> m = new HashMap<String, String>();
m.put("a", "b");
byte[] data = writePaxHeader(m);
assertEquals("00000000006 ",
new String(data, TarConstants.NAMELEN
+ TarConstants.MODELEN
+ TarConstants.UIDLEN
+ TarConstants.GIDLEN, 12,
CharsetNames.UTF_8));
assertEquals("6 a=b\n", new String(data, 512, 6, CharsetNames.UTF_8));
}
public void testPaxHeadersWithLength99() throws Exception {
Map<String, String> m = new HashMap<String, String>();
m.put("a",
"0123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "012");
byte[] data = writePaxHeader(m);
assertEquals("00000000143 ",
new String(data, TarConstants.NAMELEN
+ TarConstants.MODELEN
+ TarConstants.UIDLEN
+ TarConstants.GIDLEN, 12,
CharsetNames.UTF_8));
assertEquals("99 a=0123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "012\n", new String(data, 512, 99, CharsetNames.UTF_8));
}
public void testPaxHeadersWithLength101() throws Exception {
Map<String, String> m = new HashMap<String, String>();
m.put("a",
"0123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "0123");
byte[] data = writePaxHeader(m);
assertEquals("00000000145 ",
new String(data, TarConstants.NAMELEN
+ TarConstants.MODELEN
+ TarConstants.UIDLEN
+ TarConstants.GIDLEN, 12,
CharsetNames.UTF_8));
assertEquals("101 a=0123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "0123\n", new String(data, 512, 101, CharsetNames.UTF_8));
}
private byte[] writePaxHeader(Map<String, String> m) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
tos.writePaxHeaders("foo", m);
// add a dummy entry so data gets written
TarArchiveEntry t = new TarArchiveEntry("foo");
t.setSize(10 * 1024);
tos.putArchiveEntry(t);
tos.write(new byte[10 * 1024]);
tos.closeArchiveEntry();
return bos.toByteArray();
}
public void testWriteLongFileNamePosixMode() throws Exception {
String n = "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789"
+ "01234567890123456789012345678901234567890123456789";
TarArchiveEntry t =
new TarArchiveEntry(n);
t.setSize(10 * 1024);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
tos.putArchiveEntry(t);
tos.write(new byte[10 * 1024]);
tos.closeArchiveEntry();
byte[] data = bos.toByteArray();
assertEquals("160 path=" + n + "\n",
new String(data, 512, 160, CharsetNames.UTF_8));
TarArchiveInputStream tin =
new TarArchiveInputStream(new ByteArrayInputStream(data));
TarArchiveEntry e = tin.getNextTarEntry();
assertEquals(n, e.getName());
}
public void testOldEntryStarMode() throws Exception {
TarArchiveEntry t = new TarArchiveEntry("foo");
t.setSize(Integer.MAX_VALUE);
t.setModTime(-1000);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR);
tos.putArchiveEntry(t);
// make sure header is written to byte array
tos.write(new byte[10 * 1024]);
byte[] data = bos.toByteArray();
assertEquals((byte) 0xff,
data[TarConstants.NAMELEN
+ TarConstants.MODELEN
+ TarConstants.UIDLEN
+ TarConstants.GIDLEN
+ TarConstants.SIZELEN]);
TarArchiveInputStream tin =
new TarArchiveInputStream(new ByteArrayInputStream(data));
TarArchiveEntry e = tin.getNextTarEntry();
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.set(1969, 11, 31, 23, 59, 59);
cal.set(Calendar.MILLISECOND, 0);
assertEquals(cal.getTime(), e.getLastModifiedDate());
}
public void testOldEntryPosixMode() throws Exception {
TarArchiveEntry t = new TarArchiveEntry("foo");
t.setSize(Integer.MAX_VALUE);
t.setModTime(-1000);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
tos.putArchiveEntry(t);
// make sure header is written to byte array
tos.write(new byte[10 * 1024]);
byte[] data = bos.toByteArray();
assertEquals("00000000000 ",
new String(data,
1024 + TarConstants.NAMELEN
+ TarConstants.MODELEN
+ TarConstants.UIDLEN
+ TarConstants.GIDLEN
+ TarConstants.SIZELEN, 12,
CharsetNames.UTF_8));
TarArchiveInputStream tin =
new TarArchiveInputStream(new ByteArrayInputStream(data));
TarArchiveEntry e = tin.getNextTarEntry();
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.set(1969, 11, 31, 23, 59, 59);
cal.set(Calendar.MILLISECOND, 0);
assertEquals(cal.getTime(), e.getLastModifiedDate());
}
public void testOldEntryError() throws Exception {
TarArchiveEntry t = new TarArchiveEntry("foo");
t.setSize(Integer.MAX_VALUE);
t.setModTime(-1000);
TarArchiveOutputStream tos =
new TarArchiveOutputStream(new ByteArrayOutputStream());
try {
tos.putArchiveEntry(t);
fail("Should have generated RuntimeException");
} catch (RuntimeException expected) {
}
}
public void testWriteNonAsciiPathNamePaxHeader() throws Exception {
String n = "\u00e4";
TarArchiveEntry t = new TarArchiveEntry(n);
t.setSize(10 * 1024);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
tos.setAddPaxHeadersForNonAsciiNames(true);
tos.putArchiveEntry(t);
tos.write(new byte[10 * 1024]);
tos.closeArchiveEntry();
tos.close();
byte[] data = bos.toByteArray();
assertEquals("11 path=" + n + "\n",
new String(data, 512, 11, CharsetNames.UTF_8));
TarArchiveInputStream tin =
new TarArchiveInputStream(new ByteArrayInputStream(data));
TarArchiveEntry e = tin.getNextTarEntry();
assertEquals(n, e.getName());
}
public void testWriteNonAsciiLinkPathNamePaxHeader() throws Exception {
String n = "\u00e4";
TarArchiveEntry t = new TarArchiveEntry("a", TarConstants.LF_LINK);
t.setSize(10 * 1024);
t.setLinkName(n);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
tos.setAddPaxHeadersForNonAsciiNames(true);
tos.putArchiveEntry(t);
tos.write(new byte[10 * 1024]);
tos.closeArchiveEntry();
tos.close();
byte[] data = bos.toByteArray();
assertEquals("15 linkpath=" + n + "\n",
new String(data, 512, 15, CharsetNames.UTF_8));
TarArchiveInputStream tin =
new TarArchiveInputStream(new ByteArrayInputStream(data));
TarArchiveEntry e = tin.getNextTarEntry();
assertEquals(n, e.getLinkName());
}
}