Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java
32288 views
/*1* Copyright (c) 2008, 2013, 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.*;28import java.nio.file.attribute.*;29import java.nio.channels.*;30import java.net.URI;31import java.util.concurrent.ExecutorService;32import java.io.*;33import java.util.*;34import java.security.AccessController;35import sun.misc.Unsafe;36import sun.nio.ch.ThreadPool;37import sun.security.util.SecurityConstants;3839import static sun.nio.fs.WindowsNativeDispatcher.*;40import static sun.nio.fs.WindowsSecurity.*;41import static sun.nio.fs.WindowsConstants.*;4243public class WindowsFileSystemProvider44extends AbstractFileSystemProvider45{46private static final Unsafe unsafe = Unsafe.getUnsafe();4748private static final String USER_DIR = "user.dir";49private final WindowsFileSystem theFileSystem;5051public WindowsFileSystemProvider() {52theFileSystem = new WindowsFileSystem(this, System.getProperty(USER_DIR));53}5455@Override56public String getScheme() {57return "file";58}5960private void checkUri(URI uri) {61if (!uri.getScheme().equalsIgnoreCase(getScheme()))62throw new IllegalArgumentException("URI does not match this provider");63if (uri.getAuthority() != null)64throw new IllegalArgumentException("Authority component present");65if (uri.getPath() == null)66throw new IllegalArgumentException("Path component is undefined");67if (!uri.getPath().equals("/"))68throw new IllegalArgumentException("Path component should be '/'");69if (uri.getQuery() != null)70throw new IllegalArgumentException("Query component present");71if (uri.getFragment() != null)72throw new IllegalArgumentException("Fragment component present");73}7475@Override76public FileSystem newFileSystem(URI uri, Map<String,?> env)77throws IOException78{79checkUri(uri);80throw new FileSystemAlreadyExistsException();81}8283@Override84public final FileSystem getFileSystem(URI uri) {85checkUri(uri);86return theFileSystem;87}8889@Override90public Path getPath(URI uri) {91return WindowsUriSupport.fromUri(theFileSystem, uri);92}9394@Override95public FileChannel newFileChannel(Path path,96Set<? extends OpenOption> options,97FileAttribute<?>... attrs)98throws IOException99{100if (path == null)101throw new NullPointerException();102if (!(path instanceof WindowsPath))103throw new ProviderMismatchException();104WindowsPath file = (WindowsPath)path;105106WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs);107try {108return WindowsChannelFactory109.newFileChannel(file.getPathForWin32Calls(),110file.getPathForPermissionCheck(),111options,112sd.address());113} catch (WindowsException x) {114x.rethrowAsIOException(file);115return null;116} finally {117if (sd != null)118sd.release();119}120}121122@Override123public AsynchronousFileChannel newAsynchronousFileChannel(Path path,124Set<? extends OpenOption> options,125ExecutorService executor,126FileAttribute<?>... attrs)127throws IOException128{129if (path == null)130throw new NullPointerException();131if (!(path instanceof WindowsPath))132throw new ProviderMismatchException();133WindowsPath file = (WindowsPath)path;134ThreadPool pool = (executor == null) ? null : ThreadPool.wrap(executor, 0);135WindowsSecurityDescriptor sd =136WindowsSecurityDescriptor.fromAttribute(attrs);137try {138return WindowsChannelFactory139.newAsynchronousFileChannel(file.getPathForWin32Calls(),140file.getPathForPermissionCheck(),141options,142sd.address(),143pool);144} catch (WindowsException x) {145x.rethrowAsIOException(file);146return null;147} finally {148if (sd != null)149sd.release();150}151}152153@Override154@SuppressWarnings("unchecked")155public <V extends FileAttributeView> V156getFileAttributeView(Path obj, Class<V> view, LinkOption... options)157{158WindowsPath file = WindowsPath.toWindowsPath(obj);159if (view == null)160throw new NullPointerException();161boolean followLinks = Util.followLinks(options);162if (view == BasicFileAttributeView.class)163return (V) WindowsFileAttributeViews.createBasicView(file, followLinks);164if (view == DosFileAttributeView.class)165return (V) WindowsFileAttributeViews.createDosView(file, followLinks);166if (view == AclFileAttributeView.class)167return (V) new WindowsAclFileAttributeView(file, followLinks);168if (view == FileOwnerAttributeView.class)169return (V) new FileOwnerAttributeViewImpl(170new WindowsAclFileAttributeView(file, followLinks));171if (view == UserDefinedFileAttributeView.class)172return (V) new WindowsUserDefinedFileAttributeView(file, followLinks);173return (V) null;174}175176@Override177@SuppressWarnings("unchecked")178public <A extends BasicFileAttributes> A readAttributes(Path file,179Class<A> type,180LinkOption... options)181throws IOException182{183Class<? extends BasicFileAttributeView> view;184if (type == BasicFileAttributes.class)185view = BasicFileAttributeView.class;186else if (type == DosFileAttributes.class)187view = DosFileAttributeView.class;188else if (type == null)189throw new NullPointerException();190else191throw new UnsupportedOperationException();192return (A) getFileAttributeView(file, view, options).readAttributes();193}194195@Override196public DynamicFileAttributeView getFileAttributeView(Path obj, String name, LinkOption... options) {197WindowsPath file = WindowsPath.toWindowsPath(obj);198boolean followLinks = Util.followLinks(options);199if (name.equals("basic"))200return WindowsFileAttributeViews.createBasicView(file, followLinks);201if (name.equals("dos"))202return WindowsFileAttributeViews.createDosView(file, followLinks);203if (name.equals("acl"))204return new WindowsAclFileAttributeView(file, followLinks);205if (name.equals("owner"))206return new FileOwnerAttributeViewImpl(207new WindowsAclFileAttributeView(file, followLinks));208if (name.equals("user"))209return new WindowsUserDefinedFileAttributeView(file, followLinks);210return null;211}212213@Override214public SeekableByteChannel newByteChannel(Path obj,215Set<? extends OpenOption> options,216FileAttribute<?>... attrs)217throws IOException218{219WindowsPath file = WindowsPath.toWindowsPath(obj);220WindowsSecurityDescriptor sd =221WindowsSecurityDescriptor.fromAttribute(attrs);222try {223return WindowsChannelFactory224.newFileChannel(file.getPathForWin32Calls(),225file.getPathForPermissionCheck(),226options,227sd.address());228} catch (WindowsException x) {229x.rethrowAsIOException(file);230return null; // keep compiler happy231} finally {232sd.release();233}234}235236@Override237boolean implDelete(Path obj, boolean failIfNotExists) throws IOException {238WindowsPath file = WindowsPath.toWindowsPath(obj);239file.checkDelete();240241WindowsFileAttributes attrs = null;242try {243// need to know if file is a directory or junction244attrs = WindowsFileAttributes.get(file, false);245if (attrs.isDirectory() || attrs.isDirectoryLink()) {246RemoveDirectory(file.getPathForWin32Calls());247} else {248DeleteFile(file.getPathForWin32Calls());249}250return true;251} catch (WindowsException x) {252253// no-op if file does not exist254if (!failIfNotExists &&255(x.lastError() == ERROR_FILE_NOT_FOUND ||256x.lastError() == ERROR_PATH_NOT_FOUND)) return false;257258if (attrs != null && attrs.isDirectory()) {259// ERROR_ALREADY_EXISTS is returned when attempting to delete260// non-empty directory on SAMBA servers.261if (x.lastError() == ERROR_DIR_NOT_EMPTY ||262x.lastError() == ERROR_ALREADY_EXISTS)263{264throw new DirectoryNotEmptyException(265file.getPathForExceptionMessage());266}267}268x.rethrowAsIOException(file);269return false;270}271}272273@Override274public void copy(Path source, Path target, CopyOption... options)275throws IOException276{277WindowsFileCopy.copy(WindowsPath.toWindowsPath(source),278WindowsPath.toWindowsPath(target),279options);280}281282@Override283public void move(Path source, Path target, CopyOption... options)284throws IOException285{286WindowsFileCopy.move(WindowsPath.toWindowsPath(source),287WindowsPath.toWindowsPath(target),288options);289}290291/**292* Checks the file security against desired access.293*/294private static boolean hasDesiredAccess(WindowsPath file, int rights) throws IOException {295// read security descriptor containing ACL (symlinks are followed)296boolean hasRights = false;297String target = WindowsLinkSupport.getFinalPath(file, true);298NativeBuffer aclBuffer = WindowsAclFileAttributeView299.getFileSecurity(target,300DACL_SECURITY_INFORMATION301| OWNER_SECURITY_INFORMATION302| GROUP_SECURITY_INFORMATION);303try {304hasRights = checkAccessMask(aclBuffer.address(), rights,305FILE_GENERIC_READ,306FILE_GENERIC_WRITE,307FILE_GENERIC_EXECUTE,308FILE_ALL_ACCESS);309} catch (WindowsException exc) {310exc.rethrowAsIOException(file);311} finally {312aclBuffer.release();313}314return hasRights;315}316317/**318* Checks if the given file(or directory) exists and is readable.319*/320private void checkReadAccess(WindowsPath file) throws IOException {321try {322Set<OpenOption> opts = Collections.emptySet();323FileChannel fc = WindowsChannelFactory324.newFileChannel(file.getPathForWin32Calls(),325file.getPathForPermissionCheck(),326opts,3270L);328fc.close();329} catch (WindowsException exc) {330// Windows errors are very inconsistent when the file is a directory331// (ERROR_PATH_NOT_FOUND returned for root directories for example)332// so we retry by attempting to open it as a directory.333try {334new WindowsDirectoryStream(file, null).close();335} catch (IOException ioe) {336// translate and throw original exception337exc.rethrowAsIOException(file);338}339}340}341342@Override343public void checkAccess(Path obj, AccessMode... modes) throws IOException {344WindowsPath file = WindowsPath.toWindowsPath(obj);345346boolean r = false;347boolean w = false;348boolean x = false;349for (AccessMode mode: modes) {350switch (mode) {351case READ : r = true; break;352case WRITE : w = true; break;353case EXECUTE : x = true; break;354default: throw new AssertionError("Should not get here");355}356}357358// special-case read access to avoid needing to determine effective359// access to file; default if modes not specified360if (!w && !x) {361checkReadAccess(file);362return;363}364365int mask = 0;366if (r) {367file.checkRead();368mask |= FILE_READ_DATA;369}370if (w) {371file.checkWrite();372mask |= FILE_WRITE_DATA;373}374if (x) {375SecurityManager sm = System.getSecurityManager();376if (sm != null)377sm.checkExec(file.getPathForPermissionCheck());378mask |= FILE_EXECUTE;379}380381if (!hasDesiredAccess(file, mask))382throw new AccessDeniedException(383file.getPathForExceptionMessage(), null,384"Permissions does not allow requested access");385386// for write access we neeed to check if the DOS readonly attribute387// and if the volume is read-only388if (w) {389try {390WindowsFileAttributes attrs = WindowsFileAttributes.get(file, true);391if (!attrs.isDirectory() && attrs.isReadOnly())392throw new AccessDeniedException(393file.getPathForExceptionMessage(), null,394"DOS readonly attribute is set");395} catch (WindowsException exc) {396exc.rethrowAsIOException(file);397}398399if (WindowsFileStore.create(file).isReadOnly()) {400throw new AccessDeniedException(401file.getPathForExceptionMessage(), null, "Read-only file system");402}403}404}405406@Override407public boolean isSameFile(Path obj1, Path obj2) throws IOException {408WindowsPath file1 = WindowsPath.toWindowsPath(obj1);409if (file1.equals(obj2))410return true;411if (obj2 == null)412throw new NullPointerException();413if (!(obj2 instanceof WindowsPath))414return false;415WindowsPath file2 = (WindowsPath)obj2;416417// check security manager access to both files418file1.checkRead();419file2.checkRead();420421// open both files and see if they are the same422long h1 = 0L;423try {424h1 = file1.openForReadAttributeAccess(true);425} catch (WindowsException x) {426x.rethrowAsIOException(file1);427}428try {429WindowsFileAttributes attrs1 = null;430try {431attrs1 = WindowsFileAttributes.readAttributes(h1);432} catch (WindowsException x) {433x.rethrowAsIOException(file1);434}435long h2 = 0L;436try {437h2 = file2.openForReadAttributeAccess(true);438} catch (WindowsException x) {439x.rethrowAsIOException(file2);440}441try {442WindowsFileAttributes attrs2 = null;443try {444attrs2 = WindowsFileAttributes.readAttributes(h2);445} catch (WindowsException x) {446x.rethrowAsIOException(file2);447}448return WindowsFileAttributes.isSameFile(attrs1, attrs2);449} finally {450CloseHandle(h2);451}452} finally {453CloseHandle(h1);454}455}456457@Override458public boolean isHidden(Path obj) throws IOException {459WindowsPath file = WindowsPath.toWindowsPath(obj);460file.checkRead();461WindowsFileAttributes attrs = null;462try {463attrs = WindowsFileAttributes.get(file, true);464} catch (WindowsException x) {465x.rethrowAsIOException(file);466}467// DOS hidden attribute not meaningful when set on directories468if (attrs.isDirectory())469return false;470return attrs.isHidden();471}472473@Override474public FileStore getFileStore(Path obj) throws IOException {475WindowsPath file = WindowsPath.toWindowsPath(obj);476SecurityManager sm = System.getSecurityManager();477if (sm != null) {478sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));479file.checkRead();480}481return WindowsFileStore.create(file);482}483484485@Override486public void createDirectory(Path obj, FileAttribute<?>... attrs)487throws IOException488{489WindowsPath dir = WindowsPath.toWindowsPath(obj);490dir.checkWrite();491WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs);492try {493CreateDirectory(dir.getPathForWin32Calls(), sd.address());494} catch (WindowsException x) {495// convert ERROR_ACCESS_DENIED to FileAlreadyExistsException if we can496// verify that the directory exists497if (x.lastError() == ERROR_ACCESS_DENIED) {498try {499if (WindowsFileAttributes.get(dir, false).isDirectory())500throw new FileAlreadyExistsException(dir.toString());501} catch (WindowsException ignore) { }502}503x.rethrowAsIOException(dir);504} finally {505sd.release();506}507}508509@Override510public DirectoryStream<Path> newDirectoryStream(Path obj, DirectoryStream.Filter<? super Path> filter)511throws IOException512{513WindowsPath dir = WindowsPath.toWindowsPath(obj);514dir.checkRead();515if (filter == null)516throw new NullPointerException();517return new WindowsDirectoryStream(dir, filter);518}519520@Override521public void createSymbolicLink(Path obj1, Path obj2, FileAttribute<?>... attrs)522throws IOException523{524WindowsPath link = WindowsPath.toWindowsPath(obj1);525WindowsPath target = WindowsPath.toWindowsPath(obj2);526527if (!link.getFileSystem().supportsLinks()) {528throw new UnsupportedOperationException("Symbolic links not supported "529+ "on this operating system");530}531532// no attributes allowed533if (attrs.length > 0) {534WindowsSecurityDescriptor.fromAttribute(attrs); // may throw NPE or UOE535throw new UnsupportedOperationException("Initial file attributes" +536"not supported when creating symbolic link");537}538539// permission check540SecurityManager sm = System.getSecurityManager();541if (sm != null) {542sm.checkPermission(new LinkPermission("symbolic"));543link.checkWrite();544}545546/**547* Throw I/O exception for the drive-relative case because Windows548* creates a link with the resolved target for this case.549*/550if (target.type() == WindowsPathType.DRIVE_RELATIVE) {551throw new IOException("Cannot create symbolic link to working directory relative target");552}553554/*555* Windows treates symbolic links to directories differently than it556* does to other file types. For that reason we need to check if the557* target is a directory (or a directory junction).558*/559WindowsPath resolvedTarget;560if (target.type() == WindowsPathType.RELATIVE) {561WindowsPath parent = link.getParent();562resolvedTarget = (parent == null) ? target : parent.resolve(target);563} else {564resolvedTarget = link.resolve(target);565}566int flags = 0;567try {568WindowsFileAttributes wattrs = WindowsFileAttributes.get(resolvedTarget, false);569if (wattrs.isDirectory() || wattrs.isDirectoryLink())570flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;571} catch (WindowsException x) {572// unable to access target so assume target is not a directory573}574575// create the link576try {577CreateSymbolicLink(link.getPathForWin32Calls(),578WindowsPath.addPrefixIfNeeded(target.toString()),579flags);580} catch (WindowsException x) {581if (x.lastError() == ERROR_INVALID_REPARSE_DATA) {582x.rethrowAsIOException(link, target);583} else {584x.rethrowAsIOException(link);585}586}587}588589@Override590public void createLink(Path obj1, Path obj2) throws IOException {591WindowsPath link = WindowsPath.toWindowsPath(obj1);592WindowsPath existing = WindowsPath.toWindowsPath(obj2);593594// permission check595SecurityManager sm = System.getSecurityManager();596if (sm != null) {597sm.checkPermission(new LinkPermission("hard"));598link.checkWrite();599existing.checkWrite();600}601602// create hard link603try {604CreateHardLink(link.getPathForWin32Calls(),605existing.getPathForWin32Calls());606} catch (WindowsException x) {607x.rethrowAsIOException(link, existing);608}609}610611@Override612public Path readSymbolicLink(Path obj1) throws IOException {613WindowsPath link = WindowsPath.toWindowsPath(obj1);614WindowsFileSystem fs = link.getFileSystem();615if (!fs.supportsLinks()) {616throw new UnsupportedOperationException("symbolic links not supported");617}618619// permission check620SecurityManager sm = System.getSecurityManager();621if (sm != null) {622FilePermission perm = new FilePermission(link.getPathForPermissionCheck(),623SecurityConstants.FILE_READLINK_ACTION);624sm.checkPermission(perm);625}626627String target = WindowsLinkSupport.readLink(link);628return WindowsPath.createFromNormalizedPath(fs, target);629}630}631632633