Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsliebig2007-11-06 03:49:04 -0500
committersliebig2007-11-06 03:49:04 -0500
commit1d5257c7ef12f0bf60ae5f7531ffdb355cb13202 (patch)
treedea5ead90c4630476a731f3ee023c843ab45c490 /bundles/ie.wombat.jbdiff
parent11397eb218b6c3964c0c903de1776c2b7e2dd15a (diff)
downloadrt.equinox.p2-1d5257c7ef12f0bf60ae5f7531ffdb355cb13202.tar.gz
rt.equinox.p2-1d5257c7ef12f0bf60ae5f7531ffdb355cb13202.tar.xz
rt.equinox.p2-1d5257c7ef12f0bf60ae5f7531ffdb355cb13202.zip
Extended version of Joe Desbonnet┬┤s (joe@galway.net) JBDiff library which is a is a Java translation of the bsdiff (v4.2) utility by Colin Percival. See http://www.daemonology.net/bsdiff/
Diffstat (limited to 'bundles/ie.wombat.jbdiff')
-rw-r--r--bundles/ie.wombat.jbdiff/.classpath7
-rw-r--r--bundles/ie.wombat.jbdiff/.project28
-rw-r--r--bundles/ie.wombat.jbdiff/.settings/org.eclipse.pde.core.prefs4
-rw-r--r--bundles/ie.wombat.jbdiff/META-INF/MANIFEST.MF12
-rw-r--r--bundles/ie.wombat.jbdiff/build.properties4
-rw-r--r--bundles/ie.wombat.jbdiff/src/README.txt48
-rw-r--r--bundles/ie.wombat.jbdiff/src/bsd-license.txt22
-rw-r--r--bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/Activator.java34
-rw-r--r--bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/JBDiff.java604
-rw-r--r--bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/JBPatch.java234
-rw-r--r--bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/Util.java109
-rw-r--r--bundles/ie.wombat.jbdiff/src/readme-more.txt10
12 files changed, 1116 insertions, 0 deletions
diff --git a/bundles/ie.wombat.jbdiff/.classpath b/bundles/ie.wombat.jbdiff/.classpath
new file mode 100644
index 000000000..751c8f2e5
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/ie.wombat.jbdiff/.project b/bundles/ie.wombat.jbdiff/.project
new file mode 100644
index 000000000..76d444192
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ie.wombat.jbdiff</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/bundles/ie.wombat.jbdiff/.settings/org.eclipse.pde.core.prefs b/bundles/ie.wombat.jbdiff/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 000000000..950e19447
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,4 @@
+#Thu Nov 01 14:00:53 CET 2007
+eclipse.preferences.version=1
+pluginProject.extensions=false
+resolve.requirebundle=false
diff --git a/bundles/ie.wombat.jbdiff/META-INF/MANIFEST.MF b/bundles/ie.wombat.jbdiff/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..53b210470
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Jbdiff Plug-in
+Bundle-SymbolicName: ie.wombat.jbdiff
+Bundle-Version: 0.1.0.1
+Bundle-Activator: ie.wombat.jbdiff.Activator
+Import-Package: org.osgi.framework;version="1.3.0"
+Eclipse-LazyStart: true
+Require-Bundle: org.apache.tools.bzip2
+Export-Package: ie.wombat.jbdiff
+Bundle-RequiredExecutionEnvironment: CDC-1.1/Foundation-1.1,
+ J2SE-1.4
diff --git a/bundles/ie.wombat.jbdiff/build.properties b/bundles/ie.wombat.jbdiff/build.properties
new file mode 100644
index 000000000..34d2e4d2d
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/bundles/ie.wombat.jbdiff/src/README.txt b/bundles/ie.wombat.jbdiff/src/README.txt
new file mode 100644
index 000000000..30ce0658e
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/README.txt
@@ -0,0 +1,48 @@
+README file for JBDiff (Java Binary Diff)
+Version: 0.1
+Release date: 8 Mar 2005.
+
+JBDiff (Java Binary Diff) utility is a Java translation of the bsdiff (v4.2) utility
+by Colin Percival. See http://www.daemonology.net/bsdiff/
+
+The file format is similar to, but currently not compatible with the bsdiff utility.
+This is because bsdiff uses bzip2 for compression which is not available in the
+standard Java libraries. Instead I use gzip (java.util.zip.*)
+
+The diff utility is very memory hungry. Attempting to diff very large files with
+insufficient RAM may cause your computer to 'trash' (ie become unusably slow and may
+require a reset to recover). Comparing two 20MB files will take approx 80 seconds
+on a 2GHz Pentium 4 and will require a maximum heap size of at least 220 MBytes. The
+maximum heap size can be specified using the -Xmx switch to the Java VM (see examples
+below). The patch utility has more modest resource requirements.
+
+EXAMPLES:
+
+To compare old.bin with new.bin and produce diff file new-old.diff:
+
+java -Xmx200m -classpath jbdiff.jar ie.wombat.jbdiff.JBDiff old.bin new.bin new-old.diff
+
+To patch old.bin with new-old.diff to produce new.bin:
+
+java -Xmx200m -classpath jbdiff.jar ie.wombat.jbdiff.JBPatch old.bin new.bin new-old.diff
+
+TODO:
+
+This first release is a rather blind port of the bsdiff utility. A vast bulk of
+the code ported to Java without any modification. There is scope
+for optimization (the C bsdiff runs in approx 50% faster than JBDiff).
+
+Also it would be nice to be able to produce output that is compatible with bsdiff.
+I need a bzip2 library for that.
+
+Any suggestions, feedback and bugs will be much appreciated. Please email
+to joe@galway.net
+
+LICENSE:
+
+This software is distributed under the GPL v2 license (see LICENSE.txt file in
+the distribution). If this license does not suit your needs, please contact me.
+
+Joe Desbonnet
+joe@galway.net
+8 Mar 2005
diff --git a/bundles/ie.wombat.jbdiff/src/bsd-license.txt b/bundles/ie.wombat.jbdiff/src/bsd-license.txt
new file mode 100644
index 000000000..f94a2fd82
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/bsd-license.txt
@@ -0,0 +1,22 @@
+
+Copyright (c) <YEAR>, <OWNER>
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/Activator.java b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/Activator.java
new file mode 100644
index 000000000..73b553185
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/Activator.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * compeople AG (Stefan Liebig) - initial API and implementation
+ *******************************************************************************/
+package ie.wombat.jbdiff;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ }
+
+}
diff --git a/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/JBDiff.java b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/JBDiff.java
new file mode 100644
index 000000000..cee25fe65
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/JBDiff.java
@@ -0,0 +1,604 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package ie.wombat.jbdiff;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.tools.bzip2.CBZip2OutputStream;
+
+/**
+ * Java Binary Diff utility. Based on bsdiff (v4.2) by Colin Percival (see
+ * http://www.daemonology.net/bsdiff/ ) and distributed under BSD license.
+ *
+ * <p>
+ * Running this on large files will probably require an increase of the default
+ * maximum heap size (use java -Xmx200m)
+ * </p>
+ *
+ * @author Joe Desbonnet, joe@galway.net
+ *
+ */
+public class JBDiff {
+
+ // JBDiff extensions by Stefan.Liebig@compeople.de:
+ //
+ // - uses an extended version of the org.apache.tools.bzip2 compressor to
+ // compress all of the blocks (ctrl,diff,extra).
+ // - added interfaces that allows using of JBDiff with streams and byte
+ // arrays.
+
+ private static final String VERSION = "jbdiff-0.1.0";
+
+ // This is ┤jbdiff40┤.
+ private static final byte[] MAGIC_BYTES = new byte[] { 0x6a, 0x62, 0x64,
+ 0x69, 0x66, 0x66, 0x34, 0x30 };
+
+ private final static void split(int[] I, int[] V, int start, int len, int h) {
+
+ int i, j, k, x, tmp, jj, kk;
+
+ if (len < 16) {
+ for (k = start; k < start + len; k += j) {
+ j = 1;
+ x = V[I[k] + h];
+ for (i = 1; k + i < start + len; i++) {
+ if (V[I[k + i] + h] < x) {
+ x = V[I[k + i] + h];
+ j = 0;
+ }
+
+ if (V[I[k + i] + h] == x) {
+ tmp = I[k + j];
+ I[k + j] = I[k + i];
+ I[k + i] = tmp;
+ j++;
+ }
+
+ }
+
+ for (i = 0; i < j; i++) {
+ V[I[k + i]] = k + j - 1;
+ }
+ if (j == 1) {
+ I[k] = -1;
+ }
+ }
+
+ return;
+ }
+
+ x = V[I[start + len / 2] + h];
+ jj = 0;
+ kk = 0;
+ for (i = start; i < start + len; i++) {
+ if (V[I[i] + h] < x) {
+ jj++;
+ }
+ if (V[I[i] + h] == x) {
+ kk++;
+ }
+ }
+
+ jj += start;
+ kk += jj;
+
+ i = start;
+ j = 0;
+ k = 0;
+ while (i < jj) {
+ if (V[I[i] + h] < x) {
+ i++;
+ } else if (V[I[i] + h] == x) {
+ tmp = I[i];
+ I[i] = I[jj + j];
+ I[jj + j] = tmp;
+ j++;
+ } else {
+ tmp = I[i];
+ I[i] = I[kk + k];
+ I[kk + k] = tmp;
+ k++;
+ }
+
+ }
+
+ while (jj + j < kk) {
+ if (V[I[jj + j] + h] == x) {
+ j++;
+ } else {
+ tmp = I[jj + j];
+ I[jj + j] = I[kk + k];
+ I[kk + k] = tmp;
+ k++;
+ }
+
+ }
+
+ if (jj > start) {
+ split(I, V, start, jj - start, h);
+ }
+
+ for (i = 0; i < kk - jj; i++) {
+ V[I[jj + i]] = kk - 1;
+ }
+
+ if (jj == kk - 1) {
+ I[jj] = -1;
+ }
+
+ if (start + len > kk) {
+ split(I, V, kk, start + len - kk, h);
+ }
+
+ }
+
+ /**
+ * Fast suffix sporting. Larsson and Sadakane's qsufsort algorithm. See
+ * http://www.cs.lth.se/Research/Algorithms/Papers/jesper5.ps
+ *
+ * @param I
+ * @param V
+ * @param oldBuf
+ * @param oldsize
+ */
+ private static void qsufsort(int[] I, int[] V, byte[] oldBuf, int oldsize) {
+
+ // int oldsize = oldBuf.length;
+ int[] buckets = new int[256];
+
+ // No need to do that in Java.
+ // for ( int i = 0; i < 256; i++ ) {
+ // buckets[i] = 0;
+ // }
+
+ for (int i = 0; i < oldsize; i++) {
+ buckets[oldBuf[i] & 0xff]++;
+ }
+
+ for (int i = 1; i < 256; i++) {
+ buckets[i] += buckets[i - 1];
+ }
+
+ for (int i = 255; i > 0; i--) {
+ buckets[i] = buckets[i - 1];
+ }
+
+ buckets[0] = 0;
+
+ for (int i = 0; i < oldsize; i++) {
+ I[++buckets[oldBuf[i] & 0xff]] = i;
+ }
+
+ I[0] = oldsize;
+ for (int i = 0; i < oldsize; i++) {
+ V[i] = buckets[oldBuf[i] & 0xff];
+ }
+ V[oldsize] = 0;
+
+ for (int i = 1; i < 256; i++) {
+ if (buckets[i] == buckets[i - 1] + 1) {
+ I[buckets[i]] = -1;
+ }
+ }
+
+ I[0] = -1;
+
+ for (int h = 1; I[0] != -(oldsize + 1); h += h) {
+ int len = 0;
+ int i;
+ for (i = 0; i < oldsize + 1;) {
+ if (I[i] < 0) {
+ len -= I[i];
+ i -= I[i];
+ } else {
+ // if(len) I[i-len]=-len;
+ if (len != 0) {
+ I[i - len] = -len;
+ }
+ len = V[I[i]] + 1 - i;
+ split(I, V, i, len, h);
+ i += len;
+ len = 0;
+ }
+
+ }
+
+ if (len != 0) {
+ I[i - len] = -len;
+ }
+ }
+
+ for (int i = 0; i < oldsize + 1; i++) {
+ I[V[i]] = i;
+ }
+ }
+
+ /**
+ * Count the number of bytes that match in oldBuf (starting at offset
+ * oldOffset) and newBuf (starting at offset newOffset).
+ *
+ * @param oldBuf
+ * @param oldOffset
+ * @param newBuf
+ * @param newOffset
+ * @return
+ */
+ private final static int matchlen(byte[] oldBuf, int oldSize,
+ int oldOffset, byte[] newBuf, int newSize, int newOffset) {
+ // int end = Math
+ // .min(oldBuf.length - oldOffset, newBuf.length - newOffset);
+ int end = Math.min(oldSize - oldOffset, newSize - newOffset);
+ for (int i = 0; i < end; i++) {
+ if (oldBuf[oldOffset + i] != newBuf[newOffset + i]) {
+ return i;
+ }
+ }
+ return end;
+ }
+
+ private final static int search(int[] I, byte[] oldBuf, int oldSize,
+ byte[] newBuf, int newSize, int newBufOffset, int start, int end,
+ IntByRef pos) {
+
+ if (end - start < 2) {
+ int x = matchlen(oldBuf, oldSize, I[start], newBuf, newSize,
+ newBufOffset);
+ int y = matchlen(oldBuf, oldSize, I[end], newBuf, newSize,
+ newBufOffset);
+
+ if (x > y) {
+ pos.value = I[start];
+ return x;
+ } else {
+ pos.value = I[end];
+ return y;
+ }
+ }
+
+ int x = start + (end - start) / 2;
+ if (Util.memcmp(oldBuf, oldSize, I[x], newBuf, newSize, newBufOffset) < 0) {
+ return search(I, oldBuf, oldSize, newBuf, newSize, newBufOffset, x,
+ end, pos);
+ } else {
+ return search(I, oldBuf, oldSize, newBuf, newSize, newBufOffset,
+ start, x, pos);
+ }
+
+ }
+
+ /**
+ * @param oldFile
+ * @param newFile
+ * @param diffFile
+ * @throws IOException
+ */
+ public static void bsdiff(File oldFile, File newFile, File diffFile)
+ throws IOException {
+ InputStream oldInputStream = new BufferedInputStream(
+ new FileInputStream(oldFile));
+ InputStream newInputStream = new BufferedInputStream(
+ new FileInputStream(newFile));
+ OutputStream diffOutputStream = new FileOutputStream(diffFile);
+
+ byte[] diffBytes = bsdiff(oldInputStream, (int) oldFile.length(),
+ newInputStream, (int) newFile.length());
+
+ diffOutputStream.write(diffBytes);
+ diffOutputStream.close();
+ }
+
+ /**
+ * @param oldInputStream
+ * @param oldsize
+ * @param newInputStream
+ * @param newsize
+ * @return
+ * @throws IOException
+ */
+ public static byte[] bsdiff(InputStream oldInputStream, int oldsize,
+ InputStream newInputStream, int newsize) throws IOException {
+
+ byte[] oldBuf = new byte[oldsize];
+
+ Util.readFromStream(oldInputStream, oldBuf, 0, oldsize);
+ oldInputStream.close();
+
+ byte[] newBuf = new byte[newsize];
+ Util.readFromStream(newInputStream, newBuf, 0, newsize);
+ newInputStream.close();
+
+ return bsdiff(oldBuf, oldsize, newBuf, newsize);
+ }
+
+ /**
+ * @param oldBuf
+ * @param oldsize
+ * @param newBuf
+ * @param newsize
+ * @return
+ * @throws IOException
+ */
+ public static byte[] bsdiff(byte[] oldBuf, int oldsize, byte[] newBuf,
+ int newsize) throws IOException {
+
+ int[] I = new int[oldsize + 1];
+ qsufsort(I, new int[oldsize + 1], oldBuf, oldsize);
+
+ // diff block
+ int dblen = 0;
+ byte[] db = new byte[newsize];
+
+ // extra block
+ int eblen = 0;
+ byte[] eb = new byte[newsize];
+
+ /*
+ * Diff file is composed as follows:
+ *
+ * Header (32 bytes) Data (from offset 32 to end of file)
+ *
+ * Header: Offset 0, length 8 bytes: file magic "jbdiff40" Offset 8,
+ * length 8 bytes: length of compressed ctrl block Offset 16, length 8
+ * bytes: length of compressed diff block Offset 24, length 8 bytes:
+ * length of new file
+ *
+ * Data: 32 (length ctrlBlockLen): ctrlBlock (bzip2) 32+ctrlBlockLen
+ * (length diffBlockLen): diffBlock (bzip2) 32+ctrlBlockLen+diffBlockLen
+ * (to end of file): extraBlock (bzip2)
+ *
+ * ctrlBlock comprises a set of records, each record 12 bytes. A record
+ * comprises 3 x 32 bit integers. The ctrlBlock is not compressed.
+ */
+
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ DataOutputStream diffOut = new DataOutputStream(byteOut);
+
+ /*
+ * Write as much of header as we have now. Size of ctrlBlock and
+ * diffBlock must be filled in later.
+ */
+ diffOut.write(MAGIC_BYTES);
+ diffOut.writeLong(-1); // place holder for ctrlBlockLen
+ diffOut.writeLong(-1); // place holder for diffBlockLen
+ diffOut.writeLong(newsize);
+ diffOut.flush();
+
+ CBZip2OutputStream bzip2Out = new CBZip2OutputStream(diffOut);
+ DataOutputStream dataOut = new DataOutputStream(bzip2Out);
+
+ int oldscore, scsc;
+
+ int overlap, Ss, lens;
+ int i;
+ int scan = 0;
+ int len = 0;
+ int lastscan = 0;
+ int lastpos = 0;
+ int lastoffset = 0;
+
+ IntByRef pos = new IntByRef();
+ // int ctrlBlockLen = 0;
+
+ while (scan < newsize) {
+ oldscore = 0;
+
+ for (scsc = scan += len; scan < newsize; scan++) {
+
+ len = search(I, oldBuf, oldsize, newBuf, newsize, scan, 0,
+ oldsize, pos);
+
+ for (; scsc < scan + len; scsc++) {
+ if ((scsc + lastoffset < oldsize)
+ && (oldBuf[scsc + lastoffset] == newBuf[scsc])) {
+ oldscore++;
+ }
+ }
+
+ if (((len == oldscore) && (len != 0)) || (len > oldscore + 8)) {
+ break;
+ }
+
+ if ((scan + lastoffset < oldsize)
+ && (oldBuf[scan + lastoffset] == newBuf[scan])) {
+ oldscore--;
+ }
+ }
+
+ if ((len != oldscore) || (scan == newsize)) {
+ int s = 0;
+ int Sf = 0;
+ int lenf = 0;
+ for (i = 0; (lastscan + i < scan) && (lastpos + i < oldsize);) {
+ if (oldBuf[lastpos + i] == newBuf[lastscan + i])
+ s++;
+ i++;
+ if (s * 2 - i > Sf * 2 - lenf) {
+ Sf = s;
+ lenf = i;
+ }
+ }
+
+ int lenb = 0;
+ if (scan < newsize) {
+ s = 0;
+ int Sb = 0;
+ for (i = 1; (scan >= lastscan + i) && (pos.value >= i); i++) {
+ if (oldBuf[pos.value - i] == newBuf[scan - i])
+ s++;
+ if (s * 2 - i > Sb * 2 - lenb) {
+ Sb = s;
+ lenb = i;
+ }
+ }
+ }
+
+ if (lastscan + lenf > scan - lenb) {
+ overlap = (lastscan + lenf) - (scan - lenb);
+ s = 0;
+ Ss = 0;
+ lens = 0;
+ for (i = 0; i < overlap; i++) {
+ if (newBuf[lastscan + lenf - overlap + i] == oldBuf[lastpos
+ + lenf - overlap + i]) {
+ s++;
+ }
+ if (newBuf[scan - lenb + i] == oldBuf[pos.value - lenb
+ + i]) {
+ s--;
+ }
+ if (s > Ss) {
+ Ss = s;
+ lens = i + 1;
+ }
+ }
+
+ lenf += lens - overlap;
+ lenb -= lens;
+ }
+
+ // ? byte casting introduced here -- might affect things
+ for (i = 0; i < lenf; i++) {
+ db[dblen + i] = (byte) (newBuf[lastscan + i] - oldBuf[lastpos
+ + i]);
+ }
+
+ for (i = 0; i < (scan - lenb) - (lastscan + lenf); i++) {
+ eb[eblen + i] = newBuf[lastscan + lenf + i];
+ }
+
+ dblen += lenf;
+ eblen += (scan - lenb) - (lastscan + lenf);
+
+ /*
+ * Write control block entry (3 x int)
+ */
+ // diffOut.writeInt( lenf );
+ // diffOut.writeInt( ( scan - lenb ) - ( lastscan + lenf ) );
+ // diffOut.writeInt( ( pos[0] - lenb ) - ( lastpos + lenf ) );
+ // ctrlBlockLen += 12;
+ dataOut.writeInt(lenf);
+ dataOut.writeInt((scan - lenb) - (lastscan + lenf));
+ dataOut.writeInt((pos.value - lenb) - (lastpos + lenf));
+
+ lastscan = scan - lenb;
+ lastpos = pos.value - lenb;
+ lastoffset = pos.value - scan;
+ } // end if
+ } // end while loop
+
+ dataOut.flush();
+ bzip2Out.finish();
+
+ // now compressed ctrlBlockLen
+ int ctrlBlockLen = diffOut.size() - Util.HEADER_SIZE;
+ // System.err.println( "Diff: ctrlBlockLen=" + ctrlBlockLen );
+
+ // GZIPOutputStream gzOut;
+
+ /*
+ * Write diff block
+ */
+ // gzOut = new GZIPOutputStream( diffOut );
+ bzip2Out = new CBZip2OutputStream(diffOut);
+ bzip2Out.write(db, 0, dblen);
+ bzip2Out.finish();
+ bzip2Out.flush();
+ int diffBlockLen = diffOut.size() - ctrlBlockLen - Util.HEADER_SIZE;
+ // System.err.println( "Diff: diffBlockLen=" + diffBlockLen );
+
+ /*
+ * Write extra block
+ */
+ // gzOut = new GZIPOutputStream( diffOut );
+ bzip2Out = new CBZip2OutputStream(diffOut);
+ bzip2Out.write(eb, 0, eblen);
+ bzip2Out.finish();
+ bzip2Out.flush();
+ // long extraBlockLen = diffOut.size() - diffBlockLen - ctrlBlockLen -
+ // HEADER_SIZE;
+ // System.err.println( "Diff: extraBlockLen=" + extraBlockLen );
+
+ diffOut.close();
+
+ /*
+ * Write missing header info.
+ */
+ ByteArrayOutputStream byteHeaderOut = new ByteArrayOutputStream(
+ Util.HEADER_SIZE);
+ DataOutputStream headerOut = new DataOutputStream(byteHeaderOut);
+ headerOut.write(MAGIC_BYTES);
+ headerOut.writeLong(ctrlBlockLen); // place holder for ctrlBlockLen
+ headerOut.writeLong(diffBlockLen); // place holder for diffBlockLen
+ headerOut.writeLong(newsize);
+ headerOut.close();
+
+ // Copy header information into the diff
+ byte[] diffBytes = byteOut.toByteArray();
+ byte[] headerBytes = byteHeaderOut.toByteArray();
+
+ System.arraycopy(headerBytes, 0, diffBytes, 0, headerBytes.length);
+
+ return diffBytes;
+ // /*
+ // * Write missing header info. Need to reopen the file with
+ // RandomAccessFile
+ // * for this.
+ // */
+ // RandomAccessFile diff = new RandomAccessFile( diffFile, "rw" );
+ // diff.seek( 8 );
+ // diff.writeLong( ctrlBlockLen ); // ctrlBlockLen (compressed) @offset
+ // 8
+ // diff.writeLong( diffBlockLen ); // diffBlockLen (compressed) @offset
+ // 16
+ // diff.close();
+ }
+
+ /**
+ * Run JBDiff from the command line. Params: oldfile newfile difffile. diff
+ * file will be created.
+ *
+ * @param arg
+ * @throws IOException
+ */
+ public static void main(String[] arg) throws IOException {
+
+ if (arg.length != 3) {
+ System.err
+ .println("usage example: java -Xmx200m ie.wombat.jbdiff.JBDiff oldfile newfile patchfile\n");
+ return;
+ }
+
+ File oldFile = new File(arg[0]);
+ File newFile = new File(arg[1]);
+ File diffFile = new File(arg[2]);
+
+ bsdiff(oldFile, newFile, diffFile);
+
+ }
+
+ private static class IntByRef {
+ private int value;
+ }
+}
diff --git a/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/JBPatch.java b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/JBPatch.java
new file mode 100644
index 000000000..550b25e96
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/JBPatch.java
@@ -0,0 +1,234 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package ie.wombat.jbdiff;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.tools.bzip2.CBZip2InputStream;
+
+/**
+ * Java Binary patcher (based on bspatch by Colin Percival)
+ *
+ * @author Joe Desbonnet, joe@galway.net
+ */
+public class JBPatch {
+
+ // JBPatch extensions by Stefan.Liebig@compeople.de:
+ //
+ // - uses an extended version of the org.apache.tools.bzip2 compressor to
+ // compress all of the blocks (ctrl,diff,extra).
+ // - added an interface that allows using of JBPatch with streams and byte
+ // arrays
+
+ private static final String VERSION = "jbdiff-0.1.0";
+
+ /**
+ * Run JBPatch from the command line. Params: oldfile newfile patchfile.
+ * newfile will be created.
+ *
+ * @param arg
+ * @throws IOException
+ */
+ public static void main(String[] arg) throws IOException {
+
+ if (arg.length != 3) {
+ System.err
+ .println("usage example: java -Xmx200m ie.wombat.jbdiff.JBPatch oldfile newfile patchfile");
+ }
+
+ File oldFile = new File(arg[0]);
+ File newFile = new File(arg[1]);
+ File diffFile = new File(arg[2]);
+
+ bspatch(oldFile, newFile, diffFile);
+ }
+
+ /**
+ * @param oldFile
+ * @param newFile
+ * @param diffFile
+ * @throws IOException
+ */
+ public static void bspatch(File oldFile, File newFile, File diffFile)
+ throws IOException {
+ InputStream oldInputStream = new BufferedInputStream(
+ new FileInputStream(oldFile));
+ byte[] diffBytes = new byte[(int) diffFile.length()];
+ InputStream diffInputStream = new FileInputStream(diffFile);
+ Util.readFromStream(diffInputStream, diffBytes, 0, diffBytes.length);
+
+ byte[] newBytes = bspatch(oldInputStream, (int) oldFile.length(),
+ diffBytes);
+
+ OutputStream newOutputStream = new FileOutputStream(newFile);
+ newOutputStream.write(newBytes);
+ newOutputStream.close();
+ }
+
+ /**
+ * @param oldInputStream
+ * @param diffInputStream
+ * @return
+ */
+ public static byte[] bspatch(InputStream oldInputStream, int oldsize,
+ byte[] diffBytes) throws IOException {
+ /*
+ * Read in old file (file to be patched) to oldBuf
+ */
+ // int oldsize = (int) oldFile.length();
+ // byte[] oldBuf = new byte[oldsize + 1];
+ byte[] oldBuf = new byte[oldsize];
+ // InputStream oldIn = new FileInputStream( oldFile );
+ Util.readFromStream(oldInputStream, oldBuf, 0, oldsize);
+ oldInputStream.close();
+ // oldIn.close();
+
+ return JBPatch.bspatch(oldBuf, oldsize, diffBytes);
+ }
+
+ /**
+ * @param oldBuf
+ * @param oldsize
+ * @param diffBytes
+ * @return
+ * @throws IOException
+ */
+ public static byte[] bspatch(byte[] oldBuf, int oldsize, byte[] diffBytes)
+ throws IOException {
+ return bspatch(oldBuf, oldsize, diffBytes, diffBytes.length);
+ }
+
+ /**
+ * @param oldBuf
+ * @param oldsize
+ * @param diffBuf
+ * @param diffSize
+ * @return
+ * @throws IOException
+ */
+ public static byte[] bspatch(byte[] oldBuf, int oldsize, byte[] diffBuf,
+ int diffSize) throws IOException {
+
+ DataInputStream diffIn = new DataInputStream(new ByteArrayInputStream(
+ diffBuf, 0, diffSize));
+
+ // skip headerMagic at header offset 0 (length 8 bytes)
+ diffIn.skip(8);
+
+ // ctrlBlockLen after bzip2 compression at heater offset 8 (length 8
+ // bytes)
+ long ctrlBlockLen = diffIn.readLong();
+
+ // diffBlockLen after bzip2 compression at header offset 16 (length 8
+ // bytes)
+ long diffBlockLen = diffIn.readLong();
+
+ // size of new file at header offset 24 (length 8 bytes)
+ int newsize = (int) diffIn.readLong();
+
+ // System.err.println( "newsize=" + newsize );
+ // System.err.println( "ctrlBlockLen=" + ctrlBlockLen );
+ // System.err.println( "diffBlockLen=" + diffBlockLen );
+ // System.err.println( "newsize=" + newsize );
+
+ InputStream in;
+ in = new ByteArrayInputStream(diffBuf, 0, diffSize);
+ in.skip(Util.HEADER_SIZE);
+ DataInputStream ctrlBlockIn = new DataInputStream(
+ new CBZip2InputStream(in));
+
+ in = new ByteArrayInputStream(diffBuf, 0, diffSize);
+ in.skip(ctrlBlockLen + Util.HEADER_SIZE);
+ InputStream diffBlockIn = new CBZip2InputStream(in);
+
+ in = new ByteArrayInputStream(diffBuf, 0, diffSize);
+ in.skip(diffBlockLen + ctrlBlockLen + Util.HEADER_SIZE);
+ InputStream extraBlockIn = new CBZip2InputStream(in);
+
+ // byte[] newBuf = new byte[newsize + 1];
+ byte[] newBuf = new byte[newsize];
+
+ int oldpos = 0;
+ int newpos = 0;
+ int[] ctrl = new int[3];
+ // int nbytes;
+ while (newpos < newsize) {
+
+ for (int i = 0; i <= 2; i++) {
+ // ctrl[i] = diffIn.readInt();
+ ctrl[i] = ctrlBlockIn.readInt();
+ // System.err.println (" ctrl[" + i + "]=" + ctrl[i]);
+ }
+
+ if (newpos + ctrl[0] > newsize) {
+ throw new IOException("Corrupt patch.");
+ }
+
+ /*
+ * Read ctrl[0] bytes from diffBlock stream
+ */
+
+ Util.readFromStream(diffBlockIn, newBuf, newpos, ctrl[0]);
+
+ for (int i = 0; i < ctrl[0]; i++) {
+ if ((oldpos + i >= 0) && (oldpos + i < oldsize)) {
+ newBuf[newpos + i] += oldBuf[oldpos + i];
+ }
+ }
+
+ newpos += ctrl[0];
+ oldpos += ctrl[0];
+
+ if (newpos + ctrl[1] > newsize) {
+ throw new IOException("Corrupt patch.");
+ }
+
+ Util.readFromStream(extraBlockIn, newBuf, newpos, ctrl[1]);
+
+ newpos += ctrl[1];
+ oldpos += ctrl[2];
+ }
+
+ // TODO: Check if at end of ctrlIn
+ // TODO: Check if at the end of diffIn
+ // TODO: Check if at the end of extraIn
+
+ // This check is not needed since the byte array has been allocated with
+ // this constraint!
+ // if ( newBuf.length - 1 != newsize ) {
+ // throw new IOException( "Corrupt patch." );
+ // }
+
+ ctrlBlockIn.close();
+ diffBlockIn.close();
+ extraBlockIn.close();
+ diffIn.close();
+
+ return newBuf;
+ // OutputStream out = new FileOutputStream( newFile );
+ // out.write( newBuf, 0, newBuf.length - 1 );
+ // out.close();
+ }
+}
diff --git a/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/Util.java b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/Util.java
new file mode 100644
index 000000000..175808e84
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/ie/wombat/jbdiff/Util.java
@@ -0,0 +1,109 @@
+/*
+ * Created on Feb 28, 2005
+ */
+package ie.wombat.jbdiff;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author
+ * @author Joe Desbonnet, joe@galway.net
+ *
+ */
+public class Util {
+
+ // JBDiff extensions by Stefan.Liebig@compeople.de:
+ //
+ // - introduced a HEADER_SIZE constant here
+
+ /**
+ * Length of the diff file header.
+ */
+ public static final int HEADER_SIZE = 32;
+
+ /**
+ * Equiv of C library memcmp().
+ *
+ * @param s1
+ * @param s1offset
+ * @param s2
+ * @param n
+ * @return
+ */
+ /*
+ * public final static int memcmp(byte[] s1, int s1offset, byte[] s2, int
+ * s2offset, int n) {
+ *
+ * if ((s1offset + n) > s1.length) { n = s1.length - s1offset; } if
+ * ((s2offset + n) > s2.length) { n = s2.length - s2offset; } for (int i =
+ * 0; i < n; i++) { if (s1[i + s1offset] != s2[i + s2offset]) { return s1[i +
+ * s1offset] < s2[i + s2offset] ? -1 : 1; } }
+ *
+ * return 0; }
+ */
+
+ /**
+ * Equiv of C library memcmp().
+ *
+ * @param s1
+ * @param s1offset
+ * @param s2
+ * @param n
+ * @return
+ */
+ public final static int memcmp(byte[] s1, int s1Size, int s1offset,
+ byte[] s2, int s2Size, int s2offset) {
+
+ int n = s1Size - s1offset;
+
+ if (n > (s2Size - s2offset)) {
+ n = s2Size - s2offset;
+ }
+ for (int i = 0; i < n; i++) {
+ if (s1[i + s1offset] != s2[i + s2offset]) {
+ return s1[i + s1offset] < s2[i + s2offset] ? -1 : 1;
+ }
+ }
+
+ return 0;
+ // int n = s1.length - s1offset;
+ //
+ // if (n > (s2.length - s2offset)) {
+ // n = s2.length - s2offset;
+ // }
+ // for (int i = 0; i < n; i++) {
+ // if (s1[i + s1offset] != s2[i + s2offset]) {
+ // return s1[i + s1offset] < s2[i + s2offset] ? -1 : 1;
+ // }
+ // }
+ //
+ // return 0;
+ }
+
+ /**
+ * Read from input stream and fill the given buffer from the given offset up
+ * to length len.
+ *
+ * @param in
+ * @param buf
+ * @param offset
+ * @param len
+ * @throws IOException
+ */
+ public static final void readFromStream(InputStream in, byte[] buf,
+ int offset, int len) throws IOException {
+
+ int totalBytesRead = 0;
+ while (totalBytesRead < len) {
+ int bytesRead = in.read(buf, offset + totalBytesRead, len
+ - totalBytesRead);
+ if (bytesRead < 0) {
+ throw new IOException(
+ "Could not read expected number of bytes.");
+ }
+ totalBytesRead += bytesRead;
+ }
+ }
+
+}
diff --git a/bundles/ie.wombat.jbdiff/src/readme-more.txt b/bundles/ie.wombat.jbdiff/src/readme-more.txt
new file mode 100644
index 000000000..d822079cf
--- /dev/null
+++ b/bundles/ie.wombat.jbdiff/src/readme-more.txt
@@ -0,0 +1,10 @@
+This library version is based on JBDiff (http://freshmeat.net/projects/jbdiff/)
+which is also available under the OSI Approved :: BSD License (original)
+http://www.opensource.org/licenses/bsd-license.html
+
+This library uses a modified version of the package org.apache.tools.bzip2
+of the Apache Ant project 1.7.
+
+Version 0.1.0.1
+ - Extended interface so that it is not only file based and uses the extended CBZip2 as compressor.
+

Back to the top