1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.hadoop.fs.viewfs; 19 import java.io.FileNotFoundException; 20 import java.io.IOException; 21 import java.net.URI; 22 import java.util.EnumSet; 23 import java.util.List; 24 import java.util.Map; 25 26 import org.apache.hadoop.classification.InterfaceAudience; 27 import org.apache.hadoop.classification.InterfaceStability; 28 import org.apache.hadoop.conf.Configuration; 29 import org.apache.hadoop.fs.BlockLocation; 30 import org.apache.hadoop.fs.ContentSummary; 31 import org.apache.hadoop.fs.CreateFlag; 32 import org.apache.hadoop.fs.FSDataInputStream; 33 import org.apache.hadoop.fs.FSDataOutputStream; 34 import org.apache.hadoop.fs.FileChecksum; 35 import org.apache.hadoop.fs.FileStatus; 36 import org.apache.hadoop.fs.FileSystem; 37 import org.apache.hadoop.fs.FilterFileSystem; 38 import org.apache.hadoop.fs.FsServerDefaults; 39 import org.apache.hadoop.fs.FsStatus; 40 import org.apache.hadoop.fs.LocatedFileStatus; 41 import org.apache.hadoop.fs.Path; 42 import org.apache.hadoop.fs.XAttrSetFlag; 43 import org.apache.hadoop.fs.RemoteIterator; 44 import org.apache.hadoop.fs.permission.AclEntry; 45 import org.apache.hadoop.fs.permission.AclStatus; 46 import org.apache.hadoop.fs.permission.FsAction; 47 import org.apache.hadoop.fs.permission.FsPermission; 48 import org.apache.hadoop.security.AccessControlException; 49 import org.apache.hadoop.util.Progressable; 50 51 /** 52 * <code>ChRootedFileSystem</code> is a file system with its root some path 53 * below the root of its base file system. 54 * 55 * Example: For a base file system hdfs://nn1/ with chRoot at /usr/foo, the 56 * members will be setup as shown below. 57 * <ul> 58 * <li>myFs is the base file system and points to hdfs at nn1</li> 59 * <li>myURI is hdfs://nn1/user/foo</li> 60 * <li>chRootPathPart is /user/foo</li> 61 * <li>workingDir is a directory related to chRoot</li> 62 * </ul> 63 * 64 * The paths are resolved as follows by ChRootedFileSystem: 65 * <ul> 66 * <li> Absolute path /a/b/c is resolved to /user/foo/a/b/c at myFs</li> 67 * <li> Relative path x/y is resolved to /user/foo/<workingDir>/x/y</li> 68 * </ul> 69 */ 70 71 @InterfaceAudience.Private 72 @InterfaceStability.Evolving /*Evolving for a release,to be changed to Stable */ 73 class ChRootedFileSystem extends FilterFileSystem { 74 private final URI myUri; // the base URI + the chRoot 75 private final Path chRootPathPart; // the root below the root of the base 76 private final String chRootPathPartString; 77 private Path workingDir; 78 getMyFs()79 protected FileSystem getMyFs() { 80 return getRawFileSystem(); 81 } 82 83 /** 84 * @param path 85 * @return full path including the chroot 86 */ fullPath(final Path path)87 protected Path fullPath(final Path path) { 88 super.checkPath(path); 89 return path.isAbsolute() ? 90 new Path((chRootPathPart.isRoot() ? "" : chRootPathPartString) 91 + path.toUri().getPath()) : 92 new Path(chRootPathPartString + workingDir.toUri().getPath(), path); 93 } 94 95 /** 96 * Constructor 97 * @param uri base file system 98 * @param conf configuration 99 * @throws IOException 100 */ ChRootedFileSystem(final URI uri, Configuration conf)101 public ChRootedFileSystem(final URI uri, Configuration conf) 102 throws IOException { 103 super(FileSystem.get(uri, conf)); 104 String pathString = uri.getPath(); 105 if (pathString.isEmpty()) { 106 pathString = "/"; 107 } 108 chRootPathPart = new Path(pathString); 109 chRootPathPartString = chRootPathPart.toUri().getPath(); 110 myUri = uri; 111 workingDir = getHomeDirectory(); 112 // We don't use the wd of the myFs 113 } 114 115 /** 116 * Called after a new FileSystem instance is constructed. 117 * @param name a uri whose authority section names the host, port, etc. 118 * for this FileSystem 119 * @param conf the configuration 120 */ 121 @Override initialize(final URI name, final Configuration conf)122 public void initialize(final URI name, final Configuration conf) 123 throws IOException { 124 super.initialize(name, conf); 125 setConf(conf); 126 } 127 128 @Override getUri()129 public URI getUri() { 130 return myUri; 131 } 132 133 /** 134 * Strip out the root from the path. 135 * @param p - fully qualified path p 136 * @return - the remaining path without the begining / 137 * @throws IOException if the p is not prefixed with root 138 */ stripOutRoot(final Path p)139 String stripOutRoot(final Path p) throws IOException { 140 try { 141 checkPath(p); 142 } catch (IllegalArgumentException e) { 143 throw new IOException("Internal Error - path " + p + 144 " should have been with URI: " + myUri); 145 } 146 String pathPart = p.toUri().getPath(); 147 return (pathPart.length() == chRootPathPartString.length()) ? "" : pathPart 148 .substring(chRootPathPartString.length() + (chRootPathPart.isRoot() ? 0 : 1)); 149 } 150 151 @Override getInitialWorkingDirectory()152 protected Path getInitialWorkingDirectory() { 153 /* 154 * 3 choices here: 155 * null or / or /user/<uname> or strip out the root out of myFs's 156 * inital wd. 157 * Only reasonable choice for initialWd for chrooted fds is null 158 * so that the default rule for wd is applied 159 */ 160 return null; 161 } 162 getResolvedQualifiedPath(final Path f)163 public Path getResolvedQualifiedPath(final Path f) 164 throws FileNotFoundException { 165 return makeQualified( 166 new Path(chRootPathPartString + f.toUri().toString())); 167 } 168 169 @Override getWorkingDirectory()170 public Path getWorkingDirectory() { 171 return workingDir; 172 } 173 174 @Override setWorkingDirectory(final Path new_dir)175 public void setWorkingDirectory(final Path new_dir) { 176 workingDir = new_dir.isAbsolute() ? new_dir : new Path(workingDir, new_dir); 177 } 178 179 @Override create(final Path f, final FsPermission permission, final boolean overwrite, final int bufferSize, final short replication, final long blockSize, final Progressable progress)180 public FSDataOutputStream create(final Path f, final FsPermission permission, 181 final boolean overwrite, final int bufferSize, final short replication, 182 final long blockSize, final Progressable progress) throws IOException { 183 return super.create(fullPath(f), permission, overwrite, bufferSize, 184 replication, blockSize, progress); 185 } 186 187 @Override 188 @Deprecated createNonRecursive(Path f, FsPermission permission, EnumSet<CreateFlag> flags, int bufferSize, short replication, long blockSize, Progressable progress)189 public FSDataOutputStream createNonRecursive(Path f, FsPermission permission, 190 EnumSet<CreateFlag> flags, int bufferSize, short replication, long blockSize, 191 Progressable progress) throws IOException { 192 193 return super.createNonRecursive(fullPath(f), permission, flags, bufferSize, replication, blockSize, 194 progress); 195 } 196 197 @Override delete(final Path f, final boolean recursive)198 public boolean delete(final Path f, final boolean recursive) 199 throws IOException { 200 return super.delete(fullPath(f), recursive); 201 } 202 203 204 @Override 205 @SuppressWarnings("deprecation") delete(Path f)206 public boolean delete(Path f) throws IOException { 207 return delete(f, true); 208 } 209 210 @Override getFileBlockLocations(final FileStatus fs, final long start, final long len)211 public BlockLocation[] getFileBlockLocations(final FileStatus fs, final long start, 212 final long len) throws IOException { 213 return super.getFileBlockLocations( 214 new ViewFsFileStatus(fs, fullPath(fs.getPath())), start, len); 215 } 216 217 @Override getFileChecksum(final Path f)218 public FileChecksum getFileChecksum(final Path f) 219 throws IOException { 220 return super.getFileChecksum(fullPath(f)); 221 } 222 223 @Override getFileStatus(final Path f)224 public FileStatus getFileStatus(final Path f) 225 throws IOException { 226 return super.getFileStatus(fullPath(f)); 227 } 228 229 @Override access(Path path, FsAction mode)230 public void access(Path path, FsAction mode) throws AccessControlException, 231 FileNotFoundException, IOException { 232 super.access(fullPath(path), mode); 233 } 234 235 @Override getStatus(Path p)236 public FsStatus getStatus(Path p) throws IOException { 237 return super.getStatus(fullPath(p)); 238 } 239 240 @Override listStatus(final Path f)241 public FileStatus[] listStatus(final Path f) 242 throws IOException { 243 return super.listStatus(fullPath(f)); 244 } 245 246 @Override listLocatedStatus(Path f)247 public RemoteIterator<LocatedFileStatus> listLocatedStatus(Path f) 248 throws IOException { 249 return super.listLocatedStatus(fullPath(f)); 250 } 251 252 @Override mkdirs(final Path f, final FsPermission permission)253 public boolean mkdirs(final Path f, final FsPermission permission) 254 throws IOException { 255 return super.mkdirs(fullPath(f), permission); 256 } 257 258 @Override open(final Path f, final int bufferSize)259 public FSDataInputStream open(final Path f, final int bufferSize) 260 throws IOException { 261 return super.open(fullPath(f), bufferSize); 262 } 263 264 @Override append(final Path f, final int bufferSize, final Progressable progress)265 public FSDataOutputStream append(final Path f, final int bufferSize, 266 final Progressable progress) throws IOException { 267 return super.append(fullPath(f), bufferSize, progress); 268 } 269 270 @Override rename(final Path src, final Path dst)271 public boolean rename(final Path src, final Path dst) throws IOException { 272 // note fullPath will check that paths are relative to this FileSystem. 273 // Hence both are in same file system and a rename is valid 274 return super.rename(fullPath(src), fullPath(dst)); 275 } 276 277 @Override setOwner(final Path f, final String username, final String groupname)278 public void setOwner(final Path f, final String username, 279 final String groupname) 280 throws IOException { 281 super.setOwner(fullPath(f), username, groupname); 282 } 283 284 @Override setPermission(final Path f, final FsPermission permission)285 public void setPermission(final Path f, final FsPermission permission) 286 throws IOException { 287 super.setPermission(fullPath(f), permission); 288 } 289 290 @Override setReplication(final Path f, final short replication)291 public boolean setReplication(final Path f, final short replication) 292 throws IOException { 293 return super.setReplication(fullPath(f), replication); 294 } 295 296 @Override setTimes(final Path f, final long mtime, final long atime)297 public void setTimes(final Path f, final long mtime, final long atime) 298 throws IOException { 299 super.setTimes(fullPath(f), mtime, atime); 300 } 301 302 @Override modifyAclEntries(Path path, List<AclEntry> aclSpec)303 public void modifyAclEntries(Path path, List<AclEntry> aclSpec) 304 throws IOException { 305 super.modifyAclEntries(fullPath(path), aclSpec); 306 } 307 308 @Override removeAclEntries(Path path, List<AclEntry> aclSpec)309 public void removeAclEntries(Path path, List<AclEntry> aclSpec) 310 throws IOException { 311 super.removeAclEntries(fullPath(path), aclSpec); 312 } 313 314 @Override removeDefaultAcl(Path path)315 public void removeDefaultAcl(Path path) throws IOException { 316 super.removeDefaultAcl(fullPath(path)); 317 } 318 319 @Override removeAcl(Path path)320 public void removeAcl(Path path) throws IOException { 321 super.removeAcl(fullPath(path)); 322 } 323 324 @Override setAcl(Path path, List<AclEntry> aclSpec)325 public void setAcl(Path path, List<AclEntry> aclSpec) throws IOException { 326 super.setAcl(fullPath(path), aclSpec); 327 } 328 329 @Override getAclStatus(Path path)330 public AclStatus getAclStatus(Path path) throws IOException { 331 return super.getAclStatus(fullPath(path)); 332 } 333 334 @Override setXAttr(Path path, String name, byte[] value, EnumSet<XAttrSetFlag> flag)335 public void setXAttr(Path path, String name, byte[] value, 336 EnumSet<XAttrSetFlag> flag) throws IOException { 337 super.setXAttr(fullPath(path), name, value, flag); 338 } 339 340 @Override getXAttr(Path path, String name)341 public byte[] getXAttr(Path path, String name) throws IOException { 342 return super.getXAttr(fullPath(path), name); 343 } 344 345 @Override getXAttrs(Path path)346 public Map<String, byte[]> getXAttrs(Path path) throws IOException { 347 return super.getXAttrs(fullPath(path)); 348 } 349 350 @Override getXAttrs(Path path, List<String> names)351 public Map<String, byte[]> getXAttrs(Path path, List<String> names) 352 throws IOException { 353 return super.getXAttrs(fullPath(path), names); 354 } 355 356 @Override listXAttrs(Path path)357 public List<String> listXAttrs(Path path) throws IOException { 358 return super.listXAttrs(fullPath(path)); 359 } 360 361 @Override removeXAttr(Path path, String name)362 public void removeXAttr(Path path, String name) throws IOException { 363 super.removeXAttr(fullPath(path), name); 364 } 365 366 @Override resolvePath(final Path p)367 public Path resolvePath(final Path p) throws IOException { 368 return super.resolvePath(fullPath(p)); 369 } 370 371 @Override getContentSummary(Path f)372 public ContentSummary getContentSummary(Path f) throws IOException { 373 return fs.getContentSummary(fullPath(f)); 374 } 375 376 377 private static Path rootPath = new Path(Path.SEPARATOR); 378 379 @Override getDefaultBlockSize()380 public long getDefaultBlockSize() { 381 return getDefaultBlockSize(fullPath(rootPath)); 382 } 383 384 @Override getDefaultBlockSize(Path f)385 public long getDefaultBlockSize(Path f) { 386 return super.getDefaultBlockSize(fullPath(f)); 387 } 388 389 @Override getDefaultReplication()390 public short getDefaultReplication() { 391 return getDefaultReplication(fullPath(rootPath)); 392 } 393 394 @Override getDefaultReplication(Path f)395 public short getDefaultReplication(Path f) { 396 return super.getDefaultReplication(fullPath(f)); 397 } 398 399 @Override getServerDefaults()400 public FsServerDefaults getServerDefaults() throws IOException { 401 return getServerDefaults(fullPath(rootPath)); 402 } 403 404 @Override getServerDefaults(Path f)405 public FsServerDefaults getServerDefaults(Path f) throws IOException { 406 return super.getServerDefaults(fullPath(f)); 407 } 408 } 409