38 /** |
38 /** |
39 * Unix implementation of SecureDirectoryStream. |
39 * Unix implementation of SecureDirectoryStream. |
40 */ |
40 */ |
41 |
41 |
42 class UnixSecureDirectoryStream |
42 class UnixSecureDirectoryStream |
43 extends SecureDirectoryStream |
43 extends SecureDirectoryStream<Path> |
44 { |
44 { |
45 private final UnixDirectoryStream ds; |
45 private final UnixDirectoryStream ds; |
46 private final int dfd; |
46 private final int dfd; |
47 |
47 |
48 UnixSecureDirectoryStream(UnixPath dir, |
48 UnixSecureDirectoryStream(UnixPath dir, |
83 |
83 |
84 /** |
84 /** |
85 * Opens sub-directory in this directory |
85 * Opens sub-directory in this directory |
86 */ |
86 */ |
87 @Override |
87 @Override |
88 public SecureDirectoryStream newDirectoryStream(Path obj, |
88 public SecureDirectoryStream<Path> newDirectoryStream(Path obj, |
89 boolean followLinks, |
89 LinkOption... options) |
90 DirectoryStream.Filter<? super Path> filter) |
|
91 throws IOException |
90 throws IOException |
92 { |
91 { |
93 UnixPath file = getName(obj); |
92 UnixPath file = getName(obj); |
94 UnixPath child = ds.directory().resolve(file); |
93 UnixPath child = ds.directory().resolve(file); |
|
94 boolean followLinks = file.getFileSystem().followLinks(options); |
95 |
95 |
96 // permission check using name resolved against original path of directory |
96 // permission check using name resolved against original path of directory |
97 SecurityManager sm = System.getSecurityManager(); |
97 SecurityManager sm = System.getSecurityManager(); |
98 if (sm != null) { |
98 if (sm != null) { |
99 child.checkRead(); |
99 child.checkRead(); |
122 UnixNativeDispatcher.close(newdfd2); |
122 UnixNativeDispatcher.close(newdfd2); |
123 if (x.errno() == UnixConstants.ENOTDIR) |
123 if (x.errno() == UnixConstants.ENOTDIR) |
124 throw new NotDirectoryException(file.toString()); |
124 throw new NotDirectoryException(file.toString()); |
125 x.rethrowAsIOException(file); |
125 x.rethrowAsIOException(file); |
126 } |
126 } |
127 return new UnixSecureDirectoryStream(child, ptr, newdfd2, filter); |
127 return new UnixSecureDirectoryStream(child, ptr, newdfd2, null); |
128 } finally { |
128 } finally { |
129 ds.readLock().unlock(); |
129 ds.readLock().unlock(); |
130 } |
130 } |
131 } |
131 } |
132 |
132 |
308 |
308 |
309 /** |
309 /** |
310 * A BasicFileAttributeView implementation that using a dfd/name pair. |
310 * A BasicFileAttributeView implementation that using a dfd/name pair. |
311 */ |
311 */ |
312 private class BasicFileAttributeViewImpl |
312 private class BasicFileAttributeViewImpl |
313 extends AbstractBasicFileAttributeView |
313 implements BasicFileAttributeView |
314 { |
314 { |
315 final UnixPath file; |
315 final UnixPath file; |
316 final boolean followLinks; |
316 final boolean followLinks; |
317 |
|
318 // set to true when binding to another object |
|
319 volatile boolean forwarding; |
|
320 |
317 |
321 BasicFileAttributeViewImpl(UnixPath file, boolean followLinks) |
318 BasicFileAttributeViewImpl(UnixPath file, boolean followLinks) |
322 { |
319 { |
323 this.file = file; |
320 this.file = file; |
324 this.followLinks = followLinks; |
321 this.followLinks = followLinks; |
378 ds.readLock().unlock(); |
375 ds.readLock().unlock(); |
379 } |
376 } |
380 } |
377 } |
381 |
378 |
382 @Override |
379 @Override |
383 public void setTimes(Long lastModifiedTime, |
380 public void setTimes(FileTime lastModifiedTime, |
384 Long lastAccessTime, |
381 FileTime lastAccessTime, |
385 Long createTime, // ignore |
382 FileTime createTime) // ignore |
386 TimeUnit unit) |
|
387 throws IOException |
383 throws IOException |
388 { |
384 { |
389 // no effect |
|
390 if (lastModifiedTime == null && lastAccessTime == null) { |
|
391 return; |
|
392 } |
|
393 |
|
394 checkWriteAccess(); |
385 checkWriteAccess(); |
395 |
386 |
396 ds.readLock().lock(); |
387 ds.readLock().lock(); |
397 try { |
388 try { |
398 if (!ds.isOpen()) |
389 if (!ds.isOpen()) |
399 throw new ClosedDirectoryStreamException(); |
390 throw new ClosedDirectoryStreamException(); |
400 |
391 |
401 int fd = (file == null) ? dfd : open(); |
392 int fd = (file == null) ? dfd : open(); |
402 try { |
393 try { |
403 UnixFileAttributes attrs = null; |
|
404 |
|
405 // if not changing both attributes then need existing attributes |
394 // if not changing both attributes then need existing attributes |
406 if (lastModifiedTime == null || lastAccessTime == null) { |
395 if (lastModifiedTime == null || lastAccessTime == null) { |
407 try { |
396 try { |
408 attrs = UnixFileAttributes.get(fd); |
397 UnixFileAttributes attrs = UnixFileAttributes.get(fd); |
|
398 if (lastModifiedTime == null) |
|
399 lastModifiedTime = attrs.lastModifiedTime(); |
|
400 if (lastAccessTime == null) |
|
401 lastAccessTime = attrs.lastAccessTime(); |
409 } catch (UnixException x) { |
402 } catch (UnixException x) { |
410 x.rethrowAsIOException(file); |
403 x.rethrowAsIOException(file); |
411 } |
404 } |
412 } |
405 } |
413 |
406 // update times |
414 // modified time = existing, now, or new value |
|
415 long modTime; |
|
416 if (lastModifiedTime == null) { |
|
417 modTime = attrs.lastModifiedTime(); |
|
418 } else { |
|
419 if (lastModifiedTime >= 0L) { |
|
420 modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit); |
|
421 } else { |
|
422 if (lastModifiedTime != -1L) |
|
423 throw new IllegalArgumentException(); |
|
424 modTime = System.currentTimeMillis(); |
|
425 } |
|
426 } |
|
427 |
|
428 // access time = existing, now, or new value |
|
429 long accTime; |
|
430 if (lastAccessTime == null) { |
|
431 accTime = attrs.lastAccessTime(); |
|
432 } else { |
|
433 if (lastAccessTime >= 0L) { |
|
434 accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit); |
|
435 } else { |
|
436 if (lastAccessTime != -1L) |
|
437 throw new IllegalArgumentException(); |
|
438 accTime = System.currentTimeMillis(); |
|
439 } |
|
440 } |
|
441 |
|
442 try { |
407 try { |
443 futimes(fd, accTime, modTime); |
408 futimes(fd, |
|
409 lastAccessTime.to(TimeUnit.MICROSECONDS), |
|
410 lastModifiedTime.to(TimeUnit.MICROSECONDS)); |
444 } catch (UnixException x) { |
411 } catch (UnixException x) { |
445 x.rethrowAsIOException(file); |
412 x.rethrowAsIOException(file); |
446 } |
413 } |
447 } finally { |
414 } finally { |
448 if (file != null) |
415 if (file != null) |
458 * A PosixFileAttributeView implementation that using a dfd/name pair. |
425 * A PosixFileAttributeView implementation that using a dfd/name pair. |
459 */ |
426 */ |
460 private class PosixFileAttributeViewImpl |
427 private class PosixFileAttributeViewImpl |
461 extends BasicFileAttributeViewImpl implements PosixFileAttributeView |
428 extends BasicFileAttributeViewImpl implements PosixFileAttributeView |
462 { |
429 { |
463 private static final String PERMISSIONS_NAME = "permissions"; |
|
464 private static final String OWNER_NAME = "owner"; |
|
465 private static final String GROUP_NAME = "group"; |
|
466 |
|
467 PosixFileAttributeViewImpl(UnixPath file, boolean followLinks) { |
430 PosixFileAttributeViewImpl(UnixPath file, boolean followLinks) { |
468 super(file, followLinks); |
431 super(file, followLinks); |
469 } |
432 } |
470 |
433 |
471 private void checkWriteAndUserAccess() { |
434 private void checkWriteAndUserAccess() { |
477 } |
440 } |
478 |
441 |
479 @Override |
442 @Override |
480 public String name() { |
443 public String name() { |
481 return "posix"; |
444 return "posix"; |
482 } |
|
483 |
|
484 @Override |
|
485 public Object getAttribute(String attribute) throws IOException { |
|
486 if (attribute.equals(PERMISSIONS_NAME)) |
|
487 return readAttributes().permissions(); |
|
488 if (attribute.equals(OWNER_NAME)) |
|
489 return readAttributes().owner(); |
|
490 if (attribute.equals(GROUP_NAME)) |
|
491 return readAttributes().group(); |
|
492 return super.getAttribute(attribute); |
|
493 } |
|
494 |
|
495 @Override |
|
496 @SuppressWarnings("unchecked") |
|
497 public void setAttribute(String attribute, Object value) |
|
498 throws IOException |
|
499 { |
|
500 if (attribute.equals(PERMISSIONS_NAME)) { |
|
501 setPermissions((Set<PosixFilePermission>)value); |
|
502 return; |
|
503 } |
|
504 if (attribute.equals(OWNER_NAME)) { |
|
505 setOwner((UserPrincipal)value); |
|
506 return; |
|
507 } |
|
508 if (attribute.equals(GROUP_NAME)) { |
|
509 setGroup((GroupPrincipal)value); |
|
510 return; |
|
511 } |
|
512 super.setAttribute(attribute, value); |
|
513 } |
|
514 |
|
515 final void addPosixAttributesToBuilder(PosixFileAttributes attrs, |
|
516 AttributesBuilder builder) |
|
517 { |
|
518 if (builder.match(PERMISSIONS_NAME)) |
|
519 builder.add(PERMISSIONS_NAME, attrs.permissions()); |
|
520 if (builder.match(OWNER_NAME)) |
|
521 builder.add(OWNER_NAME, attrs.owner()); |
|
522 if (builder.match(GROUP_NAME)) |
|
523 builder.add(GROUP_NAME, attrs.group()); |
|
524 } |
|
525 |
|
526 @Override |
|
527 public Map<String,?> readAttributes(String first, String[] rest) |
|
528 throws IOException |
|
529 { |
|
530 AttributesBuilder builder = AttributesBuilder.create(first, rest); |
|
531 PosixFileAttributes attrs = readAttributes(); |
|
532 addBasicAttributesToBuilder(attrs, builder); |
|
533 addPosixAttributesToBuilder(attrs, builder); |
|
534 return builder.unmodifiableMap(); |
|
535 } |
445 } |
536 |
446 |
537 @Override |
447 @Override |
538 public PosixFileAttributes readAttributes() throws IOException { |
448 public PosixFileAttributes readAttributes() throws IOException { |
539 SecurityManager sm = System.getSecurityManager(); |
449 SecurityManager sm = System.getSecurityManager(); |