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 * 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 symbolic link?
156 * @return true if this is a symbolic link
157 */
158 public boolean isSymlink() {
159 return symlink != null;
160 }
161
162 /**
163 * Get the block size of the file.
164 * @return the number of bytes
165 */
166 public long getBlockSize() {
167 return blocksize;
168 }
169
170 /**
171 * Get the replication factor of a file.
172 * @return the replication factor of a file.
173 */
174 public short getReplication() {
175 return block_replication;
176 }
177
178 /**
179 * Get the modification time of the file.
180 * @return the modification time of file in milliseconds since January 1, 1970 UTC.
181 */
182 public long getModificationTime() {
183 return modification_time;
184 }
185
186 /**
187 * Get the access time of the file.
188 * @return the access time of file in milliseconds since January 1, 1970 UTC.
189 */
190 public long getAccessTime() {
191 return access_time;
192 }
193
194 /**
195 * Get FsPermission associated with the file.
196 * @return permssion. If a filesystem does not have a notion of permissions
197 * or if permissions could not be determined, then default
198 * permissions equivalent of "rwxrwxrwx" is returned.
199 */
200 public FsPermission getPermission() {
201 return permission;
202 }
203
204 /**
205 * Tell whether the underlying file or directory is encrypted or not.
206 *
207 * @return true if the underlying file is encrypted.
208 */
209 public boolean isEncrypted() {
210 return permission.getEncryptedBit();
211 }
212
213 /**
214 * Get the owner of the file.
215 * @return owner of the file. The string could be empty if there is no
216 * notion of owner of a file in a filesystem or if it could not
217 * be determined (rare).
218 */
219 public String getOwner() {
220 return owner;
221 }
222
223 /**
224 * Get the group associated with the file.
225 * @return group for the file. The string could be empty if there is no
226 * notion of group of a file in a filesystem or if it could not
227 * be determined (rare).
228 */
229 public String getGroup() {
230 return group;
231 }
232
233 public Path getPath() {
234 return path;
235 }
236
237 public void setPath(final Path p) {
238 path = p;
239 }
240
241 /* These are provided so that these values could be loaded lazily
242 * by a filesystem (e.g. local file system).
243 */
244
245 /**
246 * Sets permission.
247 * @param permission if permission is null, default value is set
248 */
249 protected void setPermission(FsPermission permission) {
250 this.permission = (permission == null) ?
251 FsPermission.getFileDefault() : permission;
252 }
253
254 /**
255 * Sets owner.
256 * @param owner if it is null, default value is set
257 */
258 protected void setOwner(String owner) {
259 this.owner = (owner == null) ? "" : owner;
260 }
261
262 /**
263 * Sets group.
264 * @param group if it is null, default value is set
265 */
266 protected void setGroup(String group) {
267 this.group = (group == null) ? "" : group;
268 }
269
270 /**
271 * @return The contents of the symbolic link.
272 */
273 public Path getSymlink() throws IOException {
274 if (!isSymlink()) {
275 throw new IOException("Path " + path + " is not a symbolic link");
276 }
277 return symlink;
278 }
279
280 public void setSymlink(final Path p) {
281 symlink = p;
282 }
283
284 //////////////////////////////////////////////////
285 // Writable
286 //////////////////////////////////////////////////
287 @Override
288 public void write(DataOutput out) throws IOException {
289 Text.writeString(out, getPath().toString(), Text.DEFAULT_MAX_LEN);
290 out.writeLong(getLen());
291 out.writeBoolean(isDirectory());
292 out.writeShort(getReplication());
293 out.writeLong(getBlockSize());
294 out.writeLong(getModificationTime());
295 out.writeLong(getAccessTime());
296 getPermission().write(out);
297 Text.writeString(out, getOwner(), Text.DEFAULT_MAX_LEN);
298 Text.writeString(out, getGroup(), Text.DEFAULT_MAX_LEN);
299 out.writeBoolean(isSymlink());
300 if (isSymlink()) {
301 Text.writeString(out, getSymlink().toString(), Text.DEFAULT_MAX_LEN);
302 }
303 }
304
305 @Override
306 public void readFields(DataInput in) throws IOException {
307 String strPath = Text.readString(in, Text.DEFAULT_MAX_LEN);
308 this.path = new Path(strPath);
309 this.length = in.readLong();
310 this.isdir = in.readBoolean();
311 this.block_replication = in.readShort();
312 blocksize = in.readLong();
313 modification_time = in.readLong();
314 access_time = in.readLong();
315 permission.readFields(in);
316 owner = Text.readString(in, Text.DEFAULT_MAX_LEN);
317 group = Text.readString(in, Text.DEFAULT_MAX_LEN);
318 if (in.readBoolean()) {
319 this.symlink = new Path(Text.readString(in, Text.DEFAULT_MAX_LEN));
320 } else {
321 this.symlink = null;
322 }
323 }
324
325 /**
326 * Compare this object to another object
327 *
328 * @param o the object to be compared.
329 * @return a negative integer, zero, or a positive integer as this object
330 * is less than, equal to, or greater than the specified object.
331 *
332 * @throws ClassCastException if the specified object's is not of
333 * type FileStatus
334 */
335 @Override
336 public int compareTo(Object o) {
337 FileStatus other = (FileStatus)o;
338 return this.getPath().compareTo(other.getPath());
339 }
340
341 /** Compare if this object is equal to another object
342 * @param o the object to be compared.
343 * @return true if two file status has the same path name; false if not.
344 */
345 @Override
346 public boolean equals(Object o) {
347 if (o == null) {
348 return false;
349 }
350 if (this == o) {
351 return true;
352 }
353 if (!(o instanceof FileStatus)) {
354 return false;
355 }
356 FileStatus other = (FileStatus)o;
357 return this.getPath().equals(other.getPath());
358 }
359
360 /**
361 * Returns a hash code value for the object, which is defined as
362 * the hash code of the path name.
363 *
364 * @return a hash code value for the path name.
365 */
366 @Override
367 public int hashCode() {
368 return getPath().hashCode();
369 }
370
371 @Override
372 public String toString() {
373 StringBuilder sb = new StringBuilder();
374 sb.append(getClass().getSimpleName());
375 sb.append("{");
376 sb.append("path=" + path);
377 sb.append("; isDirectory=" + isdir);
378 if(!isDirectory()){
379 sb.append("; length=" + length);
380 sb.append("; replication=" + block_replication);
381 sb.append("; blocksize=" + blocksize);
382 }
383 sb.append("; modification_time=" + modification_time);
384 sb.append("; access_time=" + access_time);
385 sb.append("; owner=" + owner);
386 sb.append("; group=" + group);
387 sb.append("; permission=" + permission);
388 sb.append("; isSymlink=" + isSymlink());
389 if(isSymlink()) {
390 sb.append("; symlink=" + symlink);
391 }
392 sb.append("}");
393 return sb.toString();
394 }
395 }