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_LEGACY_INDEX_ICING_FILESYSTEM_H_ 18 #define ICING_LEGACY_INDEX_ICING_FILESYSTEM_H_ 19 20 #include <sys/types.h> 21 22 #include <cstddef> 23 #include <cstdint> 24 #include <cstdio> 25 #include <memory> 26 #include <string> 27 #include <unordered_set> 28 #include <utility> 29 #include <vector> 30 31 namespace icing { 32 namespace lib { 33 34 // Closes fd when it goes out of scope, if fd >= 0. 35 class IcingScopedFd { 36 public: fd_(fd)37 explicit IcingScopedFd(int fd = -1) : fd_(fd) {} 38 IcingScopedFd(const IcingScopedFd &) = delete; IcingScopedFd(IcingScopedFd && other)39 IcingScopedFd(IcingScopedFd &&other) : IcingScopedFd() { 40 *this = std::move(other); 41 } 42 43 IcingScopedFd &operator=(const IcingScopedFd &) = delete; 44 IcingScopedFd &operator=(IcingScopedFd &&other) { 45 std::swap(fd_, other.fd_); 46 return *this; 47 } 48 ~IcingScopedFd(); 49 is_valid()50 bool is_valid() const { return fd_ >= 0; } 51 int operator*() const { return fd_; } get()52 int get() const { return fd_; } 53 void reset(int fd = -1); 54 55 private: 56 int fd_; 57 }; 58 59 struct IcingFILEDeleter { operatorIcingFILEDeleter60 void operator()(FILE *fp) const { 61 if (fp) { 62 fclose(fp); 63 } 64 } 65 }; 66 typedef std::unique_ptr<FILE, IcingFILEDeleter> IcingScopedFILE; 67 68 // Class containing file operation methods. 69 // If you change methods in this class, don't forget to update the mock: 70 // java/com/google/android/gmscore/integ/modules/icing/jni/index/mock-filesystem.h 71 class IcingFilesystem { 72 public: 73 static const uint64_t kBadFileSize = static_cast<uint64_t>(-1); 74 IcingFilesystem()75 constexpr IcingFilesystem() {} ~IcingFilesystem()76 virtual ~IcingFilesystem() {} 77 78 // Deletes a file, returns true on success or if the file did 79 // not yet exist. 80 virtual bool DeleteFile(const char *file_name) const; 81 82 // Deletes a directory, returns true on success or if the directory did 83 // not yet exist. 84 virtual bool DeleteDirectory(const char *dir_name) const; 85 86 // Deletes a directory, including any contents, and returns true on 87 // success or if the directory did not yet exist. 88 virtual bool DeleteDirectoryRecursively(const char *dir_name) const; 89 90 // Returns true if a file exists. False if the file doesn't exist. 91 // If there is an error getting stat on the file, it logs the error and 92 // asserts. 93 virtual bool FileExists(const char *file_name) const; 94 95 // Returns true if a directory exists. False if the file doesn't exist. 96 // If there is an error getting stat on the file, it logs the error and 97 // asserts. 98 virtual bool DirectoryExists(const char *dir_name) const; 99 100 // Return index to start of basename in file_name. Anything before 101 // basename is the dirname (including the final slash). 102 virtual int GetBasenameIndex(const char *file_name) const; 103 104 // Return a string containing the basename. 105 virtual std::string GetBasename(const char *file_name) const; 106 107 // Return a string containing the dirname. 108 virtual std::string GetDirname(const char *file_name) const; 109 110 // Gets the names of the entries of a given directory. Does not include "." 111 // and "..". Returns false on error. 112 virtual bool ListDirectory(const char *dir_name, 113 std::vector<std::string> *entries) const; 114 115 // Adds the names of the entries of a given directory -- recursively if 116 // specified, and excluding files/directories named in exclude -- to entries. 117 // Regardless of exclude, does not include "." and "..". Excluded files are 118 // excluded at every level. Returns false on error. 119 // 120 // Example use case: list all files & directories in fooDir/, recursively, 121 // excluding anything named "tmp" or "cache" (presumed directories) and the 122 // files within them. 123 virtual bool ListDirectory(const char *dir_name, 124 const std::unordered_set<std::string> &exclude, 125 bool recursive, 126 std::vector<std::string> *entries) const; 127 128 // Use glob to return matched files into "matches". Returns false if 129 // glob had an error. 130 // 131 // Cannot match multiple directories so everything up the last slash 132 // must be literal. 133 virtual bool GetMatchingFiles(const char *glob, 134 std::vector<std::string> *matches) const; 135 136 // Opens the file for read/write. Creates if not existing. Returns 137 // -1 on fail or an open file descriptor on success. 138 virtual int OpenForWrite(const char *file_name) const; 139 140 // Opens the file for read/write, and positions the file at the 141 // end for appending. Creates if not existing. Returns -1 on fail 142 // or an open file descriptor on success. 143 virtual int OpenForAppend(const char *file_name) const; 144 145 // Opens a file for read only. Fails if file does exist. Returns 146 // file descriptor or -1 on fail. Set quiet to true to suppress 147 // log warnings. 148 virtual int OpenForRead(const char *file_name) const; 149 150 // Gets the size of a file, given an open file descriptor. 151 // Returns kBadFileSize on error. 152 virtual uint64_t GetFileSize(int fd) const; 153 154 // Gets the size of a file, given a filename. 155 virtual uint64_t GetFileSize(const char *filename) const; 156 157 // Truncates the file to the requested size. Seeks to the 158 // end position of the file after truncate. Returns false 159 // if fails. 160 virtual bool Truncate(int fd, uint64_t new_size) const; 161 162 // Truncates the file to the requested size. 163 // Returns false if fails. 164 virtual bool Truncate(const char *filename, uint64_t new_size) const; 165 166 // Grows the file to the requested size. Does not change the 167 // position pointer. 168 virtual bool Grow(int fd, uint64_t new_size) const; 169 170 // Implementation of Grow that calls Pwrite to directly append zero-filled 171 // byte arrays into the file. Does not change the position pointer. 172 // 173 // This is different from Grow (which uses ftruncate), which doesn't actually 174 // allocate an underlying disk block. Grow has lead to crashes in the past as 175 // there is no effective way to signal that disk block allocation failed, and 176 // we end up trying to access memory-mapped region with unallocated disk 177 // block. 178 // 179 // Using Pwrite forces block allocation and ensures that we can return false 180 // when the disk block is not allocated. 181 // 182 // Note: This method does not change the file size if new_size <= current 183 // file size. Caller should use Truncate for reducing the file size. 184 virtual bool GrowUsingPWrite(int fd, uint64_t new_size) const; 185 186 // Writes to a file. Returns true if all the data was successfully 187 // written. Handles interrupted writes. 188 virtual bool Write(int fd, const void *data, size_t data_size) const; 189 virtual bool PWrite(int fd, off_t offset, const void *data, 190 size_t data_size) 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 // Copy a file. 210 virtual bool CopyFile(const char *src, const char *dst) const; 211 212 // Compute an adler32 checksum over the [offset, offset+length) span 213 // of an open file. Returns false if the file could not be read. 214 // The checksum is an input/output variable (whatever value is 215 // stored there will prime the checksum computation). If length is 216 // 0, can be used to prime a checksum for future appends. 217 virtual bool ComputeChecksum(int fd, uint32_t *checksum, uint64_t offset, 218 uint64_t length) const; 219 220 // Compute the disk usage of the given file. Similarly to the 221 // 'du' command, it attempts to estimate the actual disk usage, so for 222 // sparse files it may return less than their length. 223 // Returns kBadFileSize on error. 224 virtual uint64_t GetDiskUsage(int fd) const; 225 226 // Compute the disk usage of the given file or directory. Similarly to the 227 // 'du' command, it attempts to estimate the actual disk usage, so for 228 // sparse files it may return less than their length. Returns kBadFileSize on 229 // error. 230 // Does not recurse on directories. 231 virtual uint64_t GetFileDiskUsage(const char *path) const; 232 233 // Compute the disk usage of the given file or directory. Similarly to the 234 // 'du' command, it attempts to estimate the actual disk usage, so for 235 // sparse files it may return less than their length. Returns kBadFileSize on 236 // error. 237 // Recurses on directories. 238 virtual uint64_t GetDiskUsage(const char *path) const; 239 240 // Increments to_increment by size if size is valid, or sets to_increment 241 // to kBadFileSize if either size or to_increment is kBadFileSize. 242 static void IncrementByOrSetInvalid(uint64_t size, uint64_t *to_increment); 243 244 // Return -1 if file_size is invalid. Otherwise, return file_size. SanitizeFileSize(int64_t file_size)245 static int64_t SanitizeFileSize(int64_t file_size) { 246 return (file_size != kBadFileSize) ? file_size : -1; 247 } 248 }; 249 250 } // namespace lib 251 } // namespace icing 252 253 #endif // ICING_LEGACY_INDEX_ICING_FILESYSTEM_H_ 254