]> source.dussan.org Git - jgit.git/commitdiff
Don't use java.nio channel for file size determination 76/5276/11
authorMarkus Duft <markus.duft@salomon.at>
Mon, 2 Apr 2012 05:27:19 +0000 (07:27 +0200)
committerMarkus Duft <markus.duft@salomon.at>
Mon, 2 Apr 2012 05:27:25 +0000 (07:27 +0200)
Java NIO has some problems (like files closing unexpectedly because the
thread was interrupted). To avoid those problems, don't use a NIO
channel to determine the size of a file, but rather ask the File itself.

We have to be prepared to handle wrong/outdated information in this case
too, as the inode of the File may change between opening and determining
file size.

Change-Id: Ic7aa6c3337480879efcce4a3058b548cd0e2cef0

org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java

index 412bd04e67c7d97815eda665256c62305e422567..fab86025dce2da0d47962d0e68ac9b5f4f3c6a3f 100644 (file)
@@ -137,12 +137,38 @@ public class IO {
                        throws FileNotFoundException, IOException {
                final FileInputStream in = new FileInputStream(path);
                try {
-                       final long sz = in.getChannel().size();
+                       long sz = Math.max(path.length(), 1);
                        if (sz > max)
                                throw new IOException(MessageFormat.format(
                                                JGitText.get().fileIsTooLarge, path));
-                       final byte[] buf = new byte[(int) sz];
-                       IO.readFully(in, buf, 0);
+
+                       byte[] buf = new byte[(int) sz];
+                       int valid = 0;
+                       for (;;) {
+                               if (buf.length == valid) {
+                                       if (buf.length == max) {
+                                               int next = in.read();
+                                               if (next < 0)
+                                                       break;
+
+                                               throw new IOException(MessageFormat.format(
+                                                               JGitText.get().fileIsTooLarge, path));
+                                       }
+
+                                       byte[] nb = new byte[Math.min(buf.length * 2, max)];
+                                       System.arraycopy(buf, 0, nb, 0, valid);
+                                       buf = nb;
+                               }
+                               int n = in.read(buf, valid, buf.length - valid);
+                               if (n < 0)
+                                       break;
+                               valid += n;
+                       }
+                       if (valid < buf.length) {
+                               byte[] nb = new byte[valid];
+                               System.arraycopy(buf, 0, nb, 0, valid);
+                               buf = nb;
+                       }
                        return buf;
                } finally {
                        try {