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