// Copyright 2016 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. #ifndef BAZEL_SRC_MAIN_CPP_UTIL_FILE_PLATFORM_H_ #define BAZEL_SRC_MAIN_CPP_UTIL_FILE_PLATFORM_H_ #include #include #include namespace blaze_util { class IPipe; IPipe* CreatePipe(); // Class to query/manipulate the last modification time (mtime) of files. class IFileMtime { public: virtual ~IFileMtime() {} // Checks if `path` is a file/directory in the embedded tools directory that // was not tampered with. // Returns true if `path` is a directory or directory symlink, or if `path` is // a file with an mtime in the distant future. // Returns false otherwise, or if querying the information failed. // TODO(laszlocsomor): move this function, and with it the whole IFileMtime // class into blaze_util_.cc, because it is Bazel-specific logic, // not generic file-handling logic. virtual bool IsUntampered(const std::string &path) = 0; // Sets the mtime of file under `path` to the current time. // Returns true if the mtime was changed successfully. virtual bool SetToNow(const std::string &path) = 0; // Sets the mtime of file under `path` to the distant future. // "Distant future" should be on the order of some years into the future, like // a decade. // Returns true if the mtime was changed successfully. virtual bool SetToDistantFuture(const std::string &path) = 0; }; // Creates a platform-specific implementation of `IFileMtime`. IFileMtime *CreateFileMtime(); #if defined(_WIN32) || defined(__CYGWIN__) // We cannot include because it #defines many symbols that conflict // with our function names, e.g. GetUserName, SendMessage. // Instead of typedef'ing HANDLE, let's use the actual type, void*. If that ever // changes in the future and HANDLE would no longer be compatible with void* // (very unlikely, given how fundamental this type is in Windows), then we'd get // a compilation error. typedef /* HANDLE */ void *file_handle_type; #else // !(defined(_WIN32) || defined(__CYGWIN__)) typedef int file_handle_type; #endif // defined(_WIN32) || defined(__CYGWIN__) // Result of a `ReadFromHandle` operation. // // This is a platform-independent abstraction of `errno`. If you need to handle // an errno value, add an entry here and update the platform-specific // `ReadFromHandle` implementations accordingly. struct ReadFileResult { enum Errors { SUCCESS = 0, OTHER_ERROR = 1, INTERRUPTED = 2, AGAIN = 3, }; }; int ReadFromHandle(file_handle_type handle, void *data, size_t size, int *error); // Replaces 'content' with contents of file 'filename'. // If `max_size` is positive, the method reads at most that many bytes; // otherwise the method reads the whole file. // Returns false on error. Can be called from a signal handler. bool ReadFile(const std::string &filename, std::string *content, int max_size = 0); // Reads up to `size` bytes from the file `filename` into `data`. // There must be enough memory allocated at `data`. // Returns true on success, false on error. bool ReadFile(const std::string &filename, void *data, size_t size); // Writes `size` bytes from `data` into file `filename` and chmods it to `perm`. // Returns false on failure, sets errno. bool WriteFile(const void *data, size_t size, const std::string &filename, unsigned int perm = 0644); // Result of a `WriteToStdOutErr` operation. // // This is a platform-independent abstraction of `errno`. If you need to handle // an errno value, add an entry here and update the platform-specific // `WriteToStdOutErr` implementations accordingly. struct WriteResult { enum Errors { SUCCESS = 0, OTHER_ERROR = 1, // some uncategorized error occurred BROKEN_PIPE = 2, // EPIPE (reading end of the pipe is closed) }; }; // Writes `size` bytes from `data` into stdout/stderr. // Writes to stdout if `to_stdout` is true, writes to stderr otherwise. // Returns one of `WriteResult::Errors`. // // This is a platform-independent abstraction of `fwrite` with `errno` checking // and awareness of pipes (i.e. in case stderr/stdout is connected to a pipe). int WriteToStdOutErr(const void *data, size_t size, bool to_stdout); enum RenameDirectoryResult { kRenameDirectorySuccess = 0, kRenameDirectoryFailureNotEmpty = 1, kRenameDirectoryFailureOtherError = 2, }; // Renames the directory at `old_name` to `new_name`. // Returns one of the RenameDirectoryResult enum values. int RenameDirectory(const std::string &old_name, const std::string &new_name); // Reads which directory a symlink points to. Puts the target of the symlink // in ``result`` and returns if the operation was successful. Will not work on // symlinks that don't point to directories on Windows. bool ReadDirectorySymlink(const std::string &symlink, std::string *result); // Unlinks the file given by 'file_path'. // Returns true on success. In case of failure sets errno. bool UnlinkPath(const std::string &file_path); // Returns true if this path exists, following symlinks. bool PathExists(const std::string& path); // Returns the real, absolute path corresponding to `path`. // The method resolves all symlink components of `path`. // Returns the empty string upon error. // // This is a wrapper around realpath(3). std::string MakeCanonical(const char *path); // Returns true if `path` exists, is a file or symlink to one, and is readable. // Follows symlinks. bool CanReadFile(const std::string &path); // Returns true if `path` exists, is a file or symlink to one, and is writable. // Follows symlinks. bool CanExecuteFile(const std::string &path); // Returns true if `path` exists, is a directory or symlink/junction to one, and // is both readable and writable. // Follows symlinks/junctions. bool CanAccessDirectory(const std::string &path); // Returns true if `path` refers to a directory or a symlink/junction to one. bool IsDirectory(const std::string& path); // Calls fsync() on the file (or directory) specified in 'file_path'. // pdie() if syncing fails. void SyncFile(const std::string& path); // mkdir -p path. All newly created directories use the given mode. // `mode` should be an octal permission mask, e.g. 0755. // Returns false on failure, sets errno. bool MakeDirectories(const std::string &path, unsigned int mode); // Returns the current working directory. // The path is platform-specific (e.g. Windows path of Windows) and absolute. std::string GetCwd(); // Changes the current working directory to `path`, returns true upon success. bool ChangeDirectory(const std::string& path); // Interface to be implemented by ForEachDirectoryEntry clients. class DirectoryEntryConsumer { public: virtual ~DirectoryEntryConsumer() {} // This method is called for each entry in a directory. // `name` is the full path of the entry. // `is_directory` is true if this entry is a directory (but false if this is a // symlink pointing to a directory). virtual void Consume(const std::string &name, bool is_directory) = 0; }; // Executes a function for each entry in a directory (except "." and ".."). // // Returns true if the `path` referred to a directory or directory symlink, // false otherwise. // // See DirectoryEntryConsumer for more details. void ForEachDirectoryEntry(const std::string &path, DirectoryEntryConsumer *consume); #if defined(_WIN32) || defined(__CYGWIN__) std::wstring GetCwdW(); #endif // defined(_WIN32) || defined(__CYGWIN__) } // namespace blaze_util #endif // BAZEL_SRC_MAIN_CPP_UTIL_FILE_PLATFORM_H_