1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2009 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBARTBASE_BASE_UNIX_FILE_FD_FILE_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_LIBARTBASE_BASE_UNIX_FILE_FD_FILE_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <fcntl.h> 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker #include <string> 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 25*795d594fSAndroid Build Coastguard Worker #include "random_access_file.h" 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Worker namespace unix_file { 28*795d594fSAndroid Build Coastguard Worker 29*795d594fSAndroid Build Coastguard Worker // If true, check whether Flush and Close are called before destruction. 30*795d594fSAndroid Build Coastguard Worker static constexpr bool kCheckSafeUsage = true; 31*795d594fSAndroid Build Coastguard Worker 32*795d594fSAndroid Build Coastguard Worker // A RandomAccessFile implementation backed by a file descriptor. 33*795d594fSAndroid Build Coastguard Worker // 34*795d594fSAndroid Build Coastguard Worker // Not thread safe. 35*795d594fSAndroid Build Coastguard Worker class FdFile : public RandomAccessFile { 36*795d594fSAndroid Build Coastguard Worker public: 37*795d594fSAndroid Build Coastguard Worker static constexpr int kInvalidFd = -1; 38*795d594fSAndroid Build Coastguard Worker 39*795d594fSAndroid Build Coastguard Worker FdFile() = default; 40*795d594fSAndroid Build Coastguard Worker // Creates an FdFile using the given file descriptor. 41*795d594fSAndroid Build Coastguard Worker // Takes ownership of the file descriptor. 42*795d594fSAndroid Build Coastguard Worker FdFile(int fd, bool check_usage); 43*795d594fSAndroid Build Coastguard Worker FdFile(int fd, const std::string& path, bool check_usage); 44*795d594fSAndroid Build Coastguard Worker FdFile(int fd, const std::string& path, bool check_usage, bool read_only_mode); 45*795d594fSAndroid Build Coastguard Worker FdFile(const std::string & path,int flags,bool check_usage)46*795d594fSAndroid Build Coastguard Worker FdFile(const std::string& path, int flags, bool check_usage) 47*795d594fSAndroid Build Coastguard Worker : FdFile(path, flags, 0640, check_usage) {} 48*795d594fSAndroid Build Coastguard Worker FdFile(const std::string& path, int flags, mode_t mode, bool check_usage); 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker // Move constructor. 51*795d594fSAndroid Build Coastguard Worker FdFile(FdFile&& other) noexcept; 52*795d594fSAndroid Build Coastguard Worker 53*795d594fSAndroid Build Coastguard Worker // Move assignment operator. 54*795d594fSAndroid Build Coastguard Worker FdFile& operator=(FdFile&& other) noexcept; 55*795d594fSAndroid Build Coastguard Worker 56*795d594fSAndroid Build Coastguard Worker // Release the file descriptor. This will make further accesses to this FdFile invalid. Disables 57*795d594fSAndroid Build Coastguard Worker // all further state checking. 58*795d594fSAndroid Build Coastguard Worker int Release(); 59*795d594fSAndroid Build Coastguard Worker 60*795d594fSAndroid Build Coastguard Worker void Reset(int fd, bool check_usage); 61*795d594fSAndroid Build Coastguard Worker 62*795d594fSAndroid Build Coastguard Worker // Destroys an FdFile, closing the file descriptor if Close hasn't already 63*795d594fSAndroid Build Coastguard Worker // been called. (If you care about the return value of Close, call it 64*795d594fSAndroid Build Coastguard Worker // yourself; this is meant to handle failure cases and read-only accesses. 65*795d594fSAndroid Build Coastguard Worker // Note though that calling Close and checking its return value is still no 66*795d594fSAndroid Build Coastguard Worker // guarantee that data actually made it to stable storage.) 67*795d594fSAndroid Build Coastguard Worker virtual ~FdFile(); 68*795d594fSAndroid Build Coastguard Worker 69*795d594fSAndroid Build Coastguard Worker // RandomAccessFile API. 70*795d594fSAndroid Build Coastguard Worker int Close() override WARN_UNUSED; 71*795d594fSAndroid Build Coastguard Worker int64_t Read(char* buf, int64_t byte_count, int64_t offset) const override WARN_UNUSED; 72*795d594fSAndroid Build Coastguard Worker int SetLength(int64_t new_length) override WARN_UNUSED; 73*795d594fSAndroid Build Coastguard Worker int64_t GetLength() const override; 74*795d594fSAndroid Build Coastguard Worker int64_t Write(const char* buf, int64_t byte_count, int64_t offset) override WARN_UNUSED; 75*795d594fSAndroid Build Coastguard Worker Flush()76*795d594fSAndroid Build Coastguard Worker int Flush() override WARN_UNUSED { return Flush(/*flush_metadata=*/false); } 77*795d594fSAndroid Build Coastguard Worker int Flush(bool flush_metadata) WARN_UNUSED; 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker // Short for SetLength(0); Flush(); Close(); 80*795d594fSAndroid Build Coastguard Worker // If the file was opened with a path name and unlink = true, also calls Unlink() on the path. 81*795d594fSAndroid Build Coastguard Worker // Note that it is the the caller's responsibility to avoid races. 82*795d594fSAndroid Build Coastguard Worker bool Erase(bool unlink = false); 83*795d594fSAndroid Build Coastguard Worker 84*795d594fSAndroid Build Coastguard Worker // Call unlink(), though only if FilePathMatchesFd() returns true. 85*795d594fSAndroid Build Coastguard Worker bool Unlink(); 86*795d594fSAndroid Build Coastguard Worker 87*795d594fSAndroid Build Coastguard Worker // Try to Flush(), then try to Close(); If either fails, call Erase(). 88*795d594fSAndroid Build Coastguard Worker int FlushCloseOrErase() WARN_UNUSED; 89*795d594fSAndroid Build Coastguard Worker 90*795d594fSAndroid Build Coastguard Worker // Try to Flush and Close(). Attempts both, but returns the first error. 91*795d594fSAndroid Build Coastguard Worker int FlushClose() WARN_UNUSED; 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker // Bonus API. 94*795d594fSAndroid Build Coastguard Worker int Fd() const; 95*795d594fSAndroid Build Coastguard Worker bool ReadOnlyMode() const; 96*795d594fSAndroid Build Coastguard Worker bool CheckUsage() const; 97*795d594fSAndroid Build Coastguard Worker 98*795d594fSAndroid Build Coastguard Worker // Check whether the underlying file descriptor refers to an open file. 99*795d594fSAndroid Build Coastguard Worker bool IsOpened() const; 100*795d594fSAndroid Build Coastguard Worker 101*795d594fSAndroid Build Coastguard Worker // Check whether the numeric value of the underlying file descriptor is valid (Fd() != -1). IsValid()102*795d594fSAndroid Build Coastguard Worker bool IsValid() const { return fd_ != kInvalidFd; } 103*795d594fSAndroid Build Coastguard Worker GetPath()104*795d594fSAndroid Build Coastguard Worker const std::string& GetPath() const { 105*795d594fSAndroid Build Coastguard Worker return file_path_; 106*795d594fSAndroid Build Coastguard Worker } 107*795d594fSAndroid Build Coastguard Worker bool ReadFully(void* buffer, size_t byte_count) WARN_UNUSED; 108*795d594fSAndroid Build Coastguard Worker bool PreadFully(void* buffer, size_t byte_count, size_t offset) WARN_UNUSED; 109*795d594fSAndroid Build Coastguard Worker bool WriteFully(const void* buffer, size_t byte_count) WARN_UNUSED; 110*795d594fSAndroid Build Coastguard Worker bool PwriteFully(const void* buffer, size_t byte_count, size_t offset) WARN_UNUSED; 111*795d594fSAndroid Build Coastguard Worker 112*795d594fSAndroid Build Coastguard Worker // Change the file path, though only if FilePathMatchesFd() returns true. 113*795d594fSAndroid Build Coastguard Worker // 114*795d594fSAndroid Build Coastguard Worker // If a file at new_path already exists, it will be replaced. 115*795d594fSAndroid Build Coastguard Worker // On Linux, the rename syscall will fail unless the source and destination are on the same 116*795d594fSAndroid Build Coastguard Worker // mounted filesystem. 117*795d594fSAndroid Build Coastguard Worker // This function is not expected to modify the file data itself, instead it modifies the inodes of 118*795d594fSAndroid Build Coastguard Worker // the source and destination directories, and therefore the function flushes those file 119*795d594fSAndroid Build Coastguard Worker // descriptors following the rename. 120*795d594fSAndroid Build Coastguard Worker bool Rename(const std::string& new_path); 121*795d594fSAndroid Build Coastguard Worker // Copy data from another file. 122*795d594fSAndroid Build Coastguard Worker // On Linux, we only support copies that will append regions to the file, and we require the file 123*795d594fSAndroid Build Coastguard Worker // offset of the output file descriptor to be aligned with the filesystem blocksize (see comments 124*795d594fSAndroid Build Coastguard Worker // in implementation). 125*795d594fSAndroid Build Coastguard Worker bool Copy(FdFile* input_file, int64_t offset, int64_t size); 126*795d594fSAndroid Build Coastguard Worker // Clears the file content and resets the file offset to 0. 127*795d594fSAndroid Build Coastguard Worker // Returns true upon success, false otherwise. 128*795d594fSAndroid Build Coastguard Worker bool ClearContent(); 129*795d594fSAndroid Build Coastguard Worker // Resets the file offset to the beginning of the file. 130*795d594fSAndroid Build Coastguard Worker bool ResetOffset(); 131*795d594fSAndroid Build Coastguard Worker 132*795d594fSAndroid Build Coastguard Worker // This enum is public so that we can define the << operator over it. 133*795d594fSAndroid Build Coastguard Worker enum class GuardState { 134*795d594fSAndroid Build Coastguard Worker kBase, // Base, file has not been flushed or closed. 135*795d594fSAndroid Build Coastguard Worker kFlushed, // File has been flushed, but not closed. 136*795d594fSAndroid Build Coastguard Worker kClosed, // File has been flushed and closed. 137*795d594fSAndroid Build Coastguard Worker kNoCheck // Do not check for the current file instance. 138*795d594fSAndroid Build Coastguard Worker }; 139*795d594fSAndroid Build Coastguard Worker 140*795d594fSAndroid Build Coastguard Worker // WARNING: Only use this when you know what you're doing! 141*795d594fSAndroid Build Coastguard Worker void MarkUnchecked(); 142*795d594fSAndroid Build Coastguard Worker 143*795d594fSAndroid Build Coastguard Worker // Compare against another file. Returns 0 if the files are equivalent, otherwise returns -1 or 1 144*795d594fSAndroid Build Coastguard Worker // depending on if the lengths are different. If the lengths are the same, the function returns 145*795d594fSAndroid Build Coastguard Worker // the difference of the first byte that differs. 146*795d594fSAndroid Build Coastguard Worker int Compare(FdFile* other); 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker // Check that `fd` has a valid value (!= kInvalidFd) and refers to an open file. 149*795d594fSAndroid Build Coastguard Worker // On Windows, this call only checks that the value of `fd` is valid . 150*795d594fSAndroid Build Coastguard Worker static bool IsOpenFd(int fd); 151*795d594fSAndroid Build Coastguard Worker 152*795d594fSAndroid Build Coastguard Worker protected: 153*795d594fSAndroid Build Coastguard Worker // If the guard state indicates checking (!=kNoCheck), go to the target state `target`. Print the 154*795d594fSAndroid Build Coastguard Worker // given warning if the current state is or exceeds warn_threshold. 155*795d594fSAndroid Build Coastguard Worker void moveTo(GuardState target, GuardState warn_threshold, const char* warning); 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker // If the guard state indicates checking (<kNoCheck), and is below the target state `target`, go 158*795d594fSAndroid Build Coastguard Worker // to `target`. If the current state is higher (excluding kNoCheck) than the target state, print 159*795d594fSAndroid Build Coastguard Worker // the warning. 160*795d594fSAndroid Build Coastguard Worker void moveUp(GuardState target, const char* warning); 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker // Forcefully sets the state to the given one. This can overwrite kNoCheck. resetGuard(GuardState new_state)163*795d594fSAndroid Build Coastguard Worker void resetGuard(GuardState new_state) { 164*795d594fSAndroid Build Coastguard Worker if (kCheckSafeUsage) { 165*795d594fSAndroid Build Coastguard Worker guard_state_ = new_state; 166*795d594fSAndroid Build Coastguard Worker } 167*795d594fSAndroid Build Coastguard Worker } 168*795d594fSAndroid Build Coastguard Worker 169*795d594fSAndroid Build Coastguard Worker GuardState guard_state_ = GuardState::kClosed; 170*795d594fSAndroid Build Coastguard Worker 171*795d594fSAndroid Build Coastguard Worker // Opens file `file_path` using `flags` and `mode`. 172*795d594fSAndroid Build Coastguard Worker bool Open(const std::string& file_path, int flags); 173*795d594fSAndroid Build Coastguard Worker bool Open(const std::string& file_path, int flags, mode_t mode); 174*795d594fSAndroid Build Coastguard Worker 175*795d594fSAndroid Build Coastguard Worker private: 176*795d594fSAndroid Build Coastguard Worker template <bool kUseOffset> 177*795d594fSAndroid Build Coastguard Worker bool WriteFullyGeneric(const void* buffer, size_t byte_count, size_t offset); 178*795d594fSAndroid Build Coastguard Worker 179*795d594fSAndroid Build Coastguard Worker // The file path we hold for the file descriptor may be invalid, or may not even exist (e.g. if 180*795d594fSAndroid Build Coastguard Worker // the FdFile wasn't initialised with a path). This helper function checks if calling open() on 181*795d594fSAndroid Build Coastguard Worker // the file path (if it is set) returns the expected up-to-date file descriptor. This is still 182*795d594fSAndroid Build Coastguard Worker // racy, though, and it is up to the caller to ensure correctness in a multi-process setup. 183*795d594fSAndroid Build Coastguard Worker bool FilePathMatchesFd(); 184*795d594fSAndroid Build Coastguard Worker 185*795d594fSAndroid Build Coastguard Worker #ifdef __linux__ 186*795d594fSAndroid Build Coastguard Worker // Sparse copy of 'size' bytes from an input file, starting at 'off'. Both this file's offset and 187*795d594fSAndroid Build Coastguard Worker // the input file's offset will be incremented by 'size' bytes. 188*795d594fSAndroid Build Coastguard Worker // 189*795d594fSAndroid Build Coastguard Worker // Note: in order to preserve the same sparsity, the input and output files must be on mounted 190*795d594fSAndroid Build Coastguard Worker // filesystems that use the same blocksize, and the offsets used for the copy must be aligned to 191*795d594fSAndroid Build Coastguard Worker // it. Otherwise, the copied region's sparsity within the output file may differ from its original 192*795d594fSAndroid Build Coastguard Worker // sparsity in the input file. 193*795d594fSAndroid Build Coastguard Worker bool UserspaceSparseCopy(const FdFile* input_file, off_t off, size_t size, size_t fs_blocksize); 194*795d594fSAndroid Build Coastguard Worker 195*795d594fSAndroid Build Coastguard Worker // Write 'size' bytes from 'data' to the file if any are non-zero. Otherwise, just update the file 196*795d594fSAndroid Build Coastguard Worker // offset and skip the write. For efficiency, the function expects a vector of zeroed uint8_t 197*795d594fSAndroid Build Coastguard Worker // values to check the data array against. This vector 'zeroes' must have length greater than or 198*795d594fSAndroid Build Coastguard Worker // equal to 'size'. 199*795d594fSAndroid Build Coastguard Worker // 200*795d594fSAndroid Build Coastguard Worker // As filesystems which support sparse files only allocate physical space to blocks that have been 201*795d594fSAndroid Build Coastguard Worker // written, any whole filesystem blocks in the output file which are skipped in this way will save 202*795d594fSAndroid Build Coastguard Worker // storage space. Subsequent reads of bytes in non-allocated blocks will simply return zeros 203*795d594fSAndroid Build Coastguard Worker // without accessing the underlying storage. 204*795d594fSAndroid Build Coastguard Worker bool SparseWrite(const uint8_t* data, 205*795d594fSAndroid Build Coastguard Worker size_t size, 206*795d594fSAndroid Build Coastguard Worker const std::vector<uint8_t>& zeroes); 207*795d594fSAndroid Build Coastguard Worker #endif 208*795d594fSAndroid Build Coastguard Worker 209*795d594fSAndroid Build Coastguard Worker void Destroy(); // For ~FdFile and operator=(&&). 210*795d594fSAndroid Build Coastguard Worker 211*795d594fSAndroid Build Coastguard Worker int fd_ = kInvalidFd; 212*795d594fSAndroid Build Coastguard Worker std::string file_path_; 213*795d594fSAndroid Build Coastguard Worker bool read_only_mode_ = false; 214*795d594fSAndroid Build Coastguard Worker 215*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(FdFile); 216*795d594fSAndroid Build Coastguard Worker }; 217*795d594fSAndroid Build Coastguard Worker 218*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, FdFile::GuardState kind); 219*795d594fSAndroid Build Coastguard Worker 220*795d594fSAndroid Build Coastguard Worker } // namespace unix_file 221*795d594fSAndroid Build Coastguard Worker 222*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBARTBASE_BASE_UNIX_FILE_FD_FILE_H_ 223