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