jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java
changeset 2057 3acf8e5e2ca0
child 3065 452aaa2899fc
equal deleted inserted replaced
2056:115e09b7a004 2057:3acf8e5e2ca0
       
     1 /*
       
     2  * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.nio.fs;
       
    27 
       
    28 import java.nio.file.*;
       
    29 import java.nio.file.attribute.*;
       
    30 import java.nio.file.spi.*;
       
    31 import java.io.IOException;
       
    32 import java.util.*;
       
    33 import java.util.regex.Pattern;
       
    34 import java.security.AccessController;
       
    35 import sun.security.action.GetPropertyAction;
       
    36 
       
    37 /**
       
    38  * Base implementation of FileSystem for Unix-like implementations.
       
    39  */
       
    40 
       
    41 abstract class UnixFileSystem
       
    42     extends FileSystem
       
    43 {
       
    44     private final UnixFileSystemProvider provider;
       
    45     private final byte[] defaultDirectory;
       
    46     private final boolean needToResolveAgainstDefaultDirectory;
       
    47     private final UnixPath rootDirectory;
       
    48 
       
    49     // package-private
       
    50     UnixFileSystem(UnixFileSystemProvider provider, String dir) {
       
    51         this.provider = provider;
       
    52         this.defaultDirectory = UnixPath.normalizeAndCheck(dir).getBytes();
       
    53         if (this.defaultDirectory[0] != '/') {
       
    54             throw new RuntimeException("default directory must be absolute");
       
    55         }
       
    56 
       
    57         // if process-wide chdir is allowed or default directory is not the
       
    58         // process working directory then paths must be resolved against the
       
    59         // default directory.
       
    60         String propValue = AccessController.doPrivileged(
       
    61             new GetPropertyAction("sun.nio.fs.chdirAllowed", "false"));
       
    62         boolean chdirAllowed = (propValue.length() == 0) ?
       
    63             true : Boolean.valueOf(propValue);
       
    64         if (chdirAllowed) {
       
    65             this.needToResolveAgainstDefaultDirectory = true;
       
    66         } else {
       
    67             byte[] cwd = UnixNativeDispatcher.getcwd();
       
    68             boolean defaultIsCwd = (cwd.length == defaultDirectory.length);
       
    69             if (defaultIsCwd) {
       
    70                 for (int i=0; i<cwd.length; i++) {
       
    71                     if (cwd[i] != defaultDirectory[i]) {
       
    72                         defaultIsCwd = false;
       
    73                         break;
       
    74                     }
       
    75                 }
       
    76             }
       
    77             this.needToResolveAgainstDefaultDirectory = !defaultIsCwd;
       
    78         }
       
    79 
       
    80         // the root directory
       
    81         this.rootDirectory = new UnixPath(this, "/");
       
    82     }
       
    83 
       
    84     // package-private
       
    85     byte[] defaultDirectory() {
       
    86         return defaultDirectory;
       
    87     }
       
    88 
       
    89     boolean needToResolveAgainstDefaultDirectory() {
       
    90         return needToResolveAgainstDefaultDirectory;
       
    91     }
       
    92 
       
    93     UnixPath rootDirectory() {
       
    94         return rootDirectory;
       
    95     }
       
    96 
       
    97     boolean isSolaris() {
       
    98         return false;
       
    99     }
       
   100 
       
   101     @Override
       
   102     public final FileSystemProvider provider() {
       
   103         return provider;
       
   104     }
       
   105 
       
   106     @Override
       
   107     public final String getSeparator() {
       
   108         return "/";
       
   109     }
       
   110 
       
   111     @Override
       
   112     public final boolean isOpen() {
       
   113         return true;
       
   114     }
       
   115 
       
   116     @Override
       
   117     public final boolean isReadOnly() {
       
   118         return false;
       
   119     }
       
   120 
       
   121     @Override
       
   122     public final void close() throws IOException {
       
   123         throw new UnsupportedOperationException();
       
   124     }
       
   125 
       
   126     /**
       
   127      * Copies non-POSIX attributes from the source to target file.
       
   128      *
       
   129      * Copying a file preserving attributes, or moving a file, will preserve
       
   130      * the file owner/group/permissions/timestamps but it does not preserve
       
   131      * other non-POSIX attributes. This method is invoked by the
       
   132      * copy or move operation to preserve these attributes. It should copy
       
   133      * extended attributes, ACLs, or other attributes.
       
   134      *
       
   135      * @param   sfd
       
   136      *          Open file descriptor to source file
       
   137      * @param   tfd
       
   138      *          Open file descriptor to target file
       
   139      */
       
   140     abstract void copyNonPosixAttributes(int sfd, int tfd);
       
   141 
       
   142     /**
       
   143      * Tells if directory relative system calls (openat, etc.) are available
       
   144      * on this operating system.
       
   145      */
       
   146     abstract boolean supportsSecureDirectoryStreams();
       
   147 
       
   148     /**
       
   149      * Unix systems only have a single root directory (/)
       
   150      */
       
   151     @Override
       
   152     public final Iterable<Path> getRootDirectories() {
       
   153         final List<Path> allowedList =
       
   154            Collections.unmodifiableList(Arrays.asList((Path)rootDirectory));
       
   155         return new Iterable<Path>() {
       
   156             public Iterator<Path> iterator() {
       
   157                 try {
       
   158                     SecurityManager sm = System.getSecurityManager();
       
   159                     if (sm != null)
       
   160                         sm.checkRead(rootDirectory.toString());
       
   161                     return allowedList.iterator();
       
   162                 } catch (SecurityException x) {
       
   163                     List<Path> disallowed = Collections.emptyList();
       
   164                     return disallowed.iterator();
       
   165                 }
       
   166             }
       
   167         };
       
   168     }
       
   169 
       
   170     /**
       
   171      * Returns object to iterate over entries in mounttab or equivalent
       
   172      */
       
   173     abstract Iterable<UnixMountEntry> getMountEntries();
       
   174 
       
   175     /**
       
   176      * Returns a FileStore to represent the file system where the given file
       
   177      * reside.
       
   178      */
       
   179     abstract FileStore getFileStore(UnixPath path) throws IOException;
       
   180 
       
   181     /**
       
   182      * Returns a FileStore to represent the file system for the given mount
       
   183      * mount.
       
   184      */
       
   185     abstract FileStore getFileStore(UnixMountEntry entry) throws IOException;
       
   186 
       
   187     /**
       
   188      * Iterator returned by getFileStores method.
       
   189      */
       
   190     private class FileStoreIterator implements Iterator<FileStore> {
       
   191         private final Iterator<UnixMountEntry> entries;
       
   192         private FileStore next;
       
   193 
       
   194         FileStoreIterator() {
       
   195             this.entries = getMountEntries().iterator();
       
   196         }
       
   197 
       
   198         private FileStore readNext() {
       
   199             assert Thread.holdsLock(this);
       
   200             for (;;) {
       
   201                 if (!entries.hasNext())
       
   202                     return null;
       
   203                 UnixMountEntry entry = entries.next();
       
   204 
       
   205                 // skip entries with the "ignore" option
       
   206                 if (entry.isIgnored())
       
   207                     continue;
       
   208 
       
   209                 // check permission to read mount point
       
   210                 SecurityManager sm = System.getSecurityManager();
       
   211                 if (sm != null) {
       
   212                     try {
       
   213                         sm.checkRead(new String(entry.dir()));
       
   214                     } catch (SecurityException x) {
       
   215                         continue;
       
   216                     }
       
   217                 }
       
   218                 try {
       
   219                     return getFileStore(entry);
       
   220                 } catch (IOException ignore) {
       
   221                     // ignore as per spec
       
   222                 }
       
   223             }
       
   224         }
       
   225 
       
   226         @Override
       
   227         public synchronized boolean hasNext() {
       
   228             if (next != null)
       
   229                 return true;
       
   230             next = readNext();
       
   231             return next != null;
       
   232         }
       
   233 
       
   234         @Override
       
   235         public synchronized FileStore next() {
       
   236             if (next == null)
       
   237                 next = readNext();
       
   238             if (next == null) {
       
   239                 throw new NoSuchElementException();
       
   240             } else {
       
   241                 FileStore result = next;
       
   242                 next = null;
       
   243                 return result;
       
   244             }
       
   245         }
       
   246 
       
   247         @Override
       
   248         public void remove() {
       
   249             throw new UnsupportedOperationException();
       
   250         }
       
   251     }
       
   252 
       
   253     @Override
       
   254     public final Iterable<FileStore> getFileStores() {
       
   255         SecurityManager sm = System.getSecurityManager();
       
   256         if (sm != null) {
       
   257             try {
       
   258                 sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
       
   259             } catch (SecurityException se) {
       
   260                 return Collections.emptyList();
       
   261             }
       
   262         }
       
   263         return new Iterable<FileStore>() {
       
   264             public Iterator<FileStore> iterator() {
       
   265                 return new FileStoreIterator();
       
   266             }
       
   267         };
       
   268     }
       
   269 
       
   270     @Override
       
   271     public final UnixPath getPath(String path) {
       
   272         return new UnixPath(this, path);
       
   273     }
       
   274 
       
   275     @Override
       
   276     public PathMatcher getPathMatcher(String syntaxAndInput) {
       
   277         int pos = syntaxAndInput.indexOf(':');
       
   278         if (pos <= 0 || pos == syntaxAndInput.length())
       
   279             throw new IllegalArgumentException();
       
   280         String syntax = syntaxAndInput.substring(0, pos);
       
   281         String input = syntaxAndInput.substring(pos+1);
       
   282 
       
   283         String expr;
       
   284         if (syntax.equals(GLOB_SYNTAX)) {
       
   285             expr = Globs.toUnixRegexPattern(input);
       
   286         } else {
       
   287             if (syntax.equals(REGEX_SYNTAX)) {
       
   288                 expr = input;
       
   289             } else {
       
   290                 throw new UnsupportedOperationException("Syntax '" + syntax +
       
   291                     "' not recognized");
       
   292             }
       
   293         }
       
   294 
       
   295         // return matcher
       
   296         final Pattern pattern = Pattern.compile(expr);
       
   297         return new PathMatcher() {
       
   298             @Override
       
   299             public boolean matches(Path path) {
       
   300                 return pattern.matcher(path.toString()).matches();
       
   301             }
       
   302         };
       
   303     }
       
   304     private static final String GLOB_SYNTAX = "glob";
       
   305     private static final String REGEX_SYNTAX = "regex";
       
   306 
       
   307     protected boolean followLinks(LinkOption... options) {
       
   308         boolean followLinks = true;
       
   309         for (LinkOption option: options) {
       
   310             if (option == LinkOption.NOFOLLOW_LINKS) {
       
   311                 followLinks = false;
       
   312                 continue;
       
   313             }
       
   314             if (option == null)
       
   315                 throw new NullPointerException();
       
   316             throw new AssertionError("Should not get here");
       
   317         }
       
   318         return followLinks;
       
   319     }
       
   320 
       
   321     @SuppressWarnings("unchecked")
       
   322     protected <V extends FileAttributeView> V newFileAttributeView(Class<V> view,
       
   323                                                                    UnixPath file,
       
   324                                                                    LinkOption... options)
       
   325     {
       
   326         if (view == null)
       
   327             throw new NullPointerException();
       
   328         boolean followLinks = followLinks(options);
       
   329         Class<?> c = view;
       
   330         if (c == BasicFileAttributeView.class)
       
   331             return (V) UnixFileAttributeViews.createBasicView(file, followLinks);
       
   332         if (c == PosixFileAttributeView.class)
       
   333             return (V) UnixFileAttributeViews.createPosixView(file, followLinks);
       
   334         if (c == FileOwnerAttributeView.class)
       
   335             return (V) UnixFileAttributeViews.createOwnerView(file, followLinks);
       
   336         return (V) null;
       
   337     }
       
   338 
       
   339     static List<String> standardFileAttributeViews() {
       
   340         return Arrays.asList("basic", "posix", "unix", "owner");
       
   341     }
       
   342 
       
   343     protected FileAttributeView newFileAttributeView(String name,
       
   344                                                      UnixPath file,
       
   345                                                      LinkOption... options)
       
   346     {
       
   347         boolean followLinks = followLinks(options);
       
   348         if (name.equals("basic"))
       
   349             return UnixFileAttributeViews.createBasicView(file, followLinks);
       
   350         if (name.equals("posix"))
       
   351             return UnixFileAttributeViews.createPosixView(file, followLinks);
       
   352         if (name.equals("unix"))
       
   353             return UnixFileAttributeViews.createUnixView(file, followLinks);
       
   354         if (name.equals("owner"))
       
   355             return UnixFileAttributeViews.createOwnerView(file, followLinks);
       
   356         return null;
       
   357     }
       
   358 
       
   359     @Override
       
   360     public final UserPrincipalLookupService getUserPrincipalLookupService() {
       
   361         return theLookupService;
       
   362     }
       
   363 
       
   364     private static final UserPrincipalLookupService theLookupService =
       
   365         new UserPrincipalLookupService() {
       
   366             @Override
       
   367             public UserPrincipal lookupPrincipalByName(String name)
       
   368                 throws IOException
       
   369             {
       
   370                 return UnixUserPrincipals.lookupUser(name);
       
   371             }
       
   372 
       
   373             @Override
       
   374             public GroupPrincipal lookupPrincipalByGroupName(String group)
       
   375                 throws IOException
       
   376             {
       
   377                 return UnixUserPrincipals.lookupGroup(group);
       
   378             }
       
   379         };
       
   380 }