diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/vfs')
17 files changed, 129 insertions, 66 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystem.java index de67af85cf..1d0b4dc070 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/AbstractFileSystem.java @@ -36,7 +36,7 @@ abstract class AbstractFileSystem extends FileSystem { protected static final Profiler profiler = Profiler.instance(); @Override - protected InputStream getInputStream(Path path) throws FileNotFoundException { + protected InputStream getInputStream(Path path) throws IOException { // This loop is a workaround for an apparent bug in FileInputStrean.open, which delegates // ultimately to JVM_Open in the Hotspot JVM. This call is not EINTR-safe, so we must do the // retry here. @@ -144,4 +144,28 @@ abstract class AbstractFileSystem extends FileSystem { } } } + + @Override + protected boolean isFile(Path path, boolean followSymlinks) { + FileStatus stat = statNullable(path, followSymlinks); + return stat != null ? stat.isFile() : false; + } + + @Override + protected boolean isSpecialFile(Path path, boolean followSymlinks) { + FileStatus stat = statNullable(path, followSymlinks); + return stat != null ? stat.isSpecialFile() : false; + } + + @Override + protected boolean isSymbolicLink(Path path) { + FileStatus stat = statNullable(path, false); + return stat != null ? stat.isSymbolicLink() : false; + } + + @Override + protected boolean isDirectory(Path path, boolean followSymlinks) { + FileStatus stat = statNullable(path, followSymlinks); + return stat != null ? stat.isDirectory() : false; + } } diff --git a/src/main/java/com/google/devtools/build/lib/vfs/Dirent.java b/src/main/java/com/google/devtools/build/lib/vfs/Dirent.java index 49d41a119b..2b81c831c8 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/Dirent.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/Dirent.java @@ -25,9 +25,13 @@ public class Dirent implements Serializable { /** Type of the directory entry */ public enum Type { + // A regular file. FILE, + // A directory. DIRECTORY, + // A symlink. SYMLINK, + // Not one of the above. For example, a special file. UNKNOWN; } diff --git a/src/main/java/com/google/devtools/build/lib/vfs/FileStatus.java b/src/main/java/com/google/devtools/build/lib/vfs/FileStatus.java index 4c7c206c6e..712f96da14 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/FileStatus.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/FileStatus.java @@ -37,8 +37,7 @@ import java.io.IOException; public interface FileStatus { /** - * Returns true iff this file is a regular or special file (e.g. socket, - * fifo or device). + * Returns true iff this file is a regular file or {@code isSpecial()}. */ boolean isFile(); @@ -53,6 +52,12 @@ public interface FileStatus { boolean isSymbolicLink(); /** + * Returns true iff this file is a special file (e.g. socket, fifo or device). {@link #getSize()} + * can't be trusted for such files. + */ + boolean isSpecialFile(); + + /** * Returns the total size, in bytes, of this file. */ long getSize() throws IOException; diff --git a/src/main/java/com/google/devtools/build/lib/vfs/FileStatusWithDigestAdapter.java b/src/main/java/com/google/devtools/build/lib/vfs/FileStatusWithDigestAdapter.java index ab034b063b..5daeaa668c 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/FileStatusWithDigestAdapter.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/FileStatusWithDigestAdapter.java @@ -45,6 +45,11 @@ public class FileStatusWithDigestAdapter implements FileStatusWithDigest { } @Override + public boolean isSpecialFile() { + return stat.isSpecialFile(); + } + + @Override public boolean isDirectory() { return stat.isDirectory(); } diff --git a/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java index 82597e3603..d396139cfe 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java @@ -362,6 +362,7 @@ public abstract class FileSystem { volatile Boolean isFile; volatile Boolean isDirectory; volatile Boolean isSymbolicLink; + volatile Boolean isSpecial; volatile long size = -1; volatile long mtime = -1; @@ -386,6 +387,12 @@ public abstract class FileSystem { } @Override + public boolean isSpecialFile() { + if (isSpecial == null) { isSpecial = FileSystem.this.isSpecialFile(path, followSymlinks); } + return isSpecial; + } + + @Override public long getSize() throws IOException { if (size == -1) { size = getFileSize(path, followSymlinks); } return size; @@ -453,6 +460,12 @@ public abstract class FileSystem { protected abstract boolean isFile(Path path, boolean followSymlinks); /** + * Returns true iff {@code path} denotes a special file. + * See {@link Path#isSpecialFile(Symlinks)} for specification. + */ + protected abstract boolean isSpecialFile(Path path, boolean followSymlinks); + + /** * Creates a symbolic link. See {@link Path#createSymbolicLink(Path)} for * specification. * @@ -505,6 +518,8 @@ public abstract class FileSystem { protected static Dirent.Type direntFromStat(FileStatus stat) { if (stat == null) { return Type.UNKNOWN; + } else if (stat.isSpecialFile()) { + return Type.UNKNOWN; } else if (stat.isFile()) { return Type.FILE; } else if (stat.isDirectory()) { diff --git a/src/main/java/com/google/devtools/build/lib/vfs/JavaIoFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/JavaIoFileSystem.java index 3ae4e96749..9d9f16e5ae 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/JavaIoFileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/JavaIoFileSystem.java @@ -94,34 +94,6 @@ public class JavaIoFileSystem extends AbstractFileSystem { } @Override - protected boolean isDirectory(Path path, boolean followSymlinks) { - File file = getIoFile(path); - long startTime = Profiler.nanoTimeMaybe(); - try { - if (!followSymlinks && fileIsSymbolicLink(file)) { - return false; - } - return file.isDirectory(); - } finally { - profiler.logSimpleTask(startTime, ProfilerTask.VFS_STAT, path.toString()); - } - } - - @Override - protected boolean isFile(Path path, boolean followSymlinks) { - File file = getIoFile(path); - long startTime = Profiler.nanoTimeMaybe(); - try { - if (!followSymlinks && fileIsSymbolicLink(file)) { - return false; - } - return file.isFile(); - } finally { - profiler.logSimpleTask(startTime, ProfilerTask.VFS_STAT, path.toString()); - } - } - - @Override protected boolean isReadable(Path path) throws IOException { File file = getIoFile(path); long startTime = Profiler.nanoTimeMaybe(); @@ -365,17 +337,6 @@ public class JavaIoFileSystem extends AbstractFileSystem { } } - @Override - protected boolean isSymbolicLink(Path path) { - File file = getIoFile(path); - long startTime = Profiler.nanoTimeMaybe(); - try { - return fileIsSymbolicLink(file); - } finally { - profiler.logSimpleTask(startTime, ProfilerTask.VFS_STAT, file.getPath()); - } - } - private boolean fileIsSymbolicLink(File file) { return Files.isSymbolicLink(file.toPath()); } @@ -428,7 +389,12 @@ public class JavaIoFileSystem extends AbstractFileSystem { FileStatus status = new FileStatus() { @Override public boolean isFile() { - return attributes.isRegularFile(); + return attributes.isRegularFile() || isSpecialFile(); + } + + @Override + public boolean isSpecialFile() { + return attributes.isOther(); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/vfs/Path.java b/src/main/java/com/google/devtools/build/lib/vfs/Path.java index aac68ee8b0..c7c54712a3 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/Path.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/Path.java @@ -533,6 +533,25 @@ public class Path implements Comparable<Path>, Serializable { } /** + * Returns true iff this path denotes an existing special file (e.g. fifo). + * Follows symbolic links. + */ + public boolean isSpecialFile() { + return fileSystem.isSpecialFile(this, true); + } + + /** + * Returns true iff this path denotes an existing special file (e.g. fifo). + * + * @param followSymlinks if {@link Symlinks#FOLLOW}, and this path denotes a + * symbolic link, the link is dereferenced until a path other than a + * symbolic link is found. + */ + public boolean isSpecialFile(Symlinks followSymlinks) { + return fileSystem.isSpecialFile(this, followSymlinks.toBoolean()); + } + + /** * Returns true iff this path denotes an existing symbolic link. Does not * follow symbolic links. */ @@ -814,7 +833,7 @@ public class Path implements Comparable<Path>, Serializable { * Returns the size in bytes of the file denoted by the current path, * following symbolic links. * - * <p>The size of directory or special file is undefined. + * <p>The size of a directory or special file is undefined and should not be used. * * @throws FileNotFoundException if the file denoted by the current path does * not exist diff --git a/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystem.java index 821e4704f0..e3cf56fe3a 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/ReadonlyFileSystem.java @@ -33,7 +33,7 @@ import java.io.OutputStream; * </ul> * The above calls will always result in an {@link IOException}. */ -public abstract class ReadonlyFileSystem extends FileSystem { +public abstract class ReadonlyFileSystem extends AbstractFileSystem { protected ReadonlyFileSystem() { } diff --git a/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java index b774543575..a1ef71f844 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java @@ -248,6 +248,12 @@ public class UnionFileSystem extends FileSystem { } @Override + protected boolean isSpecialFile(Path path, boolean followSymlinks) { + FileSystem delegate = getDelegate(path); + return delegate.isSpecialFile(adjustPath(path, delegate), followSymlinks); + } + + @Override protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) throws IOException { checkModifiable(); if (!supportsSymbolicLinks()) { diff --git a/src/main/java/com/google/devtools/build/lib/vfs/UnixFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/UnixFileSystem.java index d730cab2de..29a8636b06 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/UnixFileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/UnixFileSystem.java @@ -63,6 +63,9 @@ public class UnixFileSystem extends AbstractFileSystem { public boolean isSymbolicLink() { return status.isSymbolicLink(); } @Override + public boolean isSpecialFile() { return isFile() && !status.isRegularFile(); } + + @Override public long getSize() { return status.getSize(); } @Override @@ -225,20 +228,6 @@ public class UnixFileSystem extends AbstractFileSystem { } @Override - protected boolean isDirectory(Path path, boolean followSymlinks) { - FileStatus stat = statNullable(path, followSymlinks); - return stat != null && stat.isDirectory(); - } - - @Override - protected boolean isFile(Path path, boolean followSymlinks) { - // Note, FileStatus.isFile means *regular* file whereas Path.isFile may - // mean special file too, so we don't return FileStatus.isFile here. - FileStatus status = statNullable(path, followSymlinks); - return status != null && !(status.isSymbolicLink() || status.isDirectory()); - } - - @Override protected boolean isReadable(Path path) throws IOException { return (statInternal(path, true).getPermissions() & 0400) != 0; } @@ -374,12 +363,6 @@ public class UnixFileSystem extends AbstractFileSystem { } @Override - protected boolean isSymbolicLink(Path path) { - FileStatus stat = statNullable(path, false); - return stat != null && stat.isSymbolicLink(); - } - - @Override protected void setLastModifiedTime(Path path, long newTime) throws IOException { synchronized (path) { if (newTime == -1L) { // "now" diff --git a/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java index 78961c8f30..393110d5f8 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java @@ -198,6 +198,11 @@ public class ZipFileSystem extends ReadonlyFileSystem { } @Override + protected boolean isSpecialFile(Path path, boolean followSymlinks) { + return false; + } + + @Override protected boolean isReadable(Path path) throws IOException { zipEntryNonNull(path); return true; diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/FileInfo.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/FileInfo.java index 2c578d1214..3c5d55c9fe 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/FileInfo.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/FileInfo.java @@ -43,6 +43,11 @@ public abstract class FileInfo extends InMemoryContentInfo { return true; } + @Override + public boolean isSpecialFile() { + return false; + } + protected abstract byte[] readContent() throws IOException; protected abstract OutputStream getOutputStream(boolean append) throws IOException; diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java index 6a721f1f94..d0044ccd28 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java @@ -80,12 +80,18 @@ public abstract class InMemoryContentInfo implements ScopeEscapableStatus { public abstract boolean isSymbolicLink(); /** - * Returns true if the current object is a regular file. + * Returns true if the current object is a regular or special file. */ @Override public abstract boolean isFile(); /** + * Returns true if the current object is a special file. + */ + @Override + public abstract boolean isSpecialFile(); + + /** * Returns the size of the entity denoted by the current object. For files, * this is the length in bytes, for directories the number of children. The * size of links is unspecified. diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryDirectoryInfo.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryDirectoryInfo.java index d7a6cf5407..66d7523b16 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryDirectoryInfo.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryDirectoryInfo.java @@ -96,6 +96,11 @@ class InMemoryDirectoryInfo extends InMemoryContentInfo { return false; } + @Override + public boolean isSpecialFile() { + return false; + } + /** * In the InMemory hierarchy, the getSize on a directory always returns the * number of children in the directory. diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java index 2138af1ba7..fe3731ef90 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java @@ -537,6 +537,15 @@ public class InMemoryFileSystem extends ScopeEscapableFileSystem { } @Override + protected boolean isSpecialFile(Path path, boolean followSymlinks) { + try { + return stat(path, followSymlinks).isSpecialFile(); + } catch (IOException e) { + return false; + } + } + + @Override protected boolean isSymbolicLink(Path path) { try { return stat(path, false).isSymbolicLink(); diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryLinkInfo.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryLinkInfo.java index 5d55fb563c..56204926e2 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryLinkInfo.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryLinkInfo.java @@ -50,6 +50,11 @@ class InMemoryLinkInfo extends InMemoryContentInfo { } @Override + public boolean isSpecialFile() { + return false; + } + + @Override public long getSize() { return linkContent.toString().length(); } diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/OutOfScopeFileStatus.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/OutOfScopeFileStatus.java index 6a71c5b203..287d97d5fe 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/OutOfScopeFileStatus.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/OutOfScopeFileStatus.java @@ -51,6 +51,7 @@ final class OutOfScopeFileStatus extends InMemoryContentInfo { @Override public boolean isDirectory() { throw failure(); } @Override public boolean isSymbolicLink() { throw failure(); } @Override public boolean isFile() { throw failure(); } + @Override public boolean isSpecialFile() { throw failure(); } @Override public long getSize() { throw failure(); } @Override protected void markModificationTime() { throw failure(); } @Override public synchronized long getLastModifiedTime() { throw failure(); } |