91 @Override |
95 @Override |
92 public Path getPath(URI uri) { |
96 public Path getPath(URI uri) { |
93 return UnixUriUtils.fromUri(theFileSystem, uri); |
97 return UnixUriUtils.fromUri(theFileSystem, uri); |
94 } |
98 } |
95 |
99 |
96 protected UnixPath checkPath(Path obj) { |
100 UnixPath checkPath(Path obj) { |
97 if (obj == null) |
101 if (obj == null) |
98 throw new NullPointerException(); |
102 throw new NullPointerException(); |
99 if (!(obj instanceof UnixPath)) |
103 if (!(obj instanceof UnixPath)) |
100 throw new ProviderMismatchException(); |
104 throw new ProviderMismatchException(); |
101 return (UnixPath)obj; |
105 return (UnixPath)obj; |
102 } |
106 } |
103 |
107 |
|
108 boolean followLinks(LinkOption... options) { |
|
109 boolean followLinks = true; |
|
110 for (LinkOption option: options) { |
|
111 if (option == LinkOption.NOFOLLOW_LINKS) { |
|
112 followLinks = false; |
|
113 continue; |
|
114 } |
|
115 if (option == null) |
|
116 throw new NullPointerException(); |
|
117 throw new AssertionError("Should not get here"); |
|
118 } |
|
119 return followLinks; |
|
120 } |
|
121 |
|
122 @Override |
|
123 @SuppressWarnings("unchecked") |
|
124 public <V extends FileAttributeView> V getFileAttributeView(Path obj, |
|
125 Class<V> type, |
|
126 LinkOption... options) |
|
127 { |
|
128 UnixPath file = UnixPath.toUnixPath(obj); |
|
129 boolean followLinks = followLinks(options); |
|
130 if (type == BasicFileAttributeView.class) |
|
131 return (V) UnixFileAttributeViews.createBasicView(file, followLinks); |
|
132 if (type == PosixFileAttributeView.class) |
|
133 return (V) UnixFileAttributeViews.createPosixView(file, followLinks); |
|
134 if (type == FileOwnerAttributeView.class) |
|
135 return (V) UnixFileAttributeViews.createOwnerView(file, followLinks); |
|
136 if (type == null) |
|
137 throw new NullPointerException(); |
|
138 return (V) null; |
|
139 } |
|
140 |
|
141 @Override |
|
142 @SuppressWarnings("unchecked") |
|
143 public <A extends BasicFileAttributes> A readAttributes(Path file, |
|
144 Class<A> type, |
|
145 LinkOption... options) |
|
146 throws IOException |
|
147 { |
|
148 Class<? extends BasicFileAttributeView> view; |
|
149 if (type == BasicFileAttributes.class) |
|
150 view = BasicFileAttributeView.class; |
|
151 else if (type == PosixFileAttributes.class) |
|
152 view = PosixFileAttributeView.class; |
|
153 else if (type == null) |
|
154 throw new NullPointerException(); |
|
155 else |
|
156 throw new UnsupportedOperationException(); |
|
157 return (A) getFileAttributeView(file, view, options).readAttributes(); |
|
158 } |
|
159 |
|
160 @Override |
|
161 protected DynamicFileAttributeView getFileAttributeView(Path obj, |
|
162 String name, |
|
163 LinkOption... options) |
|
164 { |
|
165 UnixPath file = UnixPath.toUnixPath(obj); |
|
166 boolean followLinks = followLinks(options); |
|
167 if (name.equals("basic")) |
|
168 return UnixFileAttributeViews.createBasicView(file, followLinks); |
|
169 if (name.equals("posix")) |
|
170 return UnixFileAttributeViews.createPosixView(file, followLinks); |
|
171 if (name.equals("unix")) |
|
172 return UnixFileAttributeViews.createUnixView(file, followLinks); |
|
173 if (name.equals("owner")) |
|
174 return UnixFileAttributeViews.createOwnerView(file, followLinks); |
|
175 return null; |
|
176 } |
|
177 |
104 @Override |
178 @Override |
105 public FileChannel newFileChannel(Path obj, |
179 public FileChannel newFileChannel(Path obj, |
106 Set<? extends OpenOption> options, |
180 Set<? extends OpenOption> options, |
107 FileAttribute<?>... attrs) |
181 FileAttribute<?>... attrs) |
108 throws IOException |
182 throws IOException |
134 } catch (UnixException x) { |
208 } catch (UnixException x) { |
135 x.rethrowAsIOException(file); |
209 x.rethrowAsIOException(file); |
136 return null; |
210 return null; |
137 } |
211 } |
138 } |
212 } |
|
213 |
|
214 |
|
215 @Override |
|
216 public SeekableByteChannel newByteChannel(Path obj, |
|
217 Set<? extends OpenOption> options, |
|
218 FileAttribute<?>... attrs) |
|
219 throws IOException |
|
220 { |
|
221 UnixPath file = UnixPath.toUnixPath(obj); |
|
222 int mode = UnixFileModeAttribute |
|
223 .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); |
|
224 try { |
|
225 return UnixChannelFactory.newFileChannel(file, options, mode); |
|
226 } catch (UnixException x) { |
|
227 x.rethrowAsIOException(file); |
|
228 return null; // keep compiler happy |
|
229 } |
|
230 } |
|
231 |
|
232 @Override |
|
233 boolean implDelete(Path obj, boolean failIfNotExists) throws IOException { |
|
234 UnixPath file = UnixPath.toUnixPath(obj); |
|
235 file.checkDelete(); |
|
236 |
|
237 // need file attributes to know if file is directory |
|
238 UnixFileAttributes attrs = null; |
|
239 try { |
|
240 attrs = UnixFileAttributes.get(file, false); |
|
241 if (attrs.isDirectory()) { |
|
242 rmdir(file); |
|
243 } else { |
|
244 unlink(file); |
|
245 } |
|
246 return true; |
|
247 } catch (UnixException x) { |
|
248 // no-op if file does not exist |
|
249 if (!failIfNotExists && x.errno() == ENOENT) |
|
250 return false; |
|
251 |
|
252 // DirectoryNotEmptyException if not empty |
|
253 if (attrs != null && attrs.isDirectory() && |
|
254 (x.errno() == EEXIST || x.errno() == ENOTEMPTY)) |
|
255 throw new DirectoryNotEmptyException(file.getPathForExecptionMessage()); |
|
256 |
|
257 x.rethrowAsIOException(file); |
|
258 return false; |
|
259 } |
|
260 } |
|
261 |
|
262 @Override |
|
263 public void copy(Path source, Path target, CopyOption... options) |
|
264 throws IOException |
|
265 { |
|
266 UnixCopyFile.copy(UnixPath.toUnixPath(source), |
|
267 UnixPath.toUnixPath(target), |
|
268 options); |
|
269 } |
|
270 |
|
271 @Override |
|
272 public void move(Path source, Path target, CopyOption... options) |
|
273 throws IOException |
|
274 { |
|
275 UnixCopyFile.move(UnixPath.toUnixPath(source), |
|
276 UnixPath.toUnixPath(target), |
|
277 options); |
|
278 } |
|
279 |
|
280 @Override |
|
281 public void checkAccess(Path obj, AccessMode... modes) throws IOException { |
|
282 UnixPath file = UnixPath.toUnixPath(obj); |
|
283 boolean e = false; |
|
284 boolean r = false; |
|
285 boolean w = false; |
|
286 boolean x = false; |
|
287 |
|
288 if (modes.length == 0) { |
|
289 e = true; |
|
290 } else { |
|
291 for (AccessMode mode: modes) { |
|
292 switch (mode) { |
|
293 case READ : r = true; break; |
|
294 case WRITE : w = true; break; |
|
295 case EXECUTE : x = true; break; |
|
296 default: throw new AssertionError("Should not get here"); |
|
297 } |
|
298 } |
|
299 } |
|
300 |
|
301 int mode = 0; |
|
302 if (e || r) { |
|
303 file.checkRead(); |
|
304 mode |= (r) ? R_OK : F_OK; |
|
305 } |
|
306 if (w) { |
|
307 file.checkWrite(); |
|
308 mode |= W_OK; |
|
309 } |
|
310 if (x) { |
|
311 SecurityManager sm = System.getSecurityManager(); |
|
312 if (sm != null) { |
|
313 // not cached |
|
314 sm.checkExec(file.getPathForPermissionCheck()); |
|
315 } |
|
316 mode |= X_OK; |
|
317 } |
|
318 try { |
|
319 access(file, mode); |
|
320 } catch (UnixException exc) { |
|
321 exc.rethrowAsIOException(file); |
|
322 } |
|
323 } |
|
324 |
|
325 @Override |
|
326 public boolean isSameFile(Path obj1, Path obj2) throws IOException { |
|
327 UnixPath file1 = UnixPath.toUnixPath(obj1); |
|
328 if (file1.equals(obj2)) |
|
329 return true; |
|
330 if (obj2 == null) |
|
331 throw new NullPointerException(); |
|
332 if (!(obj2 instanceof UnixPath)) |
|
333 return false; |
|
334 UnixPath file2 = (UnixPath)obj2; |
|
335 |
|
336 // check security manager access to both files |
|
337 file1.checkRead(); |
|
338 file2.checkRead(); |
|
339 |
|
340 UnixFileAttributes attrs1; |
|
341 UnixFileAttributes attrs2; |
|
342 try { |
|
343 attrs1 = UnixFileAttributes.get(file1, true); |
|
344 } catch (UnixException x) { |
|
345 x.rethrowAsIOException(file1); |
|
346 return false; // keep compiler happy |
|
347 } |
|
348 try { |
|
349 attrs2 = UnixFileAttributes.get(file2, true); |
|
350 } catch (UnixException x) { |
|
351 x.rethrowAsIOException(file2); |
|
352 return false; // keep compiler happy |
|
353 } |
|
354 return attrs1.isSameFile(attrs2); |
|
355 } |
|
356 |
|
357 @Override |
|
358 public boolean isHidden(Path obj) { |
|
359 UnixPath file = UnixPath.toUnixPath(obj); |
|
360 file.checkRead(); |
|
361 UnixPath name = file.getFileName(); |
|
362 if (name == null) |
|
363 return false; |
|
364 return (name.asByteArray()[0] == '.'); |
|
365 } |
|
366 |
|
367 /** |
|
368 * Returns a FileStore to represent the file system where the given file |
|
369 * reside. |
|
370 */ |
|
371 abstract FileStore getFileStore(UnixPath path) throws IOException; |
|
372 |
|
373 @Override |
|
374 public FileStore getFileStore(Path obj) throws IOException { |
|
375 UnixPath file = UnixPath.toUnixPath(obj); |
|
376 SecurityManager sm = System.getSecurityManager(); |
|
377 if (sm != null) { |
|
378 sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); |
|
379 file.checkRead(); |
|
380 } |
|
381 return getFileStore(file); |
|
382 } |
|
383 |
|
384 @Override |
|
385 public void createDirectory(Path obj, FileAttribute<?>... attrs) |
|
386 throws IOException |
|
387 { |
|
388 UnixPath dir = UnixPath.toUnixPath(obj); |
|
389 dir.checkWrite(); |
|
390 |
|
391 int mode = UnixFileModeAttribute |
|
392 .toUnixMode(UnixFileModeAttribute.ALL_PERMISSIONS, attrs); |
|
393 try { |
|
394 mkdir(dir, mode); |
|
395 } catch (UnixException x) { |
|
396 x.rethrowAsIOException(dir); |
|
397 } |
|
398 } |
|
399 |
|
400 |
|
401 @Override |
|
402 public DirectoryStream<Path> newDirectoryStream(Path obj, DirectoryStream.Filter<? super Path> filter) |
|
403 throws IOException |
|
404 { |
|
405 UnixPath dir = UnixPath.toUnixPath(obj); |
|
406 dir.checkRead(); |
|
407 if (filter == null) |
|
408 throw new NullPointerException(); |
|
409 |
|
410 // can't return SecureDirectoryStream on kernels that don't support |
|
411 // openat, etc. |
|
412 if (!supportsAtSysCalls()) { |
|
413 try { |
|
414 long ptr = opendir(dir); |
|
415 return new UnixDirectoryStream(dir, ptr, filter); |
|
416 } catch (UnixException x) { |
|
417 if (x.errno() == ENOTDIR) |
|
418 throw new NotDirectoryException(dir.getPathForExecptionMessage()); |
|
419 x.rethrowAsIOException(dir); |
|
420 } |
|
421 } |
|
422 |
|
423 // open directory and dup file descriptor for use by |
|
424 // opendir/readdir/closedir |
|
425 int dfd1 = -1; |
|
426 int dfd2 = -1; |
|
427 long dp = 0L; |
|
428 try { |
|
429 dfd1 = open(dir, O_RDONLY, 0); |
|
430 dfd2 = dup(dfd1); |
|
431 dp = fdopendir(dfd1); |
|
432 } catch (UnixException x) { |
|
433 if (dfd1 != -1) |
|
434 UnixNativeDispatcher.close(dfd1); |
|
435 if (dfd2 != -1) |
|
436 UnixNativeDispatcher.close(dfd2); |
|
437 if (x.errno() == UnixConstants.ENOTDIR) |
|
438 throw new NotDirectoryException(dir.getPathForExecptionMessage()); |
|
439 x.rethrowAsIOException(dir); |
|
440 } |
|
441 return new UnixSecureDirectoryStream(dir, dp, dfd2, filter); |
|
442 } |
|
443 |
|
444 @Override |
|
445 public void createSymbolicLink(Path obj1, Path obj2, FileAttribute<?>... attrs) |
|
446 throws IOException |
|
447 { |
|
448 UnixPath link = UnixPath.toUnixPath(obj1); |
|
449 UnixPath target = UnixPath.toUnixPath(obj2); |
|
450 |
|
451 // no attributes supported when creating links |
|
452 if (attrs.length > 0) { |
|
453 UnixFileModeAttribute.toUnixMode(0, attrs); // may throw NPE or UOE |
|
454 throw new UnsupportedOperationException("Initial file attributes" + |
|
455 "not supported when creating symbolic link"); |
|
456 } |
|
457 |
|
458 // permission check |
|
459 SecurityManager sm = System.getSecurityManager(); |
|
460 if (sm != null) { |
|
461 sm.checkPermission(new LinkPermission("symbolic")); |
|
462 link.checkWrite(); |
|
463 } |
|
464 |
|
465 // create link |
|
466 try { |
|
467 symlink(target.asByteArray(), link); |
|
468 } catch (UnixException x) { |
|
469 x.rethrowAsIOException(link); |
|
470 } |
|
471 } |
|
472 |
|
473 @Override |
|
474 public void createLink(Path obj1, Path obj2) throws IOException { |
|
475 UnixPath link = UnixPath.toUnixPath(obj1); |
|
476 UnixPath existing = UnixPath.toUnixPath(obj2); |
|
477 |
|
478 // permission check |
|
479 SecurityManager sm = System.getSecurityManager(); |
|
480 if (sm != null) { |
|
481 sm.checkPermission(new LinkPermission("hard")); |
|
482 link.checkWrite(); |
|
483 existing.checkWrite(); |
|
484 } |
|
485 try { |
|
486 link(existing, link); |
|
487 } catch (UnixException x) { |
|
488 x.rethrowAsIOException(link, existing); |
|
489 } |
|
490 } |
|
491 |
|
492 @Override |
|
493 public Path readSymbolicLink(Path obj1) throws IOException { |
|
494 UnixPath link = UnixPath.toUnixPath(obj1); |
|
495 // permission check |
|
496 SecurityManager sm = System.getSecurityManager(); |
|
497 if (sm != null) { |
|
498 FilePermission perm = new FilePermission(link.getPathForPermissionCheck(), |
|
499 SecurityConstants.FILE_READLINK_ACTION); |
|
500 AccessController.checkPermission(perm); |
|
501 } |
|
502 try { |
|
503 byte[] target = readlink(link); |
|
504 return new UnixPath(link.getFileSystem(), target); |
|
505 } catch (UnixException x) { |
|
506 if (x.errno() == UnixConstants.EINVAL) |
|
507 throw new NotLinkException(link.getPathForExecptionMessage()); |
|
508 x.rethrowAsIOException(link); |
|
509 return null; // keep compiler happy |
|
510 } |
|
511 } |
139 } |
512 } |