| /* |
| * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.nio.fs; |
| |
| import java.nio.file.attribute.*; |
| import java.util.concurrent.TimeUnit; |
| import java.util.Set; |
| import java.util.HashSet; |
| |
| /** |
| * Unix implementation of PosixFileAttributes. |
| */ |
| |
| class UnixFileAttributes |
| implements PosixFileAttributes |
| { |
| private int st_mode; |
| private long st_ino; |
| private long st_dev; |
| private long st_rdev; |
| private int st_nlink; |
| private int st_uid; |
| private int st_gid; |
| private long st_size; |
| private long st_atime_sec; |
| private long st_atime_nsec; |
| private long st_mtime_sec; |
| private long st_mtime_nsec; |
| private long st_ctime_sec; |
| private long st_ctime_nsec; |
| private long st_birthtime_sec; |
| |
| // created lazily |
| private volatile UserPrincipal owner; |
| private volatile GroupPrincipal group; |
| private volatile UnixFileKey key; |
| |
| private UnixFileAttributes() { |
| } |
| |
| // get the UnixFileAttributes for a given file |
| static UnixFileAttributes get(UnixPath path, boolean followLinks) |
| throws UnixException |
| { |
| UnixFileAttributes attrs = new UnixFileAttributes(); |
| if (followLinks) { |
| UnixNativeDispatcher.stat(path, attrs); |
| } else { |
| UnixNativeDispatcher.lstat(path, attrs); |
| } |
| return attrs; |
| } |
| |
| // get the UnixFileAttributes for an open file |
| static UnixFileAttributes get(int fd) throws UnixException { |
| UnixFileAttributes attrs = new UnixFileAttributes(); |
| UnixNativeDispatcher.fstat(fd, attrs); |
| return attrs; |
| } |
| |
| // get the UnixFileAttributes for a given file, relative to open directory |
| static UnixFileAttributes get(int dfd, UnixPath path, boolean followLinks) |
| throws UnixException |
| { |
| UnixFileAttributes attrs = new UnixFileAttributes(); |
| int flag = (followLinks) ? 0 : UnixConstants.AT_SYMLINK_NOFOLLOW; |
| UnixNativeDispatcher.fstatat(dfd, path.asByteArray(), flag, attrs); |
| return attrs; |
| } |
| |
| // package-private |
| boolean isSameFile(UnixFileAttributes attrs) { |
| return ((st_ino == attrs.st_ino) && (st_dev == attrs.st_dev)); |
| } |
| |
| // package-private |
| int mode() { return st_mode; } |
| long ino() { return st_ino; } |
| long dev() { return st_dev; } |
| long rdev() { return st_rdev; } |
| int nlink() { return st_nlink; } |
| int uid() { return st_uid; } |
| int gid() { return st_gid; } |
| |
| private static FileTime toFileTime(long sec, long nsec) { |
| if (nsec == 0) { |
| return FileTime.from(sec, TimeUnit.SECONDS); |
| } else { |
| // truncate to microseconds to avoid overflow with timestamps |
| // way out into the future. We can re-visit this if FileTime |
| // is updated to define a from(secs,nsecs) method. |
| long micro = sec*1000000L + nsec/1000L; |
| return FileTime.from(micro, TimeUnit.MICROSECONDS); |
| } |
| } |
| |
| FileTime ctime() { |
| return toFileTime(st_ctime_sec, st_ctime_nsec); |
| } |
| |
| boolean isDevice() { |
| int type = st_mode & UnixConstants.S_IFMT; |
| return (type == UnixConstants.S_IFCHR || |
| type == UnixConstants.S_IFBLK || |
| type == UnixConstants.S_IFIFO); |
| } |
| |
| @Override |
| public FileTime lastModifiedTime() { |
| return toFileTime(st_mtime_sec, st_mtime_nsec); |
| } |
| |
| @Override |
| public FileTime lastAccessTime() { |
| return toFileTime(st_atime_sec, st_atime_nsec); |
| } |
| |
| @Override |
| public FileTime creationTime() { |
| if (UnixNativeDispatcher.birthtimeSupported()) { |
| return FileTime.from(st_birthtime_sec, TimeUnit.SECONDS); |
| } else { |
| // return last modified when birth time not supported |
| return lastModifiedTime(); |
| } |
| } |
| |
| @Override |
| public boolean isRegularFile() { |
| return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFREG); |
| } |
| |
| @Override |
| public boolean isDirectory() { |
| return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFDIR); |
| } |
| |
| @Override |
| public boolean isSymbolicLink() { |
| return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFLNK); |
| } |
| |
| @Override |
| public boolean isOther() { |
| int type = st_mode & UnixConstants.S_IFMT; |
| return (type != UnixConstants.S_IFREG && |
| type != UnixConstants.S_IFDIR && |
| type != UnixConstants.S_IFLNK); |
| } |
| |
| @Override |
| public long size() { |
| return st_size; |
| } |
| |
| @Override |
| public UnixFileKey fileKey() { |
| if (key == null) { |
| synchronized (this) { |
| if (key == null) { |
| key = new UnixFileKey(st_dev, st_ino); |
| } |
| } |
| } |
| return key; |
| } |
| |
| @Override |
| public UserPrincipal owner() { |
| if (owner == null) { |
| synchronized (this) { |
| if (owner == null) { |
| owner = UnixUserPrincipals.fromUid(st_uid); |
| } |
| } |
| } |
| return owner; |
| } |
| |
| @Override |
| public GroupPrincipal group() { |
| if (group == null) { |
| synchronized (this) { |
| if (group == null) { |
| group = UnixUserPrincipals.fromGid(st_gid); |
| } |
| } |
| } |
| return group; |
| } |
| |
| @Override |
| public Set<PosixFilePermission> permissions() { |
| int bits = (st_mode & UnixConstants.S_IAMB); |
| HashSet<PosixFilePermission> perms = new HashSet<>(); |
| |
| if ((bits & UnixConstants.S_IRUSR) > 0) |
| perms.add(PosixFilePermission.OWNER_READ); |
| if ((bits & UnixConstants.S_IWUSR) > 0) |
| perms.add(PosixFilePermission.OWNER_WRITE); |
| if ((bits & UnixConstants.S_IXUSR) > 0) |
| perms.add(PosixFilePermission.OWNER_EXECUTE); |
| |
| if ((bits & UnixConstants.S_IRGRP) > 0) |
| perms.add(PosixFilePermission.GROUP_READ); |
| if ((bits & UnixConstants.S_IWGRP) > 0) |
| perms.add(PosixFilePermission.GROUP_WRITE); |
| if ((bits & UnixConstants.S_IXGRP) > 0) |
| perms.add(PosixFilePermission.GROUP_EXECUTE); |
| |
| if ((bits & UnixConstants.S_IROTH) > 0) |
| perms.add(PosixFilePermission.OTHERS_READ); |
| if ((bits & UnixConstants.S_IWOTH) > 0) |
| perms.add(PosixFilePermission.OTHERS_WRITE); |
| if ((bits & UnixConstants.S_IXOTH) > 0) |
| perms.add(PosixFilePermission.OTHERS_EXECUTE); |
| |
| return perms; |
| } |
| |
| // wrap this object with BasicFileAttributes object to prevent leaking of |
| // user information |
| BasicFileAttributes asBasicFileAttributes() { |
| return UnixAsBasicFileAttributes.wrap(this); |
| } |
| |
| // unwrap BasicFileAttributes to get the underlying UnixFileAttributes |
| // object. Returns null is not wrapped. |
| static UnixFileAttributes toUnixFileAttributes(BasicFileAttributes attrs) { |
| if (attrs instanceof UnixFileAttributes) |
| return (UnixFileAttributes)attrs; |
| if (attrs instanceof UnixAsBasicFileAttributes) { |
| return ((UnixAsBasicFileAttributes)attrs).unwrap(); |
| } |
| return null; |
| } |
| |
| // wrap a UnixFileAttributes object as a BasicFileAttributes |
| private static class UnixAsBasicFileAttributes implements BasicFileAttributes { |
| private final UnixFileAttributes attrs; |
| |
| private UnixAsBasicFileAttributes(UnixFileAttributes attrs) { |
| this.attrs = attrs; |
| } |
| |
| static UnixAsBasicFileAttributes wrap(UnixFileAttributes attrs) { |
| return new UnixAsBasicFileAttributes(attrs); |
| } |
| |
| UnixFileAttributes unwrap() { |
| return attrs; |
| } |
| |
| @Override |
| public FileTime lastModifiedTime() { |
| return attrs.lastModifiedTime(); |
| } |
| @Override |
| public FileTime lastAccessTime() { |
| return attrs.lastAccessTime(); |
| } |
| @Override |
| public FileTime creationTime() { |
| return attrs.creationTime(); |
| } |
| @Override |
| public boolean isRegularFile() { |
| return attrs.isRegularFile(); |
| } |
| @Override |
| public boolean isDirectory() { |
| return attrs.isDirectory(); |
| } |
| @Override |
| public boolean isSymbolicLink() { |
| return attrs.isSymbolicLink(); |
| } |
| @Override |
| public boolean isOther() { |
| return attrs.isOther(); |
| } |
| @Override |
| public long size() { |
| return attrs.size(); |
| } |
| @Override |
| public Object fileKey() { |
| return attrs.fileKey(); |
| } |
| } |
| } |