893N/A/*
5195N/A * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
893N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
893N/A *
893N/A * This code is free software; you can redistribute it and/or modify it
893N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
893N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
893N/A *
893N/A * This code is distributed in the hope that it will be useful, but WITHOUT
893N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
893N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
893N/A * version 2 for more details (a copy is included in the LICENSE file that
893N/A * accompanied this code).
893N/A *
893N/A * You should have received a copy of the GNU General Public License version
893N/A * 2 along with this work; if not, write to the Free Software Foundation,
893N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
893N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
893N/A */
893N/A
893N/Apackage sun.nio.fs;
893N/A
893N/Aimport java.nio.file.*;
893N/Aimport java.nio.file.attribute.*;
5316N/Aimport java.nio.file.spi.FileTypeDetector;
893N/Aimport java.nio.channels.*;
893N/Aimport java.net.URI;
893N/Aimport java.util.concurrent.ExecutorService;
893N/Aimport java.io.IOException;
3471N/Aimport java.io.FilePermission;
893N/Aimport java.util.*;
3471N/Aimport java.security.AccessController;
893N/A
893N/Aimport sun.nio.ch.ThreadPool;
3471N/Aimport sun.security.util.SecurityConstants;
3471N/Aimport static sun.nio.fs.UnixNativeDispatcher.*;
3471N/Aimport static sun.nio.fs.UnixConstants.*;
893N/A
893N/A/**
893N/A * Base implementation of FileSystemProvider
893N/A */
893N/A
893N/Apublic abstract class UnixFileSystemProvider
3471N/A extends AbstractFileSystemProvider
893N/A{
893N/A private static final String USER_DIR = "user.dir";
893N/A private final UnixFileSystem theFileSystem;
893N/A
893N/A public UnixFileSystemProvider() {
893N/A String userDir = System.getProperty(USER_DIR);
893N/A theFileSystem = newFileSystem(userDir);
893N/A }
893N/A
893N/A /**
893N/A * Constructs a new file system using the given default directory.
893N/A */
893N/A abstract UnixFileSystem newFileSystem(String dir);
893N/A
893N/A @Override
893N/A public final String getScheme() {
893N/A return "file";
893N/A }
893N/A
893N/A private void checkUri(URI uri) {
893N/A if (!uri.getScheme().equalsIgnoreCase(getScheme()))
893N/A throw new IllegalArgumentException("URI does not match this provider");
893N/A if (uri.getAuthority() != null)
893N/A throw new IllegalArgumentException("Authority component present");
893N/A if (uri.getPath() == null)
893N/A throw new IllegalArgumentException("Path component is undefined");
893N/A if (!uri.getPath().equals("/"))
893N/A throw new IllegalArgumentException("Path component should be '/'");
893N/A if (uri.getQuery() != null)
893N/A throw new IllegalArgumentException("Query component present");
893N/A if (uri.getFragment() != null)
893N/A throw new IllegalArgumentException("Fragment component present");
893N/A }
893N/A
893N/A @Override
893N/A public final FileSystem newFileSystem(URI uri, Map<String,?> env) {
893N/A checkUri(uri);
893N/A throw new FileSystemAlreadyExistsException();
893N/A }
893N/A
893N/A @Override
893N/A public final FileSystem getFileSystem(URI uri) {
893N/A checkUri(uri);
893N/A return theFileSystem;
893N/A }
893N/A
893N/A @Override
893N/A public Path getPath(URI uri) {
893N/A return UnixUriUtils.fromUri(theFileSystem, uri);
893N/A }
893N/A
3471N/A UnixPath checkPath(Path obj) {
893N/A if (obj == null)
893N/A throw new NullPointerException();
893N/A if (!(obj instanceof UnixPath))
893N/A throw new ProviderMismatchException();
893N/A return (UnixPath)obj;
893N/A }
893N/A
3471N/A @Override
3471N/A @SuppressWarnings("unchecked")
3471N/A public <V extends FileAttributeView> V getFileAttributeView(Path obj,
3471N/A Class<V> type,
3471N/A LinkOption... options)
3471N/A {
3471N/A UnixPath file = UnixPath.toUnixPath(obj);
3899N/A boolean followLinks = Util.followLinks(options);
3471N/A if (type == BasicFileAttributeView.class)
3471N/A return (V) UnixFileAttributeViews.createBasicView(file, followLinks);
3471N/A if (type == PosixFileAttributeView.class)
3471N/A return (V) UnixFileAttributeViews.createPosixView(file, followLinks);
3471N/A if (type == FileOwnerAttributeView.class)
3471N/A return (V) UnixFileAttributeViews.createOwnerView(file, followLinks);
3471N/A if (type == null)
3471N/A throw new NullPointerException();
3471N/A return (V) null;
3471N/A }
3471N/A
3471N/A @Override
3471N/A @SuppressWarnings("unchecked")
3471N/A public <A extends BasicFileAttributes> A readAttributes(Path file,
3471N/A Class<A> type,
3471N/A LinkOption... options)
3471N/A throws IOException
3471N/A {
3471N/A Class<? extends BasicFileAttributeView> view;
3471N/A if (type == BasicFileAttributes.class)
3471N/A view = BasicFileAttributeView.class;
3471N/A else if (type == PosixFileAttributes.class)
3471N/A view = PosixFileAttributeView.class;
3471N/A else if (type == null)
3471N/A throw new NullPointerException();
3471N/A else
3471N/A throw new UnsupportedOperationException();
3471N/A return (A) getFileAttributeView(file, view, options).readAttributes();
3471N/A }
3471N/A
3471N/A @Override
3471N/A protected DynamicFileAttributeView getFileAttributeView(Path obj,
3471N/A String name,
3471N/A LinkOption... options)
3471N/A {
3471N/A UnixPath file = UnixPath.toUnixPath(obj);
3899N/A boolean followLinks = Util.followLinks(options);
3471N/A if (name.equals("basic"))
3471N/A return UnixFileAttributeViews.createBasicView(file, followLinks);
3471N/A if (name.equals("posix"))
3471N/A return UnixFileAttributeViews.createPosixView(file, followLinks);
3471N/A if (name.equals("unix"))
3471N/A return UnixFileAttributeViews.createUnixView(file, followLinks);
3471N/A if (name.equals("owner"))
3471N/A return UnixFileAttributeViews.createOwnerView(file, followLinks);
3471N/A return null;
3471N/A }
3471N/A
893N/A @Override
1319N/A public FileChannel newFileChannel(Path obj,
1319N/A Set<? extends OpenOption> options,
1319N/A FileAttribute<?>... attrs)
893N/A throws IOException
893N/A {
893N/A UnixPath file = checkPath(obj);
893N/A int mode = UnixFileModeAttribute
893N/A .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
893N/A try {
893N/A return UnixChannelFactory.newFileChannel(file, options, mode);
893N/A } catch (UnixException x) {
893N/A x.rethrowAsIOException(file);
893N/A return null;
893N/A }
893N/A }
893N/A
893N/A @Override
1319N/A public AsynchronousFileChannel newAsynchronousFileChannel(Path obj,
1319N/A Set<? extends OpenOption> options,
1319N/A ExecutorService executor,
1319N/A FileAttribute<?>... attrs) throws IOException
893N/A {
893N/A UnixPath file = checkPath(obj);
893N/A int mode = UnixFileModeAttribute
893N/A .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
893N/A ThreadPool pool = (executor == null) ? null : ThreadPool.wrap(executor, 0);
893N/A try {
893N/A return UnixChannelFactory
893N/A .newAsynchronousFileChannel(file, options, mode, pool);
893N/A } catch (UnixException x) {
893N/A x.rethrowAsIOException(file);
893N/A return null;
893N/A }
893N/A }
3471N/A
3471N/A
3471N/A @Override
3471N/A public SeekableByteChannel newByteChannel(Path obj,
3471N/A Set<? extends OpenOption> options,
3471N/A FileAttribute<?>... attrs)
3471N/A throws IOException
3471N/A {
3471N/A UnixPath file = UnixPath.toUnixPath(obj);
3471N/A int mode = UnixFileModeAttribute
3471N/A .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs);
3471N/A try {
3471N/A return UnixChannelFactory.newFileChannel(file, options, mode);
3471N/A } catch (UnixException x) {
3471N/A x.rethrowAsIOException(file);
3471N/A return null; // keep compiler happy
3471N/A }
3471N/A }
3471N/A
3471N/A @Override
3471N/A boolean implDelete(Path obj, boolean failIfNotExists) throws IOException {
3471N/A UnixPath file = UnixPath.toUnixPath(obj);
3471N/A file.checkDelete();
3471N/A
3471N/A // need file attributes to know if file is directory
3471N/A UnixFileAttributes attrs = null;
3471N/A try {
3471N/A attrs = UnixFileAttributes.get(file, false);
3471N/A if (attrs.isDirectory()) {
3471N/A rmdir(file);
3471N/A } else {
3471N/A unlink(file);
3471N/A }
3471N/A return true;
3471N/A } catch (UnixException x) {
3471N/A // no-op if file does not exist
3471N/A if (!failIfNotExists && x.errno() == ENOENT)
3471N/A return false;
3471N/A
3471N/A // DirectoryNotEmptyException if not empty
3471N/A if (attrs != null && attrs.isDirectory() &&
3471N/A (x.errno() == EEXIST || x.errno() == ENOTEMPTY))
5195N/A throw new DirectoryNotEmptyException(file.getPathForExceptionMessage());
3471N/A
3471N/A x.rethrowAsIOException(file);
3471N/A return false;
3471N/A }
3471N/A }
3471N/A
3471N/A @Override
3471N/A public void copy(Path source, Path target, CopyOption... options)
3471N/A throws IOException
3471N/A {
3471N/A UnixCopyFile.copy(UnixPath.toUnixPath(source),
3471N/A UnixPath.toUnixPath(target),
3471N/A options);
3471N/A }
3471N/A
3471N/A @Override
3471N/A public void move(Path source, Path target, CopyOption... options)
3471N/A throws IOException
3471N/A {
3471N/A UnixCopyFile.move(UnixPath.toUnixPath(source),
3471N/A UnixPath.toUnixPath(target),
3471N/A options);
3471N/A }
3471N/A
3471N/A @Override
3471N/A public void checkAccess(Path obj, AccessMode... modes) throws IOException {
3471N/A UnixPath file = UnixPath.toUnixPath(obj);
3471N/A boolean e = false;
3471N/A boolean r = false;
3471N/A boolean w = false;
3471N/A boolean x = false;
3471N/A
3471N/A if (modes.length == 0) {
3471N/A e = true;
3471N/A } else {
3471N/A for (AccessMode mode: modes) {
3471N/A switch (mode) {
3471N/A case READ : r = true; break;
3471N/A case WRITE : w = true; break;
3471N/A case EXECUTE : x = true; break;
3471N/A default: throw new AssertionError("Should not get here");
3471N/A }
3471N/A }
3471N/A }
3471N/A
3471N/A int mode = 0;
3471N/A if (e || r) {
3471N/A file.checkRead();
3471N/A mode |= (r) ? R_OK : F_OK;
3471N/A }
3471N/A if (w) {
3471N/A file.checkWrite();
3471N/A mode |= W_OK;
3471N/A }
3471N/A if (x) {
3471N/A SecurityManager sm = System.getSecurityManager();
3471N/A if (sm != null) {
3471N/A // not cached
3471N/A sm.checkExec(file.getPathForPermissionCheck());
3471N/A }
3471N/A mode |= X_OK;
3471N/A }
3471N/A try {
3471N/A access(file, mode);
3471N/A } catch (UnixException exc) {
3471N/A exc.rethrowAsIOException(file);
3471N/A }
3471N/A }
3471N/A
3471N/A @Override
3471N/A public boolean isSameFile(Path obj1, Path obj2) throws IOException {
3471N/A UnixPath file1 = UnixPath.toUnixPath(obj1);
3471N/A if (file1.equals(obj2))
3471N/A return true;
3471N/A if (obj2 == null)
3471N/A throw new NullPointerException();
3471N/A if (!(obj2 instanceof UnixPath))
3471N/A return false;
3471N/A UnixPath file2 = (UnixPath)obj2;
3471N/A
3471N/A // check security manager access to both files
3471N/A file1.checkRead();
3471N/A file2.checkRead();
3471N/A
3471N/A UnixFileAttributes attrs1;
3471N/A UnixFileAttributes attrs2;
3471N/A try {
3471N/A attrs1 = UnixFileAttributes.get(file1, true);
3471N/A } catch (UnixException x) {
3471N/A x.rethrowAsIOException(file1);
3471N/A return false; // keep compiler happy
3471N/A }
3471N/A try {
3471N/A attrs2 = UnixFileAttributes.get(file2, true);
3471N/A } catch (UnixException x) {
3471N/A x.rethrowAsIOException(file2);
3471N/A return false; // keep compiler happy
3471N/A }
3471N/A return attrs1.isSameFile(attrs2);
3471N/A }
3471N/A
3471N/A @Override
3471N/A public boolean isHidden(Path obj) {
3471N/A UnixPath file = UnixPath.toUnixPath(obj);
3471N/A file.checkRead();
3471N/A UnixPath name = file.getFileName();
3471N/A if (name == null)
3471N/A return false;
3471N/A return (name.asByteArray()[0] == '.');
3471N/A }
3471N/A
3471N/A /**
3471N/A * Returns a FileStore to represent the file system where the given file
3471N/A * reside.
3471N/A */
3471N/A abstract FileStore getFileStore(UnixPath path) throws IOException;
3471N/A
3471N/A @Override
3471N/A public FileStore getFileStore(Path obj) throws IOException {
3471N/A UnixPath file = UnixPath.toUnixPath(obj);
3471N/A SecurityManager sm = System.getSecurityManager();
3471N/A if (sm != null) {
3471N/A sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
3471N/A file.checkRead();
3471N/A }
3471N/A return getFileStore(file);
3471N/A }
3471N/A
3471N/A @Override
3471N/A public void createDirectory(Path obj, FileAttribute<?>... attrs)
3471N/A throws IOException
3471N/A {
3471N/A UnixPath dir = UnixPath.toUnixPath(obj);
3471N/A dir.checkWrite();
3471N/A
3471N/A int mode = UnixFileModeAttribute
3471N/A .toUnixMode(UnixFileModeAttribute.ALL_PERMISSIONS, attrs);
3471N/A try {
3471N/A mkdir(dir, mode);
3471N/A } catch (UnixException x) {
3471N/A x.rethrowAsIOException(dir);
3471N/A }
3471N/A }
3471N/A
3471N/A
3471N/A @Override
3471N/A public DirectoryStream<Path> newDirectoryStream(Path obj, DirectoryStream.Filter<? super Path> filter)
3471N/A throws IOException
3471N/A {
3471N/A UnixPath dir = UnixPath.toUnixPath(obj);
3471N/A dir.checkRead();
3471N/A if (filter == null)
3471N/A throw new NullPointerException();
3471N/A
3471N/A // can't return SecureDirectoryStream on kernels that don't support
3471N/A // openat, etc.
5193N/A if (!supportsAtSysCalls() || !supportsNoFollowLinks()) {
3471N/A try {
3471N/A long ptr = opendir(dir);
3471N/A return new UnixDirectoryStream(dir, ptr, filter);
3471N/A } catch (UnixException x) {
3471N/A if (x.errno() == ENOTDIR)
5195N/A throw new NotDirectoryException(dir.getPathForExceptionMessage());
3471N/A x.rethrowAsIOException(dir);
3471N/A }
3471N/A }
3471N/A
3471N/A // open directory and dup file descriptor for use by
3471N/A // opendir/readdir/closedir
3471N/A int dfd1 = -1;
3471N/A int dfd2 = -1;
3471N/A long dp = 0L;
3471N/A try {
3471N/A dfd1 = open(dir, O_RDONLY, 0);
3471N/A dfd2 = dup(dfd1);
3471N/A dp = fdopendir(dfd1);
3471N/A } catch (UnixException x) {
3471N/A if (dfd1 != -1)
3471N/A UnixNativeDispatcher.close(dfd1);
3471N/A if (dfd2 != -1)
3471N/A UnixNativeDispatcher.close(dfd2);
3471N/A if (x.errno() == UnixConstants.ENOTDIR)
5195N/A throw new NotDirectoryException(dir.getPathForExceptionMessage());
3471N/A x.rethrowAsIOException(dir);
3471N/A }
3471N/A return new UnixSecureDirectoryStream(dir, dp, dfd2, filter);
3471N/A }
3471N/A
3471N/A @Override
3471N/A public void createSymbolicLink(Path obj1, Path obj2, FileAttribute<?>... attrs)
3471N/A throws IOException
3471N/A {
3471N/A UnixPath link = UnixPath.toUnixPath(obj1);
3471N/A UnixPath target = UnixPath.toUnixPath(obj2);
3471N/A
3471N/A // no attributes supported when creating links
3471N/A if (attrs.length > 0) {
3471N/A UnixFileModeAttribute.toUnixMode(0, attrs); // may throw NPE or UOE
3471N/A throw new UnsupportedOperationException("Initial file attributes" +
3471N/A "not supported when creating symbolic link");
3471N/A }
3471N/A
3471N/A // permission check
3471N/A SecurityManager sm = System.getSecurityManager();
3471N/A if (sm != null) {
3471N/A sm.checkPermission(new LinkPermission("symbolic"));
3471N/A link.checkWrite();
3471N/A }
3471N/A
3471N/A // create link
3471N/A try {
3471N/A symlink(target.asByteArray(), link);
3471N/A } catch (UnixException x) {
3471N/A x.rethrowAsIOException(link);
3471N/A }
3471N/A }
3471N/A
3471N/A @Override
3471N/A public void createLink(Path obj1, Path obj2) throws IOException {
3471N/A UnixPath link = UnixPath.toUnixPath(obj1);
3471N/A UnixPath existing = UnixPath.toUnixPath(obj2);
3471N/A
3471N/A // permission check
3471N/A SecurityManager sm = System.getSecurityManager();
3471N/A if (sm != null) {
3471N/A sm.checkPermission(new LinkPermission("hard"));
3471N/A link.checkWrite();
3471N/A existing.checkWrite();
3471N/A }
3471N/A try {
3471N/A link(existing, link);
3471N/A } catch (UnixException x) {
3471N/A x.rethrowAsIOException(link, existing);
3471N/A }
3471N/A }
3471N/A
3471N/A @Override
3471N/A public Path readSymbolicLink(Path obj1) throws IOException {
3471N/A UnixPath link = UnixPath.toUnixPath(obj1);
3471N/A // permission check
3471N/A SecurityManager sm = System.getSecurityManager();
3471N/A if (sm != null) {
3471N/A FilePermission perm = new FilePermission(link.getPathForPermissionCheck(),
3471N/A SecurityConstants.FILE_READLINK_ACTION);
3471N/A AccessController.checkPermission(perm);
3471N/A }
3471N/A try {
3471N/A byte[] target = readlink(link);
3471N/A return new UnixPath(link.getFileSystem(), target);
3471N/A } catch (UnixException x) {
3471N/A if (x.errno() == UnixConstants.EINVAL)
5195N/A throw new NotLinkException(link.getPathForExceptionMessage());
3471N/A x.rethrowAsIOException(link);
3471N/A return null; // keep compiler happy
3471N/A }
3471N/A }
5316N/A
5316N/A /**
5316N/A * Returns a {@code FileTypeDetector} for this platform.
5316N/A */
5316N/A FileTypeDetector getFileTypeDetector() {
5316N/A return new AbstractFileTypeDetector() {
5316N/A @Override
5316N/A public String implProbeContentType(Path file) {
5316N/A return null;
5316N/A }
5316N/A };
5316N/A }
5316N/A
893N/A}