Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.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.channels.*;29import java.io.FileDescriptor;30import java.util.Set;3132import sun.nio.ch.FileChannelImpl;33import sun.nio.ch.ThreadPool;34import sun.nio.ch.SimpleAsynchronousFileChannelImpl;35import sun.misc.SharedSecrets;36import sun.misc.JavaIOFileDescriptorAccess;3738import static sun.nio.fs.UnixNativeDispatcher.*;39import static sun.nio.fs.UnixConstants.*;4041/**42* Factory for FileChannels and AsynchronousFileChannels43*/4445class UnixChannelFactory {46private static final JavaIOFileDescriptorAccess fdAccess =47SharedSecrets.getJavaIOFileDescriptorAccess();4849protected UnixChannelFactory() {50}5152/**53* Represents the flags from a user-supplied set of open options.54*/55protected static class Flags {56boolean read;57boolean write;58boolean append;59boolean truncateExisting;60boolean noFollowLinks;61boolean create;62boolean createNew;63boolean deleteOnClose;64boolean sync;65boolean dsync;6667static Flags toFlags(Set<? extends OpenOption> options) {68Flags flags = new Flags();69for (OpenOption option: options) {70if (option instanceof StandardOpenOption) {71switch ((StandardOpenOption)option) {72case READ : flags.read = true; break;73case WRITE : flags.write = true; break;74case APPEND : flags.append = true; break;75case TRUNCATE_EXISTING : flags.truncateExisting = true; break;76case CREATE : flags.create = true; break;77case CREATE_NEW : flags.createNew = true; break;78case DELETE_ON_CLOSE : flags.deleteOnClose = true; break;79case SPARSE : /* ignore */ break;80case SYNC : flags.sync = true; break;81case DSYNC : flags.dsync = true; break;82default: throw new UnsupportedOperationException();83}84continue;85}86if (option == LinkOption.NOFOLLOW_LINKS && O_NOFOLLOW != 0) {87flags.noFollowLinks = true;88continue;89}90if (option == null)91throw new NullPointerException();92throw new UnsupportedOperationException(option + " not supported");93}94return flags;95}96}979899/**100* Constructs a file channel from an existing (open) file descriptor101*/102static FileChannel newFileChannel(int fd, String path, boolean reading, boolean writing) {103FileDescriptor fdObj = new FileDescriptor();104fdAccess.set(fdObj, fd);105return FileChannelImpl.open(fdObj, path, reading, writing, null);106}107108/**109* Constructs a file channel by opening a file using a dfd/path pair110*/111static FileChannel newFileChannel(int dfd,112UnixPath path,113String pathForPermissionCheck,114Set<? extends OpenOption> options,115int mode)116throws UnixException117{118Flags flags = Flags.toFlags(options);119120// default is reading; append => writing121if (!flags.read && !flags.write) {122if (flags.append) {123flags.write = true;124} else {125flags.read = true;126}127}128129// validation130if (flags.read && flags.append)131throw new IllegalArgumentException("READ + APPEND not allowed");132if (flags.append && flags.truncateExisting)133throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");134135FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode);136return FileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, flags.append, null);137}138139/**140* Constructs a file channel by opening the given file.141*/142static FileChannel newFileChannel(UnixPath path,143Set<? extends OpenOption> options,144int mode)145throws UnixException146{147return newFileChannel(-1, path, null, options, mode);148}149150/**151* Constructs an asynchronous file channel by opening the given file.152*/153static AsynchronousFileChannel newAsynchronousFileChannel(UnixPath path,154Set<? extends OpenOption> options,155int mode,156ThreadPool pool)157throws UnixException158{159Flags flags = Flags.toFlags(options);160161// default is reading162if (!flags.read && !flags.write) {163flags.read = true;164}165166// validation167if (flags.append)168throw new UnsupportedOperationException("APPEND not allowed");169170// for now use simple implementation171FileDescriptor fdObj = open(-1, path, null, flags, mode);172return SimpleAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool);173}174175/**176* Opens file based on parameters and options, returning a FileDescriptor177* encapsulating the handle to the open file.178*/179protected static FileDescriptor open(int dfd,180UnixPath path,181String pathForPermissionCheck,182Flags flags,183int mode)184throws UnixException185{186// map to oflags187int oflags;188if (flags.read && flags.write) {189oflags = O_RDWR;190} else {191oflags = (flags.write) ? O_WRONLY : O_RDONLY;192}193if (flags.write) {194if (flags.truncateExisting)195oflags |= O_TRUNC;196if (flags.append)197oflags |= O_APPEND;198199// create flags200if (flags.createNew) {201byte[] pathForSysCall = path.asByteArray();202203// throw exception if file name is "." to avoid confusing error204if ((pathForSysCall[pathForSysCall.length-1] == '.') &&205(pathForSysCall.length == 1 ||206(pathForSysCall[pathForSysCall.length-2] == '/')))207{208throw new UnixException(EEXIST);209}210oflags |= (O_CREAT | O_EXCL);211} else {212if (flags.create)213oflags |= O_CREAT;214}215}216217// follow links by default218boolean followLinks = true;219if (!flags.createNew && (flags.noFollowLinks || flags.deleteOnClose)) {220if (flags.deleteOnClose && O_NOFOLLOW == 0) {221try {222if (UnixFileAttributes.get(path, false).isSymbolicLink())223throw new UnixException("DELETE_ON_CLOSE specified and file is a symbolic link");224} catch (UnixException x) {225if (!flags.create || x.errno() != ENOENT)226throw x;227}228}229followLinks = false;230oflags |= O_NOFOLLOW;231}232233if (flags.dsync)234oflags |= O_DSYNC;235if (flags.sync)236oflags |= O_SYNC;237238// permission check before we open the file239SecurityManager sm = System.getSecurityManager();240if (sm != null) {241if (pathForPermissionCheck == null)242pathForPermissionCheck = path.getPathForPermissionCheck();243if (flags.read)244sm.checkRead(pathForPermissionCheck);245if (flags.write)246sm.checkWrite(pathForPermissionCheck);247if (flags.deleteOnClose)248sm.checkDelete(pathForPermissionCheck);249}250251int fd;252try {253if (dfd >= 0) {254fd = openat(dfd, path.asByteArray(), oflags, mode);255} else {256fd = UnixNativeDispatcher.open(path, oflags, mode);257}258} catch (UnixException x) {259// Linux error can be EISDIR or EEXIST when file exists260if (flags.createNew && (x.errno() == EISDIR)) {261x.setError(EEXIST);262}263264// handle ELOOP to avoid confusing message265if (!followLinks && (x.errno() == ELOOP)) {266x = new UnixException(x.getMessage() + " (NOFOLLOW_LINKS specified)");267}268269throw x;270}271272// unlink file immediately if delete on close. The spec is clear that273// an implementation cannot guarantee to unlink the correct file when274// replaced by an attacker after it is opened.275if (flags.deleteOnClose) {276try {277if (dfd >= 0) {278unlinkat(dfd, path.asByteArray(), 0);279} else {280unlink(path);281}282} catch (UnixException ignore) {283// best-effort284}285}286287// create java.io.FileDescriptor288FileDescriptor fdObj = new FileDescriptor();289fdAccess.set(fdObj, fd);290return fdObj;291}292}293294295