Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added Adler32 checksum.

Also, made previous() behave better in error cases (no partial object state update).
  • Loading branch information...
commit 9543ccf3021e7b23196c9b3ffab7a02ff334432c 1 parent 809c0e8
Erik Søe Sørensen eriksoe authored
10 src/main/java/com/trifork/deltazip/DZUtil.java
View
@@ -14,6 +14,7 @@
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterOutputStream;
+import java.util.zip.Adler32;
import java.io.OutputStream;
@@ -101,6 +102,15 @@ public static void writeBufferTo(ByteBuffer data, OutputStream out) throws IOExc
while (data.hasRemaining()) channel.write(data);
}
+ public static int computeAdler32(ByteBuffer data) {
+ return computeAdler32(DeltaZip.allToByteArray(data)); // Oh, the copying.
+ }
+ public static int computeAdler32(byte[] data) {
+ Adler32 acc = new Adler32();
+ acc.update(data);
+ return (int)acc.getValue();
+ }
+
//==================== Deflate / Inflate ====================
public static class Dictionary {
43 src/main/java/com/trifork/deltazip/DeltaZip.java
View
@@ -55,6 +55,7 @@ private static void insertCM(CompressionMethod[] table, CompressionMethod cm) {
private long current_pos, current_size;
private int current_method;
private byte[] current_version;
+ private int current_checksum;
private ByteBuffer exposed_current_version;
//==================== API ==========================================
@@ -152,31 +153,45 @@ protected void set_initial_position() throws IOException {
current_pos = access.getSize();
}
+ private static final int ENVELOPE_HEADER = 4 + 4; // Start-tag + checksum
+ private static final int ENVELOPE_TRAILER = 4; // End.tag
+ private static final int ENVELOPE_OVERHEAD = ENVELOPE_HEADER + ENVELOPE_TRAILER;
protected void goto_previous_position_and_compute_current_version() throws IOException {
- ByteBuffer tag_buf = access.pread(current_pos-4, 4);
+ ByteBuffer tag_buf = access.pread(current_pos-ENVELOPE_TRAILER, ENVELOPE_TRAILER);
int tag = tag_buf.getInt(0);
int size = tag &~ (-1 << 28);
int method = (tag >> 28) & 15;
// System.err.println("DB| tag="+tag+" -> "+method+":"+size);
- // Get start-tag plus data:
- long start_pos = current_pos-size-8;
- ByteBuffer data_buf = access.pread(start_pos, size+4);
+ // Read envelope header:
+ long start_pos = current_pos - size - ENVELOPE_OVERHEAD;
+ ByteBuffer data_buf = access.pread(start_pos, size + ENVELOPE_HEADER);
data_buf.rewind();
int start_tag = data_buf.getInt();
if (start_tag != tag) throw new IOException("Data error - tag mismatch @ "+start_pos+";"+current_pos);
-
- current_pos = start_pos;
- compute_current_version(method, data_buf);
+ int adler32 = data_buf.getInt();
+
+ // Unpack:
+ byte[] version = compute_current_version(method, data_buf, start_pos);
+
+ // Verify checksum:
+ int actual_adler32 = DZUtil.computeAdler32(version);
+ if (actual_adler32 != adler32)
+ throw new IOException("Data error - checksum mismatch @ "+start_pos+": stored is "+adler32+" but computed is "+actual_adler32);
+
+ // Commit:
+ this.current_pos = start_pos;
+ this.current_method = method;
+ this.current_version = version;
+ this.exposed_current_version = ByteBuffer.wrap(current_version).asReadOnlyBuffer();
+ this.current_checksum = actual_adler32;
}
- protected void compute_current_version(int method, ByteBuffer data_buf) throws IOException {
+ protected byte[] compute_current_version(int method, ByteBuffer data_buf, long pos) throws IOException {
CompressionMethod cm = COMPRESSION_METHODS[method];
- if (cm==null) throw new IOException("Invalid compression method: "+method+" @ "+current_pos);
+ if (cm==null) throw new IOException("Invalid compression method: "+method+" @ "+pos);
- current_method = method;
- current_version = cm.uncompress(data_buf, current_version, inflater);
- exposed_current_version = ByteBuffer.wrap(current_version).asReadOnlyBuffer();
+ return cm.uncompress(data_buf, current_version, inflater);
}
//====================
@@ -192,7 +207,11 @@ protected void pack_delta(ByteBuffer version, byte[] ref_version, ExtByteArrayOu
//====================
protected void pack_entry(ByteBuffer version, byte[] ref_version, CompressionMethod cm, ExtByteArrayOutputStream dst) {
+ int adler32 = DZUtil.computeAdler32(version);
+
int tag_blank = dst.insertBlank(4);
+ dst.writeBigEndianInteger(adler32, 4);
+
int size_before = dst.size();
try {
cm.compress(version.duplicate(), ref_version, dst);
20 src/test/java/com/trifork/deltazip/DeltaZipTest.java
View
@@ -25,20 +25,22 @@ public void test_read_known() throws Exception {
/** Chunked-deflate, no prefix/suffix. */
byte[] two_revs1 = {
(byte)0xCE, (byte)0xB4, 0x7A, 0x10,
- 64,0,0,7,0,0,4,(byte)243,
- 0,113,0,64,0,0,7,0,
- 0,0,13,72,101,108,108,111,
- 44,32,87,111,114,108,100,33,
+ 64,0,0,7, 0x05,(byte)0x8C,0x01,(byte)0xF5,
+ 0,0,4,(byte)243, 0,113,0,
+ 64,0,0,7,
+ 0,0,0,13, 0x1F,(byte)0x9E,0x04,0x6A,
+ 72,101,108,108,111, 44,32,87,111,114,108,100,33,
0,0,0,13};
/** Chunked-deflate, using prefix. */
byte[] two_revs2 = {
(byte)0xCE, (byte)0xB4, 0x7A, 0x10,
- 64,0,0,5,8,0,2,0,
- 4,64,0,0,5,0,0,0,
- 13,72,101,108,108,111,44,32,
- 87,111,114,108,100,33,0,0,
- 0,13};
+ 64,0,0,5, 0x05,(byte)0x8C,0x01,(byte)0xF5,
+ 8,0,2,0, 4,
+ 64,0,0,5,
+ 0,0,0,13, 0x1F,(byte)0x9E,0x04,0x6A,
+ 72,101,108,108,111,44,32,87,111,114,108,100,33,
+ 0,0,0,13};
ByteBuffer exp_rev1 = ByteBuffer.wrap("Hello, World!".getBytes("ISO-8859-1"));
ByteBuffer exp_rev2 = ByteBuffer.wrap("Hello".getBytes("ISO-8859-1"));
Please sign in to comment.
Something went wrong with that request. Please try again.