/** * Creates a new directory stream for the directory located by the given path. The given * {@code basePathForStream} is that base path that the returned stream will use. This will be * the same as {@code dir} except for streams created relative to another secure stream. */ public DirectoryStream<Path> newDirectoryStream( JimfsPath dir, DirectoryStream.Filter<? super Path> filter, Set<? super LinkOption> options, JimfsPath basePathForStream) throws IOException { Directory file = (Directory) lookUpWithLock(dir, options) .requireDirectory(dir) .file(); FileSystemView view = new FileSystemView(store, file, basePathForStream); JimfsSecureDirectoryStream stream = new JimfsSecureDirectoryStream(view, filter, state()); return store.supportsFeature(Feature.SECURE_DIRECTORY_STREAM) ? stream : new DowngradedDirectoryStream(stream); }
@Override public void checkAccess(Path path, AccessMode... modes) throws IOException { JimfsPath checkedPath = checkPath(path); getDefaultView(checkedPath).checkAccess(checkedPath); }
checkNotNull(options); boolean sameFileSystem = isSameFileSystem(destView); lockBoth(store.writeLock(), destView.store.writeLock()); try { DirectoryEntry sourceEntry = lookUp(source, options).requireExists(source); DirectoryEntry destEntry = destView.lookUp(dest, Options.NOFOLLOW_LINKS); checkMovable(sourceFile, source); checkNotAncestor(sourceFile, destParent, destView); } else { checkDeletable(sourceFile, DeleteMode.ANY, source); return; } else if (options.contains(REPLACE_EXISTING)) { destView.delete(destEntry, DeleteMode.ANY, dest); } else { throw new FileAlreadyExistsException(dest.toString()); lockSourceAndCopy(sourceFile, copyFile); delete(sourceEntry, DeleteMode.ANY, source); unlockSourceAndCopy(sourceFile, copyFile);
/** * Gets or creates a new regular file with a write lock (assuming the file does not exist). */ private RegularFile getOrCreateRegularFileWithWriteLock( JimfsPath path, Set<OpenOption> options, FileAttribute<?>[] attrs) throws IOException { store.writeLock().lock(); try { File file = createFile(path, store.regularFileCreator(), options.contains(CREATE_NEW), attrs); // the file already existed but was not a regular file if (!file.isRegularFile()) { throw new FileSystemException(path.toString(), null, "not a regular file"); } return open((RegularFile) file, options); } finally { store.writeLock().unlock(); } }
/** * Creates a new directory at the given path. The given attributes will be set on the new file if * possible. */ public Directory createDirectory(JimfsPath path, FileAttribute<?>... attrs) throws IOException { return (Directory) createFile(path, store.directoryCreator(), true, attrs); }
@Override public void move(Path srcPath, SecureDirectoryStream<Path> targetDir, Path targetPath) throws IOException { checkOpen(); JimfsPath checkedSrcPath = checkPath(srcPath); JimfsPath checkedTargetPath = checkPath(targetPath); if (!(targetDir instanceof JimfsSecureDirectoryStream)) { throw new ProviderMismatchException( "targetDir isn't a secure directory stream associated with this file system"); } JimfsSecureDirectoryStream checkedTargetDir = (JimfsSecureDirectoryStream) targetDir; view.copy( checkedSrcPath, checkedTargetDir.view, checkedTargetPath, ImmutableSet.<CopyOption>of(), true); }
/** * Deletes the given directory entry from its parent directory. */ private void delete(DirectoryEntry entry, DeleteMode deleteMode, JimfsPath pathForException) throws IOException { Directory parent = entry.directory(); File file = entry.file(); checkDeletable(file, deleteMode, pathForException); parent.unlink(entry.name()); parent.updateModifiedTime(); file.deleted(); }
@Override public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) throws IOException { JimfsPath linkPath = checkPath(link); JimfsPath targetPath = checkPath(target); checkArgument( linkPath.getFileSystem().equals(targetPath.getFileSystem()), "link and target paths must belong to the same file system instance"); FileSystemView view = getDefaultView(linkPath); view.createSymbolicLink(linkPath, targetPath, attrs); }
@Override public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException { JimfsPath checkedPath = checkPath(dir); FileSystemView view = getDefaultView(checkedPath); view.createDirectory(checkedPath, attrs); }
/** * Creates the default view of the file system using the given working directory. */ private static FileSystemView createDefaultView( Configuration config, JimfsFileStore fileStore, PathService pathService) throws IOException { JimfsPath workingDirPath = pathService.parsePath(config.workingDirectory); Directory dir = fileStore.getRoot(workingDirPath.root()); if (dir == null) { throw new IllegalArgumentException("Invalid working dir path: " + workingDirPath); } for (Name name : workingDirPath.names()) { Directory newDir = fileStore.directoryCreator().get(); fileStore.setInitialAttributes(newDir); dir.link(name, newDir); dir = newDir; } return new FileSystemView(fileStore, dir, workingDirPath); } }
/** * Checks that the given file can be deleted, throwing an exception if it can't. */ private void checkDeletable(File file, DeleteMode mode, Path path) throws IOException { if (file.isRootDirectory()) { throw new FileSystemException(path.toString(), null, "can't delete root directory"); } if (file.isDirectory()) { if (mode == DeleteMode.NON_DIRECTORY_ONLY) { throw new FileSystemException(path.toString(), null, "can't delete: is a directory"); } checkEmpty(((Directory) file), path); } else if (mode == DeleteMode.DIRECTORY_ONLY) { throw new FileSystemException(path.toString(), null, "can't delete: is not a directory"); } if (file == workingDirectory && !path.isAbsolute()) { // this is weird, but on Unix at least, the file system seems to be happy to delete the // working directory if you give the absolute path to it but fail if you use a relative path // that resolves to the working directory (e.g. "" or ".") throw new FileSystemException(path.toString(), null, "invalid argument"); } }
/** * Gets or creates a new regular file with a write lock (assuming the file does not exist). */ private RegularFile getOrCreateRegularFileWithWriteLock( JimfsPath path, Set<OpenOption> options, FileAttribute<?>[] attrs) throws IOException { store.writeLock().lock(); try { File file = createFile(path, store.regularFileCreator(), options.contains(CREATE_NEW), attrs); // the file already existed but was not a regular file if (!file.isRegularFile()) { throw new FileSystemException(path.toString(), null, "not a regular file"); } return open((RegularFile) file, options); } finally { store.writeLock().unlock(); } }
/** * Creates a new symbolic link at the given path with the given target. The given attributes will * be set on the new file if possible. */ public SymbolicLink createSymbolicLink( JimfsPath path, JimfsPath target, FileAttribute<?>... attrs) throws IOException { if (!store.supportsFeature(Feature.SYMBOLIC_LINKS)) { throw new UnsupportedOperationException(); } return (SymbolicLink) createFile(path, store.symbolicLinkCreator(target), true, attrs); }
private void copy(Path source, Path target, ImmutableSet<CopyOption> options, boolean move) throws IOException { JimfsPath sourcePath = checkPath(source); JimfsPath targetPath = checkPath(target); FileSystemView sourceView = getDefaultView(sourcePath); FileSystemView targetView = getDefaultView(targetPath); sourceView.copy(sourcePath, targetView, targetPath, options, move); }
/** * Deletes the given directory entry from its parent directory. */ private void delete(DirectoryEntry entry, DeleteMode deleteMode, JimfsPath pathForException) throws IOException { Directory parent = entry.directory(); File file = entry.file(); checkDeletable(file, deleteMode, pathForException); parent.unlink(entry.name()); parent.updateModifiedTime(); file.deleted(); }
@Override public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) throws IOException { JimfsPath linkPath = checkPath(link); JimfsPath targetPath = checkPath(target); checkArgument( linkPath.getFileSystem().equals(targetPath.getFileSystem()), "link and target paths must belong to the same file system instance"); FileSystemView view = getDefaultView(linkPath); view.createSymbolicLink(linkPath, targetPath, attrs); }
@Override public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException { JimfsPath checkedPath = checkPath(dir); FileSystemView view = getDefaultView(checkedPath); view.createDirectory(checkedPath, attrs); }
/** * Creates the default view of the file system using the given working directory. */ private static FileSystemView createDefaultView( Configuration config, JimfsFileStore fileStore, PathService pathService) throws IOException { JimfsPath workingDirPath = pathService.parsePath(config.workingDirectory); Directory dir = fileStore.getRoot(workingDirPath.root()); if (dir == null) { throw new IllegalArgumentException("Invalid working dir path: " + workingDirPath); } for (Name name : workingDirPath.names()) { Directory newDir = fileStore.directoryCreator().get(); fileStore.setInitialAttributes(newDir); dir.link(name, newDir); dir = newDir; } return new FileSystemView(fileStore, dir, workingDirPath); } }
/** * Checks that the given file can be deleted, throwing an exception if it can't. */ private void checkDeletable(File file, DeleteMode mode, Path path) throws IOException { if (file.isRootDirectory()) { throw new FileSystemException(path.toString(), null, "can't delete root directory"); } if (file.isDirectory()) { if (mode == DeleteMode.NON_DIRECTORY_ONLY) { throw new FileSystemException(path.toString(), null, "can't delete: is a directory"); } checkEmpty(((Directory) file), path); } else if (mode == DeleteMode.DIRECTORY_ONLY) { throw new FileSystemException(path.toString(), null, "can't delete: is not a directory"); } if (file == workingDirectory && !path.isAbsolute()) { // this is weird, but on Unix at least, the file system seems to be happy to delete the // working directory if you give the absolute path to it but fail if you use a relative path // that resolves to the working directory (e.g. "" or ".") throw new FileSystemException(path.toString(), null, "invalid argument"); } }
checkNotNull(options); boolean sameFileSystem = isSameFileSystem(destView); lockBoth(store.writeLock(), destView.store.writeLock()); try { DirectoryEntry sourceEntry = lookUp(source, options).requireExists(source); DirectoryEntry destEntry = destView.lookUp(dest, Options.NOFOLLOW_LINKS); checkMovable(sourceFile, source); checkNotAncestor(sourceFile, destParent, destView); } else { checkDeletable(sourceFile, DeleteMode.ANY, source); return; } else if (options.contains(REPLACE_EXISTING)) { destView.delete(destEntry, DeleteMode.ANY, dest); } else { throw new FileAlreadyExistsException(dest.toString()); lockSourceAndCopy(sourceFile, copyFile); delete(sourceEntry, DeleteMode.ANY, source); unlockSourceAndCopy(sourceFile, copyFile);