001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.hadoop.fs.viewfs; 019 020 import static org.apache.hadoop.fs.viewfs.Constants.PERMISSION_RRR; 021 022 import java.io.FileNotFoundException; 023 import java.io.IOException; 024 import java.net.URI; 025 import java.net.URISyntaxException; 026 import java.util.ArrayList; 027 import java.util.HashSet; 028 import java.util.List; 029 import java.util.Set; 030 import java.util.StringTokenizer; 031 import java.util.Map.Entry; 032 033 import org.apache.hadoop.classification.InterfaceAudience; 034 import org.apache.hadoop.classification.InterfaceStability; 035 import org.apache.hadoop.conf.Configuration; 036 import org.apache.hadoop.fs.BlockLocation; 037 import org.apache.hadoop.fs.ContentSummary; 038 import org.apache.hadoop.fs.FSDataInputStream; 039 import org.apache.hadoop.fs.FSDataOutputStream; 040 import org.apache.hadoop.fs.FileAlreadyExistsException; 041 import org.apache.hadoop.fs.FileChecksum; 042 import org.apache.hadoop.fs.FileStatus; 043 import org.apache.hadoop.fs.FileSystem; 044 import org.apache.hadoop.fs.FsConstants; 045 import org.apache.hadoop.fs.FsServerDefaults; 046 import org.apache.hadoop.fs.InvalidPathException; 047 import org.apache.hadoop.fs.Path; 048 import org.apache.hadoop.fs.UnsupportedFileSystemException; 049 import org.apache.hadoop.fs.permission.FsPermission; 050 import org.apache.hadoop.fs.viewfs.InodeTree.INode; 051 import org.apache.hadoop.fs.viewfs.InodeTree.INodeLink; 052 import org.apache.hadoop.io.Text; 053 import org.apache.hadoop.security.AccessControlException; 054 import org.apache.hadoop.security.Credentials; 055 import org.apache.hadoop.security.UserGroupInformation; 056 import org.apache.hadoop.security.token.Token; 057 import org.apache.hadoop.util.Progressable; 058 import org.apache.hadoop.util.Time; 059 060 /** 061 * ViewFileSystem (extends the FileSystem interface) implements a client-side 062 * mount table. Its spec and implementation is identical to {@link ViewFs}. 063 */ 064 065 @InterfaceAudience.Public 066 @InterfaceStability.Evolving /*Evolving for a release,to be changed to Stable */ 067 public class ViewFileSystem extends FileSystem { 068 static AccessControlException readOnlyMountTable(final String operation, 069 final String p) { 070 return new AccessControlException( 071 "InternalDir of ViewFileSystem is readonly; operation=" + operation + 072 "Path=" + p); 073 } 074 static AccessControlException readOnlyMountTable(final String operation, 075 final Path p) { 076 return readOnlyMountTable(operation, p.toString()); 077 } 078 079 static public class MountPoint { 080 private Path src; // the src of the mount 081 private URI[] targets; // target of the mount; Multiple targets imply mergeMount 082 MountPoint(Path srcPath, URI[] targetURIs) { 083 src = srcPath; 084 targets = targetURIs; 085 } 086 Path getSrc() { 087 return src; 088 } 089 URI[] getTargets() { 090 return targets; 091 } 092 } 093 094 final long creationTime; // of the the mount table 095 final UserGroupInformation ugi; // the user/group of user who created mtable 096 URI myUri; 097 private Path workingDir; 098 Configuration config; 099 InodeTree<FileSystem> fsState; // the fs state; ie the mount table 100 Path homeDir = null; 101 102 /** 103 * Prohibits names which contain a ".", "..", ":" or "/" 104 */ 105 private static boolean isValidName(final String src) { 106 // Check for ".." "." ":" "/" 107 final StringTokenizer tokens = new StringTokenizer(src, Path.SEPARATOR); 108 while(tokens.hasMoreTokens()) { 109 String element = tokens.nextToken(); 110 if (element.equals("..") || 111 element.equals(".") || 112 (element.indexOf(":") >= 0)) { 113 return false; 114 } 115 } 116 return true; 117 } 118 119 /** 120 * Make the path Absolute and get the path-part of a pathname. 121 * Checks that URI matches this file system 122 * and that the path-part is a valid name. 123 * 124 * @param p path 125 * @return path-part of the Path p 126 */ 127 private String getUriPath(final Path p) { 128 checkPath(p); 129 String s = makeAbsolute(p).toUri().getPath(); 130 if (!isValidName(s)) { 131 throw new InvalidPathException("Path part " + s + " from URI" + p 132 + " is not a valid filename."); 133 } 134 return s; 135 } 136 137 private Path makeAbsolute(final Path f) { 138 return f.isAbsolute() ? f : new Path(workingDir, f); 139 } 140 141 /** 142 * This is the constructor with the signature needed by 143 * {@link FileSystem#createFileSystem(URI, Configuration)} 144 * 145 * After this constructor is called initialize() is called. 146 * @throws IOException 147 */ 148 public ViewFileSystem() throws IOException { 149 ugi = UserGroupInformation.getCurrentUser(); 150 creationTime = Time.now(); 151 } 152 153 /** 154 * Return the protocol scheme for the FileSystem. 155 * <p/> 156 * 157 * @return <code>viewfs</code> 158 */ 159 @Override 160 public String getScheme() { 161 return "viewfs"; 162 } 163 164 /** 165 * Called after a new FileSystem instance is constructed. 166 * @param theUri a uri whose authority section names the host, port, etc. for 167 * this FileSystem 168 * @param conf the configuration 169 */ 170 public void initialize(final URI theUri, final Configuration conf) 171 throws IOException { 172 super.initialize(theUri, conf); 173 setConf(conf); 174 config = conf; 175 // Now build client side view (i.e. client side mount table) from config. 176 final String authority = theUri.getAuthority(); 177 try { 178 myUri = new URI(FsConstants.VIEWFS_SCHEME, authority, "/", null, null); 179 fsState = new InodeTree<FileSystem>(conf, authority) { 180 181 @Override 182 protected 183 FileSystem getTargetFileSystem(final URI uri) 184 throws URISyntaxException, IOException { 185 return new ChRootedFileSystem(uri, config); 186 } 187 188 @Override 189 protected 190 FileSystem getTargetFileSystem(final INodeDir<FileSystem> dir) 191 throws URISyntaxException { 192 return new InternalDirOfViewFs(dir, creationTime, ugi, myUri); 193 } 194 195 @Override 196 protected 197 FileSystem getTargetFileSystem(URI[] mergeFsURIList) 198 throws URISyntaxException, UnsupportedFileSystemException { 199 throw new UnsupportedFileSystemException("mergefs not implemented"); 200 // return MergeFs.createMergeFs(mergeFsURIList, config); 201 } 202 }; 203 workingDir = this.getHomeDirectory(); 204 } catch (URISyntaxException e) { 205 throw new IOException("URISyntax exception: " + theUri); 206 } 207 208 } 209 210 211 /** 212 * Convenience Constructor for apps to call directly 213 * @param theUri which must be that of ViewFileSystem 214 * @param conf 215 * @throws IOException 216 */ 217 ViewFileSystem(final URI theUri, final Configuration conf) 218 throws IOException { 219 this(); 220 initialize(theUri, conf); 221 } 222 223 /** 224 * Convenience Constructor for apps to call directly 225 * @param conf 226 * @throws IOException 227 */ 228 public ViewFileSystem(final Configuration conf) throws IOException { 229 this(FsConstants.VIEWFS_URI, conf); 230 } 231 232 public Path getTrashCanLocation(final Path f) throws FileNotFoundException { 233 final InodeTree.ResolveResult<FileSystem> res = 234 fsState.resolve(getUriPath(f), true); 235 return res.isInternalDir() ? null : res.targetFileSystem.getHomeDirectory(); 236 } 237 238 @Override 239 public String getCanonicalServiceName() { 240 return null; 241 } 242 243 @Override 244 public URI getUri() { 245 return myUri; 246 } 247 248 @Override 249 public Path resolvePath(final Path f) 250 throws IOException { 251 final InodeTree.ResolveResult<FileSystem> res; 252 res = fsState.resolve(getUriPath(f), true); 253 if (res.isInternalDir()) { 254 return f; 255 } 256 return res.targetFileSystem.resolvePath(res.remainingPath); 257 } 258 259 @Override 260 public Path getHomeDirectory() { 261 if (homeDir == null) { 262 String base = fsState.getHomeDirPrefixValue(); 263 if (base == null) { 264 base = "/user"; 265 } 266 homeDir = 267 this.makeQualified(new Path(base + "/" + ugi.getShortUserName())); 268 } 269 return homeDir; 270 } 271 272 @Override 273 public Path getWorkingDirectory() { 274 return workingDir; 275 } 276 277 @Override 278 public void setWorkingDirectory(final Path new_dir) { 279 getUriPath(new_dir); // this validates the path 280 workingDir = makeAbsolute(new_dir); 281 } 282 283 @Override 284 public FSDataOutputStream append(final Path f, final int bufferSize, 285 final Progressable progress) throws IOException { 286 InodeTree.ResolveResult<FileSystem> res = 287 fsState.resolve(getUriPath(f), true); 288 return res.targetFileSystem.append(res.remainingPath, bufferSize, progress); 289 } 290 291 @Override 292 public FSDataOutputStream create(final Path f, final FsPermission permission, 293 final boolean overwrite, final int bufferSize, final short replication, 294 final long blockSize, final Progressable progress) throws IOException { 295 InodeTree.ResolveResult<FileSystem> res; 296 try { 297 res = fsState.resolve(getUriPath(f), false); 298 } catch (FileNotFoundException e) { 299 throw readOnlyMountTable("create", f); 300 } 301 assert(res.remainingPath != null); 302 return res.targetFileSystem.create(res.remainingPath, permission, 303 overwrite, bufferSize, replication, blockSize, progress); 304 } 305 306 307 @Override 308 public boolean delete(final Path f, final boolean recursive) 309 throws AccessControlException, FileNotFoundException, 310 IOException { 311 InodeTree.ResolveResult<FileSystem> res = 312 fsState.resolve(getUriPath(f), true); 313 // If internal dir or target is a mount link (ie remainingPath is Slash) 314 if (res.isInternalDir() || res.remainingPath == InodeTree.SlashPath) { 315 throw readOnlyMountTable("delete", f); 316 } 317 return res.targetFileSystem.delete(res.remainingPath, recursive); 318 } 319 320 @Override 321 @SuppressWarnings("deprecation") 322 public boolean delete(final Path f) 323 throws AccessControlException, FileNotFoundException, 324 IOException { 325 return delete(f, true); 326 } 327 328 @Override 329 public BlockLocation[] getFileBlockLocations(FileStatus fs, 330 long start, long len) throws IOException { 331 final InodeTree.ResolveResult<FileSystem> res = 332 fsState.resolve(getUriPath(fs.getPath()), true); 333 return res.targetFileSystem.getFileBlockLocations( 334 new ViewFsFileStatus(fs, res.remainingPath), start, len); 335 } 336 337 @Override 338 public FileChecksum getFileChecksum(final Path f) 339 throws AccessControlException, FileNotFoundException, 340 IOException { 341 InodeTree.ResolveResult<FileSystem> res = 342 fsState.resolve(getUriPath(f), true); 343 return res.targetFileSystem.getFileChecksum(res.remainingPath); 344 } 345 346 @Override 347 public FileStatus getFileStatus(final Path f) throws AccessControlException, 348 FileNotFoundException, IOException { 349 InodeTree.ResolveResult<FileSystem> res = 350 fsState.resolve(getUriPath(f), true); 351 352 // FileStatus#getPath is a fully qualified path relative to the root of 353 // target file system. 354 // We need to change it to viewfs URI - relative to root of mount table. 355 356 // The implementors of RawLocalFileSystem were trying to be very smart. 357 // They implement FileStatus#getOwener lazily -- the object 358 // returned is really a RawLocalFileSystem that expect the 359 // FileStatus#getPath to be unchanged so that it can get owner when needed. 360 // Hence we need to interpose a new ViewFileSystemFileStatus that 361 // works around. 362 FileStatus status = res.targetFileSystem.getFileStatus(res.remainingPath); 363 return new ViewFsFileStatus(status, this.makeQualified(f)); 364 } 365 366 367 @Override 368 public FileStatus[] listStatus(final Path f) throws AccessControlException, 369 FileNotFoundException, IOException { 370 InodeTree.ResolveResult<FileSystem> res = 371 fsState.resolve(getUriPath(f), true); 372 373 FileStatus[] statusLst = res.targetFileSystem.listStatus(res.remainingPath); 374 if (!res.isInternalDir()) { 375 // We need to change the name in the FileStatus as described in 376 // {@link #getFileStatus } 377 ChRootedFileSystem targetFs; 378 targetFs = (ChRootedFileSystem) res.targetFileSystem; 379 int i = 0; 380 for (FileStatus status : statusLst) { 381 String suffix = targetFs.stripOutRoot(status.getPath()); 382 statusLst[i++] = new ViewFsFileStatus(status, this.makeQualified( 383 suffix.length() == 0 ? f : new Path(res.resolvedPath, suffix))); 384 } 385 } 386 return statusLst; 387 } 388 389 @Override 390 public boolean mkdirs(final Path dir, final FsPermission permission) 391 throws IOException { 392 InodeTree.ResolveResult<FileSystem> res = 393 fsState.resolve(getUriPath(dir), false); 394 return res.targetFileSystem.mkdirs(res.remainingPath, permission); 395 } 396 397 @Override 398 public FSDataInputStream open(final Path f, final int bufferSize) 399 throws AccessControlException, FileNotFoundException, 400 IOException { 401 InodeTree.ResolveResult<FileSystem> res = 402 fsState.resolve(getUriPath(f), true); 403 return res.targetFileSystem.open(res.remainingPath, bufferSize); 404 } 405 406 407 @Override 408 public boolean rename(final Path src, final Path dst) throws IOException { 409 // passing resolveLastComponet as false to catch renaming a mount point to 410 // itself. We need to catch this as an internal operation and fail. 411 InodeTree.ResolveResult<FileSystem> resSrc = 412 fsState.resolve(getUriPath(src), false); 413 414 if (resSrc.isInternalDir()) { 415 throw readOnlyMountTable("rename", src); 416 } 417 418 InodeTree.ResolveResult<FileSystem> resDst = 419 fsState.resolve(getUriPath(dst), false); 420 if (resDst.isInternalDir()) { 421 throw readOnlyMountTable("rename", dst); 422 } 423 /** 424 // Alternate 1: renames within same file system - valid but we disallow 425 // Alternate 2: (as described in next para - valid but we have disallowed it 426 // 427 // Note we compare the URIs. the URIs include the link targets. 428 // hence we allow renames across mount links as long as the mount links 429 // point to the same target. 430 if (!resSrc.targetFileSystem.getUri().equals( 431 resDst.targetFileSystem.getUri())) { 432 throw new IOException("Renames across Mount points not supported"); 433 } 434 */ 435 436 // 437 // Alternate 3 : renames ONLY within the the same mount links. 438 // 439 if (resSrc.targetFileSystem !=resDst.targetFileSystem) { 440 throw new IOException("Renames across Mount points not supported"); 441 } 442 return resSrc.targetFileSystem.rename(resSrc.remainingPath, 443 resDst.remainingPath); 444 } 445 446 @Override 447 public void setOwner(final Path f, final String username, 448 final String groupname) throws AccessControlException, 449 FileNotFoundException, 450 IOException { 451 InodeTree.ResolveResult<FileSystem> res = 452 fsState.resolve(getUriPath(f), true); 453 res.targetFileSystem.setOwner(res.remainingPath, username, groupname); 454 } 455 456 @Override 457 public void setPermission(final Path f, final FsPermission permission) 458 throws AccessControlException, FileNotFoundException, 459 IOException { 460 InodeTree.ResolveResult<FileSystem> res = 461 fsState.resolve(getUriPath(f), true); 462 res.targetFileSystem.setPermission(res.remainingPath, permission); 463 } 464 465 @Override 466 public boolean setReplication(final Path f, final short replication) 467 throws AccessControlException, FileNotFoundException, 468 IOException { 469 InodeTree.ResolveResult<FileSystem> res = 470 fsState.resolve(getUriPath(f), true); 471 return res.targetFileSystem.setReplication(res.remainingPath, replication); 472 } 473 474 @Override 475 public void setTimes(final Path f, final long mtime, final long atime) 476 throws AccessControlException, FileNotFoundException, 477 IOException { 478 InodeTree.ResolveResult<FileSystem> res = 479 fsState.resolve(getUriPath(f), true); 480 res.targetFileSystem.setTimes(res.remainingPath, mtime, atime); 481 } 482 483 @Override 484 public void setVerifyChecksum(final boolean verifyChecksum) { 485 List<InodeTree.MountPoint<FileSystem>> mountPoints = 486 fsState.getMountPoints(); 487 for (InodeTree.MountPoint<FileSystem> mount : mountPoints) { 488 mount.target.targetFileSystem.setVerifyChecksum(verifyChecksum); 489 } 490 } 491 492 @Override 493 public long getDefaultBlockSize() { 494 throw new NotInMountpointException("getDefaultBlockSize"); 495 } 496 497 @Override 498 public short getDefaultReplication() { 499 throw new NotInMountpointException("getDefaultReplication"); 500 } 501 502 @Override 503 public FsServerDefaults getServerDefaults() throws IOException { 504 throw new NotInMountpointException("getServerDefaults"); 505 } 506 507 @Override 508 public long getDefaultBlockSize(Path f) { 509 try { 510 InodeTree.ResolveResult<FileSystem> res = 511 fsState.resolve(getUriPath(f), true); 512 return res.targetFileSystem.getDefaultBlockSize(res.remainingPath); 513 } catch (FileNotFoundException e) { 514 throw new NotInMountpointException(f, "getDefaultBlockSize"); 515 } 516 } 517 518 @Override 519 public short getDefaultReplication(Path f) { 520 try { 521 InodeTree.ResolveResult<FileSystem> res = 522 fsState.resolve(getUriPath(f), true); 523 return res.targetFileSystem.getDefaultReplication(res.remainingPath); 524 } catch (FileNotFoundException e) { 525 throw new NotInMountpointException(f, "getDefaultReplication"); 526 } 527 } 528 529 @Override 530 public FsServerDefaults getServerDefaults(Path f) throws IOException { 531 InodeTree.ResolveResult<FileSystem> res = 532 fsState.resolve(getUriPath(f), true); 533 return res.targetFileSystem.getServerDefaults(res.remainingPath); 534 } 535 536 @Override 537 public ContentSummary getContentSummary(Path f) throws IOException { 538 InodeTree.ResolveResult<FileSystem> res = 539 fsState.resolve(getUriPath(f), true); 540 return res.targetFileSystem.getContentSummary(res.remainingPath); 541 } 542 543 @Override 544 public void setWriteChecksum(final boolean writeChecksum) { 545 List<InodeTree.MountPoint<FileSystem>> mountPoints = 546 fsState.getMountPoints(); 547 for (InodeTree.MountPoint<FileSystem> mount : mountPoints) { 548 mount.target.targetFileSystem.setWriteChecksum(writeChecksum); 549 } 550 } 551 552 public MountPoint[] getMountPoints() { 553 List<InodeTree.MountPoint<FileSystem>> mountPoints = 554 fsState.getMountPoints(); 555 556 MountPoint[] result = new MountPoint[mountPoints.size()]; 557 for ( int i = 0; i < mountPoints.size(); ++i ) { 558 result[i] = new MountPoint(new Path(mountPoints.get(i).src), 559 mountPoints.get(i).target.targetDirLinkList); 560 } 561 return result; 562 } 563 564 565 @Override 566 public List<Token<?>> getDelegationTokens(String renewer) throws IOException { 567 List<InodeTree.MountPoint<FileSystem>> mountPoints = 568 fsState.getMountPoints(); 569 int initialListSize = 0; 570 for (InodeTree.MountPoint<FileSystem> im : mountPoints) { 571 initialListSize += im.target.targetDirLinkList.length; 572 } 573 List<Token<?>> result = new ArrayList<Token<?>>(initialListSize); 574 for ( int i = 0; i < mountPoints.size(); ++i ) { 575 List<Token<?>> tokens = 576 mountPoints.get(i).target.targetFileSystem.getDelegationTokens(renewer); 577 if (tokens != null) { 578 result.addAll(tokens); 579 } 580 } 581 return result; 582 } 583 584 @Override 585 public List<Token<?>> getDelegationTokens(String renewer, 586 Credentials credentials) throws IOException { 587 List<InodeTree.MountPoint<FileSystem>> mountPoints = 588 fsState.getMountPoints(); 589 int initialListSize = 0; 590 for (InodeTree.MountPoint<FileSystem> im : mountPoints) { 591 initialListSize += im.target.targetDirLinkList.length; 592 } 593 Set<String> seenServiceNames = new HashSet<String>(); 594 List<Token<?>> result = new ArrayList<Token<?>>(initialListSize); 595 for (int i = 0; i < mountPoints.size(); ++i) { 596 String serviceName = 597 mountPoints.get(i).target.targetFileSystem.getCanonicalServiceName(); 598 if (serviceName == null || seenServiceNames.contains(serviceName)) { 599 continue; 600 } 601 seenServiceNames.add(serviceName); 602 Token<?> knownToken = credentials.getToken(new Text(serviceName)); 603 if (knownToken != null) { 604 result.add(knownToken); 605 } else { 606 List<Token<?>> tokens = 607 mountPoints.get(i).target.targetFileSystem 608 .getDelegationTokens(renewer); 609 if (tokens != null) { 610 result.addAll(tokens); 611 } 612 } 613 } 614 return result; 615 } 616 617 /* 618 * An instance of this class represents an internal dir of the viewFs 619 * that is internal dir of the mount table. 620 * It is a read only mount tables and create, mkdir or delete operations 621 * are not allowed. 622 * If called on create or mkdir then this target is the parent of the 623 * directory in which one is trying to create or mkdir; hence 624 * in this case the path name passed in is the last component. 625 * Otherwise this target is the end point of the path and hence 626 * the path name passed in is null. 627 */ 628 static class InternalDirOfViewFs extends FileSystem { 629 final InodeTree.INodeDir<FileSystem> theInternalDir; 630 final long creationTime; // of the the mount table 631 final UserGroupInformation ugi; // the user/group of user who created mtable 632 final URI myUri; 633 634 public InternalDirOfViewFs(final InodeTree.INodeDir<FileSystem> dir, 635 final long cTime, final UserGroupInformation ugi, URI uri) 636 throws URISyntaxException { 637 myUri = uri; 638 try { 639 initialize(myUri, new Configuration()); 640 } catch (IOException e) { 641 throw new RuntimeException("Cannot occur"); 642 } 643 theInternalDir = dir; 644 creationTime = cTime; 645 this.ugi = ugi; 646 } 647 648 static private void checkPathIsSlash(final Path f) throws IOException { 649 if (f != InodeTree.SlashPath) { 650 throw new IOException ( 651 "Internal implementation error: expected file name to be /" ); 652 } 653 } 654 655 @Override 656 public URI getUri() { 657 return myUri; 658 } 659 660 @Override 661 public Path getWorkingDirectory() { 662 throw new RuntimeException ( 663 "Internal impl error: getWorkingDir should not have been called" ); 664 } 665 666 @Override 667 public void setWorkingDirectory(final Path new_dir) { 668 throw new RuntimeException ( 669 "Internal impl error: getWorkingDir should not have been called" ); 670 } 671 672 @Override 673 public FSDataOutputStream append(final Path f, final int bufferSize, 674 final Progressable progress) throws IOException { 675 throw readOnlyMountTable("append", f); 676 } 677 678 @Override 679 public FSDataOutputStream create(final Path f, 680 final FsPermission permission, final boolean overwrite, 681 final int bufferSize, final short replication, final long blockSize, 682 final Progressable progress) throws AccessControlException { 683 throw readOnlyMountTable("create", f); 684 } 685 686 @Override 687 public boolean delete(final Path f, final boolean recursive) 688 throws AccessControlException, IOException { 689 checkPathIsSlash(f); 690 throw readOnlyMountTable("delete", f); 691 } 692 693 @Override 694 @SuppressWarnings("deprecation") 695 public boolean delete(final Path f) 696 throws AccessControlException, IOException { 697 return delete(f, true); 698 } 699 700 @Override 701 public BlockLocation[] getFileBlockLocations(final FileStatus fs, 702 final long start, final long len) throws 703 FileNotFoundException, IOException { 704 checkPathIsSlash(fs.getPath()); 705 throw new FileNotFoundException("Path points to dir not a file"); 706 } 707 708 @Override 709 public FileChecksum getFileChecksum(final Path f) 710 throws FileNotFoundException, IOException { 711 checkPathIsSlash(f); 712 throw new FileNotFoundException("Path points to dir not a file"); 713 } 714 715 @Override 716 public FileStatus getFileStatus(Path f) throws IOException { 717 checkPathIsSlash(f); 718 return new FileStatus(0, true, 0, 0, creationTime, creationTime, 719 PERMISSION_RRR, ugi.getUserName(), ugi.getGroupNames()[0], 720 721 new Path(theInternalDir.fullPath).makeQualified( 722 myUri, null)); 723 } 724 725 726 @Override 727 public FileStatus[] listStatus(Path f) throws AccessControlException, 728 FileNotFoundException, IOException { 729 checkPathIsSlash(f); 730 FileStatus[] result = new FileStatus[theInternalDir.children.size()]; 731 int i = 0; 732 for (Entry<String, INode<FileSystem>> iEntry : 733 theInternalDir.children.entrySet()) { 734 INode<FileSystem> inode = iEntry.getValue(); 735 if (inode instanceof INodeLink ) { 736 INodeLink<FileSystem> link = (INodeLink<FileSystem>) inode; 737 738 result[i++] = new FileStatus(0, false, 0, 0, 739 creationTime, creationTime, PERMISSION_RRR, 740 ugi.getUserName(), ugi.getGroupNames()[0], 741 link.getTargetLink(), 742 new Path(inode.fullPath).makeQualified( 743 myUri, null)); 744 } else { 745 result[i++] = new FileStatus(0, true, 0, 0, 746 creationTime, creationTime, PERMISSION_RRR, 747 ugi.getUserName(), ugi.getGroupNames()[0], 748 new Path(inode.fullPath).makeQualified( 749 myUri, null)); 750 } 751 } 752 return result; 753 } 754 755 @Override 756 public boolean mkdirs(Path dir, FsPermission permission) 757 throws AccessControlException, FileAlreadyExistsException { 758 if (theInternalDir.isRoot & dir == null) { 759 throw new FileAlreadyExistsException("/ already exits"); 760 } 761 // Note dir starts with / 762 if (theInternalDir.children.containsKey(dir.toString().substring(1))) { 763 return true; // this is the stupid semantics of FileSystem 764 } 765 throw readOnlyMountTable("mkdirs", dir); 766 } 767 768 @Override 769 public FSDataInputStream open(Path f, int bufferSize) 770 throws AccessControlException, FileNotFoundException, IOException { 771 checkPathIsSlash(f); 772 throw new FileNotFoundException("Path points to dir not a file"); 773 } 774 775 @Override 776 public boolean rename(Path src, Path dst) throws AccessControlException, 777 IOException { 778 checkPathIsSlash(src); 779 checkPathIsSlash(dst); 780 throw readOnlyMountTable("rename", src); 781 } 782 783 @Override 784 public void setOwner(Path f, String username, String groupname) 785 throws AccessControlException, IOException { 786 checkPathIsSlash(f); 787 throw readOnlyMountTable("setOwner", f); 788 } 789 790 @Override 791 public void setPermission(Path f, FsPermission permission) 792 throws AccessControlException, IOException { 793 checkPathIsSlash(f); 794 throw readOnlyMountTable("setPermission", f); 795 } 796 797 @Override 798 public boolean setReplication(Path f, short replication) 799 throws AccessControlException, IOException { 800 checkPathIsSlash(f); 801 throw readOnlyMountTable("setReplication", f); 802 } 803 804 @Override 805 public void setTimes(Path f, long mtime, long atime) 806 throws AccessControlException, IOException { 807 checkPathIsSlash(f); 808 throw readOnlyMountTable("setTimes", f); 809 } 810 811 @Override 812 public void setVerifyChecksum(boolean verifyChecksum) { 813 // Noop for viewfs 814 } 815 816 @Override 817 public FsServerDefaults getServerDefaults(Path f) throws IOException { 818 throw new NotInMountpointException(f, "getServerDefaults"); 819 } 820 821 @Override 822 public long getDefaultBlockSize(Path f) { 823 throw new NotInMountpointException(f, "getDefaultBlockSize"); 824 } 825 826 @Override 827 public short getDefaultReplication(Path f) { 828 throw new NotInMountpointException(f, "getDefaultReplication"); 829 } 830 } 831 }