make block size configurable, auto-generate unique values for inode and dev, provide a reasonable default for mode. COMPRESS-85
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/compress/trunk@911353 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java
index fbf1566..362c6f8 100644
--- a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java
+++ b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntry.java
@@ -425,7 +425,7 @@
* @return Returns the mode.
*/
public long getMode() {
- return this.mode;
+ return mode == 0 && !CPIO_TRAILER.equals(name) ? C_ISREG : mode;
}
/**
@@ -443,7 +443,9 @@
* @return Returns the number of links.
*/
public long getNumberOfLinks() {
- return this.nlink;
+ return nlink == 0 ?
+ (isDirectory() ? 2 : 1)
+ : nlink;
}
/**
diff --git a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
index be7964c..d1ef463 100644
--- a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveOutputStream.java
@@ -82,8 +82,13 @@
private final OutputStream out;
+ private final int blockSize;
+
+ private long nextArtificalDeviceAndInode = 1;
+
/**
- * Construct the cpio output stream with a specified format
+ * Construct the cpio output stream with a specified format and a
+ * blocksize of {@link CpioConstants.BLOCK_SIZE BLOCK_SIZE}.
*
* @param out
* The cpio stream
@@ -91,6 +96,21 @@
* The format of the stream
*/
public CpioArchiveOutputStream(final OutputStream out, final short format) {
+ this(out, format, BLOCK_SIZE);
+ }
+
+ /**
+ * Construct the cpio output stream with a specified format
+ *
+ * @param out
+ * The cpio stream
+ * @param format
+ * The format of the stream
+ * @param blockSize
+ * The block size of the archive.
+ */
+ public CpioArchiveOutputStream(final OutputStream out, final short format,
+ final int blockSize) {
this.out = new CountingStream(out);
switch (format) {
case FORMAT_NEW:
@@ -100,9 +120,10 @@
break;
default:
throw new IllegalArgumentException("Unknown format: "+format);
-
+
}
this.entryFormat = format;
+ this.blockSize = blockSize;
}
/**
@@ -146,7 +167,7 @@
if(finished) {
throw new IOException("Stream has already been finished");
}
-
+
CpioArchiveEntry e = (CpioArchiveEntry) entry;
ensureOpen();
if (this.entry != null) {
@@ -193,7 +214,22 @@
}
private void writeNewEntry(final CpioArchiveEntry entry) throws IOException {
- writeAsciiLong(entry.getInode(), 8, 16);
+ long inode = entry.getInode();
+ long devMin = entry.getDeviceMin();
+ if (CPIO_TRAILER.equals(entry.getName())) {
+ inode = devMin = 0;
+ } else {
+ if (inode == 0 && devMin == 0) {
+ inode = nextArtificalDeviceAndInode & 0xFFFFFFFF;
+ devMin = (nextArtificalDeviceAndInode++ >> 32) & 0xFFFFFFFF;
+ } else {
+ nextArtificalDeviceAndInode =
+ Math.max(nextArtificalDeviceAndInode,
+ inode + 0x100000000L * devMin) + 1;
+ }
+ }
+
+ writeAsciiLong(inode, 8, 16);
writeAsciiLong(entry.getMode(), 8, 16);
writeAsciiLong(entry.getUID(), 8, 16);
writeAsciiLong(entry.getGID(), 8, 16);
@@ -201,7 +237,7 @@
writeAsciiLong(entry.getTime(), 8, 16);
writeAsciiLong(entry.getSize(), 8, 16);
writeAsciiLong(entry.getDeviceMaj(), 8, 16);
- writeAsciiLong(entry.getDeviceMin(), 8, 16);
+ writeAsciiLong(devMin, 8, 16);
writeAsciiLong(entry.getRemoteDeviceMaj(), 8, 16);
writeAsciiLong(entry.getRemoteDeviceMin(), 8, 16);
writeAsciiLong(entry.getName().length() + 1, 8, 16);
@@ -212,8 +248,23 @@
private void writeOldAsciiEntry(final CpioArchiveEntry entry)
throws IOException {
- writeAsciiLong(entry.getDevice(), 6, 8);
- writeAsciiLong(entry.getInode(), 6, 8);
+ long inode = entry.getInode();
+ long device = entry.getDevice();
+ if (CPIO_TRAILER.equals(entry.getName())) {
+ inode = device = 0;
+ } else {
+ if (inode == 0 && device == 0) {
+ inode = nextArtificalDeviceAndInode & 0777777;
+ device = (nextArtificalDeviceAndInode++ >> 18) & 0777777;
+ } else {
+ nextArtificalDeviceAndInode =
+ Math.max(nextArtificalDeviceAndInode,
+ inode + 01000000 * device) + 1;
+ }
+ }
+
+ writeAsciiLong(device, 6, 8);
+ writeAsciiLong(inode, 6, 8);
writeAsciiLong(entry.getMode(), 6, 8);
writeAsciiLong(entry.getUID(), 6, 8);
writeAsciiLong(entry.getGID(), 6, 8);
@@ -227,8 +278,23 @@
private void writeOldBinaryEntry(final CpioArchiveEntry entry,
final boolean swapHalfWord) throws IOException {
- writeBinaryLong(entry.getDevice(), 2, swapHalfWord);
- writeBinaryLong(entry.getInode(), 2, swapHalfWord);
+ long inode = entry.getInode();
+ long device = entry.getDevice();
+ if (CPIO_TRAILER.equals(entry.getName())) {
+ inode = device = 0;
+ } else {
+ if (inode == 0 && device == 0) {
+ inode = nextArtificalDeviceAndInode & 0xFFFF;
+ device = (nextArtificalDeviceAndInode++ >> 16) & 0xFFFF;
+ } else {
+ nextArtificalDeviceAndInode =
+ Math.max(nextArtificalDeviceAndInode,
+ inode + 0x10000 * device) + 1;
+ }
+ }
+
+ writeBinaryLong(device, 2, swapHalfWord);
+ writeBinaryLong(inode, 2, swapHalfWord);
writeBinaryLong(entry.getMode(), 2, swapHalfWord);
writeBinaryLong(entry.getUID(), 2, swapHalfWord);
writeBinaryLong(entry.getGID(), 2, swapHalfWord);
@@ -251,7 +317,7 @@
if(finished) {
throw new IOException("Stream has already been finished");
}
-
+
ensureOpen();
if (entry == null) {
@@ -327,7 +393,7 @@
if (finished) {
throw new IOException("This archive has already been finished");
}
-
+
if (this.entry != null) {
throw new IOException("This archive contains unclosed entries.");
}
@@ -338,9 +404,9 @@
closeArchiveEntry();
int lengthOfLastBlock =
- (int) (((CountingStream) out).getTotalWritten() % BLOCK_SIZE);
+ (int) (((CountingStream) out).getTotalWritten() % blockSize);
if (lengthOfLastBlock != 0) {
- pad(BLOCK_SIZE - lengthOfLastBlock);
+ pad(blockSize - lengthOfLastBlock);
}
finished = true;
@@ -357,7 +423,7 @@
if(!finished) {
finish();
}
-
+
if (!this.closed) {
out.close();
this.closed = true;
@@ -434,13 +500,13 @@
write(b, 0, b.length);
}
public void write(int b) throws IOException {
- totalWritten++;
out.write(b);
+ totalWritten++;
}
public void write(byte[] b, int off, int len)
throws IOException {
- totalWritten += len;
out.write(b, off, len);
+ totalWritten += len;
}
private long getTotalWritten() { return totalWritten; }
}