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 */ 018 package org.apache.hadoop.fs; 019 020 import java.io.DataInput; 021 import java.io.DataOutput; 022 import java.io.IOException; 023 024 import org.apache.hadoop.classification.InterfaceAudience; 025 import org.apache.hadoop.classification.InterfaceStability; 026 import org.apache.hadoop.fs.permission.FsPermission; 027 import org.apache.hadoop.io.Text; 028 import org.apache.hadoop.io.Writable; 029 030 /** Interface that represents the client side information for a file. 031 */ 032 @InterfaceAudience.Public 033 @InterfaceStability.Stable 034 public 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 * Get the length of this file, in bytes. 104 * @return the length of this file, in bytes. 105 */ 106 public long getLen() { 107 return length; 108 } 109 110 /** 111 * Is this a file? 112 * @return true if this is a file 113 */ 114 public boolean isFile() { 115 return !isdir && !isSymlink(); 116 } 117 118 /** 119 * Is this a directory? 120 * @return true if this is a directory 121 */ 122 public boolean isDirectory() { 123 return isdir; 124 } 125 126 /** 127 * Old interface, instead use the explicit {@link FileStatus#isFile()}, 128 * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()} 129 * @return true if this is a directory. 130 * @deprecated Use {@link FileStatus#isFile()}, 131 * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()} 132 * instead. 133 */ 134 @Deprecated 135 public boolean isDir() { 136 return isdir; 137 } 138 139 /** 140 * Is this a symbolic link? 141 * @return true if this is a symbolic link 142 */ 143 public boolean isSymlink() { 144 return symlink != null; 145 } 146 147 /** 148 * Get the block size of the file. 149 * @return the number of bytes 150 */ 151 public long getBlockSize() { 152 return blocksize; 153 } 154 155 /** 156 * Get the replication factor of a file. 157 * @return the replication factor of a file. 158 */ 159 public short getReplication() { 160 return block_replication; 161 } 162 163 /** 164 * Get the modification time of the file. 165 * @return the modification time of file in milliseconds since January 1, 1970 UTC. 166 */ 167 public long getModificationTime() { 168 return modification_time; 169 } 170 171 /** 172 * Get the access time of the file. 173 * @return the access time of file in milliseconds since January 1, 1970 UTC. 174 */ 175 public long getAccessTime() { 176 return access_time; 177 } 178 179 /** 180 * Get FsPermission associated with the file. 181 * @return permssion. If a filesystem does not have a notion of permissions 182 * or if permissions could not be determined, then default 183 * permissions equivalent of "rwxrwxrwx" is returned. 184 */ 185 public FsPermission getPermission() { 186 return permission; 187 } 188 189 /** 190 * Get the owner of the file. 191 * @return owner of the file. The string could be empty if there is no 192 * notion of owner of a file in a filesystem or if it could not 193 * be determined (rare). 194 */ 195 public String getOwner() { 196 return owner; 197 } 198 199 /** 200 * Get the group associated with the file. 201 * @return group for the file. The string could be empty if there is no 202 * notion of group of a file in a filesystem or if it could not 203 * be determined (rare). 204 */ 205 public String getGroup() { 206 return group; 207 } 208 209 public Path getPath() { 210 return path; 211 } 212 213 public void setPath(final Path p) { 214 path = p; 215 } 216 217 /* These are provided so that these values could be loaded lazily 218 * by a filesystem (e.g. local file system). 219 */ 220 221 /** 222 * Sets permission. 223 * @param permission if permission is null, default value is set 224 */ 225 protected void setPermission(FsPermission permission) { 226 this.permission = (permission == null) ? 227 FsPermission.getFileDefault() : permission; 228 } 229 230 /** 231 * Sets owner. 232 * @param owner if it is null, default value is set 233 */ 234 protected void setOwner(String owner) { 235 this.owner = (owner == null) ? "" : owner; 236 } 237 238 /** 239 * Sets group. 240 * @param group if it is null, default value is set 241 */ 242 protected void setGroup(String group) { 243 this.group = (group == null) ? "" : group; 244 } 245 246 /** 247 * @return The contents of the symbolic link. 248 */ 249 public Path getSymlink() throws IOException { 250 if (!isSymlink()) { 251 throw new IOException("Path " + path + " is not a symbolic link"); 252 } 253 return symlink; 254 } 255 256 public void setSymlink(final Path p) { 257 symlink = p; 258 } 259 260 ////////////////////////////////////////////////// 261 // Writable 262 ////////////////////////////////////////////////// 263 @Override 264 public void write(DataOutput out) throws IOException { 265 Text.writeString(out, getPath().toString(), Text.DEFAULT_MAX_LEN); 266 out.writeLong(getLen()); 267 out.writeBoolean(isDirectory()); 268 out.writeShort(getReplication()); 269 out.writeLong(getBlockSize()); 270 out.writeLong(getModificationTime()); 271 out.writeLong(getAccessTime()); 272 getPermission().write(out); 273 Text.writeString(out, getOwner(), Text.DEFAULT_MAX_LEN); 274 Text.writeString(out, getGroup(), Text.DEFAULT_MAX_LEN); 275 out.writeBoolean(isSymlink()); 276 if (isSymlink()) { 277 Text.writeString(out, getSymlink().toString(), Text.DEFAULT_MAX_LEN); 278 } 279 } 280 281 @Override 282 public void readFields(DataInput in) throws IOException { 283 String strPath = Text.readString(in, Text.DEFAULT_MAX_LEN); 284 this.path = new Path(strPath); 285 this.length = in.readLong(); 286 this.isdir = in.readBoolean(); 287 this.block_replication = in.readShort(); 288 blocksize = in.readLong(); 289 modification_time = in.readLong(); 290 access_time = in.readLong(); 291 permission.readFields(in); 292 owner = Text.readString(in, Text.DEFAULT_MAX_LEN); 293 group = Text.readString(in, Text.DEFAULT_MAX_LEN); 294 if (in.readBoolean()) { 295 this.symlink = new Path(Text.readString(in, Text.DEFAULT_MAX_LEN)); 296 } else { 297 this.symlink = null; 298 } 299 } 300 301 /** 302 * Compare this object to another object 303 * 304 * @param o the object to be compared. 305 * @return a negative integer, zero, or a positive integer as this object 306 * is less than, equal to, or greater than the specified object. 307 * 308 * @throws ClassCastException if the specified object's is not of 309 * type FileStatus 310 */ 311 @Override 312 public int compareTo(Object o) { 313 FileStatus other = (FileStatus)o; 314 return this.getPath().compareTo(other.getPath()); 315 } 316 317 /** Compare if this object is equal to another object 318 * @param o the object to be compared. 319 * @return true if two file status has the same path name; false if not. 320 */ 321 @Override 322 public boolean equals(Object o) { 323 if (o == null) { 324 return false; 325 } 326 if (this == o) { 327 return true; 328 } 329 if (!(o instanceof FileStatus)) { 330 return false; 331 } 332 FileStatus other = (FileStatus)o; 333 return this.getPath().equals(other.getPath()); 334 } 335 336 /** 337 * Returns a hash code value for the object, which is defined as 338 * the hash code of the path name. 339 * 340 * @return a hash code value for the path name. 341 */ 342 @Override 343 public int hashCode() { 344 return getPath().hashCode(); 345 } 346 347 @Override 348 public String toString() { 349 StringBuilder sb = new StringBuilder(); 350 sb.append(getClass().getSimpleName()); 351 sb.append("{"); 352 sb.append("path=" + path); 353 sb.append("; isDirectory=" + isdir); 354 if(!isDirectory()){ 355 sb.append("; length=" + length); 356 sb.append("; replication=" + block_replication); 357 sb.append("; blocksize=" + blocksize); 358 } 359 sb.append("; modification_time=" + modification_time); 360 sb.append("; access_time=" + access_time); 361 sb.append("; owner=" + owner); 362 sb.append("; group=" + group); 363 sb.append("; permission=" + permission); 364 sb.append("; isSymlink=" + isSymlink()); 365 if(isSymlink()) { 366 sb.append("; symlink=" + symlink); 367 } 368 sb.append("}"); 369 return sb.toString(); 370 } 371 }