Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java
32288 views
/*1* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.fs;2627import java.nio.file.attribute.*;28import java.util.concurrent.TimeUnit;29import java.security.AccessController;30import sun.misc.Unsafe;31import sun.security.action.GetPropertyAction;3233import static sun.nio.fs.WindowsNativeDispatcher.*;34import static sun.nio.fs.WindowsConstants.*;3536/**37* Windows implementation of DosFileAttributes/BasicFileAttributes38*/3940class WindowsFileAttributes41implements DosFileAttributes42{43private static final Unsafe unsafe = Unsafe.getUnsafe();4445/*46* typedef struct _BY_HANDLE_FILE_INFORMATION {47* DWORD dwFileAttributes;48* FILETIME ftCreationTime;49* FILETIME ftLastAccessTime;50* FILETIME ftLastWriteTime;51* DWORD dwVolumeSerialNumber;52* DWORD nFileSizeHigh;53* DWORD nFileSizeLow;54* DWORD nNumberOfLinks;55* DWORD nFileIndexHigh;56* DWORD nFileIndexLow;57* } BY_HANDLE_FILE_INFORMATION;58*/59private static final short SIZEOF_FILE_INFORMATION = 52;60private static final short OFFSETOF_FILE_INFORMATION_ATTRIBUTES = 0;61private static final short OFFSETOF_FILE_INFORMATION_CREATETIME = 4;62private static final short OFFSETOF_FILE_INFORMATION_LASTACCESSTIME = 12;63private static final short OFFSETOF_FILE_INFORMATION_LASTWRITETIME = 20;64private static final short OFFSETOF_FILE_INFORMATION_VOLSERIALNUM = 28;65private static final short OFFSETOF_FILE_INFORMATION_SIZEHIGH = 32;66private static final short OFFSETOF_FILE_INFORMATION_SIZELOW = 36;67private static final short OFFSETOF_FILE_INFORMATION_INDEXHIGH = 44;68private static final short OFFSETOF_FILE_INFORMATION_INDEXLOW = 48;6970/*71* typedef struct _WIN32_FILE_ATTRIBUTE_DATA {72* DWORD dwFileAttributes;73* FILETIME ftCreationTime;74* FILETIME ftLastAccessTime;75* FILETIME ftLastWriteTime;76* DWORD nFileSizeHigh;77* DWORD nFileSizeLow;78* } WIN32_FILE_ATTRIBUTE_DATA;79*/80private static final short SIZEOF_FILE_ATTRIBUTE_DATA = 36;81private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES = 0;82private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME = 4;83private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME = 12;84private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME = 20;85private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH = 28;86private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW = 32;8788/**89* typedef struct _WIN32_FIND_DATA {90* DWORD dwFileAttributes;91* FILETIME ftCreationTime;92* FILETIME ftLastAccessTime;93* FILETIME ftLastWriteTime;94* DWORD nFileSizeHigh;95* DWORD nFileSizeLow;96* DWORD dwReserved0;97* DWORD dwReserved1;98* TCHAR cFileName[MAX_PATH];99* TCHAR cAlternateFileName[14];100* } WIN32_FIND_DATA;101*/102private static final short SIZEOF_FIND_DATA = 592;103private static final short OFFSETOF_FIND_DATA_ATTRIBUTES = 0;104private static final short OFFSETOF_FIND_DATA_CREATETIME = 4;105private static final short OFFSETOF_FIND_DATA_LASTACCESSTIME = 12;106private static final short OFFSETOF_FIND_DATA_LASTWRITETIME = 20;107private static final short OFFSETOF_FIND_DATA_SIZEHIGH = 28;108private static final short OFFSETOF_FIND_DATA_SIZELOW = 32;109private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36;110111// used to adjust values between Windows and java epoch112private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;113114// indicates if accurate metadata is required (interesting on NTFS only)115private static final boolean ensureAccurateMetadata;116static {117String propValue = AccessController.doPrivileged(118new GetPropertyAction("sun.nio.fs.ensureAccurateMetadata", "false"));119ensureAccurateMetadata = (propValue.length() == 0) ?120true : Boolean.valueOf(propValue);121}122123// attributes124private final int fileAttrs;125private final long creationTime;126private final long lastAccessTime;127private final long lastWriteTime;128private final long size;129private final int reparseTag;130131// additional attributes when using GetFileInformationByHandle132private final int volSerialNumber;133private final int fileIndexHigh;134private final int fileIndexLow;135136/**137* Convert 64-bit value representing the number of 100-nanosecond intervals138* since January 1, 1601 to a FileTime.139*/140static FileTime toFileTime(long time) {141// 100ns -> us142time /= 10L;143// adjust to java epoch144time += WINDOWS_EPOCH_IN_MICROSECONDS;145return FileTime.from(time, TimeUnit.MICROSECONDS);146}147148/**149* Convert FileTime to 64-bit value representing the number of 100-nanosecond150* intervals since January 1, 1601.151*/152static long toWindowsTime(FileTime time) {153long value = time.to(TimeUnit.MICROSECONDS);154// adjust to Windows epoch+= 11644473600000000L;155value -= WINDOWS_EPOCH_IN_MICROSECONDS;156// us -> 100ns157value *= 10L;158return value;159}160161/**162* Initialize a new instance of this class163*/164private WindowsFileAttributes(int fileAttrs,165long creationTime,166long lastAccessTime,167long lastWriteTime,168long size,169int reparseTag,170int volSerialNumber,171int fileIndexHigh,172int fileIndexLow)173{174this.fileAttrs = fileAttrs;175this.creationTime = creationTime;176this.lastAccessTime = lastAccessTime;177this.lastWriteTime = lastWriteTime;178this.size = size;179this.reparseTag = reparseTag;180this.volSerialNumber = volSerialNumber;181this.fileIndexHigh = fileIndexHigh;182this.fileIndexLow = fileIndexLow;183}184185/**186* Create a WindowsFileAttributes from a BY_HANDLE_FILE_INFORMATION structure187*/188private static WindowsFileAttributes fromFileInformation(long address, int reparseTag) {189int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);190long creationTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_CREATETIME);191long lastAccessTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTACCESSTIME);192long lastWriteTime = unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTWRITETIME);193long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZEHIGH)) << 32)194+ (unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZELOW) & 0xFFFFFFFFL);195int volSerialNumber = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_VOLSERIALNUM);196int fileIndexHigh = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXHIGH);197int fileIndexLow = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXLOW);198return new WindowsFileAttributes(fileAttrs,199creationTime,200lastAccessTime,201lastWriteTime,202size,203reparseTag,204volSerialNumber,205fileIndexHigh,206fileIndexLow);207}208209/**210* Create a WindowsFileAttributes from a WIN32_FILE_ATTRIBUTE_DATA structure211*/212private static WindowsFileAttributes fromFileAttributeData(long address, int reparseTag) {213int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);214long creationTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME);215long lastAccessTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME);216long lastWriteTime = unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME);217long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH)) << 32)218+ (unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW) & 0xFFFFFFFFL);219return new WindowsFileAttributes(fileAttrs,220creationTime,221lastAccessTime,222lastWriteTime,223size,224reparseTag,2250, // volSerialNumber2260, // fileIndexHigh2270); // fileIndexLow228}229230231/**232* Allocates a native buffer for a WIN32_FIND_DATA structure233*/234static NativeBuffer getBufferForFindData() {235return NativeBuffers.getNativeBuffer(SIZEOF_FIND_DATA);236}237238/**239* Create a WindowsFileAttributes from a WIN32_FIND_DATA structure240*/241static WindowsFileAttributes fromFindData(long address) {242int fileAttrs = unsafe.getInt(address + OFFSETOF_FIND_DATA_ATTRIBUTES);243long creationTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_CREATETIME);244long lastAccessTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTACCESSTIME);245long lastWriteTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME);246long size = ((long)(unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZEHIGH)) << 32)247+ (unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZELOW) & 0xFFFFFFFFL);248int reparseTag = isReparsePoint(fileAttrs) ?249unsafe.getInt(address + OFFSETOF_FIND_DATA_RESERVED0) : 0;250return new WindowsFileAttributes(fileAttrs,251creationTime,252lastAccessTime,253lastWriteTime,254size,255reparseTag,2560, // volSerialNumber2570, // fileIndexHigh2580); // fileIndexLow259}260261/**262* Reads the attributes of an open file263*/264static WindowsFileAttributes readAttributes(long handle)265throws WindowsException266{267NativeBuffer buffer = NativeBuffers268.getNativeBuffer(SIZEOF_FILE_INFORMATION);269try {270long address = buffer.address();271GetFileInformationByHandle(handle, address);272273// if file is a reparse point then read the tag274int reparseTag = 0;275int fileAttrs = unsafe276.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);277if (isReparsePoint(fileAttrs)) {278int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;279NativeBuffer reparseBuffer = NativeBuffers.getNativeBuffer(size);280try {281DeviceIoControlGetReparsePoint(handle, reparseBuffer.address(), size);282reparseTag = (int)unsafe.getLong(reparseBuffer.address());283} finally {284reparseBuffer.release();285}286}287288return fromFileInformation(address, reparseTag);289} finally {290buffer.release();291}292}293294/**295* Returns attributes of given file.296*/297static WindowsFileAttributes get(WindowsPath path, boolean followLinks)298throws WindowsException299{300if (!ensureAccurateMetadata) {301WindowsException firstException = null;302303// GetFileAttributesEx is the fastest way to read the attributes304NativeBuffer buffer =305NativeBuffers.getNativeBuffer(SIZEOF_FILE_ATTRIBUTE_DATA);306try {307long address = buffer.address();308GetFileAttributesEx(path.getPathForWin32Calls(), address);309// if reparse point then file may be a sym link; otherwise310// just return the attributes311int fileAttrs = unsafe312.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);313if (!isReparsePoint(fileAttrs))314return fromFileAttributeData(address, 0);315} catch (WindowsException x) {316if (x.lastError() != ERROR_SHARING_VIOLATION)317throw x;318firstException = x;319} finally {320buffer.release();321}322323// For sharing violations, fallback to FindFirstFile if the file324// is not a root directory.325if (firstException != null) {326String search = path.getPathForWin32Calls();327char last = search.charAt(search.length() -1);328if (last == ':' || last == '\\')329throw firstException;330buffer = getBufferForFindData();331try {332long handle = FindFirstFile(search, buffer.address());333FindClose(handle);334WindowsFileAttributes attrs = fromFindData(buffer.address());335// FindFirstFile does not follow sym links. Even if336// followLinks is false, there isn't sufficient information337// in the WIN32_FIND_DATA structure to know if the reparse338// point is a sym link.339if (attrs.isReparsePoint())340throw firstException;341return attrs;342} catch (WindowsException ignore) {343throw firstException;344} finally {345buffer.release();346}347}348}349350// file is reparse point so need to open file to get attributes351long handle = path.openForReadAttributeAccess(followLinks);352try {353return readAttributes(handle);354} finally {355CloseHandle(handle);356}357}358359/**360* Returns true if the attributes are of the same file - both files must361* be open.362*/363static boolean isSameFile(WindowsFileAttributes attrs1,364WindowsFileAttributes attrs2)365{366// volume serial number and file index must be the same367return (attrs1.volSerialNumber == attrs2.volSerialNumber) &&368(attrs1.fileIndexHigh == attrs2.fileIndexHigh) &&369(attrs1.fileIndexLow == attrs2.fileIndexLow);370}371372/**373* Returns true if the attributes are of a file with a reparse point.374*/375static boolean isReparsePoint(int attributes) {376return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;377}378379// package-private380int attributes() {381return fileAttrs;382}383384int volSerialNumber() {385return volSerialNumber;386}387388int fileIndexHigh() {389return fileIndexHigh;390}391392int fileIndexLow() {393return fileIndexLow;394}395396@Override397public long size() {398return size;399}400401@Override402public FileTime lastModifiedTime() {403return toFileTime(lastWriteTime);404}405406@Override407public FileTime lastAccessTime() {408return toFileTime(lastAccessTime);409}410411@Override412public FileTime creationTime() {413return toFileTime(creationTime);414}415416@Override417public Object fileKey() {418return null;419}420421// package private422boolean isReparsePoint() {423return isReparsePoint(fileAttrs);424}425426boolean isDirectoryLink() {427return isSymbolicLink() && ((fileAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0);428}429430@Override431public boolean isSymbolicLink() {432return reparseTag == IO_REPARSE_TAG_SYMLINK;433}434435@Override436public boolean isDirectory() {437// ignore FILE_ATTRIBUTE_DIRECTORY attribute if file is a sym link438if (isSymbolicLink())439return false;440return ((fileAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0);441}442443@Override444public boolean isOther() {445if (isSymbolicLink())446return false;447// return true if device or reparse point448return ((fileAttrs & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0);449}450451@Override452public boolean isRegularFile() {453return !isSymbolicLink() && !isDirectory() && !isOther();454}455456@Override457public boolean isReadOnly() {458return (fileAttrs & FILE_ATTRIBUTE_READONLY) != 0;459}460461@Override462public boolean isHidden() {463return (fileAttrs & FILE_ATTRIBUTE_HIDDEN) != 0;464}465466@Override467public boolean isArchive() {468return (fileAttrs & FILE_ATTRIBUTE_ARCHIVE) != 0;469}470471@Override472public boolean isSystem() {473return (fileAttrs & FILE_ATTRIBUTE_SYSTEM) != 0;474}475}476477478