Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java
32288 views
/*1* Copyright (c) 2008, 2010, 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.io.FileDescriptor;28import java.io.IOException;29import java.nio.channels.AsynchronousFileChannel;30import java.nio.channels.FileChannel;31import java.nio.file.LinkOption;32import java.nio.file.OpenOption;33import java.nio.file.StandardOpenOption;34import java.util.Set;3536import com.sun.nio.file.ExtendedOpenOption;3738import sun.misc.JavaIOFileDescriptorAccess;39import sun.misc.SharedSecrets;40import sun.nio.ch.FileChannelImpl;41import sun.nio.ch.ThreadPool;42import sun.nio.ch.WindowsAsynchronousFileChannelImpl;4344import static sun.nio.fs.WindowsNativeDispatcher.*;45import static sun.nio.fs.WindowsConstants.*;4647/**48* Factory to create FileChannels and AsynchronousFileChannels.49*/5051class WindowsChannelFactory {52private static final JavaIOFileDescriptorAccess fdAccess =53SharedSecrets.getJavaIOFileDescriptorAccess();5455private WindowsChannelFactory() { }5657/**58* Do not follow reparse points when opening an existing file. Do not fail59* if the file is a reparse point.60*/61static final OpenOption OPEN_REPARSE_POINT = new OpenOption() { };6263/**64* Represents the flags from a user-supplied set of open options.65*/66private static class Flags {67boolean read;68boolean write;69boolean append;70boolean truncateExisting;71boolean create;72boolean createNew;73boolean deleteOnClose;74boolean sparse;75boolean overlapped;76boolean sync;77boolean dsync;7879// non-standard80boolean shareRead = true;81boolean shareWrite = true;82boolean shareDelete = true;83boolean noFollowLinks;84boolean openReparsePoint;8586static Flags toFlags(Set<? extends OpenOption> options) {87Flags flags = new Flags();88for (OpenOption option: options) {89if (option instanceof StandardOpenOption) {90switch ((StandardOpenOption)option) {91case READ : flags.read = true; break;92case WRITE : flags.write = true; break;93case APPEND : flags.append = true; break;94case TRUNCATE_EXISTING : flags.truncateExisting = true; break;95case CREATE : flags.create = true; break;96case CREATE_NEW : flags.createNew = true; break;97case DELETE_ON_CLOSE : flags.deleteOnClose = true; break;98case SPARSE : flags.sparse = true; break;99case SYNC : flags.sync = true; break;100case DSYNC : flags.dsync = true; break;101default: throw new UnsupportedOperationException();102}103continue;104}105if (option instanceof ExtendedOpenOption) {106switch ((ExtendedOpenOption)option) {107case NOSHARE_READ : flags.shareRead = false; break;108case NOSHARE_WRITE : flags.shareWrite = false; break;109case NOSHARE_DELETE : flags.shareDelete = false; break;110default: throw new UnsupportedOperationException();111}112continue;113}114if (option == LinkOption.NOFOLLOW_LINKS) {115flags.noFollowLinks = true;116continue;117}118if (option == OPEN_REPARSE_POINT) {119flags.openReparsePoint = true;120continue;121}122if (option == null)123throw new NullPointerException();124throw new UnsupportedOperationException();125}126return flags;127}128}129130/**131* Open/creates file, returning FileChannel to access the file132*133* @param pathForWindows134* The path of the file to open/create135* @param pathToCheck136* The path used for permission checks (if security manager)137*/138static FileChannel newFileChannel(String pathForWindows,139String pathToCheck,140Set<? extends OpenOption> options,141long pSecurityDescriptor)142throws WindowsException143{144Flags flags = Flags.toFlags(options);145146// default is reading; append => writing147if (!flags.read && !flags.write) {148if (flags.append) {149flags.write = true;150} else {151flags.read = true;152}153}154155// validation156if (flags.read && flags.append)157throw new IllegalArgumentException("READ + APPEND not allowed");158if (flags.append && flags.truncateExisting)159throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");160161FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);162return FileChannelImpl.open(fdObj, pathForWindows, flags.read, flags.write, flags.append, null);163}164165/**166* Open/creates file, returning AsynchronousFileChannel to access the file167*168* @param pathForWindows169* The path of the file to open/create170* @param pathToCheck171* The path used for permission checks (if security manager)172* @param pool173* The thread pool that the channel is associated with174*/175static AsynchronousFileChannel newAsynchronousFileChannel(String pathForWindows,176String pathToCheck,177Set<? extends OpenOption> options,178long pSecurityDescriptor,179ThreadPool pool)180throws IOException181{182Flags flags = Flags.toFlags(options);183184// Overlapped I/O required185flags.overlapped = true;186187// default is reading188if (!flags.read && !flags.write) {189flags.read = true;190}191192// validation193if (flags.append)194throw new UnsupportedOperationException("APPEND not allowed");195196// open file for overlapped I/O197FileDescriptor fdObj;198try {199fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);200} catch (WindowsException x) {201x.rethrowAsIOException(pathForWindows);202return null;203}204205// create the AsynchronousFileChannel206try {207return WindowsAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool);208} catch (IOException x) {209// IOException is thrown if the file handle cannot be associated210// with the completion port. All we can do is close the file.211long handle = fdAccess.getHandle(fdObj);212CloseHandle(handle);213throw x;214}215}216217/**218* Opens file based on parameters and options, returning a FileDescriptor219* encapsulating the handle to the open file.220*/221private static FileDescriptor open(String pathForWindows,222String pathToCheck,223Flags flags,224long pSecurityDescriptor)225throws WindowsException226{227// set to true if file must be truncated after open228boolean truncateAfterOpen = false;229230// map options231int dwDesiredAccess = 0;232if (flags.read)233dwDesiredAccess |= GENERIC_READ;234if (flags.write)235dwDesiredAccess |= GENERIC_WRITE;236237int dwShareMode = 0;238if (flags.shareRead)239dwShareMode |= FILE_SHARE_READ;240if (flags.shareWrite)241dwShareMode |= FILE_SHARE_WRITE;242if (flags.shareDelete)243dwShareMode |= FILE_SHARE_DELETE;244245int dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;246int dwCreationDisposition = OPEN_EXISTING;247if (flags.write) {248if (flags.createNew) {249dwCreationDisposition = CREATE_NEW;250// force create to fail if file is orphaned reparse point251dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;252} else {253if (flags.create)254dwCreationDisposition = OPEN_ALWAYS;255if (flags.truncateExisting) {256// Windows doesn't have a creation disposition that exactly257// corresponds to CREATE + TRUNCATE_EXISTING so we use258// the OPEN_ALWAYS mode and then truncate the file.259if (dwCreationDisposition == OPEN_ALWAYS) {260truncateAfterOpen = true;261} else {262dwCreationDisposition = TRUNCATE_EXISTING;263}264}265}266}267268if (flags.dsync || flags.sync)269dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;270if (flags.overlapped)271dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;272if (flags.deleteOnClose)273dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;274275// NOFOLLOW_LINKS and NOFOLLOW_REPARSEPOINT mean open reparse point276boolean okayToFollowLinks = true;277if (dwCreationDisposition != CREATE_NEW &&278(flags.noFollowLinks ||279flags.openReparsePoint ||280flags.deleteOnClose))281{282if (flags.noFollowLinks || flags.deleteOnClose)283okayToFollowLinks = false;284dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;285}286287// permission check288if (pathToCheck != null) {289SecurityManager sm = System.getSecurityManager();290if (sm != null) {291if (flags.read)292sm.checkRead(pathToCheck);293if (flags.write)294sm.checkWrite(pathToCheck);295if (flags.deleteOnClose)296sm.checkDelete(pathToCheck);297}298}299300// open file301long handle = CreateFile(pathForWindows,302dwDesiredAccess,303dwShareMode,304pSecurityDescriptor,305dwCreationDisposition,306dwFlagsAndAttributes);307308// make sure this isn't a symbolic link.309if (!okayToFollowLinks) {310try {311if (WindowsFileAttributes.readAttributes(handle).isSymbolicLink())312throw new WindowsException("File is symbolic link");313} catch (WindowsException x) {314CloseHandle(handle);315throw x;316}317}318319// truncate file (for CREATE + TRUNCATE_EXISTING case)320if (truncateAfterOpen) {321try {322SetEndOfFile(handle);323} catch (WindowsException x) {324CloseHandle(handle);325throw x;326}327}328329// make the file sparse if needed330if (dwCreationDisposition == CREATE_NEW && flags.sparse) {331try {332DeviceIoControlSetSparse(handle);333} catch (WindowsException x) {334// ignore as sparse option is hint335}336}337338// create FileDescriptor and return339FileDescriptor fdObj = new FileDescriptor();340fdAccess.setHandle(fdObj, handle);341return fdObj;342}343}344345346