1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "base/logging.h" 18 #include "base/unix_file/fd_file.h" 19 #include <errno.h> 20 #include <sys/stat.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 24 namespace unix_file { 25 26 FdFile::FdFile() : fd_(-1), auto_close_(true) { 27 } 28 29 FdFile::FdFile(int fd) : fd_(fd), auto_close_(true) { 30 } 31 32 FdFile::FdFile(int fd, const std::string& path) : fd_(fd), file_path_(path), auto_close_(true) { 33 CHECK_NE(0U, path.size()); 34 } 35 36 FdFile::~FdFile() { 37 if (auto_close_ && fd_ != -1) { 38 Close(); 39 } 40 } 41 42 void FdFile::DisableAutoClose() { 43 auto_close_ = false; 44 } 45 46 bool FdFile::Open(const std::string& path, int flags) { 47 return Open(path, flags, 0640); 48 } 49 50 bool FdFile::Open(const std::string& path, int flags, mode_t mode) { 51 CHECK_EQ(fd_, -1) << path; 52 fd_ = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)); 53 if (fd_ == -1) { 54 return false; 55 } 56 file_path_ = path; 57 return true; 58 } 59 60 int FdFile::Close() { 61 int result = TEMP_FAILURE_RETRY(close(fd_)); 62 if (result == -1) { 63 return -errno; 64 } else { 65 fd_ = -1; 66 file_path_ = ""; 67 return 0; 68 } 69 } 70 71 int FdFile::Flush() { 72 int rc = TEMP_FAILURE_RETRY(fdatasync(fd_)); 73 return (rc == -1) ? -errno : rc; 74 } 75 76 int64_t FdFile::Read(char* buf, int64_t byte_count, int64_t offset) const { 77 int rc = TEMP_FAILURE_RETRY(pread64(fd_, buf, byte_count, offset)); 78 return (rc == -1) ? -errno : rc; 79 } 80 81 int FdFile::SetLength(int64_t new_length) { 82 int rc = TEMP_FAILURE_RETRY(ftruncate64(fd_, new_length)); 83 return (rc == -1) ? -errno : rc; 84 } 85 86 int64_t FdFile::GetLength() const { 87 struct stat s; 88 int rc = TEMP_FAILURE_RETRY(fstat(fd_, &s)); 89 return (rc == -1) ? -errno : s.st_size; 90 } 91 92 int64_t FdFile::Write(const char* buf, int64_t byte_count, int64_t offset) { 93 int rc = TEMP_FAILURE_RETRY(pwrite64(fd_, buf, byte_count, offset)); 94 return (rc == -1) ? -errno : rc; 95 } 96 97 int FdFile::Fd() const { 98 return fd_; 99 } 100 101 bool FdFile::IsOpened() const { 102 return fd_ >= 0; 103 } 104 105 std::string FdFile::GetPath() const { 106 return file_path_; 107 } 108 109 bool FdFile::ReadFully(void* buffer, int64_t byte_count) { 110 char* ptr = static_cast<char*>(buffer); 111 while (byte_count > 0) { 112 int bytes_read = TEMP_FAILURE_RETRY(read(fd_, ptr, byte_count)); 113 if (bytes_read <= 0) { 114 return false; 115 } 116 byte_count -= bytes_read; // Reduce the number of remaining bytes. 117 ptr += bytes_read; // Move the buffer forward. 118 } 119 return true; 120 } 121 122 bool FdFile::WriteFully(const void* buffer, int64_t byte_count) { 123 const char* ptr = static_cast<const char*>(buffer); 124 while (byte_count > 0) { 125 int bytes_read = TEMP_FAILURE_RETRY(write(fd_, ptr, byte_count)); 126 if (bytes_read < 0) { 127 return false; 128 } 129 byte_count -= bytes_read; // Reduce the number of remaining bytes. 130 ptr += bytes_read; // Move the buffer forward. 131 } 132 return true; 133 } 134 135 } // namespace unix_file 136