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 */ 018package org.apache.hadoop.fs; 019 020import java.io.FileNotFoundException; 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.OutputStream; 024import java.net.URI; 025import java.security.PrivilegedExceptionAction; 026import java.util.ArrayList; 027import java.util.EnumSet; 028import java.util.HashSet; 029import java.util.IdentityHashMap; 030import java.util.List; 031import java.util.Map; 032import java.util.Set; 033import java.util.Stack; 034import java.util.TreeSet; 035import java.util.Map.Entry; 036 037import org.apache.commons.logging.Log; 038import org.apache.commons.logging.LogFactory; 039import org.apache.hadoop.HadoopIllegalArgumentException; 040import org.apache.hadoop.classification.InterfaceAudience; 041import org.apache.hadoop.classification.InterfaceStability; 042import org.apache.hadoop.conf.Configuration; 043import org.apache.hadoop.fs.FileSystem.Statistics; 044import org.apache.hadoop.fs.Options.CreateOpts; 045import org.apache.hadoop.fs.permission.AclEntry; 046import org.apache.hadoop.fs.permission.AclStatus; 047import org.apache.hadoop.fs.permission.FsAction; 048import org.apache.hadoop.fs.permission.FsPermission; 049import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_DEFAULT_NAME_KEY; 050import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_DEFAULT_NAME_DEFAULT; 051import org.apache.hadoop.io.IOUtils; 052import org.apache.hadoop.ipc.RpcClientException; 053import org.apache.hadoop.ipc.RpcServerException; 054import org.apache.hadoop.ipc.UnexpectedServerException; 055import org.apache.hadoop.fs.InvalidPathException; 056import org.apache.hadoop.security.AccessControlException; 057import org.apache.hadoop.security.UserGroupInformation; 058import org.apache.hadoop.security.token.Token; 059import org.apache.hadoop.util.ShutdownHookManager; 060import org.apache.htrace.core.Tracer; 061 062/** 063 * The FileContext class provides an interface to the application writer for 064 * using the Hadoop file system. 065 * It provides a set of methods for the usual operation: create, open, 066 * list, etc 067 * 068 * <p> 069 * <b> *** Path Names *** </b> 070 * <p> 071 * 072 * The Hadoop file system supports a URI name space and URI names. 073 * It offers a forest of file systems that can be referenced using fully 074 * qualified URIs. 075 * Two common Hadoop file systems implementations are 076 * <ul> 077 * <li> the local file system: file:///path 078 * <li> the hdfs file system hdfs://nnAddress:nnPort/path 079 * </ul> 080 * 081 * While URI names are very flexible, it requires knowing the name or address 082 * of the server. For convenience one often wants to access the default system 083 * in one's environment without knowing its name/address. This has an 084 * additional benefit that it allows one to change one's default fs 085 * (e.g. admin moves application from cluster1 to cluster2). 086 * <p> 087 * 088 * To facilitate this, Hadoop supports a notion of a default file system. 089 * The user can set his default file system, although this is 090 * typically set up for you in your environment via your default config. 091 * A default file system implies a default scheme and authority; slash-relative 092 * names (such as /for/bar) are resolved relative to that default FS. 093 * Similarly a user can also have working-directory-relative names (i.e. names 094 * not starting with a slash). While the working directory is generally in the 095 * same default FS, the wd can be in a different FS. 096 * <p> 097 * Hence Hadoop path names can be one of: 098 * <ul> 099 * <li> fully qualified URI: scheme://authority/path 100 * <li> slash relative names: /path relative to the default file system 101 * <li> wd-relative names: path relative to the working dir 102 * </ul> 103 * Relative paths with scheme (scheme:foo/bar) are illegal. 104 * 105 * <p> 106 * <b>****The Role of the FileContext and configuration defaults****</b> 107 * <p> 108 * The FileContext provides file namespace context for resolving file names; 109 * it also contains the umask for permissions, In that sense it is like the 110 * per-process file-related state in Unix system. 111 * These two properties 112 * <ul> 113 * <li> default file system i.e your slash) 114 * <li> umask 115 * </ul> 116 * in general, are obtained from the default configuration file 117 * in your environment, (@see {@link Configuration}). 118 * 119 * No other configuration parameters are obtained from the default config as 120 * far as the file context layer is concerned. All file system instances 121 * (i.e. deployments of file systems) have default properties; we call these 122 * server side (SS) defaults. Operation like create allow one to select many 123 * properties: either pass them in as explicit parameters or use 124 * the SS properties. 125 * <p> 126 * The file system related SS defaults are 127 * <ul> 128 * <li> the home directory (default is "/user/userName") 129 * <li> the initial wd (only for local fs) 130 * <li> replication factor 131 * <li> block size 132 * <li> buffer size 133 * <li> encryptDataTransfer 134 * <li> checksum option. (checksumType and bytesPerChecksum) 135 * </ul> 136 * 137 * <p> 138 * <b> *** Usage Model for the FileContext class *** </b> 139 * <p> 140 * Example 1: use the default config read from the $HADOOP_CONFIG/core.xml. 141 * Unspecified values come from core-defaults.xml in the release jar. 142 * <ul> 143 * <li> myFContext = FileContext.getFileContext(); // uses the default config 144 * // which has your default FS 145 * <li> myFContext.create(path, ...); 146 * <li> myFContext.setWorkingDir(path) 147 * <li> myFContext.open (path, ...); 148 * </ul> 149 * Example 2: Get a FileContext with a specific URI as the default FS 150 * <ul> 151 * <li> myFContext = FileContext.getFileContext(URI) 152 * <li> myFContext.create(path, ...); 153 * ... 154 * </ul> 155 * Example 3: FileContext with local file system as the default 156 * <ul> 157 * <li> myFContext = FileContext.getLocalFSFileContext() 158 * <li> myFContext.create(path, ...); 159 * <li> ... 160 * </ul> 161 * Example 4: Use a specific config, ignoring $HADOOP_CONFIG 162 * Generally you should not need use a config unless you are doing 163 * <ul> 164 * <li> configX = someConfigSomeOnePassedToYou. 165 * <li> myFContext = getFileContext(configX); // configX is not changed, 166 * // is passed down 167 * <li> myFContext.create(path, ...); 168 * <li>... 169 * </ul> 170 * 171 */ 172 173@InterfaceAudience.Public 174@InterfaceStability.Evolving /*Evolving for a release,to be changed to Stable */ 175public class FileContext { 176 177 public static final Log LOG = LogFactory.getLog(FileContext.class); 178 /** 179 * Default permission for directory and symlink 180 * In previous versions, this default permission was also used to 181 * create files, so files created end up with ugo+x permission. 182 * See HADOOP-9155 for detail. 183 * Two new constants are added to solve this, please use 184 * {@link FileContext#DIR_DEFAULT_PERM} for directory, and use 185 * {@link FileContext#FILE_DEFAULT_PERM} for file. 186 * This constant is kept for compatibility. 187 */ 188 public static final FsPermission DEFAULT_PERM = FsPermission.getDefault(); 189 /** 190 * Default permission for directory 191 */ 192 public static final FsPermission DIR_DEFAULT_PERM = FsPermission.getDirDefault(); 193 /** 194 * Default permission for file 195 */ 196 public static final FsPermission FILE_DEFAULT_PERM = FsPermission.getFileDefault(); 197 198 /** 199 * Priority of the FileContext shutdown hook. 200 */ 201 public static final int SHUTDOWN_HOOK_PRIORITY = 20; 202 203 /** 204 * List of files that should be deleted on JVM shutdown. 205 */ 206 static final Map<FileContext, Set<Path>> DELETE_ON_EXIT = 207 new IdentityHashMap<FileContext, Set<Path>>(); 208 209 /** JVM shutdown hook thread. */ 210 static final FileContextFinalizer FINALIZER = 211 new FileContextFinalizer(); 212 213 private static final PathFilter DEFAULT_FILTER = new PathFilter() { 214 @Override 215 public boolean accept(final Path file) { 216 return true; 217 } 218 }; 219 220 /** 221 * The FileContext is defined by. 222 * 1) defaultFS (slash) 223 * 2) wd 224 * 3) umask 225 */ 226 private final AbstractFileSystem defaultFS; //default FS for this FileContext. 227 private Path workingDir; // Fully qualified 228 private FsPermission umask; 229 private final Configuration conf; 230 private final UserGroupInformation ugi; 231 final boolean resolveSymlinks; 232 private final Tracer tracer; 233 234 private FileContext(final AbstractFileSystem defFs, 235 final FsPermission theUmask, final Configuration aConf) { 236 defaultFS = defFs; 237 umask = FsPermission.getUMask(aConf); 238 conf = aConf; 239 tracer = FsTracer.get(aConf); 240 try { 241 ugi = UserGroupInformation.getCurrentUser(); 242 } catch (IOException e) { 243 LOG.error("Exception in getCurrentUser: ",e); 244 throw new RuntimeException("Failed to get the current user " + 245 "while creating a FileContext", e); 246 } 247 /* 248 * Init the wd. 249 * WorkingDir is implemented at the FileContext layer 250 * NOT at the AbstractFileSystem layer. 251 * If the DefaultFS, such as localFilesystem has a notion of 252 * builtin WD, we use that as the initial WD. 253 * Otherwise the WD is initialized to the home directory. 254 */ 255 workingDir = defaultFS.getInitialWorkingDirectory(); 256 if (workingDir == null) { 257 workingDir = defaultFS.getHomeDirectory(); 258 } 259 resolveSymlinks = conf.getBoolean( 260 CommonConfigurationKeys.FS_CLIENT_RESOLVE_REMOTE_SYMLINKS_KEY, 261 CommonConfigurationKeys.FS_CLIENT_RESOLVE_REMOTE_SYMLINKS_DEFAULT); 262 util = new Util(); // for the inner class 263 } 264 265 /* 266 * Remove relative part - return "absolute": 267 * If input is relative path ("foo/bar") add wd: ie "/<workingDir>/foo/bar" 268 * A fully qualified uri ("hdfs://nn:p/foo/bar") or a slash-relative path 269 * ("/foo/bar") are returned unchanged. 270 * 271 * Applications that use FileContext should use #makeQualified() since 272 * they really want a fully qualified URI. 273 * Hence this method is not called makeAbsolute() and 274 * has been deliberately declared private. 275 */ 276 Path fixRelativePart(Path p) { 277 if (p.isUriPathAbsolute()) { 278 return p; 279 } else { 280 return new Path(workingDir, p); 281 } 282 } 283 284 /** 285 * Delete all the paths that were marked as delete-on-exit. 286 */ 287 static void processDeleteOnExit() { 288 synchronized (DELETE_ON_EXIT) { 289 Set<Entry<FileContext, Set<Path>>> set = DELETE_ON_EXIT.entrySet(); 290 for (Entry<FileContext, Set<Path>> entry : set) { 291 FileContext fc = entry.getKey(); 292 Set<Path> paths = entry.getValue(); 293 for (Path path : paths) { 294 try { 295 fc.delete(path, true); 296 } catch (IOException e) { 297 LOG.warn("Ignoring failure to deleteOnExit for path " + path); 298 } 299 } 300 } 301 DELETE_ON_EXIT.clear(); 302 } 303 } 304 305 /** 306 * Get the file system of supplied path. 307 * 308 * @param absOrFqPath - absolute or fully qualified path 309 * @return the file system of the path 310 * 311 * @throws UnsupportedFileSystemException If the file system for 312 * <code>absOrFqPath</code> is not supported. 313 * @throws IOExcepton If the file system for <code>absOrFqPath</code> could 314 * not be instantiated. 315 */ 316 protected AbstractFileSystem getFSofPath(final Path absOrFqPath) 317 throws UnsupportedFileSystemException, IOException { 318 absOrFqPath.checkNotSchemeWithRelative(); 319 absOrFqPath.checkNotRelative(); 320 321 try { 322 // Is it the default FS for this FileContext? 323 defaultFS.checkPath(absOrFqPath); 324 return defaultFS; 325 } catch (Exception e) { // it is different FileSystem 326 return getAbstractFileSystem(ugi, absOrFqPath.toUri(), conf); 327 } 328 } 329 330 private static AbstractFileSystem getAbstractFileSystem( 331 UserGroupInformation user, final URI uri, final Configuration conf) 332 throws UnsupportedFileSystemException, IOException { 333 try { 334 return user.doAs(new PrivilegedExceptionAction<AbstractFileSystem>() { 335 @Override 336 public AbstractFileSystem run() throws UnsupportedFileSystemException { 337 return AbstractFileSystem.get(uri, conf); 338 } 339 }); 340 } catch (InterruptedException ex) { 341 LOG.error(ex); 342 throw new IOException("Failed to get the AbstractFileSystem for path: " 343 + uri, ex); 344 } 345 } 346 347 /** 348 * Protected Static Factory methods for getting a FileContexts 349 * that take a AbstractFileSystem as input. To be used for testing. 350 */ 351 352 /** 353 * Create a FileContext with specified FS as default using the specified 354 * config. 355 * 356 * @param defFS 357 * @param aConf 358 * @return new FileContext with specifed FS as default. 359 */ 360 public static FileContext getFileContext(final AbstractFileSystem defFS, 361 final Configuration aConf) { 362 return new FileContext(defFS, FsPermission.getUMask(aConf), aConf); 363 } 364 365 /** 366 * Create a FileContext for specified file system using the default config. 367 * 368 * @param defaultFS 369 * @return a FileContext with the specified AbstractFileSystem 370 * as the default FS. 371 */ 372 protected static FileContext getFileContext( 373 final AbstractFileSystem defaultFS) { 374 return getFileContext(defaultFS, new Configuration()); 375 } 376 377 /** 378 * Static Factory methods for getting a FileContext. 379 * Note new file contexts are created for each call. 380 * The only singleton is the local FS context using the default config. 381 * 382 * Methods that use the default config: the default config read from the 383 * $HADOOP_CONFIG/core.xml, 384 * Unspecified key-values for config are defaulted from core-defaults.xml 385 * in the release jar. 386 * 387 * The keys relevant to the FileContext layer are extracted at time of 388 * construction. Changes to the config after the call are ignore 389 * by the FileContext layer. 390 * The conf is passed to lower layers like AbstractFileSystem and HDFS which 391 * pick up their own config variables. 392 */ 393 394 /** 395 * Create a FileContext using the default config read from the 396 * $HADOOP_CONFIG/core.xml, Unspecified key-values for config are defaulted 397 * from core-defaults.xml in the release jar. 398 * 399 * @throws UnsupportedFileSystemException If the file system from the default 400 * configuration is not supported 401 */ 402 public static FileContext getFileContext() 403 throws UnsupportedFileSystemException { 404 return getFileContext(new Configuration()); 405 } 406 407 /** 408 * @return a FileContext for the local file system using the default config. 409 * @throws UnsupportedFileSystemException If the file system for 410 * {@link FsConstants#LOCAL_FS_URI} is not supported. 411 */ 412 public static FileContext getLocalFSFileContext() 413 throws UnsupportedFileSystemException { 414 return getFileContext(FsConstants.LOCAL_FS_URI); 415 } 416 417 /** 418 * Create a FileContext for specified URI using the default config. 419 * 420 * @param defaultFsUri 421 * @return a FileContext with the specified URI as the default FS. 422 * 423 * @throws UnsupportedFileSystemException If the file system for 424 * <code>defaultFsUri</code> is not supported 425 */ 426 public static FileContext getFileContext(final URI defaultFsUri) 427 throws UnsupportedFileSystemException { 428 return getFileContext(defaultFsUri, new Configuration()); 429 } 430 431 /** 432 * Create a FileContext for specified default URI using the specified config. 433 * 434 * @param defaultFsUri 435 * @param aConf 436 * @return new FileContext for specified uri 437 * @throws UnsupportedFileSystemException If the file system with specified is 438 * not supported 439 * @throws RuntimeException If the file system specified is supported but 440 * could not be instantiated, or if login fails. 441 */ 442 public static FileContext getFileContext(final URI defaultFsUri, 443 final Configuration aConf) throws UnsupportedFileSystemException { 444 UserGroupInformation currentUser = null; 445 AbstractFileSystem defaultAfs = null; 446 if (defaultFsUri.getScheme() == null) { 447 return getFileContext(aConf); 448 } 449 try { 450 currentUser = UserGroupInformation.getCurrentUser(); 451 defaultAfs = getAbstractFileSystem(currentUser, defaultFsUri, aConf); 452 } catch (UnsupportedFileSystemException ex) { 453 throw ex; 454 } catch (IOException ex) { 455 LOG.error(ex); 456 throw new RuntimeException(ex); 457 } 458 return getFileContext(defaultAfs, aConf); 459 } 460 461 /** 462 * Create a FileContext using the passed config. Generally it is better to use 463 * {@link #getFileContext(URI, Configuration)} instead of this one. 464 * 465 * 466 * @param aConf 467 * @return new FileContext 468 * @throws UnsupportedFileSystemException If file system in the config 469 * is not supported 470 */ 471 public static FileContext getFileContext(final Configuration aConf) 472 throws UnsupportedFileSystemException { 473 return getFileContext( 474 URI.create(aConf.get(FS_DEFAULT_NAME_KEY, FS_DEFAULT_NAME_DEFAULT)), 475 aConf); 476 } 477 478 /** 479 * @param aConf - from which the FileContext is configured 480 * @return a FileContext for the local file system using the specified config. 481 * 482 * @throws UnsupportedFileSystemException If default file system in the config 483 * is not supported 484 * 485 */ 486 public static FileContext getLocalFSFileContext(final Configuration aConf) 487 throws UnsupportedFileSystemException { 488 return getFileContext(FsConstants.LOCAL_FS_URI, aConf); 489 } 490 491 /* This method is needed for tests. */ 492 @InterfaceAudience.Private 493 @InterfaceStability.Unstable /* return type will change to AFS once 494 HADOOP-6223 is completed */ 495 public AbstractFileSystem getDefaultFileSystem() { 496 return defaultFS; 497 } 498 499 /** 500 * Set the working directory for wd-relative names (such a "foo/bar"). Working 501 * directory feature is provided by simply prefixing relative names with the 502 * working dir. Note this is different from Unix where the wd is actually set 503 * to the inode. Hence setWorkingDir does not follow symlinks etc. This works 504 * better in a distributed environment that has multiple independent roots. 505 * {@link #getWorkingDirectory()} should return what setWorkingDir() set. 506 * 507 * @param newWDir new working directory 508 * @throws IOException 509 * <br> 510 * NewWdir can be one of: 511 * <ul> 512 * <li>relative path: "foo/bar";</li> 513 * <li>absolute without scheme: "/foo/bar"</li> 514 * <li>fully qualified with scheme: "xx://auth/foo/bar"</li> 515 * </ul> 516 * <br> 517 * Illegal WDs: 518 * <ul> 519 * <li>relative with scheme: "xx:foo/bar"</li> 520 * <li>non existent directory</li> 521 * </ul> 522 */ 523 public void setWorkingDirectory(final Path newWDir) throws IOException { 524 newWDir.checkNotSchemeWithRelative(); 525 /* wd is stored as a fully qualified path. We check if the given 526 * path is not relative first since resolve requires and returns 527 * an absolute path. 528 */ 529 final Path newWorkingDir = new Path(workingDir, newWDir); 530 FileStatus status = getFileStatus(newWorkingDir); 531 if (status.isFile()) { 532 throw new FileNotFoundException("Cannot setWD to a file"); 533 } 534 workingDir = newWorkingDir; 535 } 536 537 /** 538 * Gets the working directory for wd-relative names (such a "foo/bar"). 539 */ 540 public Path getWorkingDirectory() { 541 return workingDir; 542 } 543 544 /** 545 * Gets the ugi in the file-context 546 * @return UserGroupInformation 547 */ 548 public UserGroupInformation getUgi() { 549 return ugi; 550 } 551 552 /** 553 * Return the current user's home directory in this file system. 554 * The default implementation returns "/user/$USER/". 555 * @return the home directory 556 */ 557 public Path getHomeDirectory() { 558 return defaultFS.getHomeDirectory(); 559 } 560 561 /** 562 * 563 * @return the umask of this FileContext 564 */ 565 public FsPermission getUMask() { 566 return umask; 567 } 568 569 /** 570 * Set umask to the supplied parameter. 571 * @param newUmask the new umask 572 */ 573 public void setUMask(final FsPermission newUmask) { 574 umask = newUmask; 575 } 576 577 578 /** 579 * Resolve the path following any symlinks or mount points 580 * @param f to be resolved 581 * @return fully qualified resolved path 582 * 583 * @throws FileNotFoundException If <code>f</code> does not exist 584 * @throws AccessControlException if access denied 585 * @throws IOException If an IO Error occurred 586 * 587 * Exceptions applicable to file systems accessed over RPC: 588 * @throws RpcClientException If an exception occurred in the RPC client 589 * @throws RpcServerException If an exception occurred in the RPC server 590 * @throws UnexpectedServerException If server implementation throws 591 * undeclared exception to RPC server 592 * 593 * RuntimeExceptions: 594 * @throws InvalidPathException If path <code>f</code> is not valid 595 */ 596 public Path resolvePath(final Path f) throws FileNotFoundException, 597 UnresolvedLinkException, AccessControlException, IOException { 598 return resolve(f); 599 } 600 601 /** 602 * Make the path fully qualified if it is isn't. 603 * A Fully-qualified path has scheme and authority specified and an absolute 604 * path. 605 * Use the default file system and working dir in this FileContext to qualify. 606 * @param path 607 * @return qualified path 608 */ 609 public Path makeQualified(final Path path) { 610 return path.makeQualified(defaultFS.getUri(), getWorkingDirectory()); 611 } 612 613 /** 614 * Create or overwrite file on indicated path and returns an output stream for 615 * writing into the file. 616 * 617 * @param f the file name to open 618 * @param createFlag gives the semantics of create; see {@link CreateFlag} 619 * @param opts file creation options; see {@link Options.CreateOpts}. 620 * <ul> 621 * <li>Progress - to report progress on the operation - default null 622 * <li>Permission - umask is applied against permisssion: default is 623 * FsPermissions:getDefault() 624 * 625 * <li>CreateParent - create missing parent path; default is to not 626 * to create parents 627 * <li>The defaults for the following are SS defaults of the file 628 * server implementing the target path. Not all parameters make sense 629 * for all kinds of file system - eg. localFS ignores Blocksize, 630 * replication, checksum 631 * <ul> 632 * <li>BufferSize - buffersize used in FSDataOutputStream 633 * <li>Blocksize - block size for file blocks 634 * <li>ReplicationFactor - replication for blocks 635 * <li>ChecksumParam - Checksum parameters. server default is used 636 * if not specified. 637 * </ul> 638 * </ul> 639 * 640 * @return {@link FSDataOutputStream} for created file 641 * 642 * @throws AccessControlException If access is denied 643 * @throws FileAlreadyExistsException If file <code>f</code> already exists 644 * @throws FileNotFoundException If parent of <code>f</code> does not exist 645 * and <code>createParent</code> is false 646 * @throws ParentNotDirectoryException If parent of <code>f</code> is not a 647 * directory. 648 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 649 * not supported 650 * @throws IOException If an I/O error occurred 651 * 652 * Exceptions applicable to file systems accessed over RPC: 653 * @throws RpcClientException If an exception occurred in the RPC client 654 * @throws RpcServerException If an exception occurred in the RPC server 655 * @throws UnexpectedServerException If server implementation throws 656 * undeclared exception to RPC server 657 * 658 * RuntimeExceptions: 659 * @throws InvalidPathException If path <code>f</code> is not valid 660 */ 661 public FSDataOutputStream create(final Path f, 662 final EnumSet<CreateFlag> createFlag, Options.CreateOpts... opts) 663 throws AccessControlException, FileAlreadyExistsException, 664 FileNotFoundException, ParentNotDirectoryException, 665 UnsupportedFileSystemException, IOException { 666 Path absF = fixRelativePart(f); 667 668 // If one of the options is a permission, extract it & apply umask 669 // If not, add a default Perms and apply umask; 670 // AbstractFileSystem#create 671 672 CreateOpts.Perms permOpt = CreateOpts.getOpt(CreateOpts.Perms.class, opts); 673 FsPermission permission = (permOpt != null) ? permOpt.getValue() : 674 FILE_DEFAULT_PERM; 675 permission = permission.applyUMask(umask); 676 677 final CreateOpts[] updatedOpts = 678 CreateOpts.setOpt(CreateOpts.perms(permission), opts); 679 return new FSLinkResolver<FSDataOutputStream>() { 680 @Override 681 public FSDataOutputStream next(final AbstractFileSystem fs, final Path p) 682 throws IOException { 683 return fs.create(p, createFlag, updatedOpts); 684 } 685 }.resolve(this, absF); 686 } 687 688 /** 689 * Make(create) a directory and all the non-existent parents. 690 * 691 * @param dir - the dir to make 692 * @param permission - permissions is set permission&~umask 693 * @param createParent - if true then missing parent dirs are created if false 694 * then parent must exist 695 * 696 * @throws AccessControlException If access is denied 697 * @throws FileAlreadyExistsException If directory <code>dir</code> already 698 * exists 699 * @throws FileNotFoundException If parent of <code>dir</code> does not exist 700 * and <code>createParent</code> is false 701 * @throws ParentNotDirectoryException If parent of <code>dir</code> is not a 702 * directory 703 * @throws UnsupportedFileSystemException If file system for <code>dir</code> 704 * is not supported 705 * @throws IOException If an I/O error occurred 706 * 707 * Exceptions applicable to file systems accessed over RPC: 708 * @throws RpcClientException If an exception occurred in the RPC client 709 * @throws UnexpectedServerException If server implementation throws 710 * undeclared exception to RPC server 711 * 712 * RuntimeExceptions: 713 * @throws InvalidPathException If path <code>dir</code> is not valid 714 */ 715 public void mkdir(final Path dir, final FsPermission permission, 716 final boolean createParent) throws AccessControlException, 717 FileAlreadyExistsException, FileNotFoundException, 718 ParentNotDirectoryException, UnsupportedFileSystemException, 719 IOException { 720 final Path absDir = fixRelativePart(dir); 721 final FsPermission absFerms = (permission == null ? 722 FsPermission.getDirDefault() : permission).applyUMask(umask); 723 new FSLinkResolver<Void>() { 724 @Override 725 public Void next(final AbstractFileSystem fs, final Path p) 726 throws IOException, UnresolvedLinkException { 727 fs.mkdir(p, absFerms, createParent); 728 return null; 729 } 730 }.resolve(this, absDir); 731 } 732 733 /** 734 * Delete a file. 735 * @param f the path to delete. 736 * @param recursive if path is a directory and set to 737 * true, the directory is deleted else throws an exception. In 738 * case of a file the recursive can be set to either true or false. 739 * 740 * @throws AccessControlException If access is denied 741 * @throws FileNotFoundException If <code>f</code> does not exist 742 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 743 * not supported 744 * @throws IOException If an I/O error occurred 745 * 746 * Exceptions applicable to file systems accessed over RPC: 747 * @throws RpcClientException If an exception occurred in the RPC client 748 * @throws RpcServerException If an exception occurred in the RPC server 749 * @throws UnexpectedServerException If server implementation throws 750 * undeclared exception to RPC server 751 * 752 * RuntimeExceptions: 753 * @throws InvalidPathException If path <code>f</code> is invalid 754 */ 755 public boolean delete(final Path f, final boolean recursive) 756 throws AccessControlException, FileNotFoundException, 757 UnsupportedFileSystemException, IOException { 758 Path absF = fixRelativePart(f); 759 return new FSLinkResolver<Boolean>() { 760 @Override 761 public Boolean next(final AbstractFileSystem fs, final Path p) 762 throws IOException, UnresolvedLinkException { 763 return Boolean.valueOf(fs.delete(p, recursive)); 764 } 765 }.resolve(this, absF); 766 } 767 768 /** 769 * Opens an FSDataInputStream at the indicated Path using 770 * default buffersize. 771 * @param f the file name to open 772 * 773 * @throws AccessControlException If access is denied 774 * @throws FileNotFoundException If file <code>f</code> does not exist 775 * @throws UnsupportedFileSystemException If file system for <code>f</code> 776 * is not supported 777 * @throws IOException If an I/O error occurred 778 * 779 * Exceptions applicable to file systems accessed over RPC: 780 * @throws RpcClientException If an exception occurred in the RPC client 781 * @throws RpcServerException If an exception occurred in the RPC server 782 * @throws UnexpectedServerException If server implementation throws 783 * undeclared exception to RPC server 784 */ 785 public FSDataInputStream open(final Path f) throws AccessControlException, 786 FileNotFoundException, UnsupportedFileSystemException, IOException { 787 final Path absF = fixRelativePart(f); 788 return new FSLinkResolver<FSDataInputStream>() { 789 @Override 790 public FSDataInputStream next(final AbstractFileSystem fs, final Path p) 791 throws IOException, UnresolvedLinkException { 792 return fs.open(p); 793 } 794 }.resolve(this, absF); 795 } 796 797 /** 798 * Opens an FSDataInputStream at the indicated Path. 799 * 800 * @param f the file name to open 801 * @param bufferSize the size of the buffer to be used. 802 * 803 * @throws AccessControlException If access is denied 804 * @throws FileNotFoundException If file <code>f</code> does not exist 805 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 806 * not supported 807 * @throws IOException If an I/O error occurred 808 * 809 * Exceptions applicable to file systems accessed over RPC: 810 * @throws RpcClientException If an exception occurred in the RPC client 811 * @throws RpcServerException If an exception occurred in the RPC server 812 * @throws UnexpectedServerException If server implementation throws 813 * undeclared exception to RPC server 814 */ 815 public FSDataInputStream open(final Path f, final int bufferSize) 816 throws AccessControlException, FileNotFoundException, 817 UnsupportedFileSystemException, IOException { 818 final Path absF = fixRelativePart(f); 819 return new FSLinkResolver<FSDataInputStream>() { 820 @Override 821 public FSDataInputStream next(final AbstractFileSystem fs, final Path p) 822 throws IOException, UnresolvedLinkException { 823 return fs.open(p, bufferSize); 824 } 825 }.resolve(this, absF); 826 } 827 828 /** 829 * Set replication for an existing file. 830 * 831 * @param f file name 832 * @param replication new replication 833 * 834 * @return true if successful 835 * 836 * @throws AccessControlException If access is denied 837 * @throws FileNotFoundException If file <code>f</code> does not exist 838 * @throws IOException If an I/O error occurred 839 * 840 * Exceptions applicable to file systems accessed over RPC: 841 * @throws RpcClientException If an exception occurred in the RPC client 842 * @throws RpcServerException If an exception occurred in the RPC server 843 * @throws UnexpectedServerException If server implementation throws 844 * undeclared exception to RPC server 845 */ 846 public boolean setReplication(final Path f, final short replication) 847 throws AccessControlException, FileNotFoundException, 848 IOException { 849 final Path absF = fixRelativePart(f); 850 return new FSLinkResolver<Boolean>() { 851 @Override 852 public Boolean next(final AbstractFileSystem fs, final Path p) 853 throws IOException, UnresolvedLinkException { 854 return Boolean.valueOf(fs.setReplication(p, replication)); 855 } 856 }.resolve(this, absF); 857 } 858 859 /** 860 * Renames Path src to Path dst 861 * <ul> 862 * <li 863 * <li>Fails if src is a file and dst is a directory. 864 * <li>Fails if src is a directory and dst is a file. 865 * <li>Fails if the parent of dst does not exist or is a file. 866 * </ul> 867 * <p> 868 * If OVERWRITE option is not passed as an argument, rename fails if the dst 869 * already exists. 870 * <p> 871 * If OVERWRITE option is passed as an argument, rename overwrites the dst if 872 * it is a file or an empty directory. Rename fails if dst is a non-empty 873 * directory. 874 * <p> 875 * Note that atomicity of rename is dependent on the file system 876 * implementation. Please refer to the file system documentation for details 877 * <p> 878 * 879 * @param src path to be renamed 880 * @param dst new path after rename 881 * 882 * @throws AccessControlException If access is denied 883 * @throws FileAlreadyExistsException If <code>dst</code> already exists and 884 * <code>options</options> has {@link Options.Rename#OVERWRITE} 885 * option false. 886 * @throws FileNotFoundException If <code>src</code> does not exist 887 * @throws ParentNotDirectoryException If parent of <code>dst</code> is not a 888 * directory 889 * @throws UnsupportedFileSystemException If file system for <code>src</code> 890 * and <code>dst</code> is not supported 891 * @throws IOException If an I/O error occurred 892 * 893 * Exceptions applicable to file systems accessed over RPC: 894 * @throws RpcClientException If an exception occurred in the RPC client 895 * @throws RpcServerException If an exception occurred in the RPC server 896 * @throws UnexpectedServerException If server implementation throws 897 * undeclared exception to RPC server 898 */ 899 public void rename(final Path src, final Path dst, 900 final Options.Rename... options) throws AccessControlException, 901 FileAlreadyExistsException, FileNotFoundException, 902 ParentNotDirectoryException, UnsupportedFileSystemException, 903 IOException { 904 final Path absSrc = fixRelativePart(src); 905 final Path absDst = fixRelativePart(dst); 906 AbstractFileSystem srcFS = getFSofPath(absSrc); 907 AbstractFileSystem dstFS = getFSofPath(absDst); 908 if(!srcFS.getUri().equals(dstFS.getUri())) { 909 throw new IOException("Renames across AbstractFileSystems not supported"); 910 } 911 try { 912 srcFS.rename(absSrc, absDst, options); 913 } catch (UnresolvedLinkException e) { 914 /* We do not know whether the source or the destination path 915 * was unresolved. Resolve the source path up until the final 916 * path component, then fully resolve the destination. 917 */ 918 final Path source = resolveIntermediate(absSrc); 919 new FSLinkResolver<Void>() { 920 @Override 921 public Void next(final AbstractFileSystem fs, final Path p) 922 throws IOException, UnresolvedLinkException { 923 fs.rename(source, p, options); 924 return null; 925 } 926 }.resolve(this, absDst); 927 } 928 } 929 930 /** 931 * Set permission of a path. 932 * @param f 933 * @param permission - the new absolute permission (umask is not applied) 934 * 935 * @throws AccessControlException If access is denied 936 * @throws FileNotFoundException If <code>f</code> does not exist 937 * @throws UnsupportedFileSystemException If file system for <code>f</code> 938 * is not supported 939 * @throws IOException If an I/O error occurred 940 * 941 * Exceptions applicable to file systems accessed over RPC: 942 * @throws RpcClientException If an exception occurred in the RPC client 943 * @throws RpcServerException If an exception occurred in the RPC server 944 * @throws UnexpectedServerException If server implementation throws 945 * undeclared exception to RPC server 946 */ 947 public void setPermission(final Path f, final FsPermission permission) 948 throws AccessControlException, FileNotFoundException, 949 UnsupportedFileSystemException, IOException { 950 final Path absF = fixRelativePart(f); 951 new FSLinkResolver<Void>() { 952 @Override 953 public Void next(final AbstractFileSystem fs, final Path p) 954 throws IOException, UnresolvedLinkException { 955 fs.setPermission(p, permission); 956 return null; 957 } 958 }.resolve(this, absF); 959 } 960 961 /** 962 * Set owner of a path (i.e. a file or a directory). The parameters username 963 * and groupname cannot both be null. 964 * 965 * @param f The path 966 * @param username If it is null, the original username remains unchanged. 967 * @param groupname If it is null, the original groupname remains unchanged. 968 * 969 * @throws AccessControlException If access is denied 970 * @throws FileNotFoundException If <code>f</code> does not exist 971 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 972 * not supported 973 * @throws IOException If an I/O error occurred 974 * 975 * Exceptions applicable to file systems accessed over RPC: 976 * @throws RpcClientException If an exception occurred in the RPC client 977 * @throws RpcServerException If an exception occurred in the RPC server 978 * @throws UnexpectedServerException If server implementation throws 979 * undeclared exception to RPC server 980 * 981 * RuntimeExceptions: 982 * @throws HadoopIllegalArgumentException If <code>username</code> or 983 * <code>groupname</code> is invalid. 984 */ 985 public void setOwner(final Path f, final String username, 986 final String groupname) throws AccessControlException, 987 UnsupportedFileSystemException, FileNotFoundException, 988 IOException { 989 if ((username == null) && (groupname == null)) { 990 throw new HadoopIllegalArgumentException( 991 "username and groupname cannot both be null"); 992 } 993 final Path absF = fixRelativePart(f); 994 new FSLinkResolver<Void>() { 995 @Override 996 public Void next(final AbstractFileSystem fs, final Path p) 997 throws IOException, UnresolvedLinkException { 998 fs.setOwner(p, username, groupname); 999 return null; 1000 } 1001 }.resolve(this, absF); 1002 } 1003 1004 /** 1005 * Set access time of a file. 1006 * @param f The path 1007 * @param mtime Set the modification time of this file. 1008 * The number of milliseconds since epoch (Jan 1, 1970). 1009 * A value of -1 means that this call should not set modification time. 1010 * @param atime Set the access time of this file. 1011 * The number of milliseconds since Jan 1, 1970. 1012 * A value of -1 means that this call should not set access time. 1013 * 1014 * @throws AccessControlException If access is denied 1015 * @throws FileNotFoundException If <code>f</code> does not exist 1016 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1017 * not supported 1018 * @throws IOException If an I/O error occurred 1019 * 1020 * Exceptions applicable to file systems accessed over RPC: 1021 * @throws RpcClientException If an exception occurred in the RPC client 1022 * @throws RpcServerException If an exception occurred in the RPC server 1023 * @throws UnexpectedServerException If server implementation throws 1024 * undeclared exception to RPC server 1025 */ 1026 public void setTimes(final Path f, final long mtime, final long atime) 1027 throws AccessControlException, FileNotFoundException, 1028 UnsupportedFileSystemException, IOException { 1029 final Path absF = fixRelativePart(f); 1030 new FSLinkResolver<Void>() { 1031 @Override 1032 public Void next(final AbstractFileSystem fs, final Path p) 1033 throws IOException, UnresolvedLinkException { 1034 fs.setTimes(p, mtime, atime); 1035 return null; 1036 } 1037 }.resolve(this, absF); 1038 } 1039 1040 /** 1041 * Get the checksum of a file. 1042 * 1043 * @param f file path 1044 * 1045 * @return The file checksum. The default return value is null, 1046 * which indicates that no checksum algorithm is implemented 1047 * in the corresponding FileSystem. 1048 * 1049 * @throws AccessControlException If access is denied 1050 * @throws FileNotFoundException If <code>f</code> does not exist 1051 * @throws IOException If an I/O error occurred 1052 * 1053 * Exceptions applicable to file systems accessed over RPC: 1054 * @throws RpcClientException If an exception occurred in the RPC client 1055 * @throws RpcServerException If an exception occurred in the RPC server 1056 * @throws UnexpectedServerException If server implementation throws 1057 * undeclared exception to RPC server 1058 */ 1059 public FileChecksum getFileChecksum(final Path f) 1060 throws AccessControlException, FileNotFoundException, 1061 IOException { 1062 final Path absF = fixRelativePart(f); 1063 return new FSLinkResolver<FileChecksum>() { 1064 @Override 1065 public FileChecksum next(final AbstractFileSystem fs, final Path p) 1066 throws IOException, UnresolvedLinkException { 1067 return fs.getFileChecksum(p); 1068 } 1069 }.resolve(this, absF); 1070 } 1071 1072 /** 1073 * Set the verify checksum flag for the file system denoted by the path. 1074 * This is only applicable if the 1075 * corresponding FileSystem supports checksum. By default doesn't do anything. 1076 * @param verifyChecksum 1077 * @param f set the verifyChecksum for the Filesystem containing this path 1078 * 1079 * @throws AccessControlException If access is denied 1080 * @throws FileNotFoundException If <code>f</code> does not exist 1081 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1082 * not supported 1083 * @throws IOException If an I/O error occurred 1084 * 1085 * Exceptions applicable to file systems accessed over RPC: 1086 * @throws RpcClientException If an exception occurred in the RPC client 1087 * @throws RpcServerException If an exception occurred in the RPC server 1088 * @throws UnexpectedServerException If server implementation throws 1089 * undeclared exception to RPC server 1090 */ 1091 public void setVerifyChecksum(final boolean verifyChecksum, final Path f) 1092 throws AccessControlException, FileNotFoundException, 1093 UnsupportedFileSystemException, IOException { 1094 final Path absF = resolve(fixRelativePart(f)); 1095 getFSofPath(absF).setVerifyChecksum(verifyChecksum); 1096 } 1097 1098 /** 1099 * Return a file status object that represents the path. 1100 * @param f The path we want information from 1101 * 1102 * @return a FileStatus object 1103 * 1104 * @throws AccessControlException If access is denied 1105 * @throws FileNotFoundException If <code>f</code> does not exist 1106 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1107 * not supported 1108 * @throws IOException If an I/O error occurred 1109 * 1110 * Exceptions applicable to file systems accessed over RPC: 1111 * @throws RpcClientException If an exception occurred in the RPC client 1112 * @throws RpcServerException If an exception occurred in the RPC server 1113 * @throws UnexpectedServerException If server implementation throws 1114 * undeclared exception to RPC server 1115 */ 1116 public FileStatus getFileStatus(final Path f) throws AccessControlException, 1117 FileNotFoundException, UnsupportedFileSystemException, IOException { 1118 final Path absF = fixRelativePart(f); 1119 return new FSLinkResolver<FileStatus>() { 1120 @Override 1121 public FileStatus next(final AbstractFileSystem fs, final Path p) 1122 throws IOException, UnresolvedLinkException { 1123 return fs.getFileStatus(p); 1124 } 1125 }.resolve(this, absF); 1126 } 1127 1128 /** 1129 * Checks if the user can access a path. The mode specifies which access 1130 * checks to perform. If the requested permissions are granted, then the 1131 * method returns normally. If access is denied, then the method throws an 1132 * {@link AccessControlException}. 1133 * <p/> 1134 * The default implementation of this method calls {@link #getFileStatus(Path)} 1135 * and checks the returned permissions against the requested permissions. 1136 * Note that the getFileStatus call will be subject to authorization checks. 1137 * Typically, this requires search (execute) permissions on each directory in 1138 * the path's prefix, but this is implementation-defined. Any file system 1139 * that provides a richer authorization model (such as ACLs) may override the 1140 * default implementation so that it checks against that model instead. 1141 * <p> 1142 * In general, applications should avoid using this method, due to the risk of 1143 * time-of-check/time-of-use race conditions. The permissions on a file may 1144 * change immediately after the access call returns. Most applications should 1145 * prefer running specific file system actions as the desired user represented 1146 * by a {@link UserGroupInformation}. 1147 * 1148 * @param path Path to check 1149 * @param mode type of access to check 1150 * @throws AccessControlException if access is denied 1151 * @throws FileNotFoundException if the path does not exist 1152 * @throws UnsupportedFileSystemException if file system for <code>path</code> 1153 * is not supported 1154 * @throws IOException see specific implementation 1155 * 1156 * Exceptions applicable to file systems accessed over RPC: 1157 * @throws RpcClientException If an exception occurred in the RPC client 1158 * @throws RpcServerException If an exception occurred in the RPC server 1159 * @throws UnexpectedServerException If server implementation throws 1160 * undeclared exception to RPC server 1161 */ 1162 @InterfaceAudience.LimitedPrivate({"HDFS", "Hive"}) 1163 public void access(final Path path, final FsAction mode) 1164 throws AccessControlException, FileNotFoundException, 1165 UnsupportedFileSystemException, IOException { 1166 final Path absPath = fixRelativePart(path); 1167 new FSLinkResolver<Void>() { 1168 @Override 1169 public Void next(AbstractFileSystem fs, Path p) throws IOException, 1170 UnresolvedLinkException { 1171 fs.access(p, mode); 1172 return null; 1173 } 1174 }.resolve(this, absPath); 1175 } 1176 1177 /** 1178 * Return a file status object that represents the path. If the path 1179 * refers to a symlink then the FileStatus of the symlink is returned. 1180 * The behavior is equivalent to #getFileStatus() if the underlying 1181 * file system does not support symbolic links. 1182 * @param f The path we want information from. 1183 * @return A FileStatus object 1184 * 1185 * @throws AccessControlException If access is denied 1186 * @throws FileNotFoundException If <code>f</code> does not exist 1187 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1188 * not supported 1189 * @throws IOException If an I/O error occurred 1190 */ 1191 public FileStatus getFileLinkStatus(final Path f) 1192 throws AccessControlException, FileNotFoundException, 1193 UnsupportedFileSystemException, IOException { 1194 final Path absF = fixRelativePart(f); 1195 return new FSLinkResolver<FileStatus>() { 1196 @Override 1197 public FileStatus next(final AbstractFileSystem fs, final Path p) 1198 throws IOException, UnresolvedLinkException { 1199 FileStatus fi = fs.getFileLinkStatus(p); 1200 if (fi.isSymlink()) { 1201 fi.setSymlink(FSLinkResolver.qualifySymlinkTarget(fs.getUri(), p, 1202 fi.getSymlink())); 1203 } 1204 return fi; 1205 } 1206 }.resolve(this, absF); 1207 } 1208 1209 /** 1210 * Returns the target of the given symbolic link as it was specified 1211 * when the link was created. Links in the path leading up to the 1212 * final path component are resolved transparently. 1213 * 1214 * @param f the path to return the target of 1215 * @return The un-interpreted target of the symbolic link. 1216 * 1217 * @throws AccessControlException If access is denied 1218 * @throws FileNotFoundException If path <code>f</code> does not exist 1219 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1220 * not supported 1221 * @throws IOException If the given path does not refer to a symlink 1222 * or an I/O error occurred 1223 */ 1224 public Path getLinkTarget(final Path f) throws AccessControlException, 1225 FileNotFoundException, UnsupportedFileSystemException, IOException { 1226 final Path absF = fixRelativePart(f); 1227 return new FSLinkResolver<Path>() { 1228 @Override 1229 public Path next(final AbstractFileSystem fs, final Path p) 1230 throws IOException, UnresolvedLinkException { 1231 FileStatus fi = fs.getFileLinkStatus(p); 1232 return fi.getSymlink(); 1233 } 1234 }.resolve(this, absF); 1235 } 1236 1237 /** 1238 * Return blockLocation of the given file for the given offset and len. 1239 * For a nonexistent file or regions, null will be returned. 1240 * 1241 * This call is most helpful with DFS, where it returns 1242 * hostnames of machines that contain the given file. 1243 * 1244 * @param f - get blocklocations of this file 1245 * @param start position (byte offset) 1246 * @param len (in bytes) 1247 * 1248 * @return block locations for given file at specified offset of len 1249 * 1250 * @throws AccessControlException If access is denied 1251 * @throws FileNotFoundException If <code>f</code> does not exist 1252 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1253 * not supported 1254 * @throws IOException If an I/O error occurred 1255 * 1256 * Exceptions applicable to file systems accessed over RPC: 1257 * @throws RpcClientException If an exception occurred in the RPC client 1258 * @throws RpcServerException If an exception occurred in the RPC server 1259 * @throws UnexpectedServerException If server implementation throws 1260 * undeclared exception to RPC server 1261 * 1262 * RuntimeExceptions: 1263 * @throws InvalidPathException If path <code>f</code> is invalid 1264 */ 1265 @InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"}) 1266 @InterfaceStability.Evolving 1267 public BlockLocation[] getFileBlockLocations(final Path f, final long start, 1268 final long len) throws AccessControlException, FileNotFoundException, 1269 UnsupportedFileSystemException, IOException { 1270 final Path absF = fixRelativePart(f); 1271 return new FSLinkResolver<BlockLocation[]>() { 1272 @Override 1273 public BlockLocation[] next(final AbstractFileSystem fs, final Path p) 1274 throws IOException, UnresolvedLinkException { 1275 return fs.getFileBlockLocations(p, start, len); 1276 } 1277 }.resolve(this, absF); 1278 } 1279 1280 /** 1281 * Returns a status object describing the use and capacity of the 1282 * file system denoted by the Parh argument p. 1283 * If the file system has multiple partitions, the 1284 * use and capacity of the partition pointed to by the specified 1285 * path is reflected. 1286 * 1287 * @param f Path for which status should be obtained. null means the 1288 * root partition of the default file system. 1289 * 1290 * @return a FsStatus object 1291 * 1292 * @throws AccessControlException If access is denied 1293 * @throws FileNotFoundException If <code>f</code> does not exist 1294 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1295 * not supported 1296 * @throws IOException If an I/O error occurred 1297 * 1298 * Exceptions applicable to file systems accessed over RPC: 1299 * @throws RpcClientException If an exception occurred in the RPC client 1300 * @throws RpcServerException If an exception occurred in the RPC server 1301 * @throws UnexpectedServerException If server implementation throws 1302 * undeclared exception to RPC server 1303 */ 1304 public FsStatus getFsStatus(final Path f) throws AccessControlException, 1305 FileNotFoundException, UnsupportedFileSystemException, IOException { 1306 if (f == null) { 1307 return defaultFS.getFsStatus(); 1308 } 1309 final Path absF = fixRelativePart(f); 1310 return new FSLinkResolver<FsStatus>() { 1311 @Override 1312 public FsStatus next(final AbstractFileSystem fs, final Path p) 1313 throws IOException, UnresolvedLinkException { 1314 return fs.getFsStatus(p); 1315 } 1316 }.resolve(this, absF); 1317 } 1318 1319 /** 1320 * Creates a symbolic link to an existing file. An exception is thrown if 1321 * the symlink exits, the user does not have permission to create symlink, 1322 * or the underlying file system does not support symlinks. 1323 * 1324 * Symlink permissions are ignored, access to a symlink is determined by 1325 * the permissions of the symlink target. 1326 * 1327 * Symlinks in paths leading up to the final path component are resolved 1328 * transparently. If the final path component refers to a symlink some 1329 * functions operate on the symlink itself, these are: 1330 * - delete(f) and deleteOnExit(f) - Deletes the symlink. 1331 * - rename(src, dst) - If src refers to a symlink, the symlink is 1332 * renamed. If dst refers to a symlink, the symlink is over-written. 1333 * - getLinkTarget(f) - Returns the target of the symlink. 1334 * - getFileLinkStatus(f) - Returns a FileStatus object describing 1335 * the symlink. 1336 * Some functions, create() and mkdir(), expect the final path component 1337 * does not exist. If they are given a path that refers to a symlink that 1338 * does exist they behave as if the path referred to an existing file or 1339 * directory. All other functions fully resolve, ie follow, the symlink. 1340 * These are: open, setReplication, setOwner, setTimes, setWorkingDirectory, 1341 * setPermission, getFileChecksum, setVerifyChecksum, getFileBlockLocations, 1342 * getFsStatus, getFileStatus, exists, and listStatus. 1343 * 1344 * Symlink targets are stored as given to createSymlink, assuming the 1345 * underlying file system is capable of storing a fully qualified URI. 1346 * Dangling symlinks are permitted. FileContext supports four types of 1347 * symlink targets, and resolves them as follows 1348 * <pre> 1349 * Given a path referring to a symlink of form: 1350 * 1351 * <---X---> 1352 * fs://host/A/B/link 1353 * <-----Y-----> 1354 * 1355 * In this path X is the scheme and authority that identify the file system, 1356 * and Y is the path leading up to the final path component "link". If Y is 1357 * a symlink itself then let Y' be the target of Y and X' be the scheme and 1358 * authority of Y'. Symlink targets may: 1359 * 1360 * 1. Fully qualified URIs 1361 * 1362 * fs://hostX/A/B/file Resolved according to the target file system. 1363 * 1364 * 2. Partially qualified URIs (eg scheme but no host) 1365 * 1366 * fs:///A/B/file Resolved according to the target file system. Eg resolving 1367 * a symlink to hdfs:///A results in an exception because 1368 * HDFS URIs must be fully qualified, while a symlink to 1369 * file:///A will not since Hadoop's local file systems 1370 * require partially qualified URIs. 1371 * 1372 * 3. Relative paths 1373 * 1374 * path Resolves to [Y'][path]. Eg if Y resolves to hdfs://host/A and path 1375 * is "../B/file" then [Y'][path] is hdfs://host/B/file 1376 * 1377 * 4. Absolute paths 1378 * 1379 * path Resolves to [X'][path]. Eg if Y resolves hdfs://host/A/B and path 1380 * is "/file" then [X][path] is hdfs://host/file 1381 * </pre> 1382 * 1383 * @param target the target of the symbolic link 1384 * @param link the path to be created that points to target 1385 * @param createParent if true then missing parent dirs are created if 1386 * false then parent must exist 1387 * 1388 * 1389 * @throws AccessControlException If access is denied 1390 * @throws FileAlreadyExistsException If file <code>linkcode> already exists 1391 * @throws FileNotFoundException If <code>target</code> does not exist 1392 * @throws ParentNotDirectoryException If parent of <code>link</code> is not a 1393 * directory. 1394 * @throws UnsupportedFileSystemException If file system for 1395 * <code>target</code> or <code>link</code> is not supported 1396 * @throws IOException If an I/O error occurred 1397 */ 1398 @SuppressWarnings("deprecation") 1399 public void createSymlink(final Path target, final Path link, 1400 final boolean createParent) throws AccessControlException, 1401 FileAlreadyExistsException, FileNotFoundException, 1402 ParentNotDirectoryException, UnsupportedFileSystemException, 1403 IOException { 1404 if (!FileSystem.areSymlinksEnabled()) { 1405 throw new UnsupportedOperationException("Symlinks not supported"); 1406 } 1407 final Path nonRelLink = fixRelativePart(link); 1408 new FSLinkResolver<Void>() { 1409 @Override 1410 public Void next(final AbstractFileSystem fs, final Path p) 1411 throws IOException, UnresolvedLinkException { 1412 fs.createSymlink(target, p, createParent); 1413 return null; 1414 } 1415 }.resolve(this, nonRelLink); 1416 } 1417 1418 /** 1419 * List the statuses of the files/directories in the given path if the path is 1420 * a directory. 1421 * 1422 * @param f is the path 1423 * 1424 * @return an iterator that traverses statuses of the files/directories 1425 * in the given path 1426 * 1427 * @throws AccessControlException If access is denied 1428 * @throws FileNotFoundException If <code>f</code> does not exist 1429 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1430 * not supported 1431 * @throws IOException If an I/O error occurred 1432 * 1433 * Exceptions applicable to file systems accessed over RPC: 1434 * @throws RpcClientException If an exception occurred in the RPC client 1435 * @throws RpcServerException If an exception occurred in the RPC server 1436 * @throws UnexpectedServerException If server implementation throws 1437 * undeclared exception to RPC server 1438 */ 1439 public RemoteIterator<FileStatus> listStatus(final Path f) throws 1440 AccessControlException, FileNotFoundException, 1441 UnsupportedFileSystemException, IOException { 1442 final Path absF = fixRelativePart(f); 1443 return new FSLinkResolver<RemoteIterator<FileStatus>>() { 1444 @Override 1445 public RemoteIterator<FileStatus> next( 1446 final AbstractFileSystem fs, final Path p) 1447 throws IOException, UnresolvedLinkException { 1448 return fs.listStatusIterator(p); 1449 } 1450 }.resolve(this, absF); 1451 } 1452 1453 /** 1454 * @return an iterator over the corrupt files under the given path 1455 * (may contain duplicates if a file has more than one corrupt block) 1456 * @throws IOException 1457 */ 1458 public RemoteIterator<Path> listCorruptFileBlocks(Path path) 1459 throws IOException { 1460 final Path absF = fixRelativePart(path); 1461 return new FSLinkResolver<RemoteIterator<Path>>() { 1462 @Override 1463 public RemoteIterator<Path> next(final AbstractFileSystem fs, 1464 final Path p) 1465 throws IOException, UnresolvedLinkException { 1466 return fs.listCorruptFileBlocks(p); 1467 } 1468 }.resolve(this, absF); 1469 } 1470 1471 /** 1472 * List the statuses of the files/directories in the given path if the path is 1473 * a directory. 1474 * Return the file's status and block locations If the path is a file. 1475 * 1476 * If a returned status is a file, it contains the file's block locations. 1477 * 1478 * @param f is the path 1479 * 1480 * @return an iterator that traverses statuses of the files/directories 1481 * in the given path 1482 * If any IO exception (for example the input directory gets deleted while 1483 * listing is being executed), next() or hasNext() of the returned iterator 1484 * may throw a RuntimeException with the io exception as the cause. 1485 * 1486 * @throws AccessControlException If access is denied 1487 * @throws FileNotFoundException If <code>f</code> does not exist 1488 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1489 * not supported 1490 * @throws IOException If an I/O error occurred 1491 * 1492 * Exceptions applicable to file systems accessed over RPC: 1493 * @throws RpcClientException If an exception occurred in the RPC client 1494 * @throws RpcServerException If an exception occurred in the RPC server 1495 * @throws UnexpectedServerException If server implementation throws 1496 * undeclared exception to RPC server 1497 */ 1498 public RemoteIterator<LocatedFileStatus> listLocatedStatus( 1499 final Path f) throws 1500 AccessControlException, FileNotFoundException, 1501 UnsupportedFileSystemException, IOException { 1502 final Path absF = fixRelativePart(f); 1503 return new FSLinkResolver<RemoteIterator<LocatedFileStatus>>() { 1504 @Override 1505 public RemoteIterator<LocatedFileStatus> next( 1506 final AbstractFileSystem fs, final Path p) 1507 throws IOException, UnresolvedLinkException { 1508 return fs.listLocatedStatus(p); 1509 } 1510 }.resolve(this, absF); 1511 } 1512 1513 /** 1514 * Mark a path to be deleted on JVM shutdown. 1515 * 1516 * @param f the existing path to delete. 1517 * 1518 * @return true if deleteOnExit is successful, otherwise false. 1519 * 1520 * @throws AccessControlException If access is denied 1521 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1522 * not supported 1523 * @throws IOException If an I/O error occurred 1524 * 1525 * Exceptions applicable to file systems accessed over RPC: 1526 * @throws RpcClientException If an exception occurred in the RPC client 1527 * @throws RpcServerException If an exception occurred in the RPC server 1528 * @throws UnexpectedServerException If server implementation throws 1529 * undeclared exception to RPC server 1530 */ 1531 public boolean deleteOnExit(Path f) throws AccessControlException, 1532 IOException { 1533 if (!this.util().exists(f)) { 1534 return false; 1535 } 1536 synchronized (DELETE_ON_EXIT) { 1537 if (DELETE_ON_EXIT.isEmpty()) { 1538 ShutdownHookManager.get().addShutdownHook(FINALIZER, SHUTDOWN_HOOK_PRIORITY); 1539 } 1540 1541 Set<Path> set = DELETE_ON_EXIT.get(this); 1542 if (set == null) { 1543 set = new TreeSet<Path>(); 1544 DELETE_ON_EXIT.put(this, set); 1545 } 1546 set.add(f); 1547 } 1548 return true; 1549 } 1550 1551 private final Util util; 1552 public Util util() { 1553 return util; 1554 } 1555 1556 1557 /** 1558 * Utility/library methods built over the basic FileContext methods. 1559 * Since this are library functions, the oprtation are not atomic 1560 * and some of them may partially complete if other threads are making 1561 * changes to the same part of the name space. 1562 */ 1563 public class Util { 1564 /** 1565 * Does the file exist? 1566 * Note: Avoid using this method if you already have FileStatus in hand. 1567 * Instead reuse the FileStatus 1568 * @param f the file or dir to be checked 1569 * 1570 * @throws AccessControlException If access is denied 1571 * @throws IOException If an I/O error occurred 1572 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1573 * not supported 1574 * 1575 * Exceptions applicable to file systems accessed over RPC: 1576 * @throws RpcClientException If an exception occurred in the RPC client 1577 * @throws RpcServerException If an exception occurred in the RPC server 1578 * @throws UnexpectedServerException If server implementation throws 1579 * undeclared exception to RPC server 1580 */ 1581 public boolean exists(final Path f) throws AccessControlException, 1582 UnsupportedFileSystemException, IOException { 1583 try { 1584 FileStatus fs = FileContext.this.getFileStatus(f); 1585 assert fs != null; 1586 return true; 1587 } catch (FileNotFoundException e) { 1588 return false; 1589 } 1590 } 1591 1592 /** 1593 * Return the {@link ContentSummary} of path f. 1594 * @param f path 1595 * 1596 * @return the {@link ContentSummary} of path f. 1597 * 1598 * @throws AccessControlException If access is denied 1599 * @throws FileNotFoundException If <code>f</code> does not exist 1600 * @throws UnsupportedFileSystemException If file system for 1601 * <code>f</code> is not supported 1602 * @throws IOException If an I/O error occurred 1603 * 1604 * Exceptions applicable to file systems accessed over RPC: 1605 * @throws RpcClientException If an exception occurred in the RPC client 1606 * @throws RpcServerException If an exception occurred in the RPC server 1607 * @throws UnexpectedServerException If server implementation throws 1608 * undeclared exception to RPC server 1609 */ 1610 public ContentSummary getContentSummary(Path f) 1611 throws AccessControlException, FileNotFoundException, 1612 UnsupportedFileSystemException, IOException { 1613 FileStatus status = FileContext.this.getFileStatus(f); 1614 if (status.isFile()) { 1615 return new ContentSummary(status.getLen(), 1, 0); 1616 } 1617 long[] summary = {0, 0, 1}; 1618 RemoteIterator<FileStatus> statusIterator = 1619 FileContext.this.listStatus(f); 1620 while(statusIterator.hasNext()) { 1621 FileStatus s = statusIterator.next(); 1622 ContentSummary c = s.isDirectory() ? getContentSummary(s.getPath()) : 1623 new ContentSummary(s.getLen(), 1, 0); 1624 summary[0] += c.getLength(); 1625 summary[1] += c.getFileCount(); 1626 summary[2] += c.getDirectoryCount(); 1627 } 1628 return new ContentSummary(summary[0], summary[1], summary[2]); 1629 } 1630 1631 /** 1632 * See {@link #listStatus(Path[], PathFilter)} 1633 */ 1634 public FileStatus[] listStatus(Path[] files) throws AccessControlException, 1635 FileNotFoundException, IOException { 1636 return listStatus(files, DEFAULT_FILTER); 1637 } 1638 1639 /** 1640 * Filter files/directories in the given path using the user-supplied path 1641 * filter. 1642 * 1643 * @param f is the path name 1644 * @param filter is the user-supplied path filter 1645 * 1646 * @return an array of FileStatus objects for the files under the given path 1647 * after applying the filter 1648 * 1649 * @throws AccessControlException If access is denied 1650 * @throws FileNotFoundException If <code>f</code> does not exist 1651 * @throws UnsupportedFileSystemException If file system for 1652 * <code>pathPattern</code> is not supported 1653 * @throws IOException If an I/O error occurred 1654 * 1655 * Exceptions applicable to file systems accessed over RPC: 1656 * @throws RpcClientException If an exception occurred in the RPC client 1657 * @throws RpcServerException If an exception occurred in the RPC server 1658 * @throws UnexpectedServerException If server implementation throws 1659 * undeclared exception to RPC server 1660 */ 1661 public FileStatus[] listStatus(Path f, PathFilter filter) 1662 throws AccessControlException, FileNotFoundException, 1663 UnsupportedFileSystemException, IOException { 1664 ArrayList<FileStatus> results = new ArrayList<FileStatus>(); 1665 listStatus(results, f, filter); 1666 return results.toArray(new FileStatus[results.size()]); 1667 } 1668 1669 /** 1670 * Filter files/directories in the given list of paths using user-supplied 1671 * path filter. 1672 * 1673 * @param files is a list of paths 1674 * @param filter is the filter 1675 * 1676 * @return a list of statuses for the files under the given paths after 1677 * applying the filter 1678 * 1679 * @throws AccessControlException If access is denied 1680 * @throws FileNotFoundException If a file in <code>files</code> does not 1681 * exist 1682 * @throws IOException If an I/O error occurred 1683 * 1684 * Exceptions applicable to file systems accessed over RPC: 1685 * @throws RpcClientException If an exception occurred in the RPC client 1686 * @throws RpcServerException If an exception occurred in the RPC server 1687 * @throws UnexpectedServerException If server implementation throws 1688 * undeclared exception to RPC server 1689 */ 1690 public FileStatus[] listStatus(Path[] files, PathFilter filter) 1691 throws AccessControlException, FileNotFoundException, IOException { 1692 ArrayList<FileStatus> results = new ArrayList<FileStatus>(); 1693 for (int i = 0; i < files.length; i++) { 1694 listStatus(results, files[i], filter); 1695 } 1696 return results.toArray(new FileStatus[results.size()]); 1697 } 1698 1699 /* 1700 * Filter files/directories in the given path using the user-supplied path 1701 * filter. Results are added to the given array <code>results</code>. 1702 */ 1703 private void listStatus(ArrayList<FileStatus> results, Path f, 1704 PathFilter filter) throws AccessControlException, 1705 FileNotFoundException, IOException { 1706 FileStatus[] listing = listStatus(f); 1707 if (listing != null) { 1708 for (int i = 0; i < listing.length; i++) { 1709 if (filter.accept(listing[i].getPath())) { 1710 results.add(listing[i]); 1711 } 1712 } 1713 } 1714 } 1715 1716 /** 1717 * List the statuses of the files/directories in the given path 1718 * if the path is a directory. 1719 * 1720 * @param f is the path 1721 * 1722 * @return an array that contains statuses of the files/directories 1723 * in the given path 1724 * 1725 * @throws AccessControlException If access is denied 1726 * @throws FileNotFoundException If <code>f</code> does not exist 1727 * @throws UnsupportedFileSystemException If file system for <code>f</code> is 1728 * not supported 1729 * @throws IOException If an I/O error occurred 1730 * 1731 * Exceptions applicable to file systems accessed over RPC: 1732 * @throws RpcClientException If an exception occurred in the RPC client 1733 * @throws RpcServerException If an exception occurred in the RPC server 1734 * @throws UnexpectedServerException If server implementation throws 1735 * undeclared exception to RPC server 1736 */ 1737 public FileStatus[] listStatus(final Path f) throws AccessControlException, 1738 FileNotFoundException, UnsupportedFileSystemException, 1739 IOException { 1740 final Path absF = fixRelativePart(f); 1741 return new FSLinkResolver<FileStatus[]>() { 1742 @Override 1743 public FileStatus[] next(final AbstractFileSystem fs, final Path p) 1744 throws IOException, UnresolvedLinkException { 1745 return fs.listStatus(p); 1746 } 1747 }.resolve(FileContext.this, absF); 1748 } 1749 1750 /** 1751 * List the statuses and block locations of the files in the given path. 1752 * 1753 * If the path is a directory, 1754 * if recursive is false, returns files in the directory; 1755 * if recursive is true, return files in the subtree rooted at the path. 1756 * The subtree is traversed in the depth-first order. 1757 * If the path is a file, return the file's status and block locations. 1758 * Files across symbolic links are also returned. 1759 * 1760 * @param f is the path 1761 * @param recursive if the subdirectories need to be traversed recursively 1762 * 1763 * @return an iterator that traverses statuses of the files 1764 * If any IO exception (for example a sub-directory gets deleted while 1765 * listing is being executed), next() or hasNext() of the returned iterator 1766 * may throw a RuntimeException with the IO exception as the cause. 1767 * 1768 * @throws AccessControlException If access is denied 1769 * @throws FileNotFoundException If <code>f</code> does not exist 1770 * @throws UnsupportedFileSystemException If file system for <code>f</code> 1771 * is not supported 1772 * @throws IOException If an I/O error occurred 1773 * 1774 * Exceptions applicable to file systems accessed over RPC: 1775 * @throws RpcClientException If an exception occurred in the RPC client 1776 * @throws RpcServerException If an exception occurred in the RPC server 1777 * @throws UnexpectedServerException If server implementation throws 1778 * undeclared exception to RPC server 1779 */ 1780 public RemoteIterator<LocatedFileStatus> listFiles( 1781 final Path f, final boolean recursive) throws AccessControlException, 1782 FileNotFoundException, UnsupportedFileSystemException, 1783 IOException { 1784 return new RemoteIterator<LocatedFileStatus>() { 1785 private Stack<RemoteIterator<LocatedFileStatus>> itors = 1786 new Stack<RemoteIterator<LocatedFileStatus>>(); 1787 RemoteIterator<LocatedFileStatus> curItor = listLocatedStatus(f); 1788 LocatedFileStatus curFile; 1789 1790 /** 1791 * Returns <tt>true</tt> if the iterator has more files. 1792 * 1793 * @return <tt>true</tt> if the iterator has more files. 1794 * @throws AccessControlException if not allowed to access next 1795 * file's status or locations 1796 * @throws FileNotFoundException if next file does not exist any more 1797 * @throws UnsupportedFileSystemException if next file's 1798 * fs is unsupported 1799 * @throws IOException for all other IO errors 1800 * for example, NameNode is not avaialbe or 1801 * NameNode throws IOException due to an error 1802 * while getting the status or block locations 1803 */ 1804 @Override 1805 public boolean hasNext() throws IOException { 1806 while (curFile == null) { 1807 if (curItor.hasNext()) { 1808 handleFileStat(curItor.next()); 1809 } else if (!itors.empty()) { 1810 curItor = itors.pop(); 1811 } else { 1812 return false; 1813 } 1814 } 1815 return true; 1816 } 1817 1818 /** 1819 * Process the input stat. 1820 * If it is a file, return the file stat. 1821 * If it is a directory, traverse the directory if recursive is true; 1822 * ignore it if recursive is false. 1823 * If it is a symlink, resolve the symlink first and then process it 1824 * depending on if it is a file or directory. 1825 * @param stat input status 1826 * @throws AccessControlException if access is denied 1827 * @throws FileNotFoundException if file is not found 1828 * @throws UnsupportedFileSystemException if fs is not supported 1829 * @throws IOException for all other IO errors 1830 */ 1831 private void handleFileStat(LocatedFileStatus stat) 1832 throws IOException { 1833 if (stat.isFile()) { // file 1834 curFile = stat; 1835 } else if (stat.isSymlink()) { // symbolic link 1836 // resolve symbolic link 1837 FileStatus symstat = FileContext.this.getFileStatus( 1838 stat.getSymlink()); 1839 if (symstat.isFile() || (recursive && symstat.isDirectory())) { 1840 itors.push(curItor); 1841 curItor = listLocatedStatus(stat.getPath()); 1842 } 1843 } else if (recursive) { // directory 1844 itors.push(curItor); 1845 curItor = listLocatedStatus(stat.getPath()); 1846 } 1847 } 1848 1849 /** 1850 * Returns the next file's status with its block locations 1851 * 1852 * @throws AccessControlException if not allowed to access next 1853 * file's status or locations 1854 * @throws FileNotFoundException if next file does not exist any more 1855 * @throws UnsupportedFileSystemException if next file's 1856 * fs is unsupported 1857 * @throws IOException for all other IO errors 1858 * for example, NameNode is not avaialbe or 1859 * NameNode throws IOException due to an error 1860 * while getting the status or block locations 1861 */ 1862 @Override 1863 public LocatedFileStatus next() throws IOException { 1864 if (hasNext()) { 1865 LocatedFileStatus result = curFile; 1866 curFile = null; 1867 return result; 1868 } 1869 throw new java.util.NoSuchElementException("No more entry in " + f); 1870 } 1871 }; 1872 } 1873 1874 /** 1875 * <p>Return all the files that match filePattern and are not checksum 1876 * files. Results are sorted by their names. 1877 * 1878 * <p> 1879 * A filename pattern is composed of <i>regular</i> characters and 1880 * <i>special pattern matching</i> characters, which are: 1881 * 1882 * <dl> 1883 * <dd> 1884 * <dl> 1885 * <p> 1886 * <dt> <tt> ? </tt> 1887 * <dd> Matches any single character. 1888 * 1889 * <p> 1890 * <dt> <tt> * </tt> 1891 * <dd> Matches zero or more characters. 1892 * 1893 * <p> 1894 * <dt> <tt> [<i>abc</i>] </tt> 1895 * <dd> Matches a single character from character set 1896 * <tt>{<i>a,b,c</i>}</tt>. 1897 * 1898 * <p> 1899 * <dt> <tt> [<i>a</i>-<i>b</i>] </tt> 1900 * <dd> Matches a single character from the character range 1901 * <tt>{<i>a...b</i>}</tt>. Note: character <tt><i>a</i></tt> must be 1902 * lexicographically less than or equal to character <tt><i>b</i></tt>. 1903 * 1904 * <p> 1905 * <dt> <tt> [^<i>a</i>] </tt> 1906 * <dd> Matches a single char that is not from character set or range 1907 * <tt>{<i>a</i>}</tt>. Note that the <tt>^</tt> character must occur 1908 * immediately to the right of the opening bracket. 1909 * 1910 * <p> 1911 * <dt> <tt> \<i>c</i> </tt> 1912 * <dd> Removes (escapes) any special meaning of character <i>c</i>. 1913 * 1914 * <p> 1915 * <dt> <tt> {ab,cd} </tt> 1916 * <dd> Matches a string from the string set <tt>{<i>ab, cd</i>} </tt> 1917 * 1918 * <p> 1919 * <dt> <tt> {ab,c{de,fh}} </tt> 1920 * <dd> Matches a string from string set <tt>{<i>ab, cde, cfh</i>}</tt> 1921 * 1922 * </dl> 1923 * </dd> 1924 * </dl> 1925 * 1926 * @param pathPattern a regular expression specifying a pth pattern 1927 * 1928 * @return an array of paths that match the path pattern 1929 * 1930 * @throws AccessControlException If access is denied 1931 * @throws UnsupportedFileSystemException If file system for 1932 * <code>pathPattern</code> is not supported 1933 * @throws IOException If an I/O error occurred 1934 * 1935 * Exceptions applicable to file systems accessed over RPC: 1936 * @throws RpcClientException If an exception occurred in the RPC client 1937 * @throws RpcServerException If an exception occurred in the RPC server 1938 * @throws UnexpectedServerException If server implementation throws 1939 * undeclared exception to RPC server 1940 */ 1941 public FileStatus[] globStatus(Path pathPattern) 1942 throws AccessControlException, UnsupportedFileSystemException, 1943 IOException { 1944 return new Globber(FileContext.this, pathPattern, DEFAULT_FILTER).glob(); 1945 } 1946 1947 /** 1948 * Return an array of FileStatus objects whose path names match pathPattern 1949 * and is accepted by the user-supplied path filter. Results are sorted by 1950 * their path names. 1951 * Return null if pathPattern has no glob and the path does not exist. 1952 * Return an empty array if pathPattern has a glob and no path matches it. 1953 * 1954 * @param pathPattern regular expression specifying the path pattern 1955 * @param filter user-supplied path filter 1956 * 1957 * @return an array of FileStatus objects 1958 * 1959 * @throws AccessControlException If access is denied 1960 * @throws UnsupportedFileSystemException If file system for 1961 * <code>pathPattern</code> is not supported 1962 * @throws IOException If an I/O error occurred 1963 * 1964 * Exceptions applicable to file systems accessed over RPC: 1965 * @throws RpcClientException If an exception occurred in the RPC client 1966 * @throws RpcServerException If an exception occurred in the RPC server 1967 * @throws UnexpectedServerException If server implementation throws 1968 * undeclared exception to RPC server 1969 */ 1970 public FileStatus[] globStatus(final Path pathPattern, 1971 final PathFilter filter) throws AccessControlException, 1972 UnsupportedFileSystemException, IOException { 1973 return new Globber(FileContext.this, pathPattern, filter).glob(); 1974 } 1975 1976 /** 1977 * Copy file from src to dest. See 1978 * {@link #copy(Path, Path, boolean, boolean)} 1979 */ 1980 public boolean copy(final Path src, final Path dst) 1981 throws AccessControlException, FileAlreadyExistsException, 1982 FileNotFoundException, ParentNotDirectoryException, 1983 UnsupportedFileSystemException, IOException { 1984 return copy(src, dst, false, false); 1985 } 1986 1987 /** 1988 * Copy from src to dst, optionally deleting src and overwriting dst. 1989 * @param src 1990 * @param dst 1991 * @param deleteSource - delete src if true 1992 * @param overwrite overwrite dst if true; throw IOException if dst exists 1993 * and overwrite is false. 1994 * 1995 * @return true if copy is successful 1996 * 1997 * @throws AccessControlException If access is denied 1998 * @throws FileAlreadyExistsException If <code>dst</code> already exists 1999 * @throws FileNotFoundException If <code>src</code> does not exist 2000 * @throws ParentNotDirectoryException If parent of <code>dst</code> is not 2001 * a directory 2002 * @throws UnsupportedFileSystemException If file system for 2003 * <code>src</code> or <code>dst</code> is not supported 2004 * @throws IOException If an I/O error occurred 2005 * 2006 * Exceptions applicable to file systems accessed over RPC: 2007 * @throws RpcClientException If an exception occurred in the RPC client 2008 * @throws RpcServerException If an exception occurred in the RPC server 2009 * @throws UnexpectedServerException If server implementation throws 2010 * undeclared exception to RPC server 2011 * 2012 * RuntimeExceptions: 2013 * @throws InvalidPathException If path <code>dst</code> is invalid 2014 */ 2015 public boolean copy(final Path src, final Path dst, boolean deleteSource, 2016 boolean overwrite) throws AccessControlException, 2017 FileAlreadyExistsException, FileNotFoundException, 2018 ParentNotDirectoryException, UnsupportedFileSystemException, 2019 IOException { 2020 src.checkNotSchemeWithRelative(); 2021 dst.checkNotSchemeWithRelative(); 2022 Path qSrc = makeQualified(src); 2023 Path qDst = makeQualified(dst); 2024 checkDest(qSrc.getName(), qDst, overwrite); 2025 FileStatus fs = FileContext.this.getFileStatus(qSrc); 2026 if (fs.isDirectory()) { 2027 checkDependencies(qSrc, qDst); 2028 mkdir(qDst, FsPermission.getDirDefault(), true); 2029 FileStatus[] contents = listStatus(qSrc); 2030 for (FileStatus content : contents) { 2031 copy(makeQualified(content.getPath()), makeQualified(new Path(qDst, 2032 content.getPath().getName())), deleteSource, overwrite); 2033 } 2034 } else { 2035 InputStream in=null; 2036 OutputStream out = null; 2037 try { 2038 in = open(qSrc); 2039 EnumSet<CreateFlag> createFlag = overwrite ? EnumSet.of( 2040 CreateFlag.CREATE, CreateFlag.OVERWRITE) : 2041 EnumSet.of(CreateFlag.CREATE); 2042 out = create(qDst, createFlag); 2043 IOUtils.copyBytes(in, out, conf, true); 2044 } finally { 2045 IOUtils.closeStream(out); 2046 IOUtils.closeStream(in); 2047 } 2048 } 2049 if (deleteSource) { 2050 return delete(qSrc, true); 2051 } else { 2052 return true; 2053 } 2054 } 2055 } 2056 2057 /** 2058 * Check if copying srcName to dst would overwrite an existing 2059 * file or directory. 2060 * @param srcName File or directory to be copied. 2061 * @param dst Destination to copy srcName to. 2062 * @param overwrite Whether it's ok to overwrite an existing file. 2063 * @throws AccessControlException If access is denied. 2064 * @throws IOException If dst is an existing directory, or dst is an 2065 * existing file and the overwrite option is not passed. 2066 */ 2067 private void checkDest(String srcName, Path dst, boolean overwrite) 2068 throws AccessControlException, IOException { 2069 try { 2070 FileStatus dstFs = getFileStatus(dst); 2071 if (dstFs.isDirectory()) { 2072 if (null == srcName) { 2073 throw new IOException("Target " + dst + " is a directory"); 2074 } 2075 // Recurse to check if dst/srcName exists. 2076 checkDest(null, new Path(dst, srcName), overwrite); 2077 } else if (!overwrite) { 2078 throw new IOException("Target " + new Path(dst, srcName) 2079 + " already exists"); 2080 } 2081 } catch (FileNotFoundException e) { 2082 // dst does not exist - OK to copy. 2083 } 2084 } 2085 2086 // 2087 // If the destination is a subdirectory of the source, then 2088 // generate exception 2089 // 2090 private static void checkDependencies(Path qualSrc, Path qualDst) 2091 throws IOException { 2092 if (isSameFS(qualSrc, qualDst)) { 2093 String srcq = qualSrc.toString() + Path.SEPARATOR; 2094 String dstq = qualDst.toString() + Path.SEPARATOR; 2095 if (dstq.startsWith(srcq)) { 2096 if (srcq.length() == dstq.length()) { 2097 throw new IOException("Cannot copy " + qualSrc + " to itself."); 2098 } else { 2099 throw new IOException("Cannot copy " + qualSrc + 2100 " to its subdirectory " + qualDst); 2101 } 2102 } 2103 } 2104 } 2105 2106 /** 2107 * Are qualSrc and qualDst of the same file system? 2108 * @param qualPath1 - fully qualified path 2109 * @param qualPath2 - fully qualified path 2110 * @return 2111 */ 2112 private static boolean isSameFS(Path qualPath1, Path qualPath2) { 2113 URI srcUri = qualPath1.toUri(); 2114 URI dstUri = qualPath2.toUri(); 2115 return (srcUri.getScheme().equals(dstUri.getScheme()) && 2116 !(srcUri.getAuthority() != null && dstUri.getAuthority() != null && srcUri 2117 .getAuthority().equals(dstUri.getAuthority()))); 2118 } 2119 2120 /** 2121 * Deletes all the paths in deleteOnExit on JVM shutdown. 2122 */ 2123 static class FileContextFinalizer implements Runnable { 2124 @Override 2125 public synchronized void run() { 2126 processDeleteOnExit(); 2127 } 2128 } 2129 2130 /** 2131 * Resolves all symbolic links in the specified path. 2132 * Returns the new path object. 2133 */ 2134 protected Path resolve(final Path f) throws FileNotFoundException, 2135 UnresolvedLinkException, AccessControlException, IOException { 2136 return new FSLinkResolver<Path>() { 2137 @Override 2138 public Path next(final AbstractFileSystem fs, final Path p) 2139 throws IOException, UnresolvedLinkException { 2140 return fs.resolvePath(p); 2141 } 2142 }.resolve(this, f); 2143 } 2144 2145 /** 2146 * Resolves all symbolic links in the specified path leading up 2147 * to, but not including the final path component. 2148 * @param f path to resolve 2149 * @return the new path object. 2150 */ 2151 protected Path resolveIntermediate(final Path f) throws IOException { 2152 return new FSLinkResolver<FileStatus>() { 2153 @Override 2154 public FileStatus next(final AbstractFileSystem fs, final Path p) 2155 throws IOException, UnresolvedLinkException { 2156 return fs.getFileLinkStatus(p); 2157 } 2158 }.resolve(this, f).getPath(); 2159 } 2160 2161 /** 2162 * Returns the list of AbstractFileSystems accessed in the path. The list may 2163 * contain more than one AbstractFileSystems objects in case of symlinks. 2164 * 2165 * @param f 2166 * Path which needs to be resolved 2167 * @return List of AbstractFileSystems accessed in the path 2168 * @throws IOException 2169 */ 2170 Set<AbstractFileSystem> resolveAbstractFileSystems(final Path f) 2171 throws IOException { 2172 final Path absF = fixRelativePart(f); 2173 final HashSet<AbstractFileSystem> result 2174 = new HashSet<AbstractFileSystem>(); 2175 new FSLinkResolver<Void>() { 2176 @Override 2177 public Void next(final AbstractFileSystem fs, final Path p) 2178 throws IOException, UnresolvedLinkException { 2179 result.add(fs); 2180 fs.getFileStatus(p); 2181 return null; 2182 } 2183 }.resolve(this, absF); 2184 return result; 2185 } 2186 2187 /** 2188 * Get the statistics for a particular file system 2189 * 2190 * @param uri 2191 * the uri to lookup the statistics. Only scheme and authority part 2192 * of the uri are used as the key to store and lookup. 2193 * @return a statistics object 2194 */ 2195 public static Statistics getStatistics(URI uri) { 2196 return AbstractFileSystem.getStatistics(uri); 2197 } 2198 2199 /** 2200 * Clears all the statistics stored in AbstractFileSystem, for all the file 2201 * systems. 2202 */ 2203 public static void clearStatistics() { 2204 AbstractFileSystem.clearStatistics(); 2205 } 2206 2207 /** 2208 * Prints the statistics to standard output. File System is identified by the 2209 * scheme and authority. 2210 */ 2211 public static void printStatistics() { 2212 AbstractFileSystem.printStatistics(); 2213 } 2214 2215 /** 2216 * @return Map of uri and statistics for each filesystem instantiated. The uri 2217 * consists of scheme and authority for the filesystem. 2218 */ 2219 public static Map<URI, Statistics> getAllStatistics() { 2220 return AbstractFileSystem.getAllStatistics(); 2221 } 2222 2223 /** 2224 * Get delegation tokens for the file systems accessed for a given 2225 * path. 2226 * @param p Path for which delegations tokens are requested. 2227 * @param renewer the account name that is allowed to renew the token. 2228 * @return List of delegation tokens. 2229 * @throws IOException 2230 */ 2231 @InterfaceAudience.LimitedPrivate( { "HDFS", "MapReduce" }) 2232 public List<Token<?>> getDelegationTokens( 2233 Path p, String renewer) throws IOException { 2234 Set<AbstractFileSystem> afsSet = resolveAbstractFileSystems(p); 2235 List<Token<?>> tokenList = 2236 new ArrayList<Token<?>>(); 2237 for (AbstractFileSystem afs : afsSet) { 2238 List<Token<?>> afsTokens = afs.getDelegationTokens(renewer); 2239 tokenList.addAll(afsTokens); 2240 } 2241 return tokenList; 2242 } 2243 2244 /** 2245 * Modifies ACL entries of files and directories. This method can add new ACL 2246 * entries or modify the permissions on existing ACL entries. All existing 2247 * ACL entries that are not specified in this call are retained without 2248 * changes. (Modifications are merged into the current ACL.) 2249 * 2250 * @param path Path to modify 2251 * @param aclSpec List<AclEntry> describing modifications 2252 * @throws IOException if an ACL could not be modified 2253 */ 2254 public void modifyAclEntries(final Path path, final List<AclEntry> aclSpec) 2255 throws IOException { 2256 Path absF = fixRelativePart(path); 2257 new FSLinkResolver<Void>() { 2258 @Override 2259 public Void next(final AbstractFileSystem fs, final Path p) 2260 throws IOException { 2261 fs.modifyAclEntries(p, aclSpec); 2262 return null; 2263 } 2264 }.resolve(this, absF); 2265 } 2266 2267 /** 2268 * Removes ACL entries from files and directories. Other ACL entries are 2269 * retained. 2270 * 2271 * @param path Path to modify 2272 * @param aclSpec List<AclEntry> describing entries to remove 2273 * @throws IOException if an ACL could not be modified 2274 */ 2275 public void removeAclEntries(final Path path, final List<AclEntry> aclSpec) 2276 throws IOException { 2277 Path absF = fixRelativePart(path); 2278 new FSLinkResolver<Void>() { 2279 @Override 2280 public Void next(final AbstractFileSystem fs, final Path p) 2281 throws IOException { 2282 fs.removeAclEntries(p, aclSpec); 2283 return null; 2284 } 2285 }.resolve(this, absF); 2286 } 2287 2288 /** 2289 * Removes all default ACL entries from files and directories. 2290 * 2291 * @param path Path to modify 2292 * @throws IOException if an ACL could not be modified 2293 */ 2294 public void removeDefaultAcl(Path path) 2295 throws IOException { 2296 Path absF = fixRelativePart(path); 2297 new FSLinkResolver<Void>() { 2298 @Override 2299 public Void next(final AbstractFileSystem fs, final Path p) 2300 throws IOException { 2301 fs.removeDefaultAcl(p); 2302 return null; 2303 } 2304 }.resolve(this, absF); 2305 } 2306 2307 /** 2308 * Removes all but the base ACL entries of files and directories. The entries 2309 * for user, group, and others are retained for compatibility with permission 2310 * bits. 2311 * 2312 * @param path Path to modify 2313 * @throws IOException if an ACL could not be removed 2314 */ 2315 public void removeAcl(Path path) throws IOException { 2316 Path absF = fixRelativePart(path); 2317 new FSLinkResolver<Void>() { 2318 @Override 2319 public Void next(final AbstractFileSystem fs, final Path p) 2320 throws IOException { 2321 fs.removeAcl(p); 2322 return null; 2323 } 2324 }.resolve(this, absF); 2325 } 2326 2327 /** 2328 * Fully replaces ACL of files and directories, discarding all existing 2329 * entries. 2330 * 2331 * @param path Path to modify 2332 * @param aclSpec List<AclEntry> describing modifications, must include entries 2333 * for user, group, and others for compatibility with permission bits. 2334 * @throws IOException if an ACL could not be modified 2335 */ 2336 public void setAcl(Path path, final List<AclEntry> aclSpec) 2337 throws IOException { 2338 Path absF = fixRelativePart(path); 2339 new FSLinkResolver<Void>() { 2340 @Override 2341 public Void next(final AbstractFileSystem fs, final Path p) 2342 throws IOException { 2343 fs.setAcl(p, aclSpec); 2344 return null; 2345 } 2346 }.resolve(this, absF); 2347 } 2348 2349 /** 2350 * Gets the ACLs of files and directories. 2351 * 2352 * @param path Path to get 2353 * @return RemoteIterator<AclStatus> which returns each AclStatus 2354 * @throws IOException if an ACL could not be read 2355 */ 2356 public AclStatus getAclStatus(Path path) throws IOException { 2357 Path absF = fixRelativePart(path); 2358 return new FSLinkResolver<AclStatus>() { 2359 @Override 2360 public AclStatus next(final AbstractFileSystem fs, final Path p) 2361 throws IOException { 2362 return fs.getAclStatus(p); 2363 } 2364 }.resolve(this, absF); 2365 } 2366 2367 /** 2368 * Set an xattr of a file or directory. 2369 * The name must be prefixed with the namespace followed by ".". For example, 2370 * "user.attr". 2371 * <p/> 2372 * Refer to the HDFS extended attributes user documentation for details. 2373 * 2374 * @param path Path to modify 2375 * @param name xattr name. 2376 * @param value xattr value. 2377 * @throws IOException 2378 */ 2379 public void setXAttr(Path path, String name, byte[] value) 2380 throws IOException { 2381 setXAttr(path, name, value, EnumSet.of(XAttrSetFlag.CREATE, 2382 XAttrSetFlag.REPLACE)); 2383 } 2384 2385 /** 2386 * Set an xattr of a file or directory. 2387 * The name must be prefixed with the namespace followed by ".". For example, 2388 * "user.attr". 2389 * <p/> 2390 * Refer to the HDFS extended attributes user documentation for details. 2391 * 2392 * @param path Path to modify 2393 * @param name xattr name. 2394 * @param value xattr value. 2395 * @param flag xattr set flag 2396 * @throws IOException 2397 */ 2398 public void setXAttr(Path path, final String name, final byte[] value, 2399 final EnumSet<XAttrSetFlag> flag) throws IOException { 2400 final Path absF = fixRelativePart(path); 2401 new FSLinkResolver<Void>() { 2402 @Override 2403 public Void next(final AbstractFileSystem fs, final Path p) 2404 throws IOException { 2405 fs.setXAttr(p, name, value, flag); 2406 return null; 2407 } 2408 }.resolve(this, absF); 2409 } 2410 2411 /** 2412 * Get an xattr for a file or directory. 2413 * The name must be prefixed with the namespace followed by ".". For example, 2414 * "user.attr". 2415 * <p/> 2416 * Refer to the HDFS extended attributes user documentation for details. 2417 * 2418 * @param path Path to get extended attribute 2419 * @param name xattr name. 2420 * @return byte[] xattr value. 2421 * @throws IOException 2422 */ 2423 public byte[] getXAttr(Path path, final String name) throws IOException { 2424 final Path absF = fixRelativePart(path); 2425 return new FSLinkResolver<byte[]>() { 2426 @Override 2427 public byte[] next(final AbstractFileSystem fs, final Path p) 2428 throws IOException { 2429 return fs.getXAttr(p, name); 2430 } 2431 }.resolve(this, absF); 2432 } 2433 2434 /** 2435 * Get all of the xattrs for a file or directory. 2436 * Only those xattrs for which the logged-in user has permissions to view 2437 * are returned. 2438 * <p/> 2439 * Refer to the HDFS extended attributes user documentation for details. 2440 * 2441 * @param path Path to get extended attributes 2442 * @return Map<String, byte[]> describing the XAttrs of the file or directory 2443 * @throws IOException 2444 */ 2445 public Map<String, byte[]> getXAttrs(Path path) throws IOException { 2446 final Path absF = fixRelativePart(path); 2447 return new FSLinkResolver<Map<String, byte[]>>() { 2448 @Override 2449 public Map<String, byte[]> next(final AbstractFileSystem fs, final Path p) 2450 throws IOException { 2451 return fs.getXAttrs(p); 2452 } 2453 }.resolve(this, absF); 2454 } 2455 2456 /** 2457 * Get all of the xattrs for a file or directory. 2458 * Only those xattrs for which the logged-in user has permissions to view 2459 * are returned. 2460 * <p/> 2461 * Refer to the HDFS extended attributes user documentation for details. 2462 * 2463 * @param path Path to get extended attributes 2464 * @param names XAttr names. 2465 * @return Map<String, byte[]> describing the XAttrs of the file or directory 2466 * @throws IOException 2467 */ 2468 public Map<String, byte[]> getXAttrs(Path path, final List<String> names) 2469 throws IOException { 2470 final Path absF = fixRelativePart(path); 2471 return new FSLinkResolver<Map<String, byte[]>>() { 2472 @Override 2473 public Map<String, byte[]> next(final AbstractFileSystem fs, final Path p) 2474 throws IOException { 2475 return fs.getXAttrs(p, names); 2476 } 2477 }.resolve(this, absF); 2478 } 2479 2480 /** 2481 * Remove an xattr of a file or directory. 2482 * The name must be prefixed with the namespace followed by ".". For example, 2483 * "user.attr". 2484 * <p/> 2485 * Refer to the HDFS extended attributes user documentation for details. 2486 * 2487 * @param path Path to remove extended attribute 2488 * @param name xattr name 2489 * @throws IOException 2490 */ 2491 public void removeXAttr(Path path, final String name) throws IOException { 2492 final Path absF = fixRelativePart(path); 2493 new FSLinkResolver<Void>() { 2494 @Override 2495 public Void next(final AbstractFileSystem fs, final Path p) 2496 throws IOException { 2497 fs.removeXAttr(p, name); 2498 return null; 2499 } 2500 }.resolve(this, absF); 2501 } 2502 2503 /** 2504 * Get all of the xattr names for a file or directory. 2505 * Only those xattr names which the logged-in user has permissions to view 2506 * are returned. 2507 * <p/> 2508 * Refer to the HDFS extended attributes user documentation for details. 2509 * 2510 * @param path Path to get extended attributes 2511 * @return List<String> of the XAttr names of the file or directory 2512 * @throws IOException 2513 */ 2514 public List<String> listXAttrs(Path path) throws IOException { 2515 final Path absF = fixRelativePart(path); 2516 return new FSLinkResolver<List<String>>() { 2517 @Override 2518 public List<String> next(final AbstractFileSystem fs, final Path p) 2519 throws IOException { 2520 return fs.listXAttrs(p); 2521 } 2522 }.resolve(this, absF); 2523 } 2524 2525 Tracer getTracer() { 2526 return tracer; 2527 } 2528}