Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Rosenberg2012-01-15 10:22:52 +0000
committerMatthias Sohn2012-01-15 10:22:52 +0000
commite875c905d310153165c5bdb24ead55d98596923a (patch)
treeb247debd7c714838109a23a0f103dc1a17a54de4 /org.eclipse.jgit
parent02729810f9246b9f332945f730d65c68f118d489 (diff)
downloadjgit-e875c905d310153165c5bdb24ead55d98596923a.tar.gz
jgit-e875c905d310153165c5bdb24ead55d98596923a.tar.xz
jgit-e875c905d310153165c5bdb24ead55d98596923a.zip
Make sure all bytes are written to files on close, or get an error.
Java's BufferedOutputStream swallows any errors that occur when flushing the buffer in close(). This class overrides close to make sure an error during the final flush is reported back to the caller. Change-Id: I74a82b31505fadf8378069c5f6554f1033c28f9b Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexWriter.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonClient.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/io/SafeBufferedOutputStream.java85
9 files changed, 106 insertions, 18 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
index 346b3b35f6..394c1a565f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
@@ -46,7 +46,6 @@
package org.eclipse.jgit.dircache;
import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
@@ -77,6 +76,7 @@ import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.MutableInteger;
import org.eclipse.jgit.util.NB;
import org.eclipse.jgit.util.TemporaryBuffer;
+import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
/**
* Support for the Git dircache (aka index file).
@@ -536,7 +536,7 @@ public class DirCache {
final LockFile tmp = myLock;
requireLocked(tmp);
try {
- writeTo(new BufferedOutputStream(tmp.getOutputStream()));
+ writeTo(new SafeBufferedOutputStream(tmp.getOutputStream()));
} catch (IOException err) {
tmp.unlock();
throw err;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
index cf74df638b..33607ccbd9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -86,6 +86,7 @@ import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
+import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
/**
* Represents a Git repository.
@@ -1277,7 +1278,7 @@ public abstract class Repository {
throws FileNotFoundException, IOException {
File headsFile = new File(getDirectory(), filename);
if (heads != null) {
- BufferedOutputStream bos = new BufferedOutputStream(
+ BufferedOutputStream bos = new SafeBufferedOutputStream(
new FileOutputStream(headsFile));
try {
for (ObjectId id : heads) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexWriter.java
index 6bd73adcb1..dad559a63f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackIndexWriter.java
@@ -56,6 +56,7 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.transport.PackedObjectInfo;
import org.eclipse.jgit.util.NB;
+import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
/**
* Creates a table of contents to support random access by {@link PackFile}.
@@ -161,7 +162,8 @@ public abstract class PackIndexWriter {
*/
protected PackIndexWriter(final OutputStream dst) {
out = new DigestOutputStream(dst instanceof BufferedOutputStream ? dst
- : new BufferedOutputStream(dst), Constants.newMessageDigest());
+ : new SafeBufferedOutputStream(dst),
+ Constants.newMessageDigest());
tmp = new byte[4 + Constants.OBJECT_ID_LENGTH];
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonClient.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonClient.java
index 23e3379f91..22f343899d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonClient.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonClient.java
@@ -44,7 +44,6 @@
package org.eclipse.jgit.transport;
import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -53,6 +52,7 @@ import java.net.Socket;
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
+import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
/** Active network client of {@link Daemon}. */
public class DaemonClient {
@@ -95,7 +95,7 @@ public class DaemonClient {
void execute(final Socket sock) throws IOException,
ServiceNotEnabledException, ServiceNotAuthorizedException {
rawIn = new BufferedInputStream(sock.getInputStream());
- rawOut = new BufferedOutputStream(sock.getOutputStream());
+ rawOut = new SafeBufferedOutputStream(sock.getOutputStream());
if (0 < daemon.getTimeout())
sock.setSoTimeout(daemon.getTimeout() * 1000);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
index dedd1f694b..102884a06b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
@@ -46,7 +46,6 @@
package org.eclipse.jgit.transport;
import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -63,6 +62,7 @@ import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
/**
* Transport through a git-daemon waiting for anonymous TCP connections.
@@ -173,7 +173,7 @@ class TransportGitAnon extends TcpTransport implements PackTransport {
OutputStream sOut = sock.getOutputStream();
sIn = new BufferedInputStream(sIn);
- sOut = new BufferedOutputStream(sOut);
+ sOut = new SafeBufferedOutputStream(sOut);
init(sIn, sOut);
service("git-upload-pack", pckOut);
@@ -212,7 +212,7 @@ class TransportGitAnon extends TcpTransport implements PackTransport {
OutputStream sOut = sock.getOutputStream();
sIn = new BufferedInputStream(sIn);
- sOut = new BufferedOutputStream(sOut);
+ sOut = new SafeBufferedOutputStream(sOut);
init(sIn, sOut);
service("git-receive-pack", pckOut);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
index 5c4855118d..5411f3d693 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
@@ -48,7 +48,6 @@
package org.eclipse.jgit.transport;
import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -67,6 +66,7 @@ import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.util.io.MessageWriter;
+import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
import org.eclipse.jgit.util.io.StreamCopyThread;
/**
@@ -301,7 +301,7 @@ class TransportLocal extends Transport implements PackTransport {
OutputStream upOut = uploadPack.getOutputStream();
upIn = new BufferedInputStream(upIn);
- upOut = new BufferedOutputStream(upOut);
+ upOut = new SafeBufferedOutputStream(upOut);
init(upIn, upOut);
readAdvertisedRefs();
@@ -431,7 +431,7 @@ class TransportLocal extends Transport implements PackTransport {
OutputStream rpOut = receivePack.getOutputStream();
rpIn = new BufferedInputStream(rpIn);
- rpOut = new BufferedOutputStream(rpOut);
+ rpOut = new SafeBufferedOutputStream(rpOut);
init(rpIn, rpOut);
readAdvertisedRefs();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
index 81aa4ab2b4..985b98e1d8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
@@ -45,7 +45,6 @@ package org.eclipse.jgit.transport;
import static org.eclipse.jgit.transport.WalkRemoteObjectDatabase.ROOT_DIR;
-import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
@@ -65,11 +64,12 @@ import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Ref.Storage;
import org.eclipse.jgit.lib.RefWriter;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.Ref.Storage;
import org.eclipse.jgit.storage.pack.PackWriter;
import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
+import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
/**
* Generic push support for dumb transport protocols.
@@ -259,7 +259,7 @@ class WalkPushConnection extends BaseConnection implements PushConnection {
final String wt = "Put " + base.substring(0, 12);
OutputStream os = dest.writeFile(pathPack, monitor, wt + "..pack");
try {
- os = new BufferedOutputStream(os);
+ os = new SafeBufferedOutputStream(os);
writer.writePack(monitor, monitor, os);
} finally {
os.close();
@@ -267,7 +267,7 @@ class WalkPushConnection extends BaseConnection implements PushConnection {
os = dest.writeFile(pathIdx, monitor, wt + "..idx");
try {
- os = new BufferedOutputStream(os);
+ os = new SafeBufferedOutputStream(os);
writer.writeIndex(os);
} finally {
os.close();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
index 8167c776b1..5e47fcc01a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
@@ -44,7 +44,6 @@
package org.eclipse.jgit.util;
-import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -56,6 +55,7 @@ import java.util.ArrayList;
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
/**
* A fully buffered output stream.
@@ -309,7 +309,7 @@ public abstract class TemporaryBuffer extends OutputStream {
overflow.write(b.buffer, 0, b.count);
blocks = null;
- overflow = new BufferedOutputStream(overflow, Block.SZ);
+ overflow = new SafeBufferedOutputStream(overflow, Block.SZ);
overflow.write(last.buffer, 0, last.count);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/SafeBufferedOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/SafeBufferedOutputStream.java
new file mode 100644
index 0000000000..fa15841054
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/SafeBufferedOutputStream.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011, Robin Rosenberg
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * 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 Eclipse Foundation, Inc. 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.
+ */
+package org.eclipse.jgit.util.io;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A BufferedOutputStream that throws an error if the final flush fails on
+ * close.
+ * <p>
+ * Java's BufferedOutputStream swallows errors that occur when the output stream
+ * tries to write the final bytes to the output during close. This may result in
+ * corrupted files without notice.
+ * </p>
+ */
+public class SafeBufferedOutputStream extends BufferedOutputStream {
+
+ /**
+ * @see BufferedOutputStream#BufferedOutputStream(OutputStream)
+ * @param out
+ */
+ public SafeBufferedOutputStream(OutputStream out) {
+ super(out);
+ }
+
+ /**
+ * @see BufferedOutputStream#BufferedOutputStream(OutputStream, int)
+ * @param out
+ * @param size
+ */
+ public SafeBufferedOutputStream(OutputStream out, int size) {
+ super(out);
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ flush();
+ } finally {
+ super.close();
+ }
+ }
+}

Back to the top