Skip to content

Commit 353807c

Browse files
author
Brian Burkhalter
committed
8263898: (fs) Files.newOutputStream on the "NUL" special device throws FileSystemException: "nul: Incorrect function" (win)
Reviewed-by: jpai, alanb
1 parent 2bd80f9 commit 353807c

File tree

4 files changed

+130
-5
lines changed

4 files changed

+130
-5
lines changed

src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -328,8 +328,11 @@ private static FileDescriptor open(String pathForWindows,
328328
try {
329329
SetEndOfFile(handle);
330330
} catch (WindowsException x) {
331-
CloseHandle(handle);
332-
throw x;
331+
// ignore exception if file size is zero
332+
if (GetFileSizeEx(handle) != 0) {
333+
CloseHandle(handle);
334+
throw x;
335+
}
333336
}
334337
}
335338

src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -172,6 +172,16 @@ static native void DeviceIoControlSetSparse(long handle)
172172
static native void DeviceIoControlGetReparsePoint(long handle,
173173
long bufferAddress, int bufferSize) throws WindowsException;
174174

175+
/**
176+
* Retrieves the size of the specified file.
177+
*
178+
* BOOL GetFileSizeEx(
179+
* HANDLE hFile,
180+
* PLARGE_INTEGER lpFileSize
181+
* )
182+
*/
183+
static native long GetFileSizeEx(long handle) throws WindowsException;
184+
175185
/**
176186
* HANDLE FindFirstFile(
177187
* LPCTSTR lpFileName,

src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -309,6 +309,18 @@ Java_sun_nio_fs_WindowsNativeDispatcher_CloseHandle(JNIEnv* env, jclass this,
309309
CloseHandle(h);
310310
}
311311

312+
JNIEXPORT jlong JNICALL
313+
Java_sun_nio_fs_WindowsNativeDispatcher_GetFileSizeEx(JNIEnv *env,
314+
jclass this, jlong handle)
315+
{
316+
HANDLE h = (HANDLE)jlong_to_ptr(handle);
317+
LARGE_INTEGER size;
318+
if (GetFileSizeEx(h, &size) == 0) {
319+
throwWindowsException(env, GetLastError());
320+
}
321+
return long_to_jlong(size.QuadPart);
322+
}
323+
312324
JNIEXPORT void JNICALL
313325
Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile0(JNIEnv* env, jclass this,
314326
jlong address, jobject obj)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.io.IOException;
25+
import java.io.InputStream;
26+
import java.io.OutputStream;
27+
import java.nio.ByteBuffer;
28+
import java.nio.channels.AsynchronousFileChannel;
29+
import java.nio.channels.FileChannel;
30+
import java.nio.file.Files;
31+
import java.nio.file.Path;
32+
import static java.nio.file.StandardOpenOption.*;
33+
import java.util.concurrent.ExecutionException;
34+
35+
/* @test
36+
* @bug 8263898
37+
* @summary Verify stream and channel behavior with NUL device
38+
* @requires os.family == "windows"
39+
* @run main NulDevice
40+
*/
41+
public class NulDevice {
42+
public static void main(String[] args)
43+
throws ExecutionException, InterruptedException, IOException {
44+
Path path = Path.of("nul");
45+
46+
try (OutputStream os = Files.newOutputStream(path)) {
47+
os.write(0x02);
48+
try (InputStream is = Files.newInputStream(path);) {
49+
if (is.available() != 0) {
50+
throw new RuntimeException("No bytes should be available");
51+
}
52+
int aByte = is.read();
53+
if (aByte != -1) {
54+
throw new RuntimeException("Should only read -1 from NUL");
55+
}
56+
}
57+
}
58+
59+
try (OutputStream os = Files.newOutputStream(path, WRITE)) {
60+
os.write(0x02);
61+
}
62+
63+
try (FileChannel ch = FileChannel.open(path, CREATE, TRUNCATE_EXISTING, WRITE)) {
64+
byte[] bytes = "Whatever".getBytes();
65+
ByteBuffer buf = ByteBuffer.allocate(2*bytes.length);
66+
buf.put(bytes);
67+
int nw = ch.write(buf);
68+
if (nw != bytes.length) {
69+
throw new RuntimeException("Should write " + bytes.length +
70+
" to NUL");
71+
}
72+
}
73+
74+
try (FileChannel ch = FileChannel.open(path, READ)) {
75+
if (ch.size() != 0) {
76+
throw new RuntimeException("Size should be zero");
77+
}
78+
ByteBuffer buf = ByteBuffer.allocate(10);
79+
int nr = ch.read(buf);
80+
if (nr != -1) {
81+
throw new RuntimeException("Read returns " + nr + " not -1");
82+
}
83+
}
84+
85+
try (AsynchronousFileChannel ch = AsynchronousFileChannel.open(path, READ, WRITE)) {
86+
if (ch.size() != 0) {
87+
throw new RuntimeException("Size should be zero");
88+
}
89+
int nw = ch.write(ByteBuffer.wrap(new byte[] {(byte)0x02}), 0L).get();
90+
if (nw != 1) {
91+
throw new RuntimeException("Wrote " + nw + " bytes, not one");
92+
}
93+
ByteBuffer buf = ByteBuffer.allocate(10);
94+
int nr = ch.read(buf, 0L).get();
95+
if (nr != -1) {
96+
throw new RuntimeException("Read returns " + nr + " not -1");
97+
}
98+
}
99+
}
100+
}

0 commit comments

Comments
 (0)