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