mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-25 21:07:57 +00:00
7186817: Remove Windows 95/98/ME Support
Reviewed-by: alanb
This commit is contained in:
parent
a446a98f53
commit
6e283062c6
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1997, 2012, 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
|
||||
@ -64,13 +64,11 @@ include FILES_java.gmk
|
||||
include Exportedfiles.gmk
|
||||
|
||||
ifeq ($(PLATFORM),windows)
|
||||
FILES_java += java/io/Win32FileSystem.java \
|
||||
java/io/WinNTFileSystem.java \
|
||||
FILES_java += java/io/WinNTFileSystem.java \
|
||||
java/util/prefs/WindowsPreferences.java \
|
||||
java/util/prefs/WindowsPreferencesFactory.java
|
||||
|
||||
FILES_c += ProcessImpl_md.c \
|
||||
Win32FileSystem_md.c \
|
||||
WinNTFileSystem_md.c \
|
||||
canonicalize_md.c \
|
||||
dirent_md.c \
|
||||
|
||||
@ -209,7 +209,6 @@ ifeq ($(OPENJDK_TARGET_OS),windows)
|
||||
else
|
||||
LIBJAVA_EXCLUDE_FILES += \
|
||||
ProcessImpl_md.c \
|
||||
Win32FileSystem_md.c \
|
||||
WinNTFileSystem_md.c \
|
||||
dirent_md.c \
|
||||
WindowsPreferences.c \
|
||||
|
||||
@ -1,608 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.io;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.util.Locale;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
|
||||
class Win32FileSystem extends FileSystem {
|
||||
|
||||
private final char slash;
|
||||
private final char altSlash;
|
||||
private final char semicolon;
|
||||
|
||||
public Win32FileSystem() {
|
||||
slash = AccessController.doPrivileged(
|
||||
new GetPropertyAction("file.separator")).charAt(0);
|
||||
semicolon = AccessController.doPrivileged(
|
||||
new GetPropertyAction("path.separator")).charAt(0);
|
||||
altSlash = (this.slash == '\\') ? '/' : '\\';
|
||||
}
|
||||
|
||||
private boolean isSlash(char c) {
|
||||
return (c == '\\') || (c == '/');
|
||||
}
|
||||
|
||||
private boolean isLetter(char c) {
|
||||
return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
|
||||
}
|
||||
|
||||
private String slashify(String p) {
|
||||
if ((p.length() > 0) && (p.charAt(0) != slash)) return slash + p;
|
||||
else return p;
|
||||
}
|
||||
|
||||
|
||||
/* -- Normalization and construction -- */
|
||||
|
||||
public char getSeparator() {
|
||||
return slash;
|
||||
}
|
||||
|
||||
public char getPathSeparator() {
|
||||
return semicolon;
|
||||
}
|
||||
|
||||
/* A normal Win32 pathname contains no duplicate slashes, except possibly
|
||||
for a UNC prefix, and does not end with a slash. It may be the empty
|
||||
string. Normalized Win32 pathnames have the convenient property that
|
||||
the length of the prefix almost uniquely identifies the type of the path
|
||||
and whether it is absolute or relative:
|
||||
|
||||
0 relative to both drive and directory
|
||||
1 drive-relative (begins with '\\')
|
||||
2 absolute UNC (if first char is '\\'),
|
||||
else directory-relative (has form "z:foo")
|
||||
3 absolute local pathname (begins with "z:\\")
|
||||
*/
|
||||
|
||||
private int normalizePrefix(String path, int len, StringBuffer sb) {
|
||||
int src = 0;
|
||||
while ((src < len) && isSlash(path.charAt(src))) src++;
|
||||
char c;
|
||||
if ((len - src >= 2)
|
||||
&& isLetter(c = path.charAt(src))
|
||||
&& path.charAt(src + 1) == ':') {
|
||||
/* Remove leading slashes if followed by drive specifier.
|
||||
This hack is necessary to support file URLs containing drive
|
||||
specifiers (e.g., "file://c:/path"). As a side effect,
|
||||
"/c:/path" can be used as an alternative to "c:/path". */
|
||||
sb.append(c);
|
||||
sb.append(':');
|
||||
src += 2;
|
||||
} else {
|
||||
src = 0;
|
||||
if ((len >= 2)
|
||||
&& isSlash(path.charAt(0))
|
||||
&& isSlash(path.charAt(1))) {
|
||||
/* UNC pathname: Retain first slash; leave src pointed at
|
||||
second slash so that further slashes will be collapsed
|
||||
into the second slash. The result will be a pathname
|
||||
beginning with "\\\\" followed (most likely) by a host
|
||||
name. */
|
||||
src = 1;
|
||||
sb.append(slash);
|
||||
}
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
/* Normalize the given pathname, whose length is len, starting at the given
|
||||
offset; everything before this offset is already normal. */
|
||||
private String normalize(String path, int len, int off) {
|
||||
if (len == 0) return path;
|
||||
if (off < 3) off = 0; /* Avoid fencepost cases with UNC pathnames */
|
||||
int src;
|
||||
char slash = this.slash;
|
||||
StringBuffer sb = new StringBuffer(len);
|
||||
|
||||
if (off == 0) {
|
||||
/* Complete normalization, including prefix */
|
||||
src = normalizePrefix(path, len, sb);
|
||||
} else {
|
||||
/* Partial normalization */
|
||||
src = off;
|
||||
sb.append(path.substring(0, off));
|
||||
}
|
||||
|
||||
/* Remove redundant slashes from the remainder of the path, forcing all
|
||||
slashes into the preferred slash */
|
||||
while (src < len) {
|
||||
char c = path.charAt(src++);
|
||||
if (isSlash(c)) {
|
||||
while ((src < len) && isSlash(path.charAt(src))) src++;
|
||||
if (src == len) {
|
||||
/* Check for trailing separator */
|
||||
int sn = sb.length();
|
||||
if ((sn == 2) && (sb.charAt(1) == ':')) {
|
||||
/* "z:\\" */
|
||||
sb.append(slash);
|
||||
break;
|
||||
}
|
||||
if (sn == 0) {
|
||||
/* "\\" */
|
||||
sb.append(slash);
|
||||
break;
|
||||
}
|
||||
if ((sn == 1) && (isSlash(sb.charAt(0)))) {
|
||||
/* "\\\\" is not collapsed to "\\" because "\\\\" marks
|
||||
the beginning of a UNC pathname. Even though it is
|
||||
not, by itself, a valid UNC pathname, we leave it as
|
||||
is in order to be consistent with the win32 APIs,
|
||||
which treat this case as an invalid UNC pathname
|
||||
rather than as an alias for the root directory of
|
||||
the current drive. */
|
||||
sb.append(slash);
|
||||
break;
|
||||
}
|
||||
/* Path does not denote a root directory, so do not append
|
||||
trailing slash */
|
||||
break;
|
||||
} else {
|
||||
sb.append(slash);
|
||||
}
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
String rv = sb.toString();
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Check that the given pathname is normal. If not, invoke the real
|
||||
normalizer on the part of the pathname that requires normalization.
|
||||
This way we iterate through the whole pathname string only once. */
|
||||
public String normalize(String path) {
|
||||
int n = path.length();
|
||||
char slash = this.slash;
|
||||
char altSlash = this.altSlash;
|
||||
char prev = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
char c = path.charAt(i);
|
||||
if (c == altSlash)
|
||||
return normalize(path, n, (prev == slash) ? i - 1 : i);
|
||||
if ((c == slash) && (prev == slash) && (i > 1))
|
||||
return normalize(path, n, i - 1);
|
||||
if ((c == ':') && (i > 1))
|
||||
return normalize(path, n, 0);
|
||||
prev = c;
|
||||
}
|
||||
if (prev == slash) return normalize(path, n, n - 1);
|
||||
return path;
|
||||
}
|
||||
|
||||
public int prefixLength(String path) {
|
||||
char slash = this.slash;
|
||||
int n = path.length();
|
||||
if (n == 0) return 0;
|
||||
char c0 = path.charAt(0);
|
||||
char c1 = (n > 1) ? path.charAt(1) : 0;
|
||||
if (c0 == slash) {
|
||||
if (c1 == slash) return 2; /* Absolute UNC pathname "\\\\foo" */
|
||||
return 1; /* Drive-relative "\\foo" */
|
||||
}
|
||||
if (isLetter(c0) && (c1 == ':')) {
|
||||
if ((n > 2) && (path.charAt(2) == slash))
|
||||
return 3; /* Absolute local pathname "z:\\foo" */
|
||||
return 2; /* Directory-relative "z:foo" */
|
||||
}
|
||||
return 0; /* Completely relative */
|
||||
}
|
||||
|
||||
public String resolve(String parent, String child) {
|
||||
int pn = parent.length();
|
||||
if (pn == 0) return child;
|
||||
int cn = child.length();
|
||||
if (cn == 0) return parent;
|
||||
|
||||
String c = child;
|
||||
int childStart = 0;
|
||||
int parentEnd = pn;
|
||||
|
||||
if ((cn > 1) && (c.charAt(0) == slash)) {
|
||||
if (c.charAt(1) == slash) {
|
||||
/* Drop prefix when child is a UNC pathname */
|
||||
childStart = 2;
|
||||
} else {
|
||||
/* Drop prefix when child is drive-relative */
|
||||
childStart = 1;
|
||||
|
||||
}
|
||||
if (cn == childStart) { // Child is double slash
|
||||
if (parent.charAt(pn - 1) == slash)
|
||||
return parent.substring(0, pn - 1);
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent.charAt(pn - 1) == slash)
|
||||
parentEnd--;
|
||||
|
||||
int strlen = parentEnd + cn - childStart;
|
||||
char[] theChars = null;
|
||||
if (child.charAt(childStart) == slash) {
|
||||
theChars = new char[strlen];
|
||||
parent.getChars(0, parentEnd, theChars, 0);
|
||||
child.getChars(childStart, cn, theChars, parentEnd);
|
||||
} else {
|
||||
theChars = new char[strlen + 1];
|
||||
parent.getChars(0, parentEnd, theChars, 0);
|
||||
theChars[parentEnd] = slash;
|
||||
child.getChars(childStart, cn, theChars, parentEnd + 1);
|
||||
}
|
||||
return new String(theChars);
|
||||
}
|
||||
|
||||
public String getDefaultParent() {
|
||||
return ("" + slash);
|
||||
}
|
||||
|
||||
public String fromURIPath(String path) {
|
||||
String p = path;
|
||||
if ((p.length() > 2) && (p.charAt(2) == ':')) {
|
||||
// "/c:/foo" --> "c:/foo"
|
||||
p = p.substring(1);
|
||||
// "c:/foo/" --> "c:/foo", but "c:/" --> "c:/"
|
||||
if ((p.length() > 3) && p.endsWith("/"))
|
||||
p = p.substring(0, p.length() - 1);
|
||||
} else if ((p.length() > 1) && p.endsWith("/")) {
|
||||
// "/foo/" --> "/foo"
|
||||
p = p.substring(0, p.length() - 1);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- Path operations -- */
|
||||
|
||||
public boolean isAbsolute(File f) {
|
||||
int pl = f.getPrefixLength();
|
||||
return (((pl == 2) && (f.getPath().charAt(0) == slash))
|
||||
|| (pl == 3));
|
||||
}
|
||||
|
||||
protected native String getDriveDirectory(int drive);
|
||||
|
||||
private static String[] driveDirCache = new String[26];
|
||||
|
||||
private static int driveIndex(char d) {
|
||||
if ((d >= 'a') && (d <= 'z')) return d - 'a';
|
||||
if ((d >= 'A') && (d <= 'Z')) return d - 'A';
|
||||
return -1;
|
||||
}
|
||||
|
||||
private String getDriveDirectory(char drive) {
|
||||
int i = driveIndex(drive);
|
||||
if (i < 0) return null;
|
||||
String s = driveDirCache[i];
|
||||
if (s != null) return s;
|
||||
s = getDriveDirectory(i + 1);
|
||||
driveDirCache[i] = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
private String getUserPath() {
|
||||
/* For both compatibility and security,
|
||||
we must look this up every time */
|
||||
return normalize(System.getProperty("user.dir"));
|
||||
}
|
||||
|
||||
private String getDrive(String path) {
|
||||
int pl = prefixLength(path);
|
||||
return (pl == 3) ? path.substring(0, 2) : null;
|
||||
}
|
||||
|
||||
public String resolve(File f) {
|
||||
String path = f.getPath();
|
||||
int pl = f.getPrefixLength();
|
||||
if ((pl == 2) && (path.charAt(0) == slash))
|
||||
return path; /* UNC */
|
||||
if (pl == 3)
|
||||
return path; /* Absolute local */
|
||||
if (pl == 0)
|
||||
return getUserPath() + slashify(path); /* Completely relative */
|
||||
if (pl == 1) { /* Drive-relative */
|
||||
String up = getUserPath();
|
||||
String ud = getDrive(up);
|
||||
if (ud != null) return ud + path;
|
||||
return up + path; /* User dir is a UNC path */
|
||||
}
|
||||
if (pl == 2) { /* Directory-relative */
|
||||
String up = getUserPath();
|
||||
String ud = getDrive(up);
|
||||
if ((ud != null) && path.startsWith(ud))
|
||||
return up + slashify(path.substring(2));
|
||||
char drive = path.charAt(0);
|
||||
String dir = getDriveDirectory(drive);
|
||||
String np;
|
||||
if (dir != null) {
|
||||
/* When resolving a directory-relative path that refers to a
|
||||
drive other than the current drive, insist that the caller
|
||||
have read permission on the result */
|
||||
String p = drive + (':' + dir + slashify(path.substring(2)));
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
try {
|
||||
if (security != null) security.checkRead(p);
|
||||
} catch (SecurityException x) {
|
||||
/* Don't disclose the drive's directory in the exception */
|
||||
throw new SecurityException("Cannot resolve path " + path);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
return drive + ":" + slashify(path.substring(2)); /* fake it */
|
||||
}
|
||||
throw new InternalError("Unresolvable path: " + path);
|
||||
}
|
||||
|
||||
// Caches for canonicalization results to improve startup performance.
|
||||
// The first cache handles repeated canonicalizations of the same path
|
||||
// name. The prefix cache handles repeated canonicalizations within the
|
||||
// same directory, and must not create results differing from the true
|
||||
// canonicalization algorithm in canonicalize_md.c. For this reason the
|
||||
// prefix cache is conservative and is not used for complex path names.
|
||||
private ExpiringCache cache = new ExpiringCache();
|
||||
private ExpiringCache prefixCache = new ExpiringCache();
|
||||
|
||||
public String canonicalize(String path) throws IOException {
|
||||
// If path is a drive letter only then skip canonicalization
|
||||
int len = path.length();
|
||||
if ((len == 2) &&
|
||||
(isLetter(path.charAt(0))) &&
|
||||
(path.charAt(1) == ':')) {
|
||||
char c = path.charAt(0);
|
||||
if ((c >= 'A') && (c <= 'Z'))
|
||||
return path;
|
||||
return "" + ((char) (c-32)) + ':';
|
||||
} else if ((len == 3) &&
|
||||
(isLetter(path.charAt(0))) &&
|
||||
(path.charAt(1) == ':') &&
|
||||
(path.charAt(2) == '\\')) {
|
||||
char c = path.charAt(0);
|
||||
if ((c >= 'A') && (c <= 'Z'))
|
||||
return path;
|
||||
return "" + ((char) (c-32)) + ':' + '\\';
|
||||
}
|
||||
if (!useCanonCaches) {
|
||||
return canonicalize0(path);
|
||||
} else {
|
||||
String res = cache.get(path);
|
||||
if (res == null) {
|
||||
String dir = null;
|
||||
String resDir = null;
|
||||
if (useCanonPrefixCache) {
|
||||
dir = parentOrNull(path);
|
||||
if (dir != null) {
|
||||
resDir = prefixCache.get(dir);
|
||||
if (resDir != null) {
|
||||
// Hit only in prefix cache; full path is canonical,
|
||||
// but we need to get the canonical name of the file
|
||||
// in this directory to get the appropriate capitalization
|
||||
String filename = path.substring(1 + dir.length());
|
||||
res = canonicalizeWithPrefix(resDir, filename);
|
||||
cache.put(dir + File.separatorChar + filename, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res == null) {
|
||||
res = canonicalize0(path);
|
||||
cache.put(path, res);
|
||||
if (useCanonPrefixCache && dir != null) {
|
||||
resDir = parentOrNull(res);
|
||||
if (resDir != null) {
|
||||
File f = new File(res);
|
||||
if (f.exists() && !f.isDirectory()) {
|
||||
prefixCache.put(dir, resDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
protected native String canonicalize0(String path)
|
||||
throws IOException;
|
||||
protected String canonicalizeWithPrefix(String canonicalPrefix,
|
||||
String filename) throws IOException
|
||||
{
|
||||
return canonicalizeWithPrefix0(canonicalPrefix,
|
||||
canonicalPrefix + File.separatorChar + filename);
|
||||
}
|
||||
// Run the canonicalization operation assuming that the prefix
|
||||
// (everything up to the last filename) is canonical; just gets
|
||||
// the canonical name of the last element of the path
|
||||
protected native String canonicalizeWithPrefix0(String canonicalPrefix,
|
||||
String pathWithCanonicalPrefix)
|
||||
throws IOException;
|
||||
// Best-effort attempt to get parent of this path; used for
|
||||
// optimization of filename canonicalization. This must return null for
|
||||
// any cases where the code in canonicalize_md.c would throw an
|
||||
// exception or otherwise deal with non-simple pathnames like handling
|
||||
// of "." and "..". It may conservatively return null in other
|
||||
// situations as well. Returning null will cause the underlying
|
||||
// (expensive) canonicalization routine to be called.
|
||||
static String parentOrNull(String path) {
|
||||
if (path == null) return null;
|
||||
char sep = File.separatorChar;
|
||||
char altSep = '/';
|
||||
int last = path.length() - 1;
|
||||
int idx = last;
|
||||
int adjacentDots = 0;
|
||||
int nonDotCount = 0;
|
||||
while (idx > 0) {
|
||||
char c = path.charAt(idx);
|
||||
if (c == '.') {
|
||||
if (++adjacentDots >= 2) {
|
||||
// Punt on pathnames containing . and ..
|
||||
return null;
|
||||
}
|
||||
if (nonDotCount == 0) {
|
||||
// Punt on pathnames ending in a .
|
||||
return null;
|
||||
}
|
||||
} else if (c == sep) {
|
||||
if (adjacentDots == 1 && nonDotCount == 0) {
|
||||
// Punt on pathnames containing . and ..
|
||||
return null;
|
||||
}
|
||||
if (idx == 0 ||
|
||||
idx >= last - 1 ||
|
||||
path.charAt(idx - 1) == sep ||
|
||||
path.charAt(idx - 1) == altSep) {
|
||||
// Punt on pathnames containing adjacent slashes
|
||||
// toward the end
|
||||
return null;
|
||||
}
|
||||
return path.substring(0, idx);
|
||||
} else if (c == altSep) {
|
||||
// Punt on pathnames containing both backward and
|
||||
// forward slashes
|
||||
return null;
|
||||
} else if (c == '*' || c == '?') {
|
||||
// Punt on pathnames containing wildcards
|
||||
return null;
|
||||
} else {
|
||||
++nonDotCount;
|
||||
adjacentDots = 0;
|
||||
}
|
||||
--idx;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* -- Attribute accessors -- */
|
||||
|
||||
public native int getBooleanAttributes(File f);
|
||||
public native boolean checkAccess(File f, int access);
|
||||
public native long getLastModifiedTime(File f);
|
||||
public native long getLength(File f);
|
||||
public native boolean setPermission(File f, int access, boolean enable, boolean owneronly);
|
||||
|
||||
/* -- File operations -- */
|
||||
|
||||
public native boolean createFileExclusively(String path)
|
||||
throws IOException;
|
||||
public boolean delete(File f) {
|
||||
// Keep canonicalization caches in sync after file deletion
|
||||
// and renaming operations. Could be more clever than this
|
||||
// (i.e., only remove/update affected entries) but probably
|
||||
// not worth it since these entries expire after 30 seconds
|
||||
// anyway.
|
||||
cache.clear();
|
||||
prefixCache.clear();
|
||||
return delete0(f);
|
||||
}
|
||||
protected native boolean delete0(File f);
|
||||
public native String[] list(File f);
|
||||
public native boolean createDirectory(File f);
|
||||
public boolean rename(File f1, File f2) {
|
||||
// Keep canonicalization caches in sync after file deletion
|
||||
// and renaming operations. Could be more clever than this
|
||||
// (i.e., only remove/update affected entries) but probably
|
||||
// not worth it since these entries expire after 30 seconds
|
||||
// anyway.
|
||||
cache.clear();
|
||||
prefixCache.clear();
|
||||
return rename0(f1, f2);
|
||||
}
|
||||
protected native boolean rename0(File f1, File f2);
|
||||
public native boolean setLastModifiedTime(File f, long time);
|
||||
public native boolean setReadOnly(File f);
|
||||
|
||||
|
||||
/* -- Filesystem interface -- */
|
||||
|
||||
private boolean access(String path) {
|
||||
try {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) security.checkRead(path);
|
||||
return true;
|
||||
} catch (SecurityException x) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static native int listRoots0();
|
||||
|
||||
public File[] listRoots() {
|
||||
int ds = listRoots0();
|
||||
int n = 0;
|
||||
for (int i = 0; i < 26; i++) {
|
||||
if (((ds >> i) & 1) != 0) {
|
||||
if (!access((char)('A' + i) + ":" + slash))
|
||||
ds &= ~(1 << i);
|
||||
else
|
||||
n++;
|
||||
}
|
||||
}
|
||||
File[] fs = new File[n];
|
||||
int j = 0;
|
||||
char slash = this.slash;
|
||||
for (int i = 0; i < 26; i++) {
|
||||
if (((ds >> i) & 1) != 0)
|
||||
fs[j++] = new File((char)('A' + i) + ":" + slash);
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
|
||||
|
||||
/* -- Disk usage -- */
|
||||
public long getSpace(File f, int t) {
|
||||
if (f.exists()) {
|
||||
File file = (f.isDirectory() ? f : f.getParentFile());
|
||||
return getSpace0(file, t);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private native long getSpace0(File f, int t);
|
||||
|
||||
|
||||
/* -- Basic infrastructure -- */
|
||||
|
||||
public int compare(File f1, File f2) {
|
||||
return f1.getPath().compareToIgnoreCase(f2.getPath());
|
||||
}
|
||||
|
||||
public int hashCode(File f) {
|
||||
/* Could make this more efficient: String.hashCodeIgnoreCase */
|
||||
return f.getPath().toLowerCase(Locale.ENGLISH).hashCode() ^ 1234321;
|
||||
}
|
||||
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2012, 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
|
||||
@ -23,34 +23,601 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
package java.io;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.util.Locale;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* Unicode-aware FileSystem for Windows NT/2000.
|
||||
*
|
||||
* @author Konstantin Kladko
|
||||
* @since 1.4
|
||||
*/
|
||||
class WinNTFileSystem extends Win32FileSystem {
|
||||
class WinNTFileSystem extends FileSystem {
|
||||
|
||||
protected native String canonicalize0(String path)
|
||||
throws IOException;
|
||||
protected native String canonicalizeWithPrefix0(String canonicalPrefix,
|
||||
String pathWithCanonicalPrefix)
|
||||
throws IOException;
|
||||
private final char slash;
|
||||
private final char altSlash;
|
||||
private final char semicolon;
|
||||
|
||||
public WinNTFileSystem() {
|
||||
slash = AccessController.doPrivileged(
|
||||
new GetPropertyAction("file.separator")).charAt(0);
|
||||
semicolon = AccessController.doPrivileged(
|
||||
new GetPropertyAction("path.separator")).charAt(0);
|
||||
altSlash = (this.slash == '\\') ? '/' : '\\';
|
||||
}
|
||||
|
||||
private boolean isSlash(char c) {
|
||||
return (c == '\\') || (c == '/');
|
||||
}
|
||||
|
||||
private boolean isLetter(char c) {
|
||||
return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
|
||||
}
|
||||
|
||||
private String slashify(String p) {
|
||||
if ((p.length() > 0) && (p.charAt(0) != slash)) return slash + p;
|
||||
else return p;
|
||||
}
|
||||
|
||||
/* -- Normalization and construction -- */
|
||||
|
||||
@Override
|
||||
public char getSeparator() {
|
||||
return slash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getPathSeparator() {
|
||||
return semicolon;
|
||||
}
|
||||
|
||||
/* Check that the given pathname is normal. If not, invoke the real
|
||||
normalizer on the part of the pathname that requires normalization.
|
||||
This way we iterate through the whole pathname string only once. */
|
||||
@Override
|
||||
public String normalize(String path) {
|
||||
int n = path.length();
|
||||
char slash = this.slash;
|
||||
char altSlash = this.altSlash;
|
||||
char prev = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
char c = path.charAt(i);
|
||||
if (c == altSlash)
|
||||
return normalize(path, n, (prev == slash) ? i - 1 : i);
|
||||
if ((c == slash) && (prev == slash) && (i > 1))
|
||||
return normalize(path, n, i - 1);
|
||||
if ((c == ':') && (i > 1))
|
||||
return normalize(path, n, 0);
|
||||
prev = c;
|
||||
}
|
||||
if (prev == slash) return normalize(path, n, n - 1);
|
||||
return path;
|
||||
}
|
||||
|
||||
/* Normalize the given pathname, whose length is len, starting at the given
|
||||
offset; everything before this offset is already normal. */
|
||||
private String normalize(String path, int len, int off) {
|
||||
if (len == 0) return path;
|
||||
if (off < 3) off = 0; /* Avoid fencepost cases with UNC pathnames */
|
||||
int src;
|
||||
char slash = this.slash;
|
||||
StringBuffer sb = new StringBuffer(len);
|
||||
|
||||
if (off == 0) {
|
||||
/* Complete normalization, including prefix */
|
||||
src = normalizePrefix(path, len, sb);
|
||||
} else {
|
||||
/* Partial normalization */
|
||||
src = off;
|
||||
sb.append(path.substring(0, off));
|
||||
}
|
||||
|
||||
/* Remove redundant slashes from the remainder of the path, forcing all
|
||||
slashes into the preferred slash */
|
||||
while (src < len) {
|
||||
char c = path.charAt(src++);
|
||||
if (isSlash(c)) {
|
||||
while ((src < len) && isSlash(path.charAt(src))) src++;
|
||||
if (src == len) {
|
||||
/* Check for trailing separator */
|
||||
int sn = sb.length();
|
||||
if ((sn == 2) && (sb.charAt(1) == ':')) {
|
||||
/* "z:\\" */
|
||||
sb.append(slash);
|
||||
break;
|
||||
}
|
||||
if (sn == 0) {
|
||||
/* "\\" */
|
||||
sb.append(slash);
|
||||
break;
|
||||
}
|
||||
if ((sn == 1) && (isSlash(sb.charAt(0)))) {
|
||||
/* "\\\\" is not collapsed to "\\" because "\\\\" marks
|
||||
the beginning of a UNC pathname. Even though it is
|
||||
not, by itself, a valid UNC pathname, we leave it as
|
||||
is in order to be consistent with the win32 APIs,
|
||||
which treat this case as an invalid UNC pathname
|
||||
rather than as an alias for the root directory of
|
||||
the current drive. */
|
||||
sb.append(slash);
|
||||
break;
|
||||
}
|
||||
/* Path does not denote a root directory, so do not append
|
||||
trailing slash */
|
||||
break;
|
||||
} else {
|
||||
sb.append(slash);
|
||||
}
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
String rv = sb.toString();
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* A normal Win32 pathname contains no duplicate slashes, except possibly
|
||||
for a UNC prefix, and does not end with a slash. It may be the empty
|
||||
string. Normalized Win32 pathnames have the convenient property that
|
||||
the length of the prefix almost uniquely identifies the type of the path
|
||||
and whether it is absolute or relative:
|
||||
|
||||
0 relative to both drive and directory
|
||||
1 drive-relative (begins with '\\')
|
||||
2 absolute UNC (if first char is '\\'),
|
||||
else directory-relative (has form "z:foo")
|
||||
3 absolute local pathname (begins with "z:\\")
|
||||
*/
|
||||
private int normalizePrefix(String path, int len, StringBuffer sb) {
|
||||
int src = 0;
|
||||
while ((src < len) && isSlash(path.charAt(src))) src++;
|
||||
char c;
|
||||
if ((len - src >= 2)
|
||||
&& isLetter(c = path.charAt(src))
|
||||
&& path.charAt(src + 1) == ':') {
|
||||
/* Remove leading slashes if followed by drive specifier.
|
||||
This hack is necessary to support file URLs containing drive
|
||||
specifiers (e.g., "file://c:/path"). As a side effect,
|
||||
"/c:/path" can be used as an alternative to "c:/path". */
|
||||
sb.append(c);
|
||||
sb.append(':');
|
||||
src += 2;
|
||||
} else {
|
||||
src = 0;
|
||||
if ((len >= 2)
|
||||
&& isSlash(path.charAt(0))
|
||||
&& isSlash(path.charAt(1))) {
|
||||
/* UNC pathname: Retain first slash; leave src pointed at
|
||||
second slash so that further slashes will be collapsed
|
||||
into the second slash. The result will be a pathname
|
||||
beginning with "\\\\" followed (most likely) by a host
|
||||
name. */
|
||||
src = 1;
|
||||
sb.append(slash);
|
||||
}
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prefixLength(String path) {
|
||||
char slash = this.slash;
|
||||
int n = path.length();
|
||||
if (n == 0) return 0;
|
||||
char c0 = path.charAt(0);
|
||||
char c1 = (n > 1) ? path.charAt(1) : 0;
|
||||
if (c0 == slash) {
|
||||
if (c1 == slash) return 2; /* Absolute UNC pathname "\\\\foo" */
|
||||
return 1; /* Drive-relative "\\foo" */
|
||||
}
|
||||
if (isLetter(c0) && (c1 == ':')) {
|
||||
if ((n > 2) && (path.charAt(2) == slash))
|
||||
return 3; /* Absolute local pathname "z:\\foo" */
|
||||
return 2; /* Directory-relative "z:foo" */
|
||||
}
|
||||
return 0; /* Completely relative */
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolve(String parent, String child) {
|
||||
int pn = parent.length();
|
||||
if (pn == 0) return child;
|
||||
int cn = child.length();
|
||||
if (cn == 0) return parent;
|
||||
|
||||
String c = child;
|
||||
int childStart = 0;
|
||||
int parentEnd = pn;
|
||||
|
||||
if ((cn > 1) && (c.charAt(0) == slash)) {
|
||||
if (c.charAt(1) == slash) {
|
||||
/* Drop prefix when child is a UNC pathname */
|
||||
childStart = 2;
|
||||
} else {
|
||||
/* Drop prefix when child is drive-relative */
|
||||
childStart = 1;
|
||||
|
||||
}
|
||||
if (cn == childStart) { // Child is double slash
|
||||
if (parent.charAt(pn - 1) == slash)
|
||||
return parent.substring(0, pn - 1);
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent.charAt(pn - 1) == slash)
|
||||
parentEnd--;
|
||||
|
||||
int strlen = parentEnd + cn - childStart;
|
||||
char[] theChars = null;
|
||||
if (child.charAt(childStart) == slash) {
|
||||
theChars = new char[strlen];
|
||||
parent.getChars(0, parentEnd, theChars, 0);
|
||||
child.getChars(childStart, cn, theChars, parentEnd);
|
||||
} else {
|
||||
theChars = new char[strlen + 1];
|
||||
parent.getChars(0, parentEnd, theChars, 0);
|
||||
theChars[parentEnd] = slash;
|
||||
child.getChars(childStart, cn, theChars, parentEnd + 1);
|
||||
}
|
||||
return new String(theChars);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultParent() {
|
||||
return ("" + slash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fromURIPath(String path) {
|
||||
String p = path;
|
||||
if ((p.length() > 2) && (p.charAt(2) == ':')) {
|
||||
// "/c:/foo" --> "c:/foo"
|
||||
p = p.substring(1);
|
||||
// "c:/foo/" --> "c:/foo", but "c:/" --> "c:/"
|
||||
if ((p.length() > 3) && p.endsWith("/"))
|
||||
p = p.substring(0, p.length() - 1);
|
||||
} else if ((p.length() > 1) && p.endsWith("/")) {
|
||||
// "/foo/" --> "/foo"
|
||||
p = p.substring(0, p.length() - 1);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* -- Path operations -- */
|
||||
|
||||
@Override
|
||||
public boolean isAbsolute(File f) {
|
||||
int pl = f.getPrefixLength();
|
||||
return (((pl == 2) && (f.getPath().charAt(0) == slash))
|
||||
|| (pl == 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolve(File f) {
|
||||
String path = f.getPath();
|
||||
int pl = f.getPrefixLength();
|
||||
if ((pl == 2) && (path.charAt(0) == slash))
|
||||
return path; /* UNC */
|
||||
if (pl == 3)
|
||||
return path; /* Absolute local */
|
||||
if (pl == 0)
|
||||
return getUserPath() + slashify(path); /* Completely relative */
|
||||
if (pl == 1) { /* Drive-relative */
|
||||
String up = getUserPath();
|
||||
String ud = getDrive(up);
|
||||
if (ud != null) return ud + path;
|
||||
return up + path; /* User dir is a UNC path */
|
||||
}
|
||||
if (pl == 2) { /* Directory-relative */
|
||||
String up = getUserPath();
|
||||
String ud = getDrive(up);
|
||||
if ((ud != null) && path.startsWith(ud))
|
||||
return up + slashify(path.substring(2));
|
||||
char drive = path.charAt(0);
|
||||
String dir = getDriveDirectory(drive);
|
||||
String np;
|
||||
if (dir != null) {
|
||||
/* When resolving a directory-relative path that refers to a
|
||||
drive other than the current drive, insist that the caller
|
||||
have read permission on the result */
|
||||
String p = drive + (':' + dir + slashify(path.substring(2)));
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
try {
|
||||
if (security != null) security.checkRead(p);
|
||||
} catch (SecurityException x) {
|
||||
/* Don't disclose the drive's directory in the exception */
|
||||
throw new SecurityException("Cannot resolve path " + path);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
return drive + ":" + slashify(path.substring(2)); /* fake it */
|
||||
}
|
||||
throw new InternalError("Unresolvable path: " + path);
|
||||
}
|
||||
|
||||
private String getUserPath() {
|
||||
/* For both compatibility and security,
|
||||
we must look this up every time */
|
||||
return normalize(System.getProperty("user.dir"));
|
||||
}
|
||||
|
||||
private String getDrive(String path) {
|
||||
int pl = prefixLength(path);
|
||||
return (pl == 3) ? path.substring(0, 2) : null;
|
||||
}
|
||||
|
||||
private static String[] driveDirCache = new String[26];
|
||||
|
||||
private static int driveIndex(char d) {
|
||||
if ((d >= 'a') && (d <= 'z')) return d - 'a';
|
||||
if ((d >= 'A') && (d <= 'Z')) return d - 'A';
|
||||
return -1;
|
||||
}
|
||||
|
||||
private native String getDriveDirectory(int drive);
|
||||
|
||||
private String getDriveDirectory(char drive) {
|
||||
int i = driveIndex(drive);
|
||||
if (i < 0) return null;
|
||||
String s = driveDirCache[i];
|
||||
if (s != null) return s;
|
||||
s = getDriveDirectory(i + 1);
|
||||
driveDirCache[i] = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
// Caches for canonicalization results to improve startup performance.
|
||||
// The first cache handles repeated canonicalizations of the same path
|
||||
// name. The prefix cache handles repeated canonicalizations within the
|
||||
// same directory, and must not create results differing from the true
|
||||
// canonicalization algorithm in canonicalize_md.c. For this reason the
|
||||
// prefix cache is conservative and is not used for complex path names.
|
||||
private ExpiringCache cache = new ExpiringCache();
|
||||
private ExpiringCache prefixCache = new ExpiringCache();
|
||||
|
||||
@Override
|
||||
public String canonicalize(String path) throws IOException {
|
||||
// If path is a drive letter only then skip canonicalization
|
||||
int len = path.length();
|
||||
if ((len == 2) &&
|
||||
(isLetter(path.charAt(0))) &&
|
||||
(path.charAt(1) == ':')) {
|
||||
char c = path.charAt(0);
|
||||
if ((c >= 'A') && (c <= 'Z'))
|
||||
return path;
|
||||
return "" + ((char) (c-32)) + ':';
|
||||
} else if ((len == 3) &&
|
||||
(isLetter(path.charAt(0))) &&
|
||||
(path.charAt(1) == ':') &&
|
||||
(path.charAt(2) == '\\')) {
|
||||
char c = path.charAt(0);
|
||||
if ((c >= 'A') && (c <= 'Z'))
|
||||
return path;
|
||||
return "" + ((char) (c-32)) + ':' + '\\';
|
||||
}
|
||||
if (!useCanonCaches) {
|
||||
return canonicalize0(path);
|
||||
} else {
|
||||
String res = cache.get(path);
|
||||
if (res == null) {
|
||||
String dir = null;
|
||||
String resDir = null;
|
||||
if (useCanonPrefixCache) {
|
||||
dir = parentOrNull(path);
|
||||
if (dir != null) {
|
||||
resDir = prefixCache.get(dir);
|
||||
if (resDir != null) {
|
||||
/*
|
||||
* Hit only in prefix cache; full path is canonical,
|
||||
* but we need to get the canonical name of the file
|
||||
* in this directory to get the appropriate
|
||||
* capitalization
|
||||
*/
|
||||
String filename = path.substring(1 + dir.length());
|
||||
res = canonicalizeWithPrefix(resDir, filename);
|
||||
cache.put(dir + File.separatorChar + filename, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res == null) {
|
||||
res = canonicalize0(path);
|
||||
cache.put(path, res);
|
||||
if (useCanonPrefixCache && dir != null) {
|
||||
resDir = parentOrNull(res);
|
||||
if (resDir != null) {
|
||||
File f = new File(res);
|
||||
if (f.exists() && !f.isDirectory()) {
|
||||
prefixCache.put(dir, resDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
private native String canonicalize0(String path)
|
||||
throws IOException;
|
||||
|
||||
private String canonicalizeWithPrefix(String canonicalPrefix,
|
||||
String filename) throws IOException
|
||||
{
|
||||
return canonicalizeWithPrefix0(canonicalPrefix,
|
||||
canonicalPrefix + File.separatorChar + filename);
|
||||
}
|
||||
|
||||
// Run the canonicalization operation assuming that the prefix
|
||||
// (everything up to the last filename) is canonical; just gets
|
||||
// the canonical name of the last element of the path
|
||||
private native String canonicalizeWithPrefix0(String canonicalPrefix,
|
||||
String pathWithCanonicalPrefix)
|
||||
throws IOException;
|
||||
|
||||
// Best-effort attempt to get parent of this path; used for
|
||||
// optimization of filename canonicalization. This must return null for
|
||||
// any cases where the code in canonicalize_md.c would throw an
|
||||
// exception or otherwise deal with non-simple pathnames like handling
|
||||
// of "." and "..". It may conservatively return null in other
|
||||
// situations as well. Returning null will cause the underlying
|
||||
// (expensive) canonicalization routine to be called.
|
||||
private static String parentOrNull(String path) {
|
||||
if (path == null) return null;
|
||||
char sep = File.separatorChar;
|
||||
char altSep = '/';
|
||||
int last = path.length() - 1;
|
||||
int idx = last;
|
||||
int adjacentDots = 0;
|
||||
int nonDotCount = 0;
|
||||
while (idx > 0) {
|
||||
char c = path.charAt(idx);
|
||||
if (c == '.') {
|
||||
if (++adjacentDots >= 2) {
|
||||
// Punt on pathnames containing . and ..
|
||||
return null;
|
||||
}
|
||||
if (nonDotCount == 0) {
|
||||
// Punt on pathnames ending in a .
|
||||
return null;
|
||||
}
|
||||
} else if (c == sep) {
|
||||
if (adjacentDots == 1 && nonDotCount == 0) {
|
||||
// Punt on pathnames containing . and ..
|
||||
return null;
|
||||
}
|
||||
if (idx == 0 ||
|
||||
idx >= last - 1 ||
|
||||
path.charAt(idx - 1) == sep ||
|
||||
path.charAt(idx - 1) == altSep) {
|
||||
// Punt on pathnames containing adjacent slashes
|
||||
// toward the end
|
||||
return null;
|
||||
}
|
||||
return path.substring(0, idx);
|
||||
} else if (c == altSep) {
|
||||
// Punt on pathnames containing both backward and
|
||||
// forward slashes
|
||||
return null;
|
||||
} else if (c == '*' || c == '?') {
|
||||
// Punt on pathnames containing wildcards
|
||||
return null;
|
||||
} else {
|
||||
++nonDotCount;
|
||||
adjacentDots = 0;
|
||||
}
|
||||
--idx;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* -- Attribute accessors -- */
|
||||
|
||||
@Override
|
||||
public native int getBooleanAttributes(File f);
|
||||
|
||||
@Override
|
||||
public native boolean checkAccess(File f, int access);
|
||||
|
||||
@Override
|
||||
public native long getLastModifiedTime(File f);
|
||||
|
||||
@Override
|
||||
public native long getLength(File f);
|
||||
public native boolean setPermission(File f, int access, boolean enable, boolean owneronly);
|
||||
|
||||
@Override
|
||||
public native boolean setPermission(File f, int access, boolean enable,
|
||||
boolean owneronly);
|
||||
|
||||
/* -- File operations -- */
|
||||
|
||||
@Override
|
||||
public native boolean createFileExclusively(String path)
|
||||
throws IOException;
|
||||
|
||||
@Override
|
||||
public native String[] list(File f);
|
||||
|
||||
@Override
|
||||
public native boolean createDirectory(File f);
|
||||
|
||||
@Override
|
||||
public native boolean setLastModifiedTime(File f, long time);
|
||||
|
||||
@Override
|
||||
public native boolean setReadOnly(File f);
|
||||
|
||||
@Override
|
||||
public boolean delete(File f) {
|
||||
// Keep canonicalization caches in sync after file deletion
|
||||
// and renaming operations. Could be more clever than this
|
||||
// (i.e., only remove/update affected entries) but probably
|
||||
// not worth it since these entries expire after 30 seconds
|
||||
// anyway.
|
||||
cache.clear();
|
||||
prefixCache.clear();
|
||||
return delete0(f);
|
||||
}
|
||||
|
||||
private native boolean delete0(File f);
|
||||
|
||||
@Override
|
||||
public boolean rename(File f1, File f2) {
|
||||
// Keep canonicalization caches in sync after file deletion
|
||||
// and renaming operations. Could be more clever than this
|
||||
// (i.e., only remove/update affected entries) but probably
|
||||
// not worth it since these entries expire after 30 seconds
|
||||
// anyway.
|
||||
cache.clear();
|
||||
prefixCache.clear();
|
||||
return rename0(f1, f2);
|
||||
}
|
||||
|
||||
private native boolean rename0(File f1, File f2);
|
||||
|
||||
/* -- Filesystem interface -- */
|
||||
|
||||
@Override
|
||||
public File[] listRoots() {
|
||||
int ds = listRoots0();
|
||||
int n = 0;
|
||||
for (int i = 0; i < 26; i++) {
|
||||
if (((ds >> i) & 1) != 0) {
|
||||
if (!access((char)('A' + i) + ":" + slash))
|
||||
ds &= ~(1 << i);
|
||||
else
|
||||
n++;
|
||||
}
|
||||
}
|
||||
File[] fs = new File[n];
|
||||
int j = 0;
|
||||
char slash = this.slash;
|
||||
for (int i = 0; i < 26; i++) {
|
||||
if (((ds >> i) & 1) != 0)
|
||||
fs[j++] = new File((char)('A' + i) + ":" + slash);
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
|
||||
private static native int listRoots0();
|
||||
|
||||
private boolean access(String path) {
|
||||
try {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) security.checkRead(path);
|
||||
return true;
|
||||
} catch (SecurityException x) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Disk usage -- */
|
||||
|
||||
@Override
|
||||
public long getSpace(File f, int t) {
|
||||
if (f.exists()) {
|
||||
return getSpace0(f, t);
|
||||
@ -60,20 +627,22 @@ class WinNTFileSystem extends Win32FileSystem {
|
||||
|
||||
private native long getSpace0(File f, int t);
|
||||
|
||||
/* -- File operations -- */
|
||||
/* -- Basic infrastructure -- */
|
||||
|
||||
@Override
|
||||
public int compare(File f1, File f2) {
|
||||
return f1.getPath().compareToIgnoreCase(f2.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(File f) {
|
||||
/* Could make this more efficient: String.hashCodeIgnoreCase */
|
||||
return f.getPath().toLowerCase(Locale.ENGLISH).hashCode() ^ 1234321;
|
||||
}
|
||||
|
||||
public native boolean createFileExclusively(String path)
|
||||
throws IOException;
|
||||
protected native boolean delete0(File f);
|
||||
public native String[] list(File f);
|
||||
public native boolean createDirectory(File f);
|
||||
protected native boolean rename0(File f1, File f2);
|
||||
public native boolean setLastModifiedTime(File f, long time);
|
||||
public native boolean setReadOnly(File f);
|
||||
protected native String getDriveDirectory(int drive);
|
||||
private static native void initIDs();
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
initIDs();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2012, 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
|
||||
@ -27,16 +27,8 @@
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
|
||||
extern jboolean onNT;
|
||||
extern void initializeWindowsVersion();
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_java_io_FileSystem_getFileSystem(JNIEnv *env, jclass ignored)
|
||||
{
|
||||
initializeWindowsVersion();
|
||||
if (onNT) {
|
||||
return JNU_NewObjectByName(env, "java/io/WinNTFileSystem", "()V");
|
||||
} else {
|
||||
return JNU_NewObjectByName(env, "java/io/Win32FileSystem", "()V");
|
||||
}
|
||||
return JNU_NewObjectByName(env, "java/io/WinNTFileSystem", "()V");
|
||||
}
|
||||
|
||||
@ -1,509 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
|
||||
#include "jvm.h"
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jlong.h"
|
||||
#include "io_util.h"
|
||||
#include "dirent_md.h"
|
||||
#include "java_io_FileSystem.h"
|
||||
|
||||
/* This macro relies upon the fact that JNU_GetStringPlatformChars always makes
|
||||
a copy of the string */
|
||||
|
||||
#define WITH_NATIVE_PATH(env, object, id, var) \
|
||||
WITH_FIELD_PLATFORM_STRING(env, object, id, var) \
|
||||
JVM_NativePath((char *)var);
|
||||
|
||||
#define END_NATIVE_PATH(env, var) END_PLATFORM_STRING(env, var)
|
||||
|
||||
|
||||
static struct {
|
||||
jfieldID path;
|
||||
} ids;
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_io_Win32FileSystem_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
jclass fileClass = (*env)->FindClass(env, "java/io/File");
|
||||
if (!fileClass) return;
|
||||
ids.path = (*env)->GetFieldID(env, fileClass,
|
||||
"path", "Ljava/lang/String;");
|
||||
}
|
||||
|
||||
|
||||
/* -- Path operations -- */
|
||||
|
||||
|
||||
extern int canonicalize(char *path, const char *out, int len);
|
||||
extern int canonicalizeWithPrefix(const char* canonicalPrefix, const char *pathWithCanonicalPrefix, char *out, int len);
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_java_io_Win32FileSystem_canonicalize0(JNIEnv *env, jobject this,
|
||||
jstring pathname)
|
||||
{
|
||||
jstring rv = NULL;
|
||||
|
||||
WITH_PLATFORM_STRING(env, pathname, path) {
|
||||
char canonicalPath[JVM_MAXPATHLEN];
|
||||
if (canonicalize(JVM_NativePath((char *)path),
|
||||
canonicalPath, JVM_MAXPATHLEN) < 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
|
||||
} else {
|
||||
rv = JNU_NewStringPlatform(env, canonicalPath);
|
||||
}
|
||||
} END_PLATFORM_STRING(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_java_io_Win32FileSystem_canonicalizeWithPrefix0(JNIEnv *env, jobject this,
|
||||
jstring canonicalPrefixString,
|
||||
jstring pathWithCanonicalPrefixString)
|
||||
{
|
||||
jstring rv = NULL;
|
||||
char canonicalPath[JVM_MAXPATHLEN];
|
||||
|
||||
WITH_PLATFORM_STRING(env, canonicalPrefixString, canonicalPrefix) {
|
||||
WITH_PLATFORM_STRING(env, pathWithCanonicalPrefixString, pathWithCanonicalPrefix) {
|
||||
if (canonicalizeWithPrefix(canonicalPrefix,
|
||||
pathWithCanonicalPrefix,
|
||||
canonicalPath, JVM_MAXPATHLEN) < 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
|
||||
} else {
|
||||
rv = JNU_NewStringPlatform(env, canonicalPath);
|
||||
}
|
||||
} END_PLATFORM_STRING(env, pathWithCanonicalPrefix);
|
||||
} END_PLATFORM_STRING(env, canonicalPrefix);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- Attribute accessors -- */
|
||||
|
||||
/* Check whether or not the file name in "path" is a Windows reserved
|
||||
device name (CON, PRN, AUX, NUL, COM[1-9], LPT[1-9]) based on the
|
||||
returned result from GetFullPathName. If the file name in the path
|
||||
is indeed a reserved device name GetFuulPathName returns
|
||||
"\\.\[ReservedDeviceName]".
|
||||
*/
|
||||
BOOL isReservedDeviceName(const char* path) {
|
||||
#define BUFSIZE 9
|
||||
char buf[BUFSIZE];
|
||||
char *lpf = NULL;
|
||||
DWORD retLen = GetFullPathName(path,
|
||||
BUFSIZE,
|
||||
buf,
|
||||
&lpf);
|
||||
if ((retLen == BUFSIZE - 1 || retLen == BUFSIZE - 2) &&
|
||||
buf[0] == '\\' && buf[1] == '\\' &&
|
||||
buf[2] == '.' && buf[3] == '\\') {
|
||||
char* dname = _strupr(buf + 4);
|
||||
if (strcmp(dname, "CON") == 0 ||
|
||||
strcmp(dname, "PRN") == 0 ||
|
||||
strcmp(dname, "AUX") == 0 ||
|
||||
strcmp(dname, "NUL") == 0)
|
||||
return TRUE;
|
||||
if ((strncmp(dname, "COM", 3) == 0 ||
|
||||
strncmp(dname, "LPT", 3) == 0) &&
|
||||
dname[3] - '0' > 0 &&
|
||||
dname[3] - '0' <= 9)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_io_Win32FileSystem_getBooleanAttributes(JNIEnv *env, jobject this,
|
||||
jobject file)
|
||||
{
|
||||
jint rv = 0;
|
||||
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA wfad;
|
||||
if (!isReservedDeviceName(path) &&
|
||||
GetFileAttributesEx(path, GetFileExInfoStandard, &wfad)) {
|
||||
rv = (java_io_FileSystem_BA_EXISTS
|
||||
| ((wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
? java_io_FileSystem_BA_DIRECTORY
|
||||
: java_io_FileSystem_BA_REGULAR)
|
||||
| ((wfad.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
? java_io_FileSystem_BA_HIDDEN : 0));
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_Win32FileSystem_checkAccess(JNIEnv *env, jobject this,
|
||||
jobject file, jint a)
|
||||
{
|
||||
jboolean rv = JNI_FALSE;
|
||||
int mode;
|
||||
switch (a) {
|
||||
case java_io_FileSystem_ACCESS_READ:
|
||||
case java_io_FileSystem_ACCESS_EXECUTE:
|
||||
mode = 4;
|
||||
break;
|
||||
case java_io_FileSystem_ACCESS_WRITE:
|
||||
mode = 2;
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
if (access(path, mode) == 0) {
|
||||
rv = JNI_TRUE;
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_Win32FileSystem_setPermission(JNIEnv *env, jobject this,
|
||||
jobject file,
|
||||
jint access,
|
||||
jboolean enable,
|
||||
jboolean owneronly)
|
||||
{
|
||||
jboolean rv = JNI_FALSE;
|
||||
if (access == java_io_FileSystem_ACCESS_READ ||
|
||||
access == java_io_FileSystem_ACCESS_EXECUTE) {
|
||||
return enable;
|
||||
}
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
DWORD a;
|
||||
a = GetFileAttributes(path);
|
||||
if (a != INVALID_FILE_ATTRIBUTES) {
|
||||
if (enable)
|
||||
a = a & ~FILE_ATTRIBUTE_READONLY;
|
||||
else
|
||||
a = a | FILE_ATTRIBUTE_READONLY;
|
||||
if (SetFileAttributes(path, a))
|
||||
rv = JNI_TRUE;
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_io_Win32FileSystem_getLastModifiedTime(JNIEnv *env, jobject this,
|
||||
jobject file)
|
||||
{
|
||||
jlong rv = 0;
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
/* Win95, Win98, WinME */
|
||||
WIN32_FIND_DATA fd;
|
||||
jlong temp = 0;
|
||||
LARGE_INTEGER modTime;
|
||||
HANDLE h = FindFirstFile(path, &fd);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
FindClose(h);
|
||||
modTime.LowPart = (DWORD) fd.ftLastWriteTime.dwLowDateTime;
|
||||
modTime.HighPart = (LONG) fd.ftLastWriteTime.dwHighDateTime;
|
||||
rv = modTime.QuadPart / 10000;
|
||||
rv -= 11644473600000;
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_io_Win32FileSystem_getLength(JNIEnv *env, jobject this,
|
||||
jobject file)
|
||||
{
|
||||
jlong rv = 0;
|
||||
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
struct _stati64 sb;
|
||||
if (_stati64(path, &sb) == 0) {
|
||||
rv = sb.st_size;
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/* -- File operations -- */
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_Win32FileSystem_createFileExclusively(JNIEnv *env, jclass cls,
|
||||
jstring pathname)
|
||||
{
|
||||
jboolean rv = JNI_FALSE;
|
||||
DWORD a;
|
||||
|
||||
WITH_PLATFORM_STRING(env, pathname, path) {
|
||||
int orv;
|
||||
int error;
|
||||
JVM_NativePath((char *)path);
|
||||
orv = JVM_Open(path, JVM_O_RDWR | JVM_O_CREAT | JVM_O_EXCL, 0666);
|
||||
if (orv < 0) {
|
||||
if (orv != JVM_EEXIST) {
|
||||
error = GetLastError();
|
||||
|
||||
// If a directory by the named path already exists,
|
||||
// return false (behavior of solaris and linux) instead of
|
||||
// throwing an exception
|
||||
a = GetFileAttributes(path);
|
||||
|
||||
if ((a == INVALID_FILE_ATTRIBUTES) ||
|
||||
!(a & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
SetLastError(error);
|
||||
JNU_ThrowIOExceptionWithLastError(env, path);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
JVM_Close(orv);
|
||||
rv = JNI_TRUE;
|
||||
}
|
||||
} END_PLATFORM_STRING(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
removeFileOrDirectory(const char *path) /* Returns 0 on success */
|
||||
{
|
||||
DWORD a;
|
||||
|
||||
SetFileAttributes(path, 0);
|
||||
a = GetFileAttributes(path);
|
||||
if (a == INVALID_FILE_ATTRIBUTES) {
|
||||
return 1;
|
||||
} else if (a & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
return !RemoveDirectory(path);
|
||||
} else {
|
||||
return !DeleteFile(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_Win32FileSystem_delete0(JNIEnv *env, jobject this,
|
||||
jobject file)
|
||||
{
|
||||
jboolean rv = JNI_FALSE;
|
||||
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
if (removeFileOrDirectory(path) == 0) {
|
||||
rv = JNI_TRUE;
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/* ## Clean this up to use direct Win32 calls */
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_java_io_Win32FileSystem_list(JNIEnv *env, jobject this,
|
||||
jobject file)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ptr;
|
||||
int len, maxlen;
|
||||
jobjectArray rv, old;
|
||||
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
dir = opendir(path);
|
||||
} END_NATIVE_PATH(env, path);
|
||||
if (dir == NULL) return NULL;
|
||||
|
||||
/* Allocate an initial String array */
|
||||
len = 0;
|
||||
maxlen = 16;
|
||||
rv = (*env)->NewObjectArray(env, maxlen, JNU_ClassString(env), NULL);
|
||||
if (rv == NULL) goto error;
|
||||
|
||||
/* Scan the directory */
|
||||
while ((ptr = readdir(dir)) != NULL) {
|
||||
jstring name;
|
||||
if (!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, ".."))
|
||||
continue;
|
||||
if (len == maxlen) {
|
||||
old = rv;
|
||||
rv = (*env)->NewObjectArray(env, maxlen <<= 1,
|
||||
JNU_ClassString(env), NULL);
|
||||
if (rv == NULL) goto error;
|
||||
if (JNU_CopyObjectArray(env, rv, old, len) < 0) goto error;
|
||||
(*env)->DeleteLocalRef(env, old);
|
||||
}
|
||||
name = JNU_NewStringPlatform(env, ptr->d_name);
|
||||
if (name == NULL) goto error;
|
||||
(*env)->SetObjectArrayElement(env, rv, len++, name);
|
||||
(*env)->DeleteLocalRef(env, name);
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
/* Copy the final results into an appropriately-sized array */
|
||||
old = rv;
|
||||
rv = (*env)->NewObjectArray(env, len, JNU_ClassString(env), NULL);
|
||||
if (rv == NULL) goto error;
|
||||
if (JNU_CopyObjectArray(env, rv, old, len) < 0) goto error;
|
||||
return rv;
|
||||
|
||||
error:
|
||||
closedir(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_Win32FileSystem_createDirectory(JNIEnv *env, jobject this,
|
||||
jobject file)
|
||||
{
|
||||
jboolean rv = JNI_FALSE;
|
||||
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
if (mkdir(path) == 0) {
|
||||
rv = JNI_TRUE;
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_Win32FileSystem_rename0(JNIEnv *env, jobject this,
|
||||
jobject from, jobject to)
|
||||
{
|
||||
jboolean rv = JNI_FALSE;
|
||||
|
||||
WITH_NATIVE_PATH(env, from, ids.path, fromPath) {
|
||||
WITH_NATIVE_PATH(env, to, ids.path, toPath) {
|
||||
if (rename(fromPath, toPath) == 0) {
|
||||
rv = JNI_TRUE;
|
||||
}
|
||||
} END_NATIVE_PATH(env, toPath);
|
||||
} END_NATIVE_PATH(env, fromPath);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_Win32FileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
|
||||
jobject file, jlong time)
|
||||
{
|
||||
jboolean rv = JNI_FALSE;
|
||||
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
HANDLE h;
|
||||
h = CreateFile(path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
LARGE_INTEGER modTime;
|
||||
FILETIME t;
|
||||
modTime.QuadPart = (time + 11644473600000L) * 10000L;
|
||||
t.dwLowDateTime = (DWORD)modTime.LowPart;
|
||||
t.dwHighDateTime = (DWORD)modTime.HighPart;
|
||||
if (SetFileTime(h, NULL, NULL, &t)) {
|
||||
rv = JNI_TRUE;
|
||||
}
|
||||
CloseHandle(h);
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_io_Win32FileSystem_setReadOnly(JNIEnv *env, jobject this,
|
||||
jobject file)
|
||||
{
|
||||
jboolean rv = JNI_FALSE;
|
||||
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
DWORD a;
|
||||
a = GetFileAttributes(path);
|
||||
if (a != INVALID_FILE_ATTRIBUTES) {
|
||||
if (SetFileAttributes(path, a | FILE_ATTRIBUTE_READONLY))
|
||||
rv = JNI_TRUE;
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/* -- Filesystem interface -- */
|
||||
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_java_io_Win32FileSystem_getDriveDirectory(JNIEnv *env, jclass ignored,
|
||||
jint drive)
|
||||
{
|
||||
char buf[_MAX_PATH];
|
||||
char *p = _getdcwd(drive, buf, sizeof(buf));
|
||||
if (p == NULL) return NULL;
|
||||
if (isalpha(*p) && (p[1] == ':')) p += 2;
|
||||
return JNU_NewStringPlatform(env, p);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_io_Win32FileSystem_listRoots0(JNIEnv *env, jclass ignored)
|
||||
{
|
||||
return GetLogicalDrives();
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_io_Win32FileSystem_getSpace0(JNIEnv *env, jobject this,
|
||||
jobject file, jint t)
|
||||
{
|
||||
jlong rv = 0L;
|
||||
|
||||
WITH_NATIVE_PATH(env, file, ids.path, path) {
|
||||
ULARGE_INTEGER totalSpace, freeSpace, usableSpace;
|
||||
if (GetDiskFreeSpaceEx(path, &usableSpace, &totalSpace, &freeSpace)) {
|
||||
switch(t) {
|
||||
case java_io_FileSystem_SPACE_TOTAL:
|
||||
rv = long_to_jlong(totalSpace.QuadPart);
|
||||
break;
|
||||
case java_io_FileSystem_SPACE_FREE:
|
||||
rv = long_to_jlong(freeSpace.QuadPart);
|
||||
break;
|
||||
case java_io_FileSystem_SPACE_USABLE:
|
||||
rv = long_to_jlong(usableSpace.QuadPart);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
} END_NATIVE_PATH(env, path);
|
||||
return rv;
|
||||
}
|
||||
@ -828,6 +828,12 @@ Java_java_io_WinNTFileSystem_getDriveDirectory(JNIEnv *env, jobject this,
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_io_WinNTFileSystem_listRoots0(JNIEnv *env, jclass ignored)
|
||||
{
|
||||
return GetLogicalDrives();
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_io_WinNTFileSystem_getSpace0(JNIEnv *env, jobject this,
|
||||
jobject file, jint t)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2012, 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
|
||||
@ -40,22 +40,8 @@
|
||||
#include <limits.h>
|
||||
#include <wincon.h>
|
||||
|
||||
extern jboolean onNT = JNI_FALSE;
|
||||
|
||||
static DWORD MAX_INPUT_EVENTS = 2000;
|
||||
|
||||
void
|
||||
initializeWindowsVersion() {
|
||||
OSVERSIONINFO ver;
|
||||
ver.dwOSVersionInfoSize = sizeof(ver);
|
||||
GetVersionEx(&ver);
|
||||
if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
||||
onNT = JNI_TRUE;
|
||||
} else {
|
||||
onNT = JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this returns NULL then an exception is pending */
|
||||
WCHAR*
|
||||
fileToNTPath(JNIEnv *env, jobject file, jfieldID id) {
|
||||
@ -247,27 +233,21 @@ winFileHandleOpen(JNIEnv *env, jstring path, int flags)
|
||||
const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose;
|
||||
HANDLE h = NULL;
|
||||
|
||||
if (onNT) {
|
||||
WCHAR *pathbuf = pathToNTPath(env, path, JNI_TRUE);
|
||||
if (pathbuf == NULL) {
|
||||
/* Exception already pending */
|
||||
return -1;
|
||||
}
|
||||
h = CreateFileW(
|
||||
pathbuf, /* Wide char path name */
|
||||
access, /* Read and/or write permission */
|
||||
sharing, /* File sharing flags */
|
||||
NULL, /* Security attributes */
|
||||
disposition, /* creation disposition */
|
||||
flagsAndAttributes, /* flags and attributes */
|
||||
NULL);
|
||||
free(pathbuf);
|
||||
} else {
|
||||
WITH_PLATFORM_STRING(env, path, _ps) {
|
||||
h = CreateFile(_ps, access, sharing, NULL, disposition,
|
||||
flagsAndAttributes, NULL);
|
||||
} END_PLATFORM_STRING(env, _ps);
|
||||
WCHAR *pathbuf = pathToNTPath(env, path, JNI_TRUE);
|
||||
if (pathbuf == NULL) {
|
||||
/* Exception already pending */
|
||||
return -1;
|
||||
}
|
||||
h = CreateFileW(
|
||||
pathbuf, /* Wide char path name */
|
||||
access, /* Read and/or write permission */
|
||||
sharing, /* File sharing flags */
|
||||
NULL, /* Security attributes */
|
||||
disposition, /* creation disposition */
|
||||
flagsAndAttributes, /* flags and attributes */
|
||||
NULL);
|
||||
free(pathbuf);
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
int error = GetLastError();
|
||||
if (error == ERROR_TOO_MANY_OPEN_FILES) {
|
||||
|
||||
@ -40,72 +40,6 @@
|
||||
*/
|
||||
#define PIPE_SIZE (4096+24)
|
||||
|
||||
char *
|
||||
extractExecutablePath(JNIEnv *env, char *source)
|
||||
{
|
||||
char *p, *r;
|
||||
|
||||
/* If no spaces, then use entire thing */
|
||||
if ((p = strchr(source, ' ')) == NULL)
|
||||
return source;
|
||||
|
||||
/* If no quotes, or quotes after space, return up to space */
|
||||
if (((r = strchr(source, '"')) == NULL) || (r > p)) {
|
||||
*p = 0;
|
||||
return source;
|
||||
}
|
||||
|
||||
/* Quotes before space, return up to space after next quotes */
|
||||
p = strchr(r, '"');
|
||||
if ((p = strchr(p, ' ')) == NULL)
|
||||
return source;
|
||||
*p = 0;
|
||||
return source;
|
||||
}
|
||||
|
||||
DWORD
|
||||
selectProcessFlag(JNIEnv *env, jstring cmd0)
|
||||
{
|
||||
char buf[MAX_PATH];
|
||||
DWORD newFlag = 0;
|
||||
char *exe, *p, *name;
|
||||
unsigned char buffer[2];
|
||||
long headerLoc = 0;
|
||||
int fd = 0;
|
||||
|
||||
exe = (char *)JNU_GetStringPlatformChars(env, cmd0, 0);
|
||||
exe = extractExecutablePath(env, exe);
|
||||
|
||||
if (exe != NULL) {
|
||||
if ((p = strchr(exe, '\\')) == NULL) {
|
||||
SearchPath(NULL, exe, ".exe", MAX_PATH, buf, &name);
|
||||
} else {
|
||||
p = strrchr(exe, '\\');
|
||||
*p = 0;
|
||||
p++;
|
||||
SearchPath(exe, p, ".exe", MAX_PATH, buf, &name);
|
||||
}
|
||||
}
|
||||
|
||||
fd = _open(buf, _O_RDONLY);
|
||||
if (fd > 0) {
|
||||
_read(fd, buffer, 2);
|
||||
if (buffer[0] == 'M' && buffer[1] == 'Z') {
|
||||
_lseek(fd, 60L, SEEK_SET);
|
||||
_read(fd, buffer, 2);
|
||||
headerLoc = (long)buffer[1] << 8 | (long)buffer[0];
|
||||
_lseek(fd, headerLoc, SEEK_SET);
|
||||
_read(fd, buffer, 2);
|
||||
if (buffer[0] == 'P' && buffer[1] == 'E') {
|
||||
newFlag = DETACHED_PROCESS;
|
||||
}
|
||||
}
|
||||
_close(fd);
|
||||
}
|
||||
JNU_ReleaseStringPlatformChars(env, cmd0, exe);
|
||||
return newFlag;
|
||||
}
|
||||
|
||||
static void
|
||||
win32Error(JNIEnv *env, const char *functionName)
|
||||
{
|
||||
@ -151,15 +85,8 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
|
||||
const jchar* penvBlock = NULL;
|
||||
jlong *handles = NULL;
|
||||
jlong ret = 0;
|
||||
OSVERSIONINFO ver;
|
||||
jboolean onNT = JNI_FALSE;
|
||||
DWORD processFlag;
|
||||
|
||||
ver.dwOSVersionInfoSize = sizeof(ver);
|
||||
GetVersionEx(&ver);
|
||||
if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
||||
onNT = JNI_TRUE;
|
||||
|
||||
assert(cmd != NULL);
|
||||
pcmd = (*env)->GetStringChars(env, cmd, NULL);
|
||||
if (pcmd == NULL) goto Catch;
|
||||
@ -229,10 +156,7 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
|
||||
}
|
||||
SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, TRUE);
|
||||
|
||||
if (onNT)
|
||||
processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
|
||||
else
|
||||
processFlag = selectProcessFlag(env, cmd) | CREATE_UNICODE_ENVIRONMENT;
|
||||
processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
|
||||
ret = CreateProcessW(0, /* executable name */
|
||||
(LPWSTR)pcmd, /* command line */
|
||||
0, /* process security attribute */
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2012, 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
|
||||
@ -65,8 +65,6 @@ static void *keyNames[] = {
|
||||
#define STANDARD_NAME 0
|
||||
#define STD_NAME 2
|
||||
|
||||
static int isNT = FALSE; /* TRUE if it is NT. */
|
||||
|
||||
/*
|
||||
* Calls RegQueryValueEx() to get the value for the specified key. If
|
||||
* the platform is NT, 2000 or XP, it calls the Unicode
|
||||
@ -95,12 +93,10 @@ getValueInRegistry(HKEY hKey,
|
||||
int len;
|
||||
|
||||
*typePtr = 0;
|
||||
if (isNT) {
|
||||
ret = RegQueryValueExW(hKey, (WCHAR *) keyNames[keyIndex], NULL,
|
||||
typePtr, buf, bufLengthPtr);
|
||||
if (ret == ERROR_SUCCESS && *typePtr == REG_SZ) {
|
||||
return ret;
|
||||
}
|
||||
ret = RegQueryValueExW(hKey, (WCHAR *) keyNames[keyIndex], NULL,
|
||||
typePtr, buf, bufLengthPtr);
|
||||
if (ret == ERROR_SUCCESS && *typePtr == REG_SZ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
valSize = sizeof(val);
|
||||
@ -180,8 +176,7 @@ static int getWinTimeZone(char *winZoneName, char *winMapID)
|
||||
*/
|
||||
ver.dwOSVersionInfoSize = sizeof(ver);
|
||||
GetVersionEx(&ver);
|
||||
isNT = ver.dwPlatformId == VER_PLATFORM_WIN32_NT;
|
||||
isVista = isNT && ver.dwMajorVersion >= 6;
|
||||
isVista = ver.dwMajorVersion >= 6;
|
||||
|
||||
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
|
||||
KEY_READ, (PHKEY)&hKey);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2012, 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/* @test
|
||||
* @bug 6344646
|
||||
* @summary tests that Win32FileSystem.hashCode() uses
|
||||
* @summary tests that WinNTFileSystem.hashCode() uses
|
||||
* locale independent case mapping.
|
||||
*/
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user