提交 d309677c 编写于 作者: M mchung

6402006: FileInputStream.available() returns negative values when reading a large file

Reviewed-by: alanb
上级 3459dfdc
......@@ -300,7 +300,6 @@ handleStdinAvailable(jlong, long *);
int
handleAvailable(jlong fd, jlong *pbytes) {
jlong current, end;
HANDLE h = (HANDLE)fd;
DWORD type = 0;
......@@ -320,18 +319,17 @@ handleAvailable(jlong fd, jlong *pbytes) {
}
/* Handle is for regular file */
if (type == FILE_TYPE_DISK) {
long highPos = 0;
DWORD sizeLow = 0;
DWORD sizeHigh = 0;
DWORD lowPos = SetFilePointer(h, 0, &highPos, FILE_CURRENT);
if (lowPos == ((DWORD)-1)) {
jlong current, end;
LARGE_INTEGER filesize;
current = handleLseek(fd, 0, SEEK_CUR);
if (current < 0) {
return FALSE;
}
current = (((jlong)highPos) << 32) | lowPos;
end = GetFileSize(h, &sizeHigh);
if (sizeLow == ((DWORD)-1)) {
if (GetFileSizeEx(h, &filesize) == 0) {
return FALSE;
}
end = long_to_jlong(filesize.QuadPart);
*pbytes = end - current;
return TRUE;
}
......@@ -569,6 +567,7 @@ handleClose(JNIEnv *env, jobject this, jfieldID fid)
jlong
handleLseek(jlong fd, jlong offset, jint whence)
{
LARGE_INTEGER pos, distance;
DWORD lowPos = 0;
long highPos = 0;
DWORD op = FILE_CURRENT;
......@@ -584,13 +583,9 @@ handleLseek(jlong fd, jlong offset, jint whence)
op = FILE_BEGIN;
}
lowPos = (DWORD)offset;
highPos = (long)(offset >> 32);
lowPos = SetFilePointer(h, lowPos, &highPos, op);
if (lowPos == ((DWORD)-1)) {
if (GetLastError() != ERROR_SUCCESS) {
distance.QuadPart = offset;
if (SetFilePointerEx(h, distance, &pos, op) == 0) {
return -1;
}
}
return (((jlong)highPos) << 32) | lowPos;
return long_to_jlong(pos.QuadPart);
}
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6402006
* @summary Test if available returns correct value when reading
* a large file.
*/
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import static java.nio.file.StandardOpenOption.*;
public class LargeFileAvailable {
private static final long FILESIZE = 7405576182L;
public static void main(String args[]) throws Exception {
File file = createLargeFile(FILESIZE);
try (FileInputStream fis = new FileInputStream(file)) {
if (file.length() != FILESIZE) {
throw new RuntimeException("unexpected file size = " + file.length());
}
long bigSkip = 3110608882L;
long remaining = FILESIZE;
remaining -= skipBytes(fis, bigSkip, remaining);
remaining -= skipBytes(fis, 10L, remaining);
remaining -= skipBytes(fis, bigSkip, remaining);
if (fis.available() != (int) remaining) {
throw new RuntimeException("available() returns " +
fis.available() +
" but expected " + remaining);
}
} finally {
file.delete();
}
}
// Skip toSkip number of bytes and expect that the available() method
// returns avail number of bytes.
private static long skipBytes(InputStream is, long toSkip, long avail)
throws IOException {
long skip = is.skip(toSkip);
if (skip != toSkip) {
throw new RuntimeException("skip() returns " + skip +
" but expected " + toSkip);
}
long remaining = avail - skip;
int expected = remaining >= Integer.MAX_VALUE
? Integer.MAX_VALUE
: (int) remaining;
System.out.println("Skipped " + skip + " bytes " +
" available() returns " + expected +
" remaining=" + remaining);
if (is.available() != expected) {
throw new RuntimeException("available() returns " +
is.available() + " but expected " + expected);
}
return skip;
}
private static File createLargeFile(long filesize) throws Exception {
// Create a large file as a sparse file if possible
File largefile = File.createTempFile("largefile", null);
// re-create as a sparse file
largefile.toPath().delete();
try (FileChannel fc =
FileChannel.open(largefile.toPath(),
CREATE_NEW, WRITE, SPARSE)) {
ByteBuffer bb = ByteBuffer.allocate(1).put((byte)1);
bb.rewind();
int rc = fc.write(bb, filesize-1);
if (rc != 1) {
throw new RuntimeException("Failed to write 1 byte to the large file");
}
}
return largefile;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册