mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-06 18:53:37 +00:00
539 lines
22 KiB
Java
539 lines
22 KiB
Java
/*
|
|
* Copyright (c) 2008, 2026, 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 sun.nio.fs;
|
|
|
|
import java.nio.file.attribute.*;
|
|
import java.util.concurrent.TimeUnit;
|
|
import jdk.internal.misc.Unsafe;
|
|
|
|
import static sun.nio.fs.WindowsNativeDispatcher.*;
|
|
import static sun.nio.fs.WindowsConstants.*;
|
|
|
|
/**
|
|
* Windows implementation of DosFileAttributes/BasicFileAttributes
|
|
*/
|
|
|
|
class WindowsFileAttributes
|
|
implements DosFileAttributes
|
|
{
|
|
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
|
|
|
/*
|
|
* typedef struct _BY_HANDLE_FILE_INFORMATION {
|
|
* DWORD dwFileAttributes;
|
|
* FILETIME ftCreationTime;
|
|
* FILETIME ftLastAccessTime;
|
|
* FILETIME ftLastWriteTime;
|
|
* DWORD dwVolumeSerialNumber;
|
|
* DWORD nFileSizeHigh;
|
|
* DWORD nFileSizeLow;
|
|
* DWORD nNumberOfLinks;
|
|
* DWORD nFileIndexHigh;
|
|
* DWORD nFileIndexLow;
|
|
* } BY_HANDLE_FILE_INFORMATION;
|
|
*/
|
|
private static final short SIZEOF_FILE_INFORMATION = 52;
|
|
private static final short OFFSETOF_FILE_INFORMATION_ATTRIBUTES = 0;
|
|
private static final short OFFSETOF_FILE_INFORMATION_CREATETIME = 4;
|
|
private static final short OFFSETOF_FILE_INFORMATION_LASTACCESSTIME = 12;
|
|
private static final short OFFSETOF_FILE_INFORMATION_LASTWRITETIME = 20;
|
|
private static final short OFFSETOF_FILE_INFORMATION_VOLSERIALNUM = 28;
|
|
private static final short OFFSETOF_FILE_INFORMATION_SIZEHIGH = 32;
|
|
private static final short OFFSETOF_FILE_INFORMATION_SIZELOW = 36;
|
|
private static final short OFFSETOF_FILE_INFORMATION_INDEXHIGH = 44;
|
|
private static final short OFFSETOF_FILE_INFORMATION_INDEXLOW = 48;
|
|
|
|
/*
|
|
* typedef struct _WIN32_FILE_ATTRIBUTE_DATA {
|
|
* DWORD dwFileAttributes;
|
|
* FILETIME ftCreationTime;
|
|
* FILETIME ftLastAccessTime;
|
|
* FILETIME ftLastWriteTime;
|
|
* DWORD nFileSizeHigh;
|
|
* DWORD nFileSizeLow;
|
|
* } WIN32_FILE_ATTRIBUTE_DATA;
|
|
*/
|
|
private static final short SIZEOF_FILE_ATTRIBUTE_DATA = 36;
|
|
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES = 0;
|
|
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME = 4;
|
|
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME = 12;
|
|
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME = 20;
|
|
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH = 28;
|
|
private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW = 32;
|
|
|
|
/**
|
|
* typedef struct _WIN32_FIND_DATA {
|
|
* DWORD dwFileAttributes;
|
|
* FILETIME ftCreationTime;
|
|
* FILETIME ftLastAccessTime;
|
|
* FILETIME ftLastWriteTime;
|
|
* DWORD nFileSizeHigh;
|
|
* DWORD nFileSizeLow;
|
|
* DWORD dwReserved0;
|
|
* DWORD dwReserved1;
|
|
* TCHAR cFileName[MAX_PATH];
|
|
* TCHAR cAlternateFileName[14];
|
|
* } WIN32_FIND_DATA;
|
|
*/
|
|
private static final short SIZEOF_FIND_DATA = 592;
|
|
private static final short OFFSETOF_FIND_DATA_ATTRIBUTES = 0;
|
|
private static final short OFFSETOF_FIND_DATA_CREATETIME = 4;
|
|
private static final short OFFSETOF_FIND_DATA_LASTACCESSTIME = 12;
|
|
private static final short OFFSETOF_FIND_DATA_LASTWRITETIME = 20;
|
|
private static final short OFFSETOF_FIND_DATA_SIZEHIGH = 28;
|
|
private static final short OFFSETOF_FIND_DATA_SIZELOW = 32;
|
|
private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36;
|
|
|
|
/*
|
|
* typedef struct _FILE_STAT_BASIC_INFORMATION {
|
|
* LARGE_INTEGER FileId; // offset = 0
|
|
* LARGE_INTEGER CreationTime; // offset = 8
|
|
* LARGE_INTEGER LastAccessTime; // offset = 16
|
|
* LARGE_INTEGER LastWriteTime; // offset = 24
|
|
* LARGE_INTEGER ChangeTime; // offset = 32
|
|
* LARGE_INTEGER AllocationSize; // offset = 40
|
|
* LARGE_INTEGER EndOfFile; // offset = 48
|
|
* ULONG FileAttributes; // offset = 56
|
|
* ULONG ReparseTag; // offset = 60
|
|
* ULONG NumberOfLinks; // offset = 64
|
|
* ULONG DeviceType; // offset = 68
|
|
* ULONG DeviceCharacteristics; // offset = 72
|
|
* ULONG Reserved; // offset = 76
|
|
* LARGE_INTEGER VolumeSerialNumber; // offset = 80
|
|
* FILE_ID_128 FileId128; // offset = 88
|
|
* } FILE_STAT_BASIC_INFORMATION;
|
|
*/
|
|
private static final short SIZEOF_STAT_BASIC_INFO = 104;
|
|
private static final short OFFSETOF_STAT_BASIC_INFO_FILEID = 0;
|
|
private static final short OFFSETOF_STAT_BASIC_INFO_CREATETIME = 8;
|
|
private static final short OFFSETOF_STAT_BASIC_INFO_LASTACCESSTIME = 16;
|
|
private static final short OFFSETOF_STAT_BASIC_INFO_LASTWRITETIME = 24;
|
|
private static final short OFFSETOF_STAT_BASIC_INFO_ENDOFFILE = 48;
|
|
private static final short OFFSETOF_STAT_BASIC_INFO_ATTRIBUTES = 56;
|
|
private static final short OFFSETOF_STAT_BASIC_INFO_REPARSETAG = 60;
|
|
private static final short OFFSETOF_STAT_BASIC_INFO_VOLSERIAL = 80;
|
|
|
|
// used to adjust values between Windows and java epochs
|
|
private static final long WINDOWS_EPOCH_IN_MICROS = -11644473600000000L;
|
|
private static final long WINDOWS_EPOCH_IN_100NS = -116444736000000000L;
|
|
|
|
// indicates if accurate metadata is required (interesting on NTFS only)
|
|
private static final boolean ensureAccurateMetadata;
|
|
static {
|
|
String propValue =
|
|
System.getProperty("sun.nio.fs.ensureAccurateMetadata", "false");
|
|
ensureAccurateMetadata = propValue.isEmpty() ? true : Boolean.parseBoolean(propValue);
|
|
}
|
|
|
|
// attributes
|
|
private final int fileAttrs;
|
|
private final long creationTime;
|
|
private final long lastAccessTime;
|
|
private final long lastWriteTime;
|
|
private final long size;
|
|
private final int reparseTag;
|
|
|
|
// additional attributes when using GetFileInformationByHandle
|
|
private final int volSerialNumber;
|
|
private final int fileIndexHigh;
|
|
private final int fileIndexLow;
|
|
|
|
/**
|
|
* Convert 64-bit value representing the number of 100-nanosecond intervals
|
|
* since January 1, 1601 to a FileTime.
|
|
*/
|
|
static FileTime toFileTime(long time) {
|
|
try {
|
|
long adjusted = Math.addExact(time, WINDOWS_EPOCH_IN_100NS);
|
|
long nanos = Math.multiplyExact(adjusted, 100L);
|
|
return FileTime.from(nanos, TimeUnit.NANOSECONDS);
|
|
} catch (ArithmeticException e) {
|
|
long micros = Math.addExact(time/10L, WINDOWS_EPOCH_IN_MICROS);
|
|
return FileTime.from(micros, TimeUnit.MICROSECONDS);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert FileTime to 64-bit value representing the number of
|
|
* 100-nanosecond intervals since January 1, 1601.
|
|
*/
|
|
static long toWindowsTime(FileTime time) {
|
|
long adjusted = time.to(TimeUnit.NANOSECONDS)/100L;
|
|
return adjusted - WINDOWS_EPOCH_IN_100NS;
|
|
}
|
|
|
|
/**
|
|
* Initialize a new instance of this class
|
|
*/
|
|
private WindowsFileAttributes(int fileAttrs,
|
|
long creationTime,
|
|
long lastAccessTime,
|
|
long lastWriteTime,
|
|
long size,
|
|
int reparseTag,
|
|
int volSerialNumber,
|
|
int fileIndexHigh,
|
|
int fileIndexLow)
|
|
{
|
|
this.fileAttrs = fileAttrs;
|
|
this.creationTime = creationTime;
|
|
this.lastAccessTime = lastAccessTime;
|
|
this.lastWriteTime = lastWriteTime;
|
|
this.size = size;
|
|
this.reparseTag = reparseTag;
|
|
this.volSerialNumber = volSerialNumber;
|
|
this.fileIndexHigh = fileIndexHigh;
|
|
this.fileIndexLow = fileIndexLow;
|
|
}
|
|
|
|
/**
|
|
* Create a WindowsFileAttributes from a BY_HANDLE_FILE_INFORMATION structure
|
|
*/
|
|
private static WindowsFileAttributes fromFileInformation(long address, int reparseTag) {
|
|
int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);
|
|
long creationTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_CREATETIME);
|
|
long lastAccessTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTACCESSTIME);
|
|
long lastWriteTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTWRITETIME);
|
|
long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZEHIGH)) << 32)
|
|
+ (unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZELOW) & 0xFFFFFFFFL);
|
|
int volSerialNumber = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_VOLSERIALNUM);
|
|
int fileIndexHigh = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXHIGH);
|
|
int fileIndexLow = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXLOW);
|
|
return new WindowsFileAttributes(fileAttrs,
|
|
creationTime,
|
|
lastAccessTime,
|
|
lastWriteTime,
|
|
size,
|
|
reparseTag,
|
|
volSerialNumber,
|
|
fileIndexHigh,
|
|
fileIndexLow);
|
|
}
|
|
|
|
/**
|
|
* Create a WindowsFileAttributes from a WIN32_FILE_ATTRIBUTE_DATA structure
|
|
*/
|
|
private static WindowsFileAttributes fromFileAttributeData(long address, int reparseTag) {
|
|
int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
|
|
long creationTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME);
|
|
long lastAccessTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME);
|
|
long lastWriteTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME);
|
|
long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH)) << 32)
|
|
+ (unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW) & 0xFFFFFFFFL);
|
|
return new WindowsFileAttributes(fileAttrs,
|
|
creationTime,
|
|
lastAccessTime,
|
|
lastWriteTime,
|
|
size,
|
|
reparseTag,
|
|
0, // volSerialNumber
|
|
0, // fileIndexHigh
|
|
0); // fileIndexLow
|
|
}
|
|
|
|
|
|
/**
|
|
* Create a WindowsFileAttributes from a FILE_STAT_BASIC_INFORMATION structure
|
|
*/
|
|
static WindowsFileAttributes fromStatBasicInfo(long address) {
|
|
int fileAttrs = unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_ATTRIBUTES);
|
|
long creationTime = unsafe.getLong(address + OFFSETOF_STAT_BASIC_INFO_CREATETIME);
|
|
long lastAccessTime = unsafe.getLong(address + OFFSETOF_STAT_BASIC_INFO_LASTACCESSTIME);
|
|
long lastWriteTime = unsafe.getLong(address + OFFSETOF_STAT_BASIC_INFO_LASTWRITETIME);
|
|
long size = unsafe.getLong(address + OFFSETOF_STAT_BASIC_INFO_ENDOFFILE);
|
|
int reparseTag = isReparsePoint(fileAttrs) ?
|
|
unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_REPARSETAG) : 0;
|
|
int volSerialNumber = unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_VOLSERIAL);
|
|
int fileIndexLow = unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_FILEID);
|
|
int fileIndexHigh = unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_FILEID + 4);
|
|
|
|
return new WindowsFileAttributes(fileAttrs,
|
|
creationTime,
|
|
lastAccessTime,
|
|
lastWriteTime,
|
|
size,
|
|
reparseTag,
|
|
volSerialNumber,
|
|
fileIndexHigh,
|
|
fileIndexLow);
|
|
}
|
|
|
|
/**
|
|
* Allocates a native buffer for a WIN32_FIND_DATA structure
|
|
*/
|
|
static NativeBuffer getBufferForFindData() {
|
|
return NativeBuffers.getNativeBuffer(SIZEOF_FIND_DATA);
|
|
}
|
|
|
|
/**
|
|
* Create a WindowsFileAttributes from a WIN32_FIND_DATA structure
|
|
*/
|
|
static WindowsFileAttributes fromFindData(long address) {
|
|
int fileAttrs = unsafe.getInt(address + OFFSETOF_FIND_DATA_ATTRIBUTES);
|
|
long creationTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_CREATETIME);
|
|
long lastAccessTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTACCESSTIME);
|
|
long lastWriteTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME);
|
|
long size = ((long)(unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZEHIGH)) << 32)
|
|
+ (unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZELOW) & 0xFFFFFFFFL);
|
|
int reparseTag = isReparsePoint(fileAttrs) ?
|
|
unsafe.getInt(address + OFFSETOF_FIND_DATA_RESERVED0) : 0;
|
|
return new WindowsFileAttributes(fileAttrs,
|
|
creationTime,
|
|
lastAccessTime,
|
|
lastWriteTime,
|
|
size,
|
|
reparseTag,
|
|
0, // volSerialNumber
|
|
0, // fileIndexHigh
|
|
0); // fileIndexLow
|
|
}
|
|
|
|
/**
|
|
* Reads the attributes of an open file
|
|
*/
|
|
static WindowsFileAttributes readAttributes(long handle)
|
|
throws WindowsException
|
|
{
|
|
try (NativeBuffer buffer = NativeBuffers.getNativeBuffer(SIZEOF_FILE_INFORMATION)) {
|
|
long address = buffer.address();
|
|
GetFileInformationByHandle(handle, address);
|
|
|
|
// if file is a reparse point then read the tag
|
|
int reparseTag = 0;
|
|
int fileAttrs = unsafe
|
|
.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);
|
|
if (isReparsePoint(fileAttrs)) {
|
|
int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
|
|
try (NativeBuffer reparseBuffer = NativeBuffers.getNativeBuffer(size)) {
|
|
DeviceIoControlGetReparsePoint(handle, reparseBuffer.address(), size);
|
|
reparseTag = (int)unsafe.getLong(reparseBuffer.address());
|
|
}
|
|
}
|
|
|
|
return fromFileInformation(address, reparseTag);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns attributes of given file.
|
|
*/
|
|
static WindowsFileAttributes get(WindowsPath path, boolean followLinks)
|
|
throws WindowsException
|
|
{
|
|
if (!ensureAccurateMetadata) {
|
|
WindowsException firstException = null;
|
|
|
|
// GetFileAttributesEx is the fastest way to read the attributes
|
|
try (NativeBuffer buffer =
|
|
NativeBuffers.getNativeBuffer(SIZEOF_FILE_ATTRIBUTE_DATA)) {
|
|
long address = buffer.address();
|
|
GetFileAttributesEx(path.getPathForWin32Calls(), address);
|
|
// if reparse point then file may be a sym link; otherwise
|
|
// just return the attributes
|
|
int fileAttrs = unsafe
|
|
.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
|
|
if (!isReparsePoint(fileAttrs))
|
|
return fromFileAttributeData(address, 0);
|
|
} catch (WindowsException x) {
|
|
if (x.lastError() != ERROR_SHARING_VIOLATION)
|
|
throw x;
|
|
firstException = x;
|
|
}
|
|
|
|
// For sharing violations, fallback to FindFirstFile if the file
|
|
// is not a root directory.
|
|
if (firstException != null) {
|
|
String search = path.getPathForWin32Calls();
|
|
char last = search.charAt(search.length() -1);
|
|
if (last == ':' || last == '\\')
|
|
throw firstException;
|
|
try (NativeBuffer buffer = getBufferForFindData()) {
|
|
long handle = FindFirstFile(search, buffer.address());
|
|
FindClose(handle);
|
|
WindowsFileAttributes attrs = fromFindData(buffer.address());
|
|
// FindFirstFile does not follow sym links. Even if
|
|
// followLinks is false, there isn't sufficient information
|
|
// in the WIN32_FIND_DATA structure to know if the reparse
|
|
// point is a sym link.
|
|
if (attrs.isReparsePoint())
|
|
throw firstException;
|
|
return attrs;
|
|
} catch (WindowsException ignore) {
|
|
throw firstException;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (supportsGetFileInformationByName()) {
|
|
try (NativeBuffer buffer = NativeBuffers.getNativeBuffer(SIZEOF_STAT_BASIC_INFO)) {
|
|
long addr = buffer.address();
|
|
GetFileInformationByName(path.getPathForWin32Calls(),
|
|
FileStatBasicByNameInfo, addr,
|
|
SIZEOF_STAT_BASIC_INFO);
|
|
|
|
// GetFileInformationByName() doesn't follow reparse points so if
|
|
// we discover that this is a reparse point and if we're being asked
|
|
// to follow links, then drop to the slow path.
|
|
int fileAttrs = unsafe.getInt(addr + OFFSETOF_STAT_BASIC_INFO_ATTRIBUTES);
|
|
if (!isReparsePoint(fileAttrs) || !followLinks) {
|
|
return fromStatBasicInfo(addr);
|
|
}
|
|
}
|
|
}
|
|
|
|
// file is reparse point so need to open file to get attributes
|
|
long handle = path.openForReadAttributeAccess(followLinks);
|
|
try {
|
|
return readAttributes(handle);
|
|
} finally {
|
|
CloseHandle(handle);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the attributes are of the same file - both files must
|
|
* be open.
|
|
*/
|
|
static boolean isSameFile(WindowsFileAttributes attrs1,
|
|
WindowsFileAttributes attrs2)
|
|
{
|
|
// volume serial number and file index must be the same
|
|
return (attrs1.volSerialNumber == attrs2.volSerialNumber) &&
|
|
(attrs1.fileIndexHigh == attrs2.fileIndexHigh) &&
|
|
(attrs1.fileIndexLow == attrs2.fileIndexLow);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the attributes are of a file with a reparse point.
|
|
*/
|
|
static boolean isReparsePoint(int attributes) {
|
|
return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
|
|
}
|
|
|
|
// package-private
|
|
int attributes() {
|
|
return fileAttrs;
|
|
}
|
|
|
|
int volSerialNumber() {
|
|
return volSerialNumber;
|
|
}
|
|
|
|
int fileIndexHigh() {
|
|
return fileIndexHigh;
|
|
}
|
|
|
|
int fileIndexLow() {
|
|
return fileIndexLow;
|
|
}
|
|
|
|
@Override
|
|
public long size() {
|
|
return size;
|
|
}
|
|
|
|
@Override
|
|
public FileTime lastModifiedTime() {
|
|
return toFileTime(lastWriteTime);
|
|
}
|
|
|
|
@Override
|
|
public FileTime lastAccessTime() {
|
|
return toFileTime(lastAccessTime);
|
|
}
|
|
|
|
@Override
|
|
public FileTime creationTime() {
|
|
return toFileTime(creationTime);
|
|
}
|
|
|
|
@Override
|
|
public Object fileKey() {
|
|
return null;
|
|
}
|
|
|
|
// package private
|
|
boolean isReparsePoint() {
|
|
return isReparsePoint(fileAttrs);
|
|
}
|
|
|
|
boolean isDirectoryLink() {
|
|
return isSymbolicLink() && ((fileAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
|
}
|
|
|
|
boolean isDirectoryJunction() {
|
|
return reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
|
|
}
|
|
|
|
@Override
|
|
public boolean isSymbolicLink() {
|
|
return reparseTag == IO_REPARSE_TAG_SYMLINK;
|
|
}
|
|
|
|
boolean isUnixDomainSocket() {
|
|
return reparseTag == IO_REPARSE_TAG_AF_UNIX;
|
|
}
|
|
|
|
@Override
|
|
public boolean isDirectory() {
|
|
return ((fileAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0 &&
|
|
(fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0);
|
|
}
|
|
|
|
@Override
|
|
public boolean isOther() {
|
|
if (isSymbolicLink())
|
|
return false;
|
|
// return true if device or reparse point
|
|
return ((fileAttrs & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0);
|
|
}
|
|
|
|
@Override
|
|
public boolean isRegularFile() {
|
|
return !isSymbolicLink() && !isDirectory() && !isOther();
|
|
}
|
|
|
|
@Override
|
|
public boolean isReadOnly() {
|
|
return (fileAttrs & FILE_ATTRIBUTE_READONLY) != 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean isHidden() {
|
|
return (fileAttrs & FILE_ATTRIBUTE_HIDDEN) != 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean isArchive() {
|
|
return (fileAttrs & FILE_ATTRIBUTE_ARCHIVE) != 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean isSystem() {
|
|
return (fileAttrs & FILE_ATTRIBUTE_SYSTEM) != 0;
|
|
}
|
|
}
|