summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPacho Ramos <pacho@gentoo.org>2012-04-02 20:04:21 +0000
committerPacho Ramos <pacho@gentoo.org>2012-04-02 20:04:21 +0000
commite44e1f6fce3e84984cdbac880448dbe13f256fa1 (patch)
tree0d9f1c728cd60a65cfd22a9b2ad575f6f6d2dc8c /dev-util/xdelta
parentRespect get_libdir variable, bug #255698 by Nathan Phillip Brink (binki). Rem... (diff)
downloadhistorical-e44e1f6fce3e84984cdbac880448dbe13f256fa1.tar.gz
historical-e44e1f6fce3e84984cdbac880448dbe13f256fa1.tar.bz2
historical-e44e1f6fce3e84984cdbac880448dbe13f256fa1.zip
Fix overflows with ThePythonicCow's patches, bug #380473 by Marcin Mirosław.
Package-Manager: portage-2.1.10.54/cvs/Linux x86_64
Diffstat (limited to 'dev-util/xdelta')
-rw-r--r--dev-util/xdelta/ChangeLog12
-rw-r--r--dev-util/xdelta/Manifest14
-rw-r--r--dev-util/xdelta/files/01_bigger_print_buffers.patch83
-rw-r--r--dev-util/xdelta/files/02_replace_sprintf_with_snprintf.patch226
-rw-r--r--dev-util/xdelta/files/03_fix_pipe_draining_and_closing.patch62
-rw-r--r--dev-util/xdelta/xdelta-3.0.0-r1.ebuild65
6 files changed, 455 insertions, 7 deletions
diff --git a/dev-util/xdelta/ChangeLog b/dev-util/xdelta/ChangeLog
index ee6a327a6bd7..865b957a6bfe 100644
--- a/dev-util/xdelta/ChangeLog
+++ b/dev-util/xdelta/ChangeLog
@@ -1,6 +1,14 @@
# ChangeLog for dev-util/xdelta
-# Copyright 1999-2011 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/dev-util/xdelta/ChangeLog,v 1.62 2011/08/05 22:35:09 hwoarang Exp $
+# Copyright 1999-2012 Gentoo Foundation; Distributed under the GPL v2
+# $Header: /var/cvsroot/gentoo-x86/dev-util/xdelta/ChangeLog,v 1.63 2012/04/02 20:04:21 pacho Exp $
+
+*xdelta-3.0.0-r1 (02 Apr 2012)
+
+ 02 Apr 2012; Pacho Ramos <pacho@gentoo.org>
+ +files/01_bigger_print_buffers.patch,
+ +files/02_replace_sprintf_with_snprintf.patch,
+ +files/03_fix_pipe_draining_and_closing.patch, +xdelta-3.0.0-r1.ebuild:
+ Fix overflows with ThePythonicCow's patches, bug #380473 by Marcin Mirosław.
05 Aug 2011; Markos Chandras <hwoarang@gentoo.org> -xdelta-3.0v.ebuild,
-xdelta-3.0z.ebuild:
diff --git a/dev-util/xdelta/Manifest b/dev-util/xdelta/Manifest
index 36c8204b8f83..8a197e09978d 100644
--- a/dev-util/xdelta/Manifest
+++ b/dev-util/xdelta/Manifest
@@ -1,19 +1,23 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
+AUX 01_bigger_print_buffers.patch 2841 RMD160 85ea5503384011866b0f201550e765e0afeb562d SHA1 457c04ebc1fa42f31433ed6bc77695550698c598 SHA256 9330a0c6218ee66b90772e9f1b81b76e43a6bba2a45e5d926f136f3f43069a9e
+AUX 02_replace_sprintf_with_snprintf.patch 7900 RMD160 3a4d3a91903d15560958c5896ab0d6833896e665 SHA1 155c9bc4088c87b824cd85349d72bad0a942252f SHA256 25e224a09b4780efd10e5980339a150c5baa699dcb6596d65ea8b8910c0177c7
+AUX 03_fix_pipe_draining_and_closing.patch 2238 RMD160 b417da44ea860d511dfd72ed6a3993c322f5cf1e SHA1 2bbfa02dd6f49c1bbb55a59949941f3e3fa40036 SHA256 066299426da8a486faf73ef4cc30869fd44ca97ab24f1dd7dd7644a4d7407f26
AUX xdelta-1.1.4-glib2.patch 4545 RMD160 790ca7094a8fdc458ec4fc097c1cf31de4952857 SHA1 dc2771fddc73384d1419990a56fe9b2795ef7e73 SHA256 dea479d7c6e116abd72076063adcb790226966eb720a99ffeecd77c4d22a8c03
AUX xdelta-1.1.4-m4.patch 458 RMD160 42a8d9b0b895cd7f34dfa5dfdb471232c42af4f4 SHA1 c217dbd535b96e3d14c232823d14c8e67f21859e SHA256 8a3e06cfef18ed4e976daecab0e4ebdea20dd849136ef919787f4444b8f89f2d
AUX xdelta-1.1.4-pkgconfig.patch 2551 RMD160 21de05c24c38e9773bbd00f359c6ff040af6cf8f SHA1 7b5f747cbac2a267fe892725b6ba74fa94ea0289 SHA256 1a00aad31265a5a5b8b6bbfc4c6dd57f08566c72aa4a85fdbea3f9394c4214f4
DIST xdelta-1.1.4.tar.gz 423529 RMD160 394a1e46a48328eed951fccb7b4b16b1feb682cc SHA1 7cfc3e4ea6b27d199de02906beb6c80a04facb91 SHA256 345503b60432812840991ea1d79cb10db5f34bfaba9499bd0e7d5c57ac5d5c6d
DIST xdelta3.0.0.tar.gz 282201 RMD160 6f1d64066579342fb659df862a44c279fdce64e5 SHA1 c9e54fd8dbd9f2e77ead17be9d00e0b8af109024 SHA256 dfe61aac8d6ab301be2f3aed561d15f95f30a270e25d179f7cf0bde010ada102
EBUILD xdelta-1.1.4-r1.ebuild 1001 RMD160 4abe172aa489f2883c0c443a5a5f6a89f2e6702c SHA1 d02cff94e59c97d371950e6e753d2d4667a88db7 SHA256 e2e84ff1c1f4fd2947b1ae7474f251f417ae15a366ffc508808b4d543d92d63c
+EBUILD xdelta-3.0.0-r1.ebuild 1407 RMD160 ee06d0ffc511c1c953fd78f03bb9b6ab81027418 SHA1 d492529bad213b82f7b9a07547f38c56ef646a2d SHA256 f5ad956cd350cc8885fd0dad3911f8b756354ea15d3f5bac62ee3bc3515a04eb
EBUILD xdelta-3.0.0.ebuild 1354 RMD160 581a129a74f1b1b7dee7e3e8f7fb60eb350f522a SHA1 a7019527befd6038e735dc4629f34a54f6a00963 SHA256 4d6efea491c9306e27a2d16fdbfb2059e9a5f40f41fa2c8803bf2d82cf6cf194
-MISC ChangeLog 8045 RMD160 4d30530fd04601260285919555128e2d4900b86e SHA1 e3921961aabf55de8ca0357244bf0296cd95620c SHA256 ae3c330285a4dec57ba55a9f68a7c0e6e9661599bc2ae20a2c53cbf39e91caf5
+MISC ChangeLog 8364 RMD160 284dabe350531aa2d6cfcb78626f0a5eacff2a6b SHA1 a1d392d0b45b5a154501e8cd28abee572c483ba5 SHA256 010180d30d94de790060273ab9fb29dab71293b0b3e4134dba2a320aea3ed928
MISC metadata.xml 290 RMD160 2135a92fe953d183221023fbc95b7c6d2e032dfc SHA1 4ee3535650ab802537600e207b7df760ee0d47cd SHA256 5b783baca0f7e4843f0f526066b84fcac9eb90be51230489a59b56a79565cde9
-----BEGIN PGP SIGNATURE-----
-Version: GnuPG v2.0.18 (GNU/Linux)
+Version: GnuPG v2.0.17 (GNU/Linux)
-iEYEARECAAYFAk93TdYACgkQ/ejvha5XGaPzGQCg18OA6eVQpXdMhGfNcumLfCXr
-eVUAnjBnf2LErNIe0nXIq7cT3vu7KY7B
-=qtNB
+iEYEARECAAYFAk96BkoACgkQCaWpQKGI+9RuCgCeLqre3HfwaRfPvHOKeA/ptJp0
+/+kAn31CQn1grs3Gfp0T5bmMk1B0APr9
+=nxgR
-----END PGP SIGNATURE-----
diff --git a/dev-util/xdelta/files/01_bigger_print_buffers.patch b/dev-util/xdelta/files/01_bigger_print_buffers.patch
new file mode 100644
index 000000000000..85e098c768f8
--- /dev/null
+++ b/dev-util/xdelta/files/01_bigger_print_buffers.patch
@@ -0,0 +1,83 @@
+From: Paul Jackson <pj@usa.net>, Paul Jackson <thepythoniccow@gmail.com>
+
+xdelta3 (version 3.0.0) has numerous sprintf and strcpy calls that
+write into 32 byte char buffers that are on the stack or are static
+allocations. With sufficiently large files, these strings can overflow
+the 32 char buffers, and some recent gnu libc versions will detect this
+and immediately abort with the error "*** buffer overflow detected ***"
+
+This patch, the first of three, is the only essential patch for this fix.
+It increases the 32 byte stack buffers to 48 bytes each.
+
+The subsequent two patches will replace sprintf calls with snprintf,
+to safely avoid overflowing these stack buffers in all cases, and will
+fix a hang caused by not properly closing and flushing pipes.
+
+---
+ xdelta3-blkcache.h | 10 +++++-----
+ xdelta3-main.h | 14 +++++++-------
+ 2 files changed, 12 insertions(+), 12 deletions(-)
+
+--- xdelta3.0.0.orig/xdelta3-blkcache.h 2012-03-26 22:55:03.447784216 -0500
++++ xdelta3.0.0/xdelta3-blkcache.h 2012-03-26 23:22:54.871899533 -0500
+@@ -233,11 +233,11 @@ main_set_source (xd3_stream *stream, xd3
+
+ if (option_verbose)
+ {
+- static char srcszbuf[32];
+- static char srccntbuf[32];
+- static char winszbuf[32];
+- static char blkszbuf[32];
+- static char nbufs[32];
++ static char srcszbuf[48];
++ static char srccntbuf[48];
++ static char winszbuf[48];
++ static char blkszbuf[48];
++ static char nbufs[48];
+
+ if (sfile->size_known)
+ {
+--- xdelta3.0.0.orig/xdelta3-main.h 2012-03-26 22:55:03.455784458 -0500
++++ xdelta3.0.0/xdelta3-main.h 2012-03-26 23:22:54.859899160 -0500
+@@ -633,7 +633,7 @@ static char*
+ main_format_rate (xoff_t bytes, long millis, char *buf)
+ {
+ xoff_t r = (xoff_t)(1.0 * bytes / (1.0 * millis / 1000.0));
+- static char lbuf[32];
++ static char lbuf[48];
+
+ main_format_bcnt (r, lbuf);
+ sprintf (buf, "%s/s", lbuf);
+@@ -2954,7 +2954,7 @@ static usize_t
+ main_get_winsize (main_file *ifile) {
+ xoff_t file_size = 0;
+ usize_t size = option_winsize;
+- static char iszbuf[32];
++ static char iszbuf[48];
+
+ if (main_file_stat (ifile, &file_size) == 0)
+ {
+@@ -3328,10 +3328,10 @@ main_input (xd3_cmd cmd,
+
+ if (option_verbose)
+ {
+- char rrateavg[32], wrateavg[32], tm[32];
+- char rdb[32], wdb[32];
+- char trdb[32], twdb[32];
+- char srcpos[32];
++ char rrateavg[48], wrateavg[48], tm[48];
++ char rdb[48], wdb[48];
++ char trdb[48], twdb[48];
++ char srcpos[48];
+ long millis = get_millisecs_since ();
+ usize_t this_read = (usize_t)(stream.total_in -
+ last_total_in);
+@@ -3460,7 +3460,7 @@ done:
+
+ if (option_verbose)
+ {
+- char tm[32];
++ char tm[48];
+ long end_time = get_millisecs_now ();
+ xoff_t nwrite = ofile != NULL ? ofile->nwrite : 0;
+
diff --git a/dev-util/xdelta/files/02_replace_sprintf_with_snprintf.patch b/dev-util/xdelta/files/02_replace_sprintf_with_snprintf.patch
new file mode 100644
index 000000000000..bdb731c23dca
--- /dev/null
+++ b/dev-util/xdelta/files/02_replace_sprintf_with_snprintf.patch
@@ -0,0 +1,226 @@
+From: Paul Jackson <pj@usa.net>, Paul Jackson <thepythoniccow@gmail.com>
+
+xdelta3 (version 3.0.0) has numerous sprintf and strcpy calls that
+write into 32 byte char buffers that are on the stack or are static
+allocations. With sufficiently large files, these strings can overflow
+the 32 char buffers, and some recent gnu libc versions will detect this
+and immediately abort with the error "*** buffer overflow detected ***"
+
+The first patch in this series increased these buffers from 32 to 48 bytes.
+
+This patch, the second in the series, replaces sprintf calls with
+snprintf, to safely avoid overflowing these stack buffers in all cases.
+This change necessitated changing the main_format_bcnt() and
+main_format_millis() API's, to pass the size of the buffer.
+
+The third patch will fix a hang caused by not properly closing and flushing
+pipes.
+
+---
+ xdelta3-blkcache.h | 12 ++++-----
+ xdelta3-main.h | 64 ++++++++++++++++++++++++++---------------------------
+ 2 files changed, 38 insertions(+), 38 deletions(-)
+
+--- xdelta3.0.0.orig/xdelta3-blkcache.h 2012-03-26 23:06:12.280521538 -0500
++++ xdelta3.0.0/xdelta3-blkcache.h 2012-03-26 23:06:47.049599301 -0500
+@@ -241,27 +241,27 @@ main_set_source (xd3_stream *stream, xd3
+
+ if (sfile->size_known)
+ {
+- sprintf (srcszbuf, "source size %s [%"Q"u]",
+- main_format_bcnt (source_size, srccntbuf),
++ snprintf (srcszbuf, sizeof(srcszbuf), "source size %s [%"Q"u]",
++ main_format_bcnt (source_size, srccntbuf, sizeof(srccntbuf)),
+ source_size);
+ }
+ else
+ {
+- strcpy(srcszbuf, "source size unknown");
++ strncpy(srcszbuf, "source size unknown", sizeof(srcszbuf));
+ }
+
+ nbufs[0] = 0;
+
+ if (option_verbose > 1)
+ {
+- sprintf(nbufs, " #bufs %u", lru_size);
++ snprintf(nbufs, sizeof(nbufs), " #bufs %u", lru_size);
+ }
+
+ XPR(NT "source %s %s blksize %s window %s%s%s\n",
+ sfile->filename,
+ srcszbuf,
+- main_format_bcnt (blksize, blkszbuf),
+- main_format_bcnt (option_srcwinsz, winszbuf),
++ main_format_bcnt (blksize, blkszbuf, sizeof(blkszbuf)),
++ main_format_bcnt (option_srcwinsz, winszbuf, sizeof(winszbuf)),
+ nbufs,
+ do_src_fifo ? " (FIFO)" : "");
+ }
+--- xdelta3.0.0.orig/xdelta3-main.h 2012-03-26 23:06:12.296522032 -0500
++++ xdelta3.0.0/xdelta3-main.h 2012-03-26 23:22:32.255191072 -0500
+@@ -354,7 +354,7 @@ static int main_read_primary_input (main
+ usize_t size,
+ usize_t *nread);
+
+-static const char* main_format_bcnt (xoff_t r, char *buf);
++static const char* main_format_bcnt (xoff_t r, char *buf, int szbuf);
+ static int main_help (void);
+
+ /* The code in xdelta3-blk.h is essentially part of this unit, see
+@@ -576,7 +576,7 @@ get_millisecs_since (void)
+ }
+
+ static const char*
+-main_format_bcnt (xoff_t r, char *buf)
++main_format_bcnt (xoff_t r, char *buf, int szbuf)
+ {
+ static const char* fmts[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" };
+ usize_t i;
+@@ -587,25 +587,25 @@ main_format_bcnt (xoff_t r, char *buf)
+
+ if (r == 0)
+ {
+- sprintf (buf, "0 %s", fmts[i]);
++ snprintf (buf, szbuf, "0 %s", fmts[i]);
+ return buf;
+ }
+
+ if (r >= 1 && r < 10)
+ {
+- sprintf (buf, "%.2f %s", (double) r, fmts[i]);
++ snprintf (buf, szbuf, "%.2f %s", (double) r, fmts[i]);
+ return buf;
+ }
+
+ if (r >= 10 && r < 100)
+ {
+- sprintf (buf, "%.1f %s", (double) r, fmts[i]);
++ snprintf (buf, szbuf, "%.1f %s", (double) r, fmts[i]);
+ return buf;
+ }
+
+ if (r >= 100 && r < 1000)
+ {
+- sprintf (buf, "%"Q"u %s", r, fmts[i]);
++ snprintf (buf, szbuf, "%"Q"u %s", r, fmts[i]);
+ return buf;
+ }
+
+@@ -613,13 +613,13 @@ main_format_bcnt (xoff_t r, char *buf)
+
+ if (new_r < 10)
+ {
+- sprintf (buf, "%.2f %s", (double) r / 1024.0, fmts[i + 1]);
++ snprintf (buf, szbuf, "%.2f %s", (double) r / 1024.0, fmts[i + 1]);
+ return buf;
+ }
+
+ if (new_r < 100)
+ {
+- sprintf (buf, "%.1f %s", (double) r / 1024.0, fmts[i + 1]);
++ snprintf (buf, szbuf, "%.1f %s", (double) r / 1024.0, fmts[i + 1]);
+ return buf;
+ }
+
+@@ -630,22 +630,22 @@ main_format_bcnt (xoff_t r, char *buf)
+ }
+
+ static char*
+-main_format_rate (xoff_t bytes, long millis, char *buf)
++main_format_rate (xoff_t bytes, long millis, char *buf, int szbuf)
+ {
+ xoff_t r = (xoff_t)(1.0 * bytes / (1.0 * millis / 1000.0));
+ static char lbuf[48];
+
+- main_format_bcnt (r, lbuf);
+- sprintf (buf, "%s/s", lbuf);
++ main_format_bcnt (r, lbuf, sizeof(lbuf));
++ snprintf (buf, szbuf, "%s/s", lbuf);
+ return buf;
+ }
+
+ static char*
+-main_format_millis (long millis, char *buf)
++main_format_millis (long millis, char *buf, int szbuf)
+ {
+- if (millis < 1000) { sprintf (buf, "%lu ms", millis); }
+- else if (millis < 10000) { sprintf (buf, "%.1f sec", millis / 1000.0); }
+- else { sprintf (buf, "%lu sec", millis / 1000L); }
++ if (millis < 1000) { snprintf (buf, szbuf, "%lu ms", millis); }
++ else if (millis < 10000) { snprintf (buf, szbuf, "%.1f sec", millis / 1000.0); }
++ else { snprintf (buf, szbuf, "%lu sec", millis / 1000L); }
+ return buf;
+ }
+
+@@ -2739,11 +2739,11 @@ main_set_appheader (xd3_stream *stream,
+
+ if (sfile->filename == NULL)
+ {
+- sprintf ((char*)appheader_used, "%s/%s", iname, icomp);
++ snprintf ((char*)appheader_used, len, "%s/%s", iname, icomp);
+ }
+ else
+ {
+- sprintf ((char*)appheader_used, "%s/%s/%s/%s",
++ snprintf ((char*)appheader_used, len, "%s/%s/%s/%s",
+ iname, icomp, sname, scomp);
+ }
+ }
+@@ -2967,7 +2967,7 @@ main_get_winsize (main_file *ifile) {
+ {
+ XPR(NT "input %s window size %s\n",
+ ifile->filename,
+- main_format_bcnt (size, iszbuf));
++ main_format_bcnt (size, iszbuf, sizeof(iszbuf)));
+ }
+
+ return size;
+@@ -3345,25 +3345,25 @@ main_input (xd3_cmd cmd,
+ XPR(NT "%"Q"u: in %s (%s): out %s (%s): "
+ "total in %s: out %s: %s: srcpos %s\n",
+ stream.current_window,
+- main_format_bcnt (this_read, rdb),
+- main_format_rate (this_read, millis, rrateavg),
+- main_format_bcnt (this_write, wdb),
+- main_format_rate (this_write, millis, wrateavg),
+- main_format_bcnt (stream.total_in, trdb),
+- main_format_bcnt (stream.total_out, twdb),
+- main_format_millis (millis, tm),
+- main_format_bcnt (sfile->source_position, srcpos));
++ main_format_bcnt (this_read, rdb, sizeof(rdb)),
++ main_format_rate (this_read, millis, rrateavg, sizeof(rrateavg)),
++ main_format_bcnt (this_write, wdb, sizeof(wdb)),
++ main_format_rate (this_write, millis, wrateavg, sizeof(wrateavg)),
++ main_format_bcnt (stream.total_in, trdb, sizeof(trdb)),
++ main_format_bcnt (stream.total_out, twdb, sizeof(twdb)),
++ main_format_millis (millis, tm, sizeof(tm)),
++ main_format_bcnt (sfile->source_position, srcpos, sizeof(srcpos)));
+ }
+ else
+ {
+ XPR(NT "%"Q"u: in %s: out %s: total in %s: "
+ "out %s: %s\n",
+ stream.current_window,
+- main_format_bcnt (this_read, rdb),
+- main_format_bcnt (this_write, wdb),
+- main_format_bcnt (stream.total_in, trdb),
+- main_format_bcnt (stream.total_out, twdb),
+- main_format_millis (millis, tm));
++ main_format_bcnt (this_read, rdb, sizeof(rdb)),
++ main_format_bcnt (this_write, wdb, sizeof(wdb)),
++ main_format_bcnt (stream.total_in, trdb, sizeof(trdb)),
++ main_format_bcnt (stream.total_out, twdb, sizeof(twdb)),
++ main_format_millis (millis, tm, sizeof(tm)));
+ }
+ }
+ }
+@@ -3465,7 +3465,7 @@ done:
+ xoff_t nwrite = ofile != NULL ? ofile->nwrite : 0;
+
+ XPR(NT "finished in %s; input %"Q"u output %"Q"u bytes (%0.2f%%)\n",
+- main_format_millis (end_time - start_time, tm),
++ main_format_millis (end_time - start_time, tm, sizeof(tm)),
+ ifile->nread, nwrite, 100.0 * nwrite / ifile->nread);
+ }
+
diff --git a/dev-util/xdelta/files/03_fix_pipe_draining_and_closing.patch b/dev-util/xdelta/files/03_fix_pipe_draining_and_closing.patch
new file mode 100644
index 000000000000..6ea665b8aec2
--- /dev/null
+++ b/dev-util/xdelta/files/03_fix_pipe_draining_and_closing.patch
@@ -0,0 +1,62 @@
+From: Paul Jackson <pj@usa.net>, Paul Jackson <thepythoniccow@gmail.com>
+
+xdelta3 automatically sets up child compression and decompression
+processes and pipes data to and from them, in various cases.
+
+Sometimes this can hang, due to improper closing, or lose
+data, due to improper flushing.
+
+This patch purports to fix this, but has not been tested
+very well at all. More work may be needed here.
+
+The patch also makes one error message less scary.
+
+---
+ xdelta3-main.h | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+--- xdelta3.0.0.orig/xdelta3-main.h 2012-03-26 23:11:26.346316918 -0500
++++ xdelta3.0.0/xdelta3-main.h 2012-03-26 23:11:40.218752082 -0500
+@@ -2135,9 +2135,11 @@ main_waitpid_check(pid_t pid)
+ }
+ else if (! WIFEXITED (status))
+ {
+- ret = ECHILD;
+- XPR(NT "external compression [pid %d] signal %d\n",
+- pid, WIFSIGNALED (status) ? WTERMSIG (status) : WSTOPSIG (status));
++ if ( ! (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE) ) {
++ ret = ECHILD;
++ XPR(NT "external compression [pid %d] signal %d\n",
++ pid, WIFSIGNALED (status) ? WTERMSIG (status) : WSTOPSIG (status));
++ }
+ }
+ else if (WEXITSTATUS (status) != 0)
+ {
+@@ -2221,7 +2223,8 @@ main_pipe_copier (uint8_t *pipe_buf,
+ int force_drain = 0;
+ if (nread > 0 && (ret = main_pipe_write (outfd, pipe_buf, nread)))
+ {
+- if (option_force && ret == EPIPE)
++ /* Next line: Until better fix, *always* drain if EPIPE. */
++ if ( /* option_force && */ ret == EPIPE)
+ {
+ /* This causes the loop to continue reading until nread
+ * == 0. */
+@@ -2265,7 +2268,7 @@ main_pipe_copier (uint8_t *pipe_buf,
+
+ if (garbage != 0)
+ {
+- XPR(NT "trailing garbage ignored in %s (%"Q"u bytes)\n",
++ XPR(NT "skipped trailing bytes in %s (%"Q"u bytes)\n",
+ ifile->filename, garbage);
+ }
+ return 0;
+@@ -2354,6 +2357,8 @@ main_input_decompress_setup (const main_
+ }
+
+ if (close (inpipefd[PIPE_READ_FD]) ||
++ close (outpipefd[PIPE_READ_FD]) ||
++ close (outpipefd[PIPE_WRITE_FD]) ||
+ main_pipe_copier (pipe_buf, pipe_bufsize, pipe_avail,
+ ifile, inpipefd[PIPE_WRITE_FD]) ||
+ close (inpipefd[PIPE_WRITE_FD]))
diff --git a/dev-util/xdelta/xdelta-3.0.0-r1.ebuild b/dev-util/xdelta/xdelta-3.0.0-r1.ebuild
new file mode 100644
index 000000000000..828b023dcb58
--- /dev/null
+++ b/dev-util/xdelta/xdelta-3.0.0-r1.ebuild
@@ -0,0 +1,65 @@
+# Copyright 1999-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-util/xdelta/xdelta-3.0.0-r1.ebuild,v 1.1 2012/04/02 20:04:21 pacho Exp $
+
+EAPI=4
+PYTHON_DEPEND="2:2.6"
+
+inherit distutils toolchain-funcs eutils
+
+DESCRIPTION="a binary diff and differential compression tools. VCDIFF (RFC 3284) delta compression."
+HOMEPAGE="http://xdelta.org"
+SRC_URI="http://${PN}.googlecode.com/files/${P/-}.tar.gz"
+
+LICENSE="GPL-2"
+SLOT="3"
+KEYWORDS="~alpha ~amd64 ~hppa ~ia64 ~ppc ~ppc64 ~sparc ~x86"
+IUSE="test"
+
+DEPEND="test? ( app-arch/ncompress )"
+RDEPEND=""
+
+S="${WORKDIR}/${P/-}"
+
+DOCS="draft-korn-vcdiff.txt"
+
+pkg_setup() {
+ python_set_active_version 2
+ python_pkg_setup
+}
+
+src_prepare() {
+ sed -i -e 's:-O3:-Wall:' setup.py || die "setup.py sed failed"
+ sed \
+ -e 's:-O3::g' \
+ -e 's:$(CC):$(CC) $(LDFLAGS):g' \
+ -e 's:CFLAGS=:CFLAGS+=:' \
+ -i Makefile || die "Makefile sed failed"
+
+ EPATCH_SOURCE="${FILESDIR}" epatch \
+ 01_bigger_print_buffers.patch \
+ 02_replace_sprintf_with_snprintf.patch \
+ 03_fix_pipe_draining_and_closing.patch
+}
+
+src_test() {
+ if [ $UID != 0 ]; then
+ emake test
+ else
+ ewarn "Tests can't be run as root, skipping."
+ fi
+}
+
+src_compile() {
+ tc-export CC CXX
+ distutils_src_compile
+ emake xdelta3
+ if use test; then
+ emake xdelta3-debug
+ fi
+}
+
+src_install() {
+ dobin xdelta3
+ distutils_src_install
+}