1 /* 2 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * 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.util.*; 32 import java.util.regex.Pattern; 33 import java.io.IOException; 34 import java.security.AccessController; 35 import java.security.PrivilegedAction; 36 import sun.security.action.GetPropertyAction; 37 38 class WindowsFileSystem 39 extends FileSystem 40 { 41 private final WindowsFileSystemProvider provider; 42 43 // default directory (is absolute), and default root 44 private final String defaultDirectory; 45 private final String defaultRoot; 46 47 private final boolean supportsLinks; 48 private final boolean supportsStreamEnumeration; 49 50 // package-private 51 WindowsFileSystem(WindowsFileSystemProvider provider, 52 String dir) 53 { 54 this.provider = provider; 55 56 // parse default directory and check it is absolute 57 WindowsPathParser.Result result = WindowsPathParser.parse(dir); 58 59 if ((result.type() != WindowsPathType.ABSOLUTE) && 60 (result.type() != WindowsPathType.UNC)) 61 throw new AssertionError("Default directory is not an absolute path"); 62 this.defaultDirectory = result.path(); 63 this.defaultRoot = result.root(); 64 65 PrivilegedAction<String> pa = new GetPropertyAction("os.version"); 66 String osversion = AccessController.doPrivileged(pa); 67 String[] vers = Util.split(osversion, '.'); 68 int major = Integer.parseInt(vers[0]); 69 int minor = Integer.parseInt(vers[1]); 70 71 // symbolic links available on Vista and newer 72 supportsLinks = (major >= 6); 73 74 // enumeration of data streams available on Windows Server 2003 and newer 75 supportsStreamEnumeration = (major >= 6) || (major == 5 && minor >= 2); 76 } 77 78 // package-private 79 String defaultDirectory() { 80 return defaultDirectory; 81 } 82 83 String defaultRoot() { 84 return defaultRoot; 85 } 86 87 boolean supportsLinks() { 88 return supportsLinks; 89 } 90 91 boolean supportsStreamEnumeration() { 92 return supportsStreamEnumeration; 93 } 94 95 @Override 96 public FileSystemProvider provider() { 97 return provider; 98 } 99 100 @Override 101 public String getSeparator() { 102 return "\\"; 103 } 104 105 @Override 106 public boolean isOpen() { 107 return true; 108 } 109 110 @Override 111 public boolean isReadOnly() { 112 return false; 113 } 114 115 @Override 116 public void close() throws IOException { 117 throw new UnsupportedOperationException(); 118 } 119 120 @Override 121 public Iterable<Path> getRootDirectories() { 122 int drives = 0; 123 try { 124 drives = WindowsNativeDispatcher.GetLogicalDrives(); 125 } catch (WindowsException x) { 126 // shouldn't happen 127 throw new AssertionError(x.getMessage()); 128 } 129 130 // iterate over roots, ignoring those that the security manager denies 131 ArrayList<Path> result = new ArrayList<>(); 132 SecurityManager sm = System.getSecurityManager(); 133 for (int i = 0; i <= 25; i++) { // 0->A, 1->B, 2->C... 134 if ((drives & (1 << i)) != 0) { 135 StringBuilder sb = new StringBuilder(3); 136 sb.append((char)('A' + i)); 137 sb.append(":\\"); 138 String root = sb.toString(); 139 if (sm != null) { 140 try { 141 sm.checkRead(root); 142 } catch (SecurityException x) { 143 continue; 144 } 145 } 146 result.add(WindowsPath.createFromNormalizedPath(this, root)); 147 } 148 } 149 return Collections.unmodifiableList(result); 150 } 151 152 /** 153 * Iterator returned by getFileStores method. 154 */ 155 private class FileStoreIterator implements Iterator<FileStore> { 156 private final Iterator<Path> roots; 157 private FileStore next; 158 159 FileStoreIterator() { 160 this.roots = getRootDirectories().iterator(); 161 } 162 163 private FileStore readNext() { 164 assert Thread.holdsLock(this); 165 for (;;) { 166 if (!roots.hasNext()) 167 return null; 168 WindowsPath root = (WindowsPath)roots.next(); 169 // ignore if security manager denies access 170 try { 171 root.checkRead(); 172 } catch (SecurityException x) { 173 continue; 174 } 175 try { 176 FileStore fs = WindowsFileStore.create(root.toString(), true); 177 if (fs != null) 178 return fs; 179 } catch (IOException ioe) { 180 // skip it 181 } 182 } 183 } 184 185 @Override 186 public synchronized boolean hasNext() { 187 if (next != null) 188 return true; 189 next = readNext(); 190 return next != null; 191 } 192 193 @Override 194 public synchronized FileStore next() { 195 if (next == null) 196 next = readNext(); 197 if (next == null) { 198 throw new NoSuchElementException(); 199 } else { 200 FileStore result = next; 201 next = null; 202 return result; 203 } 204 } 205 206 @Override 207 public void remove() { 208 throw new UnsupportedOperationException(); 209 } 210 } 211 212 @Override 213 public Iterable<FileStore> getFileStores() { 214 SecurityManager sm = System.getSecurityManager(); 215 if (sm != null) { 216 try { 217 sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); 218 } catch (SecurityException se) { 219 return Collections.emptyList(); 220 } 221 } 222 return new Iterable<FileStore>() { 223 public Iterator<FileStore> iterator() { 224 return new FileStoreIterator(); 225 } 226 }; 227 } 228 229 // supported views 230 private static final Set<String> supportedFileAttributeViews = Collections 231 .unmodifiableSet(new HashSet<String>(Arrays.asList("basic", "dos", "acl", "owner", "user"))); 232 233 @Override 234 public Set<String> supportedFileAttributeViews() { 235 return supportedFileAttributeViews; 236 } 237 238 @Override 239 public final Path getPath(String first, String... more) { 240 String path; 241 if (more.length == 0) { 242 path = first; 243 } else { 244 StringBuilder sb = new StringBuilder(); 245 sb.append(first); 246 for (String segment: more) { 247 if (segment.length() > 0) { 248 if (sb.length() > 0) 249 sb.append('\\'); 250 sb.append(segment); 251 } 252 } 253 path = sb.toString(); 254 } 255 return WindowsPath.parse(this, path); 256 } 257 258 @Override 259 public UserPrincipalLookupService getUserPrincipalLookupService() { 260 return LookupService.instance; 261 } 262 263 private static class LookupService { 264 static final UserPrincipalLookupService instance = 265 new UserPrincipalLookupService() { 266 @Override 267 public UserPrincipal lookupPrincipalByName(String name) 268 throws IOException 269 { 270 return WindowsUserPrincipals.lookup(name); 271 } 272 @Override 273 public GroupPrincipal lookupPrincipalByGroupName(String group) 274 throws IOException 275 { 276 UserPrincipal user = WindowsUserPrincipals.lookup(group); 277 if (!(user instanceof GroupPrincipal)) 278 throw new UserPrincipalNotFoundException(group); 279 return (GroupPrincipal)user; 280 } 281 }; 282 } 283 284 @Override 285 public PathMatcher getPathMatcher(String syntaxAndInput) { 286 int pos = syntaxAndInput.indexOf(':'); 287 if (pos <= 0 || pos == syntaxAndInput.length()) 288 throw new IllegalArgumentException(); 289 String syntax = syntaxAndInput.substring(0, pos); 290 String input = syntaxAndInput.substring(pos+1); 291 292 String expr; 293 if (syntax.equals(GLOB_SYNTAX)) { 294 expr = Globs.toWindowsRegexPattern(input); 295 } else { 296 if (syntax.equals(REGEX_SYNTAX)) { 297 expr = input; 298 } else { 299 throw new UnsupportedOperationException("Syntax '" + syntax + 300 "' not recognized"); 301 } 302 } 303 304 // match in unicode_case_insensitive 305 final Pattern pattern = Pattern.compile(expr, 306 Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); 307 308 // return matcher 309 return new PathMatcher() { 310 @Override 311 public boolean matches(Path path) { 312 return pattern.matcher(path.toString()).matches(); 313 } 314 }; 315 } 316 private static final String GLOB_SYNTAX = "glob"; 317 private static final String REGEX_SYNTAX = "regex"; 318 319 @Override 320 public WatchService newWatchService() 321 throws IOException 322 { 323 return new WindowsWatchService(this); 324 } 325 }