Skip to content

Commit 5a00b9d

Browse files
author
duke
committedFeb 26, 2025
Automatic merge of jdk:master into master
2 parents 06d4067 + 9477c70 commit 5a00b9d

File tree

5 files changed

+305
-44
lines changed

5 files changed

+305
-44
lines changed
 

‎src/java.base/share/classes/java/io/File.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
* case of Microsoft Windows UNC pathnames, a hostname. Each subsequent name
5757
* in an abstract pathname denotes a directory; the last name may denote
5858
* either a directory or a file. The <em>empty</em> abstract pathname has no
59-
* prefix and an empty name sequence.
59+
* prefix and an empty name sequence. Accessing a file with the empty abstract
60+
* pathname is equivalent to accessing the current user directory.
6061
*
6162
* <p> The conversion of a pathname string to or from an abstract pathname is
6263
* inherently system-dependent. When an abstract pathname is converted into a

‎src/java.base/share/classes/java/io/FileSystem.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2025, 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
@@ -33,6 +33,22 @@
3333

3434
abstract class FileSystem {
3535

36+
/* -- Current Working Directory --*/
37+
38+
/* lazy initialization of CWD object */
39+
private static class CurrentWorkingDirectoryHolder {
40+
static final File CURRENT_WORKING_DIRECTORY = currentWorkingDirectory();
41+
42+
private static final File currentWorkingDirectory() {
43+
return new File(".");
44+
}
45+
}
46+
47+
/* CWD object accessor */
48+
static File getCWD() {
49+
return CurrentWorkingDirectoryHolder.CURRENT_WORKING_DIRECTORY;
50+
}
51+
3652
/* -- Normalization and construction -- */
3753

3854
/**

‎src/java.base/unix/classes/java/io/UnixFileSystem.java

+24-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2025, 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
@@ -29,11 +29,18 @@
2929
import jdk.internal.util.StaticProperty;
3030

3131
final class UnixFileSystem extends FileSystem {
32-
3332
private final char slash;
3433
private final char colon;
3534
private final String userDir;
3635

36+
private String getPathForSysCalls(String path) {
37+
return path.isEmpty() ? getCWD().getPath() : path;
38+
}
39+
40+
private File getFileForSysCalls(File file) {
41+
return file.getPath().isEmpty() ? getCWD() : file;
42+
}
43+
3744
UnixFileSystem() {
3845
Properties props = System.getProperties();
3946
slash = props.getProperty("file.separator").charAt(0);
@@ -154,7 +161,7 @@ public String resolve(File f) {
154161

155162
@Override
156163
public String canonicalize(String path) throws IOException {
157-
return canonicalize0(path);
164+
return canonicalize0(getPathForSysCalls(path));
158165
}
159166
private native String canonicalize0(String path) throws IOException;
160167

@@ -164,13 +171,13 @@ public String canonicalize(String path) throws IOException {
164171

165172
@Override
166173
public int getBooleanAttributes(File f) {
167-
int rv = getBooleanAttributes0(f);
174+
int rv = getBooleanAttributes0(getFileForSysCalls(f));
168175
return rv | isHidden(f);
169176
}
170177

171178
@Override
172179
public boolean hasBooleanAttributes(File f, int attributes) {
173-
int rv = getBooleanAttributes0(f);
180+
int rv = getBooleanAttributes0(getFileForSysCalls(f));
174181
if ((attributes & BA_HIDDEN) != 0) {
175182
rv |= isHidden(f);
176183
}
@@ -183,25 +190,25 @@ private static int isHidden(File f) {
183190

184191
@Override
185192
public boolean checkAccess(File f, int access) {
186-
return checkAccess0(f, access);
193+
return checkAccess0(getFileForSysCalls(f), access);
187194
}
188195
private native boolean checkAccess0(File f, int access);
189196

190197
@Override
191198
public long getLastModifiedTime(File f) {
192-
return getLastModifiedTime0(f);
199+
return getLastModifiedTime0(getFileForSysCalls(f));
193200
}
194201
private native long getLastModifiedTime0(File f);
195202

196203
@Override
197204
public long getLength(File f) {
198-
return getLength0(f);
205+
return getLength0(getFileForSysCalls(f));
199206
}
200207
private native long getLength0(File f);
201208

202209
@Override
203210
public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
204-
return setPermission0(f, access, enable, owneronly);
211+
return setPermission0(getFileForSysCalls(f), access, enable, owneronly);
205212
}
206213
private native boolean setPermission0(File f, int access, boolean enable, boolean owneronly);
207214

@@ -215,37 +222,37 @@ public boolean createFileExclusively(String path) throws IOException {
215222

216223
@Override
217224
public boolean delete(File f) {
218-
return delete0(f);
225+
return delete0(getFileForSysCalls(f));
219226
}
220227
private native boolean delete0(File f);
221228

222229
@Override
223230
public String[] list(File f) {
224-
return list0(f);
231+
return list0(getFileForSysCalls(f));
225232
}
226233
private native String[] list0(File f);
227234

228235
@Override
229236
public boolean createDirectory(File f) {
230-
return createDirectory0(f);
237+
return createDirectory0(getFileForSysCalls(f));
231238
}
232239
private native boolean createDirectory0(File f);
233240

234241
@Override
235242
public boolean rename(File f1, File f2) {
236-
return rename0(f1, f2);
243+
return rename0(getFileForSysCalls(f1), getFileForSysCalls(f2));
237244
}
238245
private native boolean rename0(File f1, File f2);
239246

240247
@Override
241248
public boolean setLastModifiedTime(File f, long time) {
242-
return setLastModifiedTime0(f, time);
249+
return setLastModifiedTime0(getFileForSysCalls(f), time);
243250
}
244251
private native boolean setLastModifiedTime0(File f, long time);
245252

246253
@Override
247254
public boolean setReadOnly(File f) {
248-
return setReadOnly0(f);
255+
return setReadOnly0(getFileForSysCalls(f));
249256
}
250257
private native boolean setReadOnly0(File f);
251258

@@ -260,7 +267,7 @@ public File[] listRoots() {
260267

261268
@Override
262269
public long getSpace(File f, int t) {
263-
return getSpace0(f, t);
270+
return getSpace0(getFileForSysCalls(f), t);
264271
}
265272
private native long getSpace0(File f, int t);
266273

@@ -270,7 +277,7 @@ public long getSpace(File f, int t) {
270277

271278
@Override
272279
public int getNameMax(String path) {
273-
long nameMax = getNameMax0(path);
280+
long nameMax = getNameMax0(getPathForSysCalls(path));
274281
if (nameMax > Integer.MAX_VALUE) {
275282
nameMax = Integer.MAX_VALUE;
276283
}

‎src/java.base/windows/classes/java/io/WinNTFileSystem.java

+17-9
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ private static String stripLongOrUNCPrefix(String path) {
7979
return path;
8080
}
8181

82+
private String getPathForWin32Calls(String path) {
83+
return (path != null && path.isEmpty()) ? getCWD().getPath() : path;
84+
}
85+
86+
private File getFileForWin32Calls(File file) {
87+
return file.getPath().isEmpty() ? getCWD() : file;
88+
}
89+
8290
WinNTFileSystem() {
8391
Properties props = System.getProperties();
8492
slash = props.getProperty("file.separator").charAt(0);
@@ -495,31 +503,31 @@ private native String getFinalPath0(String path)
495503

496504
@Override
497505
public int getBooleanAttributes(File f) {
498-
return getBooleanAttributes0(f);
506+
return getBooleanAttributes0(getFileForWin32Calls(f));
499507
}
500508
private native int getBooleanAttributes0(File f);
501509

502510
@Override
503511
public boolean checkAccess(File f, int access) {
504-
return checkAccess0(f, access);
512+
return checkAccess0(getFileForWin32Calls(f), access);
505513
}
506514
private native boolean checkAccess0(File f, int access);
507515

508516
@Override
509517
public long getLastModifiedTime(File f) {
510-
return getLastModifiedTime0(f);
518+
return getLastModifiedTime0(getFileForWin32Calls(f));
511519
}
512520
private native long getLastModifiedTime0(File f);
513521

514522
@Override
515523
public long getLength(File f) {
516-
return getLength0(f);
524+
return getLength0(getFileForWin32Calls(f));
517525
}
518526
private native long getLength0(File f);
519527

520528
@Override
521529
public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
522-
return setPermission0(f, access, enable, owneronly);
530+
return setPermission0(getFileForWin32Calls(f), access, enable, owneronly);
523531
}
524532
private native boolean setPermission0(File f, int access, boolean enable, boolean owneronly);
525533

@@ -533,7 +541,7 @@ public boolean createFileExclusively(String path) throws IOException {
533541

534542
@Override
535543
public String[] list(File f) {
536-
return list0(f);
544+
return list0(getFileForWin32Calls(f));
537545
}
538546
private native String[] list0(File f);
539547

@@ -545,7 +553,7 @@ public boolean createDirectory(File f) {
545553

546554
@Override
547555
public boolean setLastModifiedTime(File f, long time) {
548-
return setLastModifiedTime0(f, time);
556+
return setLastModifiedTime0(getFileForWin32Calls(f), time);
549557
}
550558
private native boolean setLastModifiedTime0(File f, long time);
551559

@@ -591,7 +599,7 @@ public long getSpace(File f, int t) {
591599
// that free space <= total space
592600
if (t == SPACE_FREE)
593601
t = SPACE_USABLE;
594-
return getSpace0(f, t);
602+
return getSpace0(getFileForWin32Calls(f), t);
595603
}
596604
return 0;
597605
}
@@ -618,7 +626,7 @@ public int getNameMax(String path) {
618626
}
619627
}
620628
}
621-
return getNameMax0(s);
629+
return getNameMax0(getPathForWin32Calls(s));
622630
}
623631

624632
@Override

‎test/jdk/java/io/File/EmptyPath.java

+245-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2025, 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
@@ -22,28 +22,257 @@
2222
*/
2323

2424
/* @test
25-
@bug 4842706
26-
@summary Test some file operations with empty path
25+
* @bug 4842706 8024695
26+
* @summary Test some file operations with empty path
27+
* @run junit EmptyPath
2728
*/
2829

29-
import java.io.*;
30+
import java.io.File;
31+
import java.io.FileInputStream;
32+
import java.io.FileNotFoundException;
33+
import java.io.IOException;
34+
import java.nio.file.Files;
35+
import java.nio.file.FileStore;
36+
import java.nio.file.Path;
37+
import java.util.Arrays;
38+
import java.util.HashSet;
39+
import java.util.Set;
40+
41+
import org.junit.jupiter.api.BeforeAll;
42+
import org.junit.jupiter.api.Test;
43+
44+
import org.junit.jupiter.api.condition.DisabledOnOs;
45+
import org.junit.jupiter.api.condition.EnabledOnOs;
46+
import org.junit.jupiter.api.condition.OS;
47+
48+
import static org.junit.jupiter.api.Assertions.*;
3049

3150
public class EmptyPath {
32-
public static void main(String [] args) throws Exception {
33-
File f = new File("");
34-
f.mkdir();
51+
private static final String EMPTY_STRING = "";
52+
53+
static File f;
54+
static Path p;
55+
56+
@BeforeAll
57+
public static void init() {
58+
f = new File(EMPTY_STRING);
59+
p = Path.of(EMPTY_STRING);
60+
}
61+
62+
@Test
63+
public void canExecute() {
64+
assertTrue(f.canExecute());
65+
}
66+
67+
@Test
68+
public void canRead() {
69+
assertTrue(f.canRead());
70+
}
71+
72+
@Test
73+
public void canWrite() {
74+
assertTrue(f.canWrite());
75+
}
76+
77+
@Test
78+
public void compareTo() {
79+
assertEquals(0, f.compareTo(p.toFile()));
80+
}
81+
82+
@Test
83+
public void createNewFile() {
84+
assertThrows(IOException.class, () -> f.createNewFile());
85+
}
86+
87+
@Test
88+
public void open() throws FileNotFoundException {
89+
assertThrows(FileNotFoundException.class,
90+
() -> new FileInputStream(f));
91+
}
92+
93+
@Test
94+
public void delete() {
95+
assertFalse(f.delete());
96+
}
97+
98+
@Test
99+
public void equals() {
100+
assertTrue(f.equals(p.toFile()));
101+
}
102+
103+
@Test
104+
public void exists() {
105+
assertTrue(f.exists());
106+
}
107+
108+
@Test
109+
public void getAbsolutePath() {
110+
System.out.println(p.toAbsolutePath().toString() + "\n" +
111+
f.getAbsolutePath());
112+
assertEquals(p.toAbsolutePath().toString(), f.getAbsolutePath());
113+
}
114+
115+
private void checkSpace(long expected, long actual) {
116+
if (expected == 0) {
117+
assertEquals(0L, actual);
118+
} else {
119+
assertTrue(actual > 0);
120+
}
121+
}
122+
123+
@Test
124+
public void getFreeSpace() throws IOException {
125+
FileStore fs = Files.getFileStore(f.toPath());
126+
checkSpace(fs.getUnallocatedSpace(), f.getFreeSpace());
127+
}
128+
129+
@Test
130+
public void getName() {
131+
assertEquals(p.getFileName().toString(), f.getName());
132+
}
133+
134+
@Test
135+
public void getParent() {
136+
assertNull(f.getParent());
137+
}
138+
139+
@Test
140+
public void getPath() {
141+
assertEquals(p.toString(), f.getPath());
142+
}
143+
144+
@Test
145+
public void getTotalSpace() throws IOException {
146+
FileStore fs = Files.getFileStore(f.toPath());
147+
checkSpace(fs.getTotalSpace(), f.getTotalSpace());
148+
}
149+
150+
@Test
151+
public void getUsableSpace() throws IOException {
152+
FileStore fs = Files.getFileStore(f.toPath());
153+
checkSpace(fs.getUsableSpace(), f.getUsableSpace());
154+
}
155+
156+
@Test
157+
public void isNotAbsolute() {
158+
assertFalse(f.isAbsolute());
159+
}
160+
161+
@Test
162+
public void isAbsolute() {
163+
assertTrue(f.getAbsoluteFile().isAbsolute());
164+
}
165+
166+
@Test
167+
public void isDirectory() {
168+
assertTrue(f.isDirectory());
169+
}
170+
171+
@Test
172+
public void isFile() {
173+
assertFalse(f.isFile());
174+
}
175+
176+
@Test
177+
public void isHidden() {
178+
assertFalse(f.isHidden());
179+
}
180+
181+
@Test
182+
public void lastModified() {
183+
assertTrue(f.lastModified() > 0);
184+
}
185+
186+
@Test
187+
public void length() throws IOException {
188+
assertEquals(Files.size(f.toPath()), f.length());
189+
}
190+
191+
@Test
192+
public void list() throws IOException {
193+
String[] files = f.list();
194+
assertNotNull(files);
195+
Set<String> ioSet = new HashSet(Arrays.asList(files));
196+
Set<String> nioSet = new HashSet();
197+
Files.list(p).forEach((x) -> nioSet.add(x.toString()));
198+
assertEquals(nioSet, ioSet);
199+
}
200+
201+
@Test
202+
public void mkdir() {
203+
assertFalse(f.mkdir());
204+
}
205+
206+
@Test
207+
public void setLastModified() {
208+
long t0 = f.lastModified();
209+
long t = System.currentTimeMillis();
210+
try {
211+
assertTrue(f.setLastModified(t));
212+
assertEquals(t, f.lastModified());
213+
assertTrue(f.setLastModified(t0));
214+
assertEquals(t0, f.lastModified());
215+
} finally {
216+
f.setLastModified(t0);
217+
}
218+
}
219+
220+
// Note: Testing File.setExecutable is omitted because calling
221+
// File.setExecutable(false) makes it impossible to set the CWD to
222+
// executable again which makes subsequent tests fail
223+
224+
@Test
225+
@DisabledOnOs({OS.WINDOWS})
226+
public void setReadable() {
227+
assertTrue(f.canRead());
228+
try {
229+
assertTrue(f.setReadable(false));
230+
assertFalse(f.canRead());
231+
assertTrue(f.setReadable(true));
232+
assertTrue(f.canRead());
233+
} finally {
234+
f.setReadable(true);
235+
}
236+
}
237+
238+
@Test
239+
@DisabledOnOs({OS.WINDOWS})
240+
public void setReadOnly() {
241+
assertTrue(f.canExecute());
242+
assertTrue(f.canRead());
243+
assertTrue(f.canWrite());
35244
try {
36-
f.createNewFile();
37-
throw new RuntimeException("Expected exception not thrown");
38-
} catch (IOException ioe) {
39-
// Correct result
245+
assertTrue(f.setReadOnly());
246+
assertTrue(f.canRead());
247+
assertFalse(f.canWrite());
248+
assertTrue(f.setWritable(true, true));
249+
assertTrue(f.canWrite());
250+
} finally {
251+
f.setWritable(true, true);
40252
}
253+
}
254+
255+
@Test
256+
@DisabledOnOs({OS.WINDOWS})
257+
public void setWritable() {
258+
assertTrue(f.canWrite());
41259
try {
42-
FileInputStream fis = new FileInputStream(f);
43-
fis.close();
44-
throw new RuntimeException("Expected exception not thrown");
45-
} catch (FileNotFoundException fnfe) {
46-
// Correct result
260+
assertTrue(f.setWritable(false, true));
261+
assertFalse(f.canWrite());
262+
assertTrue(f.setWritable(true, true));
263+
assertTrue(f.canWrite());
264+
} finally {
265+
f.setWritable(true, true);
47266
}
48267
}
268+
269+
@Test
270+
public void toPath() {
271+
assertEquals(p, f.toPath());
272+
}
273+
274+
@Test
275+
public void toURI() {
276+
assertEquals(f.toPath().toUri(), f.toURI());
277+
}
49278
}

0 commit comments

Comments
 (0)
Please sign in to comment.