mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-23 08:45:33 +00:00
8024695: new File("").exists() returns false whereas it is the current working directory
Reviewed-by: alanb, rriggs, lancea
This commit is contained in:
parent
3e46480dcf
commit
9477c705c0
@ -56,7 +56,8 @@ import jdk.internal.util.StaticProperty;
|
||||
* case of Microsoft Windows UNC pathnames, a hostname. Each subsequent name
|
||||
* in an abstract pathname denotes a directory; the last name may denote
|
||||
* either a directory or a file. The <em>empty</em> abstract pathname has no
|
||||
* prefix and an empty name sequence.
|
||||
* prefix and an empty name sequence. Accessing a file with the empty abstract
|
||||
* pathname is equivalent to accessing the current user directory.
|
||||
*
|
||||
* <p> The conversion of a pathname string to or from an abstract pathname is
|
||||
* inherently system-dependent. When an abstract pathname is converted into a
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2025, 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
|
||||
@ -33,6 +33,22 @@ import java.lang.annotation.Native;
|
||||
|
||||
abstract class FileSystem {
|
||||
|
||||
/* -- Current Working Directory --*/
|
||||
|
||||
/* lazy initialization of CWD object */
|
||||
private static class CurrentWorkingDirectoryHolder {
|
||||
static final File CURRENT_WORKING_DIRECTORY = currentWorkingDirectory();
|
||||
|
||||
private static final File currentWorkingDirectory() {
|
||||
return new File(".");
|
||||
}
|
||||
}
|
||||
|
||||
/* CWD object accessor */
|
||||
static File getCWD() {
|
||||
return CurrentWorkingDirectoryHolder.CURRENT_WORKING_DIRECTORY;
|
||||
}
|
||||
|
||||
/* -- Normalization and construction -- */
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2025, 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
|
||||
@ -29,11 +29,18 @@ import java.util.Properties;
|
||||
import jdk.internal.util.StaticProperty;
|
||||
|
||||
final class UnixFileSystem extends FileSystem {
|
||||
|
||||
private final char slash;
|
||||
private final char colon;
|
||||
private final String userDir;
|
||||
|
||||
private String getPathForSysCalls(String path) {
|
||||
return path.isEmpty() ? getCWD().getPath() : path;
|
||||
}
|
||||
|
||||
private File getFileForSysCalls(File file) {
|
||||
return file.getPath().isEmpty() ? getCWD() : file;
|
||||
}
|
||||
|
||||
UnixFileSystem() {
|
||||
Properties props = System.getProperties();
|
||||
slash = props.getProperty("file.separator").charAt(0);
|
||||
@ -154,7 +161,7 @@ final class UnixFileSystem extends FileSystem {
|
||||
|
||||
@Override
|
||||
public String canonicalize(String path) throws IOException {
|
||||
return canonicalize0(path);
|
||||
return canonicalize0(getPathForSysCalls(path));
|
||||
}
|
||||
private native String canonicalize0(String path) throws IOException;
|
||||
|
||||
@ -164,13 +171,13 @@ final class UnixFileSystem extends FileSystem {
|
||||
|
||||
@Override
|
||||
public int getBooleanAttributes(File f) {
|
||||
int rv = getBooleanAttributes0(f);
|
||||
int rv = getBooleanAttributes0(getFileForSysCalls(f));
|
||||
return rv | isHidden(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBooleanAttributes(File f, int attributes) {
|
||||
int rv = getBooleanAttributes0(f);
|
||||
int rv = getBooleanAttributes0(getFileForSysCalls(f));
|
||||
if ((attributes & BA_HIDDEN) != 0) {
|
||||
rv |= isHidden(f);
|
||||
}
|
||||
@ -183,25 +190,25 @@ final class UnixFileSystem extends FileSystem {
|
||||
|
||||
@Override
|
||||
public boolean checkAccess(File f, int access) {
|
||||
return checkAccess0(f, access);
|
||||
return checkAccess0(getFileForSysCalls(f), access);
|
||||
}
|
||||
private native boolean checkAccess0(File f, int access);
|
||||
|
||||
@Override
|
||||
public long getLastModifiedTime(File f) {
|
||||
return getLastModifiedTime0(f);
|
||||
return getLastModifiedTime0(getFileForSysCalls(f));
|
||||
}
|
||||
private native long getLastModifiedTime0(File f);
|
||||
|
||||
@Override
|
||||
public long getLength(File f) {
|
||||
return getLength0(f);
|
||||
return getLength0(getFileForSysCalls(f));
|
||||
}
|
||||
private native long getLength0(File f);
|
||||
|
||||
@Override
|
||||
public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
|
||||
return setPermission0(f, access, enable, owneronly);
|
||||
return setPermission0(getFileForSysCalls(f), access, enable, owneronly);
|
||||
}
|
||||
private native boolean setPermission0(File f, int access, boolean enable, boolean owneronly);
|
||||
|
||||
@ -215,37 +222,37 @@ final class UnixFileSystem extends FileSystem {
|
||||
|
||||
@Override
|
||||
public boolean delete(File f) {
|
||||
return delete0(f);
|
||||
return delete0(getFileForSysCalls(f));
|
||||
}
|
||||
private native boolean delete0(File f);
|
||||
|
||||
@Override
|
||||
public String[] list(File f) {
|
||||
return list0(f);
|
||||
return list0(getFileForSysCalls(f));
|
||||
}
|
||||
private native String[] list0(File f);
|
||||
|
||||
@Override
|
||||
public boolean createDirectory(File f) {
|
||||
return createDirectory0(f);
|
||||
return createDirectory0(getFileForSysCalls(f));
|
||||
}
|
||||
private native boolean createDirectory0(File f);
|
||||
|
||||
@Override
|
||||
public boolean rename(File f1, File f2) {
|
||||
return rename0(f1, f2);
|
||||
return rename0(getFileForSysCalls(f1), getFileForSysCalls(f2));
|
||||
}
|
||||
private native boolean rename0(File f1, File f2);
|
||||
|
||||
@Override
|
||||
public boolean setLastModifiedTime(File f, long time) {
|
||||
return setLastModifiedTime0(f, time);
|
||||
return setLastModifiedTime0(getFileForSysCalls(f), time);
|
||||
}
|
||||
private native boolean setLastModifiedTime0(File f, long time);
|
||||
|
||||
@Override
|
||||
public boolean setReadOnly(File f) {
|
||||
return setReadOnly0(f);
|
||||
return setReadOnly0(getFileForSysCalls(f));
|
||||
}
|
||||
private native boolean setReadOnly0(File f);
|
||||
|
||||
@ -260,7 +267,7 @@ final class UnixFileSystem extends FileSystem {
|
||||
|
||||
@Override
|
||||
public long getSpace(File f, int t) {
|
||||
return getSpace0(f, t);
|
||||
return getSpace0(getFileForSysCalls(f), t);
|
||||
}
|
||||
private native long getSpace0(File f, int t);
|
||||
|
||||
@ -270,7 +277,7 @@ final class UnixFileSystem extends FileSystem {
|
||||
|
||||
@Override
|
||||
public int getNameMax(String path) {
|
||||
long nameMax = getNameMax0(path);
|
||||
long nameMax = getNameMax0(getPathForSysCalls(path));
|
||||
if (nameMax > Integer.MAX_VALUE) {
|
||||
nameMax = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@ -79,6 +79,14 @@ final class WinNTFileSystem extends FileSystem {
|
||||
return path;
|
||||
}
|
||||
|
||||
private String getPathForWin32Calls(String path) {
|
||||
return (path != null && path.isEmpty()) ? getCWD().getPath() : path;
|
||||
}
|
||||
|
||||
private File getFileForWin32Calls(File file) {
|
||||
return file.getPath().isEmpty() ? getCWD() : file;
|
||||
}
|
||||
|
||||
WinNTFileSystem() {
|
||||
Properties props = System.getProperties();
|
||||
slash = props.getProperty("file.separator").charAt(0);
|
||||
@ -495,31 +503,31 @@ final class WinNTFileSystem extends FileSystem {
|
||||
|
||||
@Override
|
||||
public int getBooleanAttributes(File f) {
|
||||
return getBooleanAttributes0(f);
|
||||
return getBooleanAttributes0(getFileForWin32Calls(f));
|
||||
}
|
||||
private native int getBooleanAttributes0(File f);
|
||||
|
||||
@Override
|
||||
public boolean checkAccess(File f, int access) {
|
||||
return checkAccess0(f, access);
|
||||
return checkAccess0(getFileForWin32Calls(f), access);
|
||||
}
|
||||
private native boolean checkAccess0(File f, int access);
|
||||
|
||||
@Override
|
||||
public long getLastModifiedTime(File f) {
|
||||
return getLastModifiedTime0(f);
|
||||
return getLastModifiedTime0(getFileForWin32Calls(f));
|
||||
}
|
||||
private native long getLastModifiedTime0(File f);
|
||||
|
||||
@Override
|
||||
public long getLength(File f) {
|
||||
return getLength0(f);
|
||||
return getLength0(getFileForWin32Calls(f));
|
||||
}
|
||||
private native long getLength0(File f);
|
||||
|
||||
@Override
|
||||
public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
|
||||
return setPermission0(f, access, enable, owneronly);
|
||||
return setPermission0(getFileForWin32Calls(f), access, enable, owneronly);
|
||||
}
|
||||
private native boolean setPermission0(File f, int access, boolean enable, boolean owneronly);
|
||||
|
||||
@ -533,7 +541,7 @@ final class WinNTFileSystem extends FileSystem {
|
||||
|
||||
@Override
|
||||
public String[] list(File f) {
|
||||
return list0(f);
|
||||
return list0(getFileForWin32Calls(f));
|
||||
}
|
||||
private native String[] list0(File f);
|
||||
|
||||
@ -545,7 +553,7 @@ final class WinNTFileSystem extends FileSystem {
|
||||
|
||||
@Override
|
||||
public boolean setLastModifiedTime(File f, long time) {
|
||||
return setLastModifiedTime0(f, time);
|
||||
return setLastModifiedTime0(getFileForWin32Calls(f), time);
|
||||
}
|
||||
private native boolean setLastModifiedTime0(File f, long time);
|
||||
|
||||
@ -591,7 +599,7 @@ final class WinNTFileSystem extends FileSystem {
|
||||
// that free space <= total space
|
||||
if (t == SPACE_FREE)
|
||||
t = SPACE_USABLE;
|
||||
return getSpace0(f, t);
|
||||
return getSpace0(getFileForWin32Calls(f), t);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -618,7 +626,7 @@ final class WinNTFileSystem extends FileSystem {
|
||||
}
|
||||
}
|
||||
}
|
||||
return getNameMax0(s);
|
||||
return getNameMax0(getPathForWin32Calls(s));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2025, 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
|
||||
@ -22,28 +22,257 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@bug 4842706
|
||||
@summary Test some file operations with empty path
|
||||
* @bug 4842706 8024695
|
||||
* @summary Test some file operations with empty path
|
||||
* @run junit EmptyPath
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.FileStore;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.junit.jupiter.api.condition.DisabledOnOs;
|
||||
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||
import org.junit.jupiter.api.condition.OS;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class EmptyPath {
|
||||
public static void main(String [] args) throws Exception {
|
||||
File f = new File("");
|
||||
f.mkdir();
|
||||
try {
|
||||
f.createNewFile();
|
||||
throw new RuntimeException("Expected exception not thrown");
|
||||
} catch (IOException ioe) {
|
||||
// Correct result
|
||||
}
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(f);
|
||||
fis.close();
|
||||
throw new RuntimeException("Expected exception not thrown");
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Correct result
|
||||
private static final String EMPTY_STRING = "";
|
||||
|
||||
static File f;
|
||||
static Path p;
|
||||
|
||||
@BeforeAll
|
||||
public static void init() {
|
||||
f = new File(EMPTY_STRING);
|
||||
p = Path.of(EMPTY_STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canExecute() {
|
||||
assertTrue(f.canExecute());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canRead() {
|
||||
assertTrue(f.canRead());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canWrite() {
|
||||
assertTrue(f.canWrite());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo() {
|
||||
assertEquals(0, f.compareTo(p.toFile()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewFile() {
|
||||
assertThrows(IOException.class, () -> f.createNewFile());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void open() throws FileNotFoundException {
|
||||
assertThrows(FileNotFoundException.class,
|
||||
() -> new FileInputStream(f));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete() {
|
||||
assertFalse(f.delete());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals() {
|
||||
assertTrue(f.equals(p.toFile()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exists() {
|
||||
assertTrue(f.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAbsolutePath() {
|
||||
System.out.println(p.toAbsolutePath().toString() + "\n" +
|
||||
f.getAbsolutePath());
|
||||
assertEquals(p.toAbsolutePath().toString(), f.getAbsolutePath());
|
||||
}
|
||||
|
||||
private void checkSpace(long expected, long actual) {
|
||||
if (expected == 0) {
|
||||
assertEquals(0L, actual);
|
||||
} else {
|
||||
assertTrue(actual > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFreeSpace() throws IOException {
|
||||
FileStore fs = Files.getFileStore(f.toPath());
|
||||
checkSpace(fs.getUnallocatedSpace(), f.getFreeSpace());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getName() {
|
||||
assertEquals(p.getFileName().toString(), f.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getParent() {
|
||||
assertNull(f.getParent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPath() {
|
||||
assertEquals(p.toString(), f.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTotalSpace() throws IOException {
|
||||
FileStore fs = Files.getFileStore(f.toPath());
|
||||
checkSpace(fs.getTotalSpace(), f.getTotalSpace());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUsableSpace() throws IOException {
|
||||
FileStore fs = Files.getFileStore(f.toPath());
|
||||
checkSpace(fs.getUsableSpace(), f.getUsableSpace());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotAbsolute() {
|
||||
assertFalse(f.isAbsolute());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAbsolute() {
|
||||
assertTrue(f.getAbsoluteFile().isAbsolute());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isDirectory() {
|
||||
assertTrue(f.isDirectory());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isFile() {
|
||||
assertFalse(f.isFile());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isHidden() {
|
||||
assertFalse(f.isHidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lastModified() {
|
||||
assertTrue(f.lastModified() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void length() throws IOException {
|
||||
assertEquals(Files.size(f.toPath()), f.length());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void list() throws IOException {
|
||||
String[] files = f.list();
|
||||
assertNotNull(files);
|
||||
Set<String> ioSet = new HashSet(Arrays.asList(files));
|
||||
Set<String> nioSet = new HashSet();
|
||||
Files.list(p).forEach((x) -> nioSet.add(x.toString()));
|
||||
assertEquals(nioSet, ioSet);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mkdir() {
|
||||
assertFalse(f.mkdir());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLastModified() {
|
||||
long t0 = f.lastModified();
|
||||
long t = System.currentTimeMillis();
|
||||
try {
|
||||
assertTrue(f.setLastModified(t));
|
||||
assertEquals(t, f.lastModified());
|
||||
assertTrue(f.setLastModified(t0));
|
||||
assertEquals(t0, f.lastModified());
|
||||
} finally {
|
||||
f.setLastModified(t0);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Testing File.setExecutable is omitted because calling
|
||||
// File.setExecutable(false) makes it impossible to set the CWD to
|
||||
// executable again which makes subsequent tests fail
|
||||
|
||||
@Test
|
||||
@DisabledOnOs({OS.WINDOWS})
|
||||
public void setReadable() {
|
||||
assertTrue(f.canRead());
|
||||
try {
|
||||
assertTrue(f.setReadable(false));
|
||||
assertFalse(f.canRead());
|
||||
assertTrue(f.setReadable(true));
|
||||
assertTrue(f.canRead());
|
||||
} finally {
|
||||
f.setReadable(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnOs({OS.WINDOWS})
|
||||
public void setReadOnly() {
|
||||
assertTrue(f.canExecute());
|
||||
assertTrue(f.canRead());
|
||||
assertTrue(f.canWrite());
|
||||
try {
|
||||
assertTrue(f.setReadOnly());
|
||||
assertTrue(f.canRead());
|
||||
assertFalse(f.canWrite());
|
||||
assertTrue(f.setWritable(true, true));
|
||||
assertTrue(f.canWrite());
|
||||
} finally {
|
||||
f.setWritable(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnOs({OS.WINDOWS})
|
||||
public void setWritable() {
|
||||
assertTrue(f.canWrite());
|
||||
try {
|
||||
assertTrue(f.setWritable(false, true));
|
||||
assertFalse(f.canWrite());
|
||||
assertTrue(f.setWritable(true, true));
|
||||
assertTrue(f.canWrite());
|
||||
} finally {
|
||||
f.setWritable(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toPath() {
|
||||
assertEquals(p, f.toPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toURI() {
|
||||
assertEquals(f.toPath().toUri(), f.toURI());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user