| // Copyright 2014 The Bazel Authors. All rights reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.devtools.build.lib.unix; | |
| import com.google.devtools.build.lib.runtime.BlazeService; | |
| import com.google.devtools.build.lib.skybridge.SkybridgeInterface; | |
| import javax.annotation.Nullable; | |
| /** A {@link BlazeService} providing access to POSIX filesystem calls. */ | |
| @SkybridgeInterface | |
| public interface NativePosixFilesService extends BlazeService { | |
| /** | |
| * Native wrapper around Linux readlink(2) call. | |
| * | |
| * @param path the file of interest | |
| * @return the pathname to which the symbolic link 'path' links, or {@code null} if 'path' is not | |
| * a symbolic link. | |
| * @throws NativePosixFilesException iff the readlink() call failed for any other reason | |
| */ | |
| @Nullable | |
| String readlink(String path) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around POSIX chmod(2) syscall. | |
| * | |
| * @param path the file of interest | |
| * @param mode the POSIX type and permission mode bits to set | |
| * @throws NativePosixFilesException iff the chmod() call failed. | |
| */ | |
| void chmod(String path, int mode) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around POSIX symlink(2) syscall. | |
| * | |
| * @param oldpath the file to link to | |
| * @param newpath the new path for the link | |
| * @throws NativePosixFilesException iff the symlink() syscall failed. | |
| */ | |
| void symlink(String oldpath, String newpath) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around POSIX link(2) syscall. | |
| * | |
| * @param oldpath the file to link to | |
| * @param newpath the new path for the link | |
| * @throws NativePosixFilesException iff the link() syscall failed. | |
| */ | |
| void link(String oldpath, String newpath) throws NativePosixFilesException; | |
| /** How stat() and lstat() should handle errors. */ | |
| public final class StatErrorHandling { | |
| private final char code; | |
| private StatErrorHandling(char code) { | |
| this.code = code; | |
| } | |
| /** Always throw an exception. */ | |
| public static final StatErrorHandling ALWAYS_THROW = new StatErrorHandling('a'); | |
| /** Throw an exception unless the error is ENOENT/ENOTDIR, in which case return null. */ | |
| public static final StatErrorHandling THROW_UNLESS_NOT_FOUND = new StatErrorHandling('f'); | |
| /* Never throw an exception. Return null instead. */ | |
| public static final StatErrorHandling NEVER_THROW = new StatErrorHandling('n'); | |
| public char getCode() { | |
| return code; | |
| } | |
| } | |
| /** File metadata, as returned by stat() or lstat(). */ | |
| @SuppressWarnings("GoodTime") | |
| public interface Stat { | |
| int mode(); | |
| long mtimeNanos(); | |
| long ctimeNanos(); | |
| long size(); | |
| long ino(); | |
| } | |
| /** | |
| * Native wrapper around POSIX stat(2) syscall. | |
| * | |
| * @param path the file to stat. | |
| * @param errorHandling how to handle errors. | |
| * @return a {@link Stat} containing the metadata. | |
| * @throws NativePosixFilesException if the stat() syscall failed. | |
| */ | |
| Stat stat(String path, StatErrorHandling errorHandling) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around POSIX lstat(2) syscall. | |
| * | |
| * @param path the file to lstat. | |
| * @param errorHandling how to handle errors. | |
| * @return a {@link Stat} containing the metadata. | |
| * @throws NativePosixFilesException if the lstat() syscall failed. | |
| */ | |
| Stat lstat(String path, StatErrorHandling errorHandling) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around POSIX utimensat(2) syscall. | |
| * | |
| * <p>Note that, even though utimensat(2) supports up to nanosecond precision, this interface only | |
| * allows millisecond precision, which is what Bazel uses internally. | |
| * | |
| * @param path the file whose modification time should be changed. | |
| * @param now if true, ignore {@code epochMilli} and use the current time. | |
| * @param epochMilli the file modification time in milliseconds since the UNIX epoch. | |
| * @throws NativePosixFilesException if the operation failed. | |
| */ | |
| void utimensat(String path, boolean now, long epochMilli) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around POSIX mkdir(2) syscall. | |
| * | |
| * <p>Caveat: errno==EEXIST is mapped to the return value "false", not IOException. It requires an | |
| * additional stat() to determine if mkdir failed because the directory already exists. | |
| * | |
| * @param path the directory to create. | |
| * @param mode the mode with which to create the directory. | |
| * @return true if the directory was successfully created; false if the system call returned | |
| * EEXIST because some kind of a file (not necessarily a directory) already exists. | |
| * @throws NativePosixFilesException if the mkdir() syscall failed for any other reason. | |
| */ | |
| boolean mkdir(String path, int mode) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around POSIX opendir(2)/readdir(3)/closedir(3) syscalls. | |
| * | |
| * @param path the directory to read. | |
| * @return an array of {@link Dirent} objects, one for each directory entry, excluding {@code .} | |
| * and {@code ..}. | |
| * @throws NativePosixFilesException if the opendir(), readdir() or closedir() calls failed for | |
| * any reason. | |
| */ | |
| Dirent[] readdir(String path) throws NativePosixFilesException; | |
| /** A directory entry and its corresponding type, as returned by readdir(). */ | |
| public interface Dirent { | |
| String name(); | |
| Type type(); | |
| /** The type of the directory entry. */ | |
| public static final class Type { | |
| /** Regular file. */ | |
| public static final Type FILE = new Type(); | |
| /** Directory. */ | |
| public static final Type DIRECTORY = new Type(); | |
| /** Symbolic link. */ | |
| public static final Type SYMLINK = new Type(); | |
| /** Character special device. */ | |
| public static final Type CHAR = new Type(); | |
| /* Block special device. */ | |
| public static final Type BLOCK = new Type(); | |
| /** Named pipe. */ | |
| public static final Type FIFO = new Type(); | |
| /** Unix domain socket. */ | |
| public static final Type SOCKET = new Type(); | |
| /** Unknown type. */ | |
| public static final Type UNKNOWN = new Type(); | |
| private Type() {} | |
| } | |
| } | |
| /** | |
| * Native wrapper around POSIX rename(2) syscall. | |
| * | |
| * @param oldpath the source location. | |
| * @param newpath the destination location. | |
| * @throws NativePosixFilesException if the rename failed for any reason. | |
| */ | |
| void rename(String oldpath, String newpath) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around POSIX remove(3) C library call. | |
| * | |
| * @param path the file or directory to remove. | |
| * @return true iff the file was actually deleted by this call. | |
| * @throws NativePosixFilesException if the remove failed, but the file was present prior to the | |
| * call. | |
| */ | |
| boolean remove(String path) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around POSIX mkfifo(3) C library call. | |
| * | |
| * @param path the name of the pipe to create. | |
| * @param mode the mode with which to create the pipe. | |
| * @throws NativePosixFilesException if the mkfifo failed. | |
| */ | |
| void mkfifo(String path, int mode) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around Linux getxattr(2) syscall. | |
| * | |
| * @param path the file whose extended attribute is to be returned. | |
| * @param name the name of the extended attribute key. | |
| * @return the value of the extended attribute associated with 'path', if any, or null if extended | |
| * attributes are unsupported by the filesystem or if no such extended attribute is defined | |
| * attribute is defined | |
| * @throws NativePosixFilesException if the call failed for any other reason | |
| */ | |
| @Nullable | |
| byte[] getxattr(String path, String name) throws NativePosixFilesException; | |
| /** | |
| * Native wrapper around Linux lgetxattr(2) syscall. | |
| * | |
| * @param path the file whose extended attribute is to be returned. | |
| * @param name the name of the extended attribute key. | |
| * @return the value of the extended attribute associated with 'path', if any, or null if extended | |
| * attributes are unsupported by the filesystem or if no such extended attribute is defined | |
| * @throws NativePosixFilesException if the call failed for any other reason | |
| */ | |
| @Nullable | |
| byte[] lgetxattr(String path, String name) throws NativePosixFilesException; | |
| /** | |
| * Deletes all directory trees recursively beneath the given path, which is expected to be a | |
| * directory. Does not remove the top directory. | |
| * | |
| * @param dir the directory hierarchy to remove | |
| * @throws NativePosixFilesException if the hierarchy cannot be removed successfully or if the | |
| * given path is not a directory | |
| */ | |
| void deleteTreesBelow(String dir) throws NativePosixFilesException; | |
| } |