1 // Copyright (C) 2019 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Methods for interacting with the filesystem. 16 17 #ifndef ICING_FILE_FILESYSTEM_H_ 18 #define ICING_FILE_FILESYSTEM_H_ 19 20 #include <cstdint> 21 #include <cstdio> 22 #include <cstring> 23 #include <memory> 24 #include <string> 25 #include <unordered_set> 26 #include <vector> 27 28 namespace icing { 29 namespace lib { 30 31 // Closes fd when it goes out of scope, if fd >= 0. 32 class ScopedFd { 33 public: fd_(fd)34 explicit ScopedFd(int fd = -1) : fd_(fd) {} 35 ScopedFd(const ScopedFd&) = delete; ScopedFd(ScopedFd && other)36 ScopedFd(ScopedFd&& other) : ScopedFd() { *this = std::move(other); } 37 38 ScopedFd& operator=(const ScopedFd&) = delete; 39 ScopedFd& operator=(ScopedFd&& other) { 40 std::swap(fd_, other.fd_); 41 return *this; 42 } 43 ~ScopedFd(); 44 is_valid()45 bool is_valid() const { return fd_ >= 0; } 46 int operator*() const { return fd_; } get()47 int get() const { return fd_; } 48 void reset(int fd = -1); 49 50 private: 51 int fd_; 52 }; 53 54 struct FILEDeleter { operatorFILEDeleter55 void operator()(FILE* fp) const { 56 if (fp) { 57 fclose(fp); 58 } 59 } 60 }; 61 typedef std::unique_ptr<FILE, FILEDeleter> ScopedFILE; 62 63 // Class containing file operation methods. 64 // LINT.IfChange 65 class Filesystem { 66 public: 67 static const int64_t kBadFileSize = std::numeric_limits<int64_t>::max(); 68 69 constexpr Filesystem() = default; 70 virtual ~Filesystem() = default; 71 72 // Deletes a file, returns true on success or if the file did 73 // not yet exist. 74 virtual bool DeleteFile(const char* file_name) const; 75 76 // Deletes a directory, returns true on success or if the directory did 77 // not yet exist. 78 virtual bool DeleteDirectory(const char* dir_name) const; 79 80 // Deletes a directory, including any contents, and returns true on 81 // success or if the directory did not yet exist. 82 virtual bool DeleteDirectoryRecursively(const char* dir_name) const; 83 84 // Copies the src file to the dst file. 85 virtual bool CopyFile(const char* src, const char* dst) const; 86 87 // Copies the src directory and its contents to the dst dir. 88 virtual bool CopyDirectory(const char* src_dir, const char* dst_dir, 89 bool recursive) const; 90 91 // Returns true if a file exists. False if the file doesn't exist. 92 // If there is an error getting stat on the file, it logs the error and 93 // asserts. 94 virtual bool FileExists(const char* file_name) const; 95 96 // Returns true if a directory exists. False if the file doesn't exist. 97 // If there is an error getting stat on the file, it logs the error and 98 // asserts. 99 virtual bool DirectoryExists(const char* dir_name) const; 100 101 // Return index to start of basename in file_name. Anything before 102 // basename is the dirname (including the final slash). 103 virtual int GetBasenameIndex(const char* file_name) const; 104 105 // Return a string containing the basename. 106 virtual std::string GetBasename(const char* file_name) const; 107 108 // Return a string containing the dirname. 109 virtual std::string GetDirname(const char* file_name) const; 110 111 // Gets the names of the entries of a given directory. Does not include "." 112 // and "..". Returns false on error. 113 virtual bool ListDirectory(const char* dir_name, 114 std::vector<std::string>* entries) const; 115 116 // Adds the names of the entries of a given directory -- recursively if 117 // specified, and excluding files/directories named in exclude -- to entries. 118 // Regardless of exclude, does not include "." and "..". Excluded files are 119 // excluded at every level. Returns false on error. 120 // 121 // Example use case: list all files & directories in fooDir/, recursively, 122 // excluding anything named "tmp" or "cache" (presumed directories) and the 123 // files within them. 124 virtual bool ListDirectory(const char* dir_name, 125 const std::unordered_set<std::string>& exclude, 126 bool recursive, 127 std::vector<std::string>* entries) const; 128 129 // Use glob to return matched files into "matches". Returns false if 130 // glob had an error. 131 // 132 // Cannot match multiple directories so everything up the last slash 133 // must be literal. 134 virtual bool GetMatchingFiles(const char* glob, 135 std::vector<std::string>* matches) const; 136 137 // Opens the file for read/write. Creates if not existing. Returns 138 // -1 on fail or an open file descriptor on success. 139 virtual int OpenForWrite(const char* file_name) const; 140 141 // Opens the file for read/write, and positions the file at the 142 // end for appending. Creates if not existing. Returns -1 on fail 143 // or an open file descriptor on success. 144 virtual int OpenForAppend(const char* file_name) const; 145 146 // Opens a file for read only. Fails if file doesn't exist. Returns 147 // file descriptor or -1 on fail. Set quiet to true to suppress 148 // log warnings. 149 virtual int OpenForRead(const char* file_name) const; 150 151 // Gets the size of a file, given an open file descriptor. 152 // Returns kBadFileSize on error. 153 virtual int64_t GetFileSize(int fd) const; 154 155 // Gets the size of a file, given a filename. 156 virtual int64_t GetFileSize(const char* filename) const; 157 158 // Truncates the file to the requested size. Seeks to the 159 // end position of the file after truncate. Returns false 160 // if fails. 161 virtual bool Truncate(int fd, int64_t new_size) const; 162 163 // Truncates the file to the requested size. 164 // Returns false if fails. 165 virtual bool Truncate(const char* filename, int64_t new_size) const; 166 167 // Grows the file to the requested size. Does not change the 168 // position pointer. 169 virtual bool Grow(int fd, int64_t new_size) const; 170 virtual bool Grow(const char* filename, int64_t new_size) const; 171 172 // Writes to a file. Returns true if all the data was successfully 173 // written. Handles interrupted writes. 174 virtual bool Write(int fd, const void* data, size_t data_size) const; 175 virtual bool Write(const char* filename, const void* data, 176 size_t data_size) const; 177 178 virtual bool PWrite(int fd, off_t offset, const void* data, 179 size_t data_size) const; 180 virtual bool PWrite(const char* filename, off_t offset, const void* data, 181 size_t data_size) const; 182 183 // Reads from a file. Returns true if data was successfully read out. If the 184 // file is seekable, read starts at the file offset, and the file offset is 185 // incremented by number of bytes read. 186 virtual bool Read(int fd, void* buf, size_t buf_size) const; 187 virtual bool Read(const char* filename, void* buf, size_t buf_size) const; 188 virtual bool PRead(int fd, void* buf, size_t buf_size, off_t offset) const; 189 virtual bool PRead(const char* filename, void* buf, size_t buf_size, 190 off_t offset) const; 191 192 // Syncs the file to disk (fdatasync). Returns true on success. 193 virtual bool DataSync(int fd) const; 194 195 // Renames a file. A file with new_name must not already exist. 196 virtual bool RenameFile(const char* old_name, const char* new_name) const; 197 198 // Renames two files or directories so their names are swapped. 199 // Both names must already exist. 200 virtual bool SwapFiles(const char* one, const char* two) const; 201 202 // Creates a directory if it does not yet exist. 203 virtual bool CreateDirectory(const char* dir_name) const; 204 205 // Creates a directory if it does not yet exist, building the entire path 206 // if it does not yet exist. 207 virtual bool CreateDirectoryRecursively(const char* dir_name) const; 208 209 // Compute the disk usage of the given file. Similarly to the 210 // 'du' command, it attempts to estimate the actual disk usage, so for 211 // sparse files it may return less than their length. 212 // Returns kBadFileSize on error. 213 virtual int64_t GetDiskUsage(int fd) const; 214 215 // Compute the disk usage of the given file or directory. Similarly to the 216 // 'du' command, it attempts to estimate the actual disk usage, so for 217 // sparse files it may return less than their length. Returns kBadFileSize 218 // on error. Does not recurse on directories. 219 virtual int64_t GetFileDiskUsage(const char* path) const; 220 221 // Compute the disk usage of the given file or directory. Similarly to the 222 // 'du' command, it attempts to estimate the actual disk usage, so for 223 // sparse files it may return less than their length. Returns kBadFileSize 224 // on error. Recurses on directories. 225 virtual int64_t GetDiskUsage(const char* path) const; 226 227 // Returns the current position in the given file. Returns -1 and sets errno 228 // on failure. 229 virtual int64_t GetCurrentPosition(int fd) const; 230 231 virtual int64_t SetPosition(int fd, int offset) const; 232 233 // Increments to_increment by size if size is valid, or sets to_increment 234 // to kBadFileSize if either size or to_increment is kBadFileSize. 235 static void IncrementByOrSetInvalid(int64_t size, int64_t* to_increment); 236 237 // Return -1 if file_size is invalid. Otherwise, return file_size. SanitizeFileSize(int64_t file_size)238 static int64_t SanitizeFileSize(int64_t file_size) { 239 return (file_size != kBadFileSize) ? file_size : -1; 240 } 241 }; 242 // LINT.ThenChange(//depot/google3/icing/file/mock-filesystem.h) 243 244 } // namespace lib 245 } // namespace icing 246 247 #endif // ICING_FILE_FILESYSTEM_H_ 248