Bug 508858: Pass a blocking InputStream to the TarArchiveInputStream. The input stream returned from copyContainer may be passing back available bytes which may not default to be 0. In this case, the tar input stream may be reading a header record and treat this incomplete record as EOF. Also fixed buffering to only write out what was read (number of bytes). Change-Id: Icbab8dc460eb613acf6e12cd2f5aba192c52e774 Reviewed-on: https://git.eclipse.org/r/86667 Tested-by: Hudson CI Reviewed-by: Jeff Johnston <jjohnstn@redhat.com>
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CopyFromContainerCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CopyFromContainerCommandHandler.java index 9a28890..a6ad080 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CopyFromContainerCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CopyFromContainerCommandHandler.java
@@ -13,6 +13,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.List; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; @@ -109,10 +110,17 @@ COPY_FROM_CONTAINER_JOB_SUBTASK, proxy.getFullPath())); monitor.worked(1); + InputStream in = ((DockerConnection) connection) + .copyContainer(container.id(), + proxy.getLink()); + /* + * The input stream from copyContainer might be + * incomplete or non-blocking so we should wrap it + * in a stream that is guaranteed to block until + * data is available. + */ TarArchiveInputStream k = new TarArchiveInputStream( - ((DockerConnection) connection) - .copyContainer(container.id(), - proxy.getLink())); + new BlockingInputStream(in)); TarArchiveEntry te = null; while ((te = k.getNextTarEntry()) != null) { long size = te.getSize(); @@ -126,17 +134,19 @@ f.createNewFile(); } FileOutputStream os = new FileOutputStream(f); - if (size > 4096) - size = 4096; - byte[] barray = new byte[(int) size]; - while (k.read(barray) > -1) { + int bufferSize = ((int) size > 4096 ? 4096 + : (int) size); + byte[] barray = new byte[bufferSize]; + int result = -1; + while ((result = k.read(barray, 0, + bufferSize)) > -1) { if (monitor.isCanceled()) { monitor.done(); k.close(); os.close(); return Status.CANCEL_STATUS; } - os.write(barray); + os.write(barray, 0, result); } os.close(); } @@ -172,4 +182,20 @@ } + /** + * A blocking input stream that waits until data is available. + */ + public class BlockingInputStream extends InputStream { + private InputStream in; + + public BlockingInputStream(InputStream in) { + this.in = in; + } + + @Override + public int read() throws IOException { + return in.read(); + } + } + }