@Override public List<AclEntry> getAcl() throws IOException { // permission check checkAccess(file, true, false); // open file (will fail if file is a link and not following links) int fd = file.openForAttributeAccess(followLinks); try { long address = unsafe.allocateMemory(SIZEOF_ACE_T * MAX_ACL_ENTRIES); try { // read ACL and decode it int n = facl(fd, ACE_GETACL, MAX_ACL_ENTRIES, address); assert n >= 0; return decode(address, n); } catch (UnixException x) { if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) { throw new FileSystemException( file.getPathForExceptionMessage(), null, x.getMessage() + " (file system does not support NFSv4 ACLs)"); } x.rethrowAsIOException(file); return null; // keep compiler happy } finally { unsafe.freeMemory(address); } } finally { close(fd); } }
@Override public void setAcl(List<AclEntry> acl) throws IOException { // permission check checkAccess(file, false, true); // open file (will fail if file is a link and not following links) int fd = file.openForAttributeAccess(followLinks); try { // SECURITY: need to copy list as can change during processing acl = new ArrayList<AclEntry>(acl); int n = acl.size(); long address = unsafe.allocateMemory(SIZEOF_ACE_T * n); try { encode(acl, address); facl(fd, ACE_SETACL, n, address); } catch (UnixException x) { if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) { throw new FileSystemException( file.getPathForExceptionMessage(), null, x.getMessage() + " (file system does not support NFSv4 ACLs)"); } if (x.errno() == EINVAL && (n < 3)) throw new IOException("ACL must contain at least 3 entries"); x.rethrowAsIOException(file); } finally { unsafe.freeMemory(address); } } finally { close(fd); } }
@Override public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException { // null => don't change if (lastModifiedTime == null && lastAccessTime == null) { // no effect return; } // permission check file.checkWrite(); int fd = file.openForAttributeAccess(followLinks); try { // if not changing both attributes then need existing attributes if (lastModifiedTime == null || lastAccessTime == null) { try { UnixFileAttributes attrs = UnixFileAttributes.get(fd); if (lastModifiedTime == null) lastModifiedTime = attrs.lastModifiedTime(); if (lastAccessTime == null) lastAccessTime = attrs.lastAccessTime(); } catch (UnixException x) { x.rethrowAsIOException(file); } } // uptime times long modValue = lastModifiedTime.to(TimeUnit.MICROSECONDS); long accessValue = lastAccessTime.to(TimeUnit.MICROSECONDS); boolean retry = false; try { futimes(fd, accessValue, modValue); } catch (UnixException x) { // if futimes fails with EINVAL and one/both of the times is // negative then we adjust the value to the epoch and retry. if (x.errno() == UnixConstants.EINVAL && (modValue < 0L || accessValue < 0L)) { retry = true; } else { x.rethrowAsIOException(file); } } if (retry) { if (modValue < 0L) modValue = 0L; if (accessValue < 0L) accessValue = 0L; try { futimes(fd, accessValue, modValue); } catch (UnixException x) { x.rethrowAsIOException(file); } } } finally { close(fd); } }