1 /* 2 * Copyright (c) 2008, 2013, 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.attribute.*; 29 import java.util.concurrent.TimeUnit; 30 import java.util.Set; 31 import java.util.HashSet; 32 33 /** 34 * Unix implementation of PosixFileAttributes. 35 */ 36 37 class UnixFileAttributes 38 implements PosixFileAttributes 39 { 40 private int st_mode; 41 private long st_ino; 42 private long st_dev; 43 private long st_rdev; 44 private int st_nlink; 45 private int st_uid; 46 private int st_gid; 47 private long st_size; 48 private long st_atime_sec; 49 private long st_atime_nsec; 50 private long st_mtime_sec; 51 private long st_mtime_nsec; 52 private long st_ctime_sec; 53 private long st_ctime_nsec; 54 private long st_birthtime_sec; 55 56 // created lazily 57 private volatile UserPrincipal owner; 58 private volatile GroupPrincipal group; 59 private volatile UnixFileKey key; 60 UnixFileAttributes()61 private UnixFileAttributes() { 62 } 63 64 // get the UnixFileAttributes for a given file get(UnixPath path, boolean followLinks)65 static UnixFileAttributes get(UnixPath path, boolean followLinks) 66 throws UnixException 67 { 68 UnixFileAttributes attrs = new UnixFileAttributes(); 69 if (followLinks) { 70 UnixNativeDispatcher.stat(path, attrs); 71 } else { 72 UnixNativeDispatcher.lstat(path, attrs); 73 } 74 return attrs; 75 } 76 77 // get the UnixFileAttributes for an open file get(int fd)78 static UnixFileAttributes get(int fd) throws UnixException { 79 UnixFileAttributes attrs = new UnixFileAttributes(); 80 UnixNativeDispatcher.fstat(fd, attrs); 81 return attrs; 82 } 83 84 // get the UnixFileAttributes for a given file, relative to open directory get(int dfd, UnixPath path, boolean followLinks)85 static UnixFileAttributes get(int dfd, UnixPath path, boolean followLinks) 86 throws UnixException 87 { 88 UnixFileAttributes attrs = new UnixFileAttributes(); 89 int flag = (followLinks) ? 0 : UnixConstants.AT_SYMLINK_NOFOLLOW; 90 UnixNativeDispatcher.fstatat(dfd, path.asByteArray(), flag, attrs); 91 return attrs; 92 } 93 94 // package-private isSameFile(UnixFileAttributes attrs)95 boolean isSameFile(UnixFileAttributes attrs) { 96 return ((st_ino == attrs.st_ino) && (st_dev == attrs.st_dev)); 97 } 98 99 // package-private mode()100 int mode() { return st_mode; } ino()101 long ino() { return st_ino; } dev()102 long dev() { return st_dev; } rdev()103 long rdev() { return st_rdev; } nlink()104 int nlink() { return st_nlink; } uid()105 int uid() { return st_uid; } gid()106 int gid() { return st_gid; } 107 toFileTime(long sec, long nsec)108 private static FileTime toFileTime(long sec, long nsec) { 109 if (nsec == 0) { 110 return FileTime.from(sec, TimeUnit.SECONDS); 111 } else { 112 // truncate to microseconds to avoid overflow with timestamps 113 // way out into the future. We can re-visit this if FileTime 114 // is updated to define a from(secs,nsecs) method. 115 long micro = sec*1000000L + nsec/1000L; 116 return FileTime.from(micro, TimeUnit.MICROSECONDS); 117 } 118 } 119 ctime()120 FileTime ctime() { 121 return toFileTime(st_ctime_sec, st_ctime_nsec); 122 } 123 isDevice()124 boolean isDevice() { 125 int type = st_mode & UnixConstants.S_IFMT; 126 return (type == UnixConstants.S_IFCHR || 127 type == UnixConstants.S_IFBLK || 128 type == UnixConstants.S_IFIFO); 129 } 130 131 @Override lastModifiedTime()132 public FileTime lastModifiedTime() { 133 return toFileTime(st_mtime_sec, st_mtime_nsec); 134 } 135 136 @Override lastAccessTime()137 public FileTime lastAccessTime() { 138 return toFileTime(st_atime_sec, st_atime_nsec); 139 } 140 141 @Override creationTime()142 public FileTime creationTime() { 143 if (UnixNativeDispatcher.birthtimeSupported()) { 144 return FileTime.from(st_birthtime_sec, TimeUnit.SECONDS); 145 } else { 146 // return last modified when birth time not supported 147 return lastModifiedTime(); 148 } 149 } 150 151 @Override isRegularFile()152 public boolean isRegularFile() { 153 return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFREG); 154 } 155 156 @Override isDirectory()157 public boolean isDirectory() { 158 return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFDIR); 159 } 160 161 @Override isSymbolicLink()162 public boolean isSymbolicLink() { 163 return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFLNK); 164 } 165 166 @Override isOther()167 public boolean isOther() { 168 int type = st_mode & UnixConstants.S_IFMT; 169 return (type != UnixConstants.S_IFREG && 170 type != UnixConstants.S_IFDIR && 171 type != UnixConstants.S_IFLNK); 172 } 173 174 @Override size()175 public long size() { 176 return st_size; 177 } 178 179 @Override fileKey()180 public UnixFileKey fileKey() { 181 if (key == null) { 182 synchronized (this) { 183 if (key == null) { 184 key = new UnixFileKey(st_dev, st_ino); 185 } 186 } 187 } 188 return key; 189 } 190 191 @Override owner()192 public UserPrincipal owner() { 193 if (owner == null) { 194 synchronized (this) { 195 if (owner == null) { 196 owner = UnixUserPrincipals.fromUid(st_uid); 197 } 198 } 199 } 200 return owner; 201 } 202 203 @Override group()204 public GroupPrincipal group() { 205 if (group == null) { 206 synchronized (this) { 207 if (group == null) { 208 group = UnixUserPrincipals.fromGid(st_gid); 209 } 210 } 211 } 212 return group; 213 } 214 215 @Override permissions()216 public Set<PosixFilePermission> permissions() { 217 int bits = (st_mode & UnixConstants.S_IAMB); 218 HashSet<PosixFilePermission> perms = new HashSet<>(); 219 220 if ((bits & UnixConstants.S_IRUSR) > 0) 221 perms.add(PosixFilePermission.OWNER_READ); 222 if ((bits & UnixConstants.S_IWUSR) > 0) 223 perms.add(PosixFilePermission.OWNER_WRITE); 224 if ((bits & UnixConstants.S_IXUSR) > 0) 225 perms.add(PosixFilePermission.OWNER_EXECUTE); 226 227 if ((bits & UnixConstants.S_IRGRP) > 0) 228 perms.add(PosixFilePermission.GROUP_READ); 229 if ((bits & UnixConstants.S_IWGRP) > 0) 230 perms.add(PosixFilePermission.GROUP_WRITE); 231 if ((bits & UnixConstants.S_IXGRP) > 0) 232 perms.add(PosixFilePermission.GROUP_EXECUTE); 233 234 if ((bits & UnixConstants.S_IROTH) > 0) 235 perms.add(PosixFilePermission.OTHERS_READ); 236 if ((bits & UnixConstants.S_IWOTH) > 0) 237 perms.add(PosixFilePermission.OTHERS_WRITE); 238 if ((bits & UnixConstants.S_IXOTH) > 0) 239 perms.add(PosixFilePermission.OTHERS_EXECUTE); 240 241 return perms; 242 } 243 244 // wrap this object with BasicFileAttributes object to prevent leaking of 245 // user information asBasicFileAttributes()246 BasicFileAttributes asBasicFileAttributes() { 247 return UnixAsBasicFileAttributes.wrap(this); 248 } 249 250 // unwrap BasicFileAttributes to get the underlying UnixFileAttributes 251 // object. Returns null is not wrapped. toUnixFileAttributes(BasicFileAttributes attrs)252 static UnixFileAttributes toUnixFileAttributes(BasicFileAttributes attrs) { 253 if (attrs instanceof UnixFileAttributes) 254 return (UnixFileAttributes)attrs; 255 if (attrs instanceof UnixAsBasicFileAttributes) { 256 return ((UnixAsBasicFileAttributes)attrs).unwrap(); 257 } 258 return null; 259 } 260 261 // wrap a UnixFileAttributes object as a BasicFileAttributes 262 private static class UnixAsBasicFileAttributes implements BasicFileAttributes { 263 private final UnixFileAttributes attrs; 264 UnixAsBasicFileAttributes(UnixFileAttributes attrs)265 private UnixAsBasicFileAttributes(UnixFileAttributes attrs) { 266 this.attrs = attrs; 267 } 268 wrap(UnixFileAttributes attrs)269 static UnixAsBasicFileAttributes wrap(UnixFileAttributes attrs) { 270 return new UnixAsBasicFileAttributes(attrs); 271 } 272 unwrap()273 UnixFileAttributes unwrap() { 274 return attrs; 275 } 276 277 @Override lastModifiedTime()278 public FileTime lastModifiedTime() { 279 return attrs.lastModifiedTime(); 280 } 281 @Override lastAccessTime()282 public FileTime lastAccessTime() { 283 return attrs.lastAccessTime(); 284 } 285 @Override creationTime()286 public FileTime creationTime() { 287 return attrs.creationTime(); 288 } 289 @Override isRegularFile()290 public boolean isRegularFile() { 291 return attrs.isRegularFile(); 292 } 293 @Override isDirectory()294 public boolean isDirectory() { 295 return attrs.isDirectory(); 296 } 297 @Override isSymbolicLink()298 public boolean isSymbolicLink() { 299 return attrs.isSymbolicLink(); 300 } 301 @Override isOther()302 public boolean isOther() { 303 return attrs.isOther(); 304 } 305 @Override size()306 public long size() { 307 return attrs.size(); 308 } 309 @Override fileKey()310 public Object fileKey() { 311 return attrs.fileKey(); 312 } 313 } 314 } 315