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 }