001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.fs; 019 020import java.io.DataInput; 021import java.io.DataOutput; 022import java.io.IOException; 023 024import org.apache.hadoop.classification.InterfaceAudience; 025import org.apache.hadoop.classification.InterfaceStability; 026import org.apache.hadoop.fs.permission.FsPermission; 027import org.apache.hadoop.io.Text; 028import org.apache.hadoop.io.Writable; 029 030/** Interface that represents the client side information for a file. 031 */ 032@InterfaceAudience.Public 033@InterfaceStability.Stable 034public class FileStatus implements Writable, Comparable { 035 036 private Path path; 037 private long length; 038 private boolean isdir; 039 private short block_replication; 040 private long blocksize; 041 private long modification_time; 042 private long access_time; 043 private FsPermission permission; 044 private String owner; 045 private String group; 046 private Path symlink; 047 048 public FileStatus() { this(0, false, 0, 0, 0, 0, null, null, null, null); } 049 050 //We should deprecate this soon? 051 public FileStatus(long length, boolean isdir, int block_replication, 052 long blocksize, long modification_time, Path path) { 053 054 this(length, isdir, block_replication, blocksize, modification_time, 055 0, null, null, null, path); 056 } 057 058 /** 059 * Constructor for file systems on which symbolic links are not supported 060 */ 061 public FileStatus(long length, boolean isdir, 062 int block_replication, 063 long blocksize, long modification_time, long access_time, 064 FsPermission permission, String owner, String group, 065 Path path) { 066 this(length, isdir, block_replication, blocksize, modification_time, 067 access_time, permission, owner, group, null, path); 068 } 069 070 public FileStatus(long length, boolean isdir, 071 int block_replication, 072 long blocksize, long modification_time, long access_time, 073 FsPermission permission, String owner, String group, 074 Path symlink, 075 Path path) { 076 this.length = length; 077 this.isdir = isdir; 078 this.block_replication = (short)block_replication; 079 this.blocksize = blocksize; 080 this.modification_time = modification_time; 081 this.access_time = access_time; 082 if (permission != null) { 083 this.permission = permission; 084 } else if (isdir) { 085 this.permission = FsPermission.getDirDefault(); 086 } else if (symlink!=null) { 087 this.permission = FsPermission.getDefault(); 088 } else { 089 this.permission = FsPermission.getFileDefault(); 090 } 091 this.owner = (owner == null) ? "" : owner; 092 this.group = (group == null) ? "" : group; 093 this.symlink = symlink; 094 this.path = path; 095 // The variables isdir and symlink indicate the type: 096 // 1. isdir implies directory, in which case symlink must be null. 097 // 2. !isdir implies a file or symlink, symlink != null implies a 098 // symlink, otherwise it's a file. 099 assert (isdir && symlink == null) || !isdir; 100 } 101 102 /** 103 * Copy constructor. 104 * 105 * @param other FileStatus to copy 106 */ 107 public FileStatus(FileStatus other) throws IOException { 108 // It's important to call the getters here instead of directly accessing the 109 // members. Subclasses like ViewFsFileStatus can override the getters. 110 this(other.getLen(), other.isDirectory(), other.getReplication(), 111 other.getBlockSize(), other.getModificationTime(), other.getAccessTime(), 112 other.getPermission(), other.getOwner(), other.getGroup(), 113 (other.isSymlink() ? other.getSymlink() : null), 114 other.getPath()); 115 } 116 117 /** 118 * Get the length of this file, in bytes. 119 * @return the length of this file, in bytes. 120 */ 121 public long getLen() { 122 return length; 123 } 124 125 /** 126 * Is this a file? 127 * @return true if this is a file 128 */ 129 public boolean isFile() { 130 return !isdir && !isSymlink(); 131 } 132 133 /** 134 * Is this a directory? 135 * @return true if this is a directory 136 */ 137 public boolean isDirectory() { 138 return isdir; 139 } 140 141 /** 142 * Old interface, instead use the explicit {@link FileStatus#isFile()}, 143 * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()} 144 * @return true if this is a directory. 145 * @deprecated Use {@link FileStatus#isFile()}, 146 * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()} 147 * instead. 148 */ 149 @Deprecated 150 public boolean isDir() { 151 return isdir; 152 } 153 154 /** 155 * Is this a table type 156 * @return true if this is a table object, it cannot be a diretory. 157 */ 158 public boolean isTable() { 159 return false; 160 } 161 162 /** 163 * Is this a symbolic link? 164 * @return true if this is a symbolic link 165 */ 166 public boolean isSymlink() { 167 return symlink != null; 168 } 169 170 /** 171 * Get the block size of the file. 172 * @return the number of bytes 173 */ 174 public long getBlockSize() { 175 return blocksize; 176 } 177 178 /** 179 * Get the replication factor of a file. 180 * @return the replication factor of a file. 181 */ 182 public short getReplication() { 183 return block_replication; 184 } 185 186 /** 187 * Get the modification time of the file. 188 * @return the modification time of file in milliseconds since January 1, 1970 UTC. 189 */ 190 public long getModificationTime() { 191 return modification_time; 192 } 193 194 /** 195 * Get the access time of the file. 196 * @return the access time of file in milliseconds since January 1, 1970 UTC. 197 */ 198 public long getAccessTime() { 199 return access_time; 200 } 201 202 /** 203 * Get FsPermission associated with the file. 204 * @return permssion. If a filesystem does not have a notion of permissions 205 * or if permissions could not be determined, then default 206 * permissions equivalent of "rwxrwxrwx" is returned. 207 */ 208 public FsPermission getPermission() { 209 return permission; 210 } 211 212 /** 213 * Tell whether the underlying file or directory is encrypted or not. 214 * 215 * @return true if the underlying file is encrypted. 216 */ 217 public boolean isEncrypted() { 218 return permission.getEncryptedBit(); 219 } 220 221 /** 222 * Get the owner of the file. 223 * @return owner of the file. The string could be empty if there is no 224 * notion of owner of a file in a filesystem or if it could not 225 * be determined (rare). 226 */ 227 public String getOwner() { 228 return owner; 229 } 230 231 /** 232 * Get the group associated with the file. 233 * @return group for the file. The string could be empty if there is no 234 * notion of group of a file in a filesystem or if it could not 235 * be determined (rare). 236 */ 237 public String getGroup() { 238 return group; 239 } 240 241 public Path getPath() { 242 return path; 243 } 244 245 public void setPath(final Path p) { 246 path = p; 247 } 248 249 /* These are provided so that these values could be loaded lazily 250 * by a filesystem (e.g. local file system). 251 */ 252 253 /** 254 * Sets permission. 255 * @param permission if permission is null, default value is set 256 */ 257 protected void setPermission(FsPermission permission) { 258 this.permission = (permission == null) ? 259 FsPermission.getFileDefault() : permission; 260 } 261 262 /** 263 * Sets owner. 264 * @param owner if it is null, default value is set 265 */ 266 protected void setOwner(String owner) { 267 this.owner = (owner == null) ? "" : owner; 268 } 269 270 /** 271 * Sets group. 272 * @param group if it is null, default value is set 273 */ 274 protected void setGroup(String group) { 275 this.group = (group == null) ? "" : group; 276 } 277 278 /** 279 * @return The contents of the symbolic link. 280 */ 281 public Path getSymlink() throws IOException { 282 if (!isSymlink()) { 283 throw new IOException("Path " + path + " is not a symbolic link"); 284 } 285 return symlink; 286 } 287 288 public void setSymlink(final Path p) { 289 symlink = p; 290 } 291 292 ////////////////////////////////////////////////// 293 // Writable 294 ////////////////////////////////////////////////// 295 @Override 296 public void write(DataOutput out) throws IOException { 297 Text.writeString(out, getPath().toString(), Text.DEFAULT_MAX_LEN); 298 out.writeLong(getLen()); 299 out.writeBoolean(isDirectory()); 300 out.writeShort(getReplication()); 301 out.writeLong(getBlockSize()); 302 out.writeLong(getModificationTime()); 303 out.writeLong(getAccessTime()); 304 getPermission().write(out); 305 Text.writeString(out, getOwner(), Text.DEFAULT_MAX_LEN); 306 Text.writeString(out, getGroup(), Text.DEFAULT_MAX_LEN); 307 out.writeBoolean(isSymlink()); 308 if (isSymlink()) { 309 Text.writeString(out, getSymlink().toString(), Text.DEFAULT_MAX_LEN); 310 } 311 } 312 313 @Override 314 public void readFields(DataInput in) throws IOException { 315 String strPath = Text.readString(in, Text.DEFAULT_MAX_LEN); 316 this.path = new Path(strPath); 317 this.length = in.readLong(); 318 this.isdir = in.readBoolean(); 319 this.block_replication = in.readShort(); 320 blocksize = in.readLong(); 321 modification_time = in.readLong(); 322 access_time = in.readLong(); 323 permission.readFields(in); 324 owner = Text.readString(in, Text.DEFAULT_MAX_LEN); 325 group = Text.readString(in, Text.DEFAULT_MAX_LEN); 326 if (in.readBoolean()) { 327 this.symlink = new Path(Text.readString(in, Text.DEFAULT_MAX_LEN)); 328 } else { 329 this.symlink = null; 330 } 331 } 332 333 /** 334 * Compare this object to another object 335 * 336 * @param o the object to be compared. 337 * @return a negative integer, zero, or a positive integer as this object 338 * is less than, equal to, or greater than the specified object. 339 * 340 * @throws ClassCastException if the specified object's is not of 341 * type FileStatus 342 */ 343 @Override 344 public int compareTo(Object o) { 345 FileStatus other = (FileStatus)o; 346 return this.getPath().compareTo(other.getPath()); 347 } 348 349 /** Compare if this object is equal to another object 350 * @param o the object to be compared. 351 * @return true if two file status has the same path name; false if not. 352 */ 353 @Override 354 public boolean equals(Object o) { 355 if (o == null) { 356 return false; 357 } 358 if (this == o) { 359 return true; 360 } 361 if (!(o instanceof FileStatus)) { 362 return false; 363 } 364 FileStatus other = (FileStatus)o; 365 return this.getPath().equals(other.getPath()); 366 } 367 368 /** 369 * Returns a hash code value for the object, which is defined as 370 * the hash code of the path name. 371 * 372 * @return a hash code value for the path name. 373 */ 374 @Override 375 public int hashCode() { 376 return getPath().hashCode(); 377 } 378 379 @Override 380 public String toString() { 381 StringBuilder sb = new StringBuilder(); 382 sb.append(getClass().getSimpleName()); 383 sb.append("{"); 384 sb.append("path=" + path); 385 sb.append("; isDirectory=" + isdir); 386 if(!isDirectory()){ 387 sb.append("; length=" + length); 388 sb.append("; replication=" + block_replication); 389 sb.append("; blocksize=" + blocksize); 390 } 391 sb.append("; modification_time=" + modification_time); 392 sb.append("; access_time=" + access_time); 393 sb.append("; owner=" + owner); 394 sb.append("; group=" + group); 395 sb.append("; permission=" + permission); 396 sb.append("; isSymlink=" + isSymlink()); 397 if(isSymlink()) { 398 sb.append("; symlink=" + symlink); 399 } 400 sb.append("}"); 401 return sb.toString(); 402 } 403}