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 * Get the owner of the file.
206 * @return owner of the file. The string could be empty if there is no
207 * notion of owner of a file in a filesystem or if it could not
208 * be determined (rare).
209 */
210 public String getOwner() {
211 return owner;
212 }
213
214 /**
215 * Get the group associated with the file.
216 * @return group for the file. The string could be empty if there is no
217 * notion of group of a file in a filesystem or if it could not
218 * be determined (rare).
219 */
220 public String getGroup() {
221 return group;
222 }
223
224 public Path getPath() {
225 return path;
226 }
227
228 public void setPath(final Path p) {
229 path = p;
230 }
231
232 /* These are provided so that these values could be loaded lazily
233 * by a filesystem (e.g. local file system).
234 */
235
236 /**
237 * Sets permission.
238 * @param permission if permission is null, default value is set
239 */
240 protected void setPermission(FsPermission permission) {
241 this.permission = (permission == null) ?
242 FsPermission.getFileDefault() : permission;
243 }
244
245 /**
246 * Sets owner.
247 * @param owner if it is null, default value is set
248 */
249 protected void setOwner(String owner) {
250 this.owner = (owner == null) ? "" : owner;
251 }
252
253 /**
254 * Sets group.
255 * @param group if it is null, default value is set
256 */
257 protected void setGroup(String group) {
258 this.group = (group == null) ? "" : group;
259 }
260
261 /**
262 * @return The contents of the symbolic link.
263 */
264 public Path getSymlink() throws IOException {
265 if (!isSymlink()) {
266 throw new IOException("Path " + path + " is not a symbolic link");
267 }
268 return symlink;
269 }
270
271 public void setSymlink(final Path p) {
272 symlink = p;
273 }
274
275 //////////////////////////////////////////////////
276 // Writable
277 //////////////////////////////////////////////////
278 @Override
279 public void write(DataOutput out) throws IOException {
280 Text.writeString(out, getPath().toString(), Text.DEFAULT_MAX_LEN);
281 out.writeLong(getLen());
282 out.writeBoolean(isDirectory());
283 out.writeShort(getReplication());
284 out.writeLong(getBlockSize());
285 out.writeLong(getModificationTime());
286 out.writeLong(getAccessTime());
287 getPermission().write(out);
288 Text.writeString(out, getOwner(), Text.DEFAULT_MAX_LEN);
289 Text.writeString(out, getGroup(), Text.DEFAULT_MAX_LEN);
290 out.writeBoolean(isSymlink());
291 if (isSymlink()) {
292 Text.writeString(out, getSymlink().toString(), Text.DEFAULT_MAX_LEN);
293 }
294 }
295
296 @Override
297 public void readFields(DataInput in) throws IOException {
298 String strPath = Text.readString(in, Text.DEFAULT_MAX_LEN);
299 this.path = new Path(strPath);
300 this.length = in.readLong();
301 this.isdir = in.readBoolean();
302 this.block_replication = in.readShort();
303 blocksize = in.readLong();
304 modification_time = in.readLong();
305 access_time = in.readLong();
306 permission.readFields(in);
307 owner = Text.readString(in, Text.DEFAULT_MAX_LEN);
308 group = Text.readString(in, Text.DEFAULT_MAX_LEN);
309 if (in.readBoolean()) {
310 this.symlink = new Path(Text.readString(in, Text.DEFAULT_MAX_LEN));
311 } else {
312 this.symlink = null;
313 }
314 }
315
316 /**
317 * Compare this object to another object
318 *
319 * @param o the object to be compared.
320 * @return a negative integer, zero, or a positive integer as this object
321 * is less than, equal to, or greater than the specified object.
322 *
323 * @throws ClassCastException if the specified object's is not of
324 * type FileStatus
325 */
326 @Override
327 public int compareTo(Object o) {
328 FileStatus other = (FileStatus)o;
329 return this.getPath().compareTo(other.getPath());
330 }
331
332 /** Compare if this object is equal to another object
333 * @param o the object to be compared.
334 * @return true if two file status has the same path name; false if not.
335 */
336 @Override
337 public boolean equals(Object o) {
338 if (o == null) {
339 return false;
340 }
341 if (this == o) {
342 return true;
343 }
344 if (!(o instanceof FileStatus)) {
345 return false;
346 }
347 FileStatus other = (FileStatus)o;
348 return this.getPath().equals(other.getPath());
349 }
350
351 /**
352 * Returns a hash code value for the object, which is defined as
353 * the hash code of the path name.
354 *
355 * @return a hash code value for the path name.
356 */
357 @Override
358 public int hashCode() {
359 return getPath().hashCode();
360 }
361
362 @Override
363 public String toString() {
364 StringBuilder sb = new StringBuilder();
365 sb.append(getClass().getSimpleName());
366 sb.append("{");
367 sb.append("path=" + path);
368 sb.append("; isDirectory=" + isdir);
369 if(!isDirectory()){
370 sb.append("; length=" + length);
371 sb.append("; replication=" + block_replication);
372 sb.append("; blocksize=" + blocksize);
373 }
374 sb.append("; modification_time=" + modification_time);
375 sb.append("; access_time=" + access_time);
376 sb.append("; owner=" + owner);
377 sb.append("; group=" + group);
378 sb.append("; permission=" + permission);
379 sb.append("; isSymlink=" + isSymlink());
380 if(isSymlink()) {
381 sb.append("; symlink=" + symlink);
382 }
383 sb.append("}");
384 return sb.toString();
385 }
386 }