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 "fd_file.h" 18 19 #include <errno.h> 20 #include <sys/stat.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 24 #if defined(__BIONIC__) 25 #include <android/fdsan.h> 26 #endif 27 28 #if defined(_WIN32) 29 #include <windows.h> 30 #endif 31 32 #include <limits> 33 34 #include <android-base/file.h> 35 #include <android-base/logging.h> 36 37 // Includes needed for FdFile::Copy(). 38 #ifdef __linux__ 39 #include <sys/sendfile.h> 40 #else 41 #include <algorithm> 42 #include "base/globals.h" 43 #include "base/stl_util.h" 44 #endif 45 46 namespace unix_file { 47 48 #if defined(_WIN32) 49 // RAII wrapper for an event object to allow asynchronous I/O to correctly signal completion. 50 class ScopedEvent { 51 public: 52 ScopedEvent() { 53 handle_ = CreateEventA(/*lpEventAttributes*/ nullptr, 54 /*bManualReset*/ true, 55 /*bInitialState*/ false, 56 /*lpName*/ nullptr); 57 } 58 59 ~ScopedEvent() { CloseHandle(handle_); } 60 61 HANDLE handle() { return handle_; } 62 63 private: 64 HANDLE handle_; 65 DISALLOW_COPY_AND_ASSIGN(ScopedEvent); 66 }; 67 68 // Windows implementation of pread/pwrite. Note that these DO move the file descriptor's read/write 69 // position, but do so atomically. 70 static ssize_t pread(int fd, void* data, size_t byte_count, off64_t offset) { 71 ScopedEvent event; 72 if (event.handle() == INVALID_HANDLE_VALUE) { 73 PLOG(ERROR) << "Could not create event handle."; 74 errno = EIO; 75 return static_cast<ssize_t>(-1); 76 } 77 78 auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); 79 DWORD bytes_read = 0; 80 OVERLAPPED overlapped = {}; 81 overlapped.Offset = static_cast<DWORD>(offset); 82 overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32); 83 overlapped.hEvent = event.handle(); 84 if (!ReadFile(handle, data, static_cast<DWORD>(byte_count), &bytes_read, &overlapped)) { 85 // If the read failed with other than ERROR_IO_PENDING, return an error. 86 // ERROR_IO_PENDING signals the write was begun asynchronously. 87 // Block until the asynchronous operation has finished or fails, and return 88 // result accordingly. 89 if (::GetLastError() != ERROR_IO_PENDING || 90 !::GetOverlappedResult(handle, &overlapped, &bytes_read, TRUE)) { 91 // In case someone tries to read errno (since this is masquerading as a POSIX call). 92 errno = EIO; 93 return static_cast<ssize_t>(-1); 94 } 95 } 96 return static_cast<ssize_t>(bytes_read); 97 } 98 99 static ssize_t pwrite(int fd, const void* buf, size_t count, off64_t offset) { 100 ScopedEvent event; 101 if (event.handle() == INVALID_HANDLE_VALUE) { 102 PLOG(ERROR) << "Could not create event handle."; 103 errno = EIO; 104 return static_cast<ssize_t>(-1); 105 } 106 107 auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); 108 DWORD bytes_written = 0; 109 OVERLAPPED overlapped = {}; 110 overlapped.Offset = static_cast<DWORD>(offset); 111 overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32); 112 overlapped.hEvent = event.handle(); 113 if (!::WriteFile(handle, buf, count, &bytes_written, &overlapped)) { 114 // If the write failed with other than ERROR_IO_PENDING, return an error. 115 // ERROR_IO_PENDING signals the write was begun asynchronously. 116 // Block until the asynchronous operation has finished or fails, and return 117 // result accordingly. 118 if (::GetLastError() != ERROR_IO_PENDING || 119 !::GetOverlappedResult(handle, &overlapped, &bytes_written, TRUE)) { 120 // In case someone tries to read errno (since this is masquerading as a POSIX call). 121 errno = EIO; 122 return static_cast<ssize_t>(-1); 123 } 124 } 125 return static_cast<ssize_t>(bytes_written); 126 } 127 128 static int fsync(int fd) { 129 auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); 130 if (handle != INVALID_HANDLE_VALUE && ::FlushFileBuffers(handle)) { 131 return 0; 132 } 133 errno = EINVAL; 134 return -1; 135 } 136 #endif 137 138 #if defined(__BIONIC__) 139 static uint64_t GetFdFileOwnerTag(FdFile* fd_file) { 140 return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE, 141 reinterpret_cast<uint64_t>(fd_file)); 142 } 143 #endif 144 145 FdFile::FdFile(int fd, bool check_usage) 146 : FdFile(fd, std::string(), check_usage) {} 147 148 FdFile::FdFile(int fd, const std::string& path, bool check_usage) 149 : FdFile(fd, path, check_usage, false) {} 150 151 FdFile::FdFile(int fd, const std::string& path, bool check_usage, 152 bool read_only_mode) 153 : guard_state_(check_usage ? GuardState::kBase : GuardState::kNoCheck), 154 fd_(fd), 155 file_path_(path), 156 read_only_mode_(read_only_mode) { 157 #if defined(__BIONIC__) 158 if (fd >= 0) { 159 android_fdsan_exchange_owner_tag(fd, 0, GetFdFileOwnerTag(this)); 160 } 161 #endif 162 } 163 164 FdFile::FdFile(const std::string& path, int flags, mode_t mode, 165 bool check_usage) { 166 Open(path, flags, mode); 167 if (!check_usage || !IsOpened()) { 168 guard_state_ = GuardState::kNoCheck; 169 } 170 } 171 172 void FdFile::Destroy() { 173 if (kCheckSafeUsage && (guard_state_ < GuardState::kNoCheck)) { 174 if (guard_state_ < GuardState::kFlushed) { 175 LOG(ERROR) << "File " << file_path_ << " wasn't explicitly flushed before destruction."; 176 } 177 if (guard_state_ < GuardState::kClosed) { 178 LOG(ERROR) << "File " << file_path_ << " wasn't explicitly closed before destruction."; 179 } 180 DCHECK_GE(guard_state_, GuardState::kClosed); 181 } 182 if (fd_ != -1) { 183 if (Close() != 0) { 184 PLOG(WARNING) << "Failed to close file with fd=" << fd_ << " path=" << file_path_; 185 } 186 } 187 } 188 189 FdFile::FdFile(FdFile&& other) noexcept 190 : guard_state_(other.guard_state_), 191 fd_(other.fd_), 192 file_path_(std::move(other.file_path_)), 193 read_only_mode_(other.read_only_mode_) { 194 #if defined(__BIONIC__) 195 if (fd_ >= 0) { 196 android_fdsan_exchange_owner_tag(fd_, GetFdFileOwnerTag(&other), GetFdFileOwnerTag(this)); 197 } 198 #endif 199 other.guard_state_ = GuardState::kClosed; 200 other.fd_ = -1; 201 } 202 203 FdFile& FdFile::operator=(FdFile&& other) noexcept { 204 if (this == &other) { 205 return *this; 206 } 207 208 if (this->fd_ != other.fd_) { 209 Destroy(); // Free old state. 210 } 211 212 guard_state_ = other.guard_state_; 213 fd_ = other.fd_; 214 file_path_ = std::move(other.file_path_); 215 read_only_mode_ = other.read_only_mode_; 216 217 #if defined(__BIONIC__) 218 if (fd_ >= 0) { 219 android_fdsan_exchange_owner_tag(fd_, GetFdFileOwnerTag(&other), GetFdFileOwnerTag(this)); 220 } 221 #endif 222 other.guard_state_ = GuardState::kClosed; 223 other.fd_ = -1; 224 return *this; 225 } 226 227 FdFile::~FdFile() { 228 Destroy(); 229 } 230 231 int FdFile::Release() { 232 int tmp_fd = fd_; 233 fd_ = -1; 234 guard_state_ = GuardState::kNoCheck; 235 #if defined(__BIONIC__) 236 if (tmp_fd >= 0) { 237 android_fdsan_exchange_owner_tag(tmp_fd, GetFdFileOwnerTag(this), 0); 238 } 239 #endif 240 return tmp_fd; 241 } 242 243 void FdFile::Reset(int fd, bool check_usage) { 244 CHECK_NE(fd, fd_); 245 246 if (fd_ != -1) { 247 Destroy(); 248 } 249 fd_ = fd; 250 251 #if defined(__BIONIC__) 252 if (fd_ >= 0) { 253 android_fdsan_exchange_owner_tag(fd_, 0, GetFdFileOwnerTag(this)); 254 } 255 #endif 256 257 if (check_usage) { 258 guard_state_ = fd == -1 ? GuardState::kNoCheck : GuardState::kBase; 259 } else { 260 guard_state_ = GuardState::kNoCheck; 261 } 262 } 263 264 void FdFile::moveTo(GuardState target, GuardState warn_threshold, const char* warning) { 265 if (kCheckSafeUsage) { 266 if (guard_state_ < GuardState::kNoCheck) { 267 if (warn_threshold < GuardState::kNoCheck && guard_state_ >= warn_threshold) { 268 LOG(ERROR) << warning; 269 } 270 guard_state_ = target; 271 } 272 } 273 } 274 275 void FdFile::moveUp(GuardState target, const char* warning) { 276 if (kCheckSafeUsage) { 277 if (guard_state_ < GuardState::kNoCheck) { 278 if (guard_state_ < target) { 279 guard_state_ = target; 280 } else if (target < guard_state_) { 281 LOG(ERROR) << warning; 282 } 283 } 284 } 285 } 286 287 bool FdFile::Open(const std::string& path, int flags) { 288 return Open(path, flags, 0640); 289 } 290 291 bool FdFile::Open(const std::string& path, int flags, mode_t mode) { 292 static_assert(O_RDONLY == 0, "Readonly flag has unexpected value."); 293 DCHECK_EQ(fd_, -1) << path; 294 read_only_mode_ = ((flags & O_ACCMODE) == O_RDONLY); 295 fd_ = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)); 296 if (fd_ == -1) { 297 return false; 298 } 299 300 #if defined(__BIONIC__) 301 android_fdsan_exchange_owner_tag(fd_, 0, GetFdFileOwnerTag(this)); 302 #endif 303 304 file_path_ = path; 305 if (kCheckSafeUsage && (flags & (O_RDWR | O_CREAT | O_WRONLY)) != 0) { 306 // Start in the base state (not flushed, not closed). 307 guard_state_ = GuardState::kBase; 308 } else { 309 // We are not concerned with read-only files. In that case, proper flushing and closing is 310 // not important. 311 guard_state_ = GuardState::kNoCheck; 312 } 313 return true; 314 } 315 316 int FdFile::Close() { 317 #if defined(__BIONIC__) 318 int result = android_fdsan_close_with_tag(fd_, GetFdFileOwnerTag(this)); 319 #else 320 int result = close(fd_); 321 #endif 322 323 // Test here, so the file is closed and not leaked. 324 if (kCheckSafeUsage) { 325 DCHECK_GE(guard_state_, GuardState::kFlushed) << "File " << file_path_ 326 << " has not been flushed before closing."; 327 moveUp(GuardState::kClosed, nullptr); 328 } 329 330 #if defined(__linux__) 331 // close always succeeds on linux, even if failure is reported. 332 UNUSED(result); 333 #else 334 if (result == -1) { 335 return -errno; 336 } 337 #endif 338 339 fd_ = -1; 340 file_path_ = ""; 341 return 0; 342 } 343 344 int FdFile::Flush() { 345 DCHECK(!read_only_mode_); 346 347 #ifdef __linux__ 348 int rc = TEMP_FAILURE_RETRY(fdatasync(fd_)); 349 #else 350 int rc = TEMP_FAILURE_RETRY(fsync(fd_)); 351 #endif 352 353 moveUp(GuardState::kFlushed, "Flushing closed file."); 354 if (rc == 0) { 355 return 0; 356 } 357 358 // Don't report failure if we just tried to flush a pipe or socket. 359 return errno == EINVAL ? 0 : -errno; 360 } 361 362 int64_t FdFile::Read(char* buf, int64_t byte_count, int64_t offset) const { 363 #ifdef __linux__ 364 int rc = TEMP_FAILURE_RETRY(pread64(fd_, buf, byte_count, offset)); 365 #else 366 int rc = TEMP_FAILURE_RETRY(pread(fd_, buf, byte_count, offset)); 367 #endif 368 return (rc == -1) ? -errno : rc; 369 } 370 371 int FdFile::SetLength(int64_t new_length) { 372 DCHECK(!read_only_mode_); 373 #ifdef __linux__ 374 int rc = TEMP_FAILURE_RETRY(ftruncate64(fd_, new_length)); 375 #else 376 int rc = TEMP_FAILURE_RETRY(ftruncate(fd_, new_length)); 377 #endif 378 moveTo(GuardState::kBase, GuardState::kClosed, "Truncating closed file."); 379 return (rc == -1) ? -errno : rc; 380 } 381 382 int64_t FdFile::GetLength() const { 383 struct stat s; 384 int rc = TEMP_FAILURE_RETRY(fstat(fd_, &s)); 385 return (rc == -1) ? -errno : s.st_size; 386 } 387 388 int64_t FdFile::Write(const char* buf, int64_t byte_count, int64_t offset) { 389 DCHECK(!read_only_mode_); 390 #ifdef __linux__ 391 int rc = TEMP_FAILURE_RETRY(pwrite64(fd_, buf, byte_count, offset)); 392 #else 393 int rc = TEMP_FAILURE_RETRY(pwrite(fd_, buf, byte_count, offset)); 394 #endif 395 moveTo(GuardState::kBase, GuardState::kClosed, "Writing into closed file."); 396 return (rc == -1) ? -errno : rc; 397 } 398 399 int FdFile::Fd() const { 400 return fd_; 401 } 402 403 bool FdFile::ReadOnlyMode() const { 404 return read_only_mode_; 405 } 406 407 bool FdFile::CheckUsage() const { 408 return guard_state_ != GuardState::kNoCheck; 409 } 410 411 bool FdFile::IsOpened() const { 412 return fd_ >= 0; 413 } 414 415 static ssize_t ReadIgnoreOffset(int fd, void *buf, size_t count, off_t offset) { 416 DCHECK_EQ(offset, 0); 417 return read(fd, buf, count); 418 } 419 420 template <ssize_t (*read_func)(int, void*, size_t, off_t)> 421 static bool ReadFullyGeneric(int fd, void* buffer, size_t byte_count, size_t offset) { 422 char* ptr = static_cast<char*>(buffer); 423 while (byte_count > 0) { 424 ssize_t bytes_read = TEMP_FAILURE_RETRY(read_func(fd, ptr, byte_count, offset)); 425 if (bytes_read <= 0) { 426 // 0: end of file 427 // -1: error 428 return false; 429 } 430 byte_count -= bytes_read; // Reduce the number of remaining bytes. 431 ptr += bytes_read; // Move the buffer forward. 432 offset += static_cast<size_t>(bytes_read); // Move the offset forward. 433 } 434 return true; 435 } 436 437 bool FdFile::ReadFully(void* buffer, size_t byte_count) { 438 return ReadFullyGeneric<ReadIgnoreOffset>(fd_, buffer, byte_count, 0); 439 } 440 441 bool FdFile::PreadFully(void* buffer, size_t byte_count, size_t offset) { 442 return ReadFullyGeneric<pread>(fd_, buffer, byte_count, offset); 443 } 444 445 template <bool kUseOffset> 446 bool FdFile::WriteFullyGeneric(const void* buffer, size_t byte_count, size_t offset) { 447 DCHECK(!read_only_mode_); 448 moveTo(GuardState::kBase, GuardState::kClosed, "Writing into closed file."); 449 DCHECK(kUseOffset || offset == 0u); 450 const char* ptr = static_cast<const char*>(buffer); 451 while (byte_count > 0) { 452 ssize_t bytes_written = kUseOffset 453 ? TEMP_FAILURE_RETRY(pwrite(fd_, ptr, byte_count, offset)) 454 : TEMP_FAILURE_RETRY(write(fd_, ptr, byte_count)); 455 if (bytes_written == -1) { 456 return false; 457 } 458 byte_count -= bytes_written; // Reduce the number of remaining bytes. 459 ptr += bytes_written; // Move the buffer forward. 460 offset += static_cast<size_t>(bytes_written); 461 } 462 return true; 463 } 464 465 bool FdFile::PwriteFully(const void* buffer, size_t byte_count, size_t offset) { 466 return WriteFullyGeneric<true>(buffer, byte_count, offset); 467 } 468 469 bool FdFile::WriteFully(const void* buffer, size_t byte_count) { 470 return WriteFullyGeneric<false>(buffer, byte_count, 0u); 471 } 472 473 bool FdFile::Copy(FdFile* input_file, int64_t offset, int64_t size) { 474 DCHECK(!read_only_mode_); 475 off_t off = static_cast<off_t>(offset); 476 off_t sz = static_cast<off_t>(size); 477 if (offset < 0 || static_cast<int64_t>(off) != offset || 478 size < 0 || static_cast<int64_t>(sz) != size || 479 sz > std::numeric_limits<off_t>::max() - off) { 480 errno = EINVAL; 481 return false; 482 } 483 if (size == 0) { 484 return true; 485 } 486 #ifdef __linux__ 487 // Use sendfile(), available for files since linux kernel 2.6.33. 488 off_t end = off + sz; 489 while (off != end) { 490 int result = TEMP_FAILURE_RETRY( 491 sendfile(Fd(), input_file->Fd(), &off, end - off)); 492 if (result == -1) { 493 return false; 494 } 495 // Ignore the number of bytes in `result`, sendfile() already updated `off`. 496 } 497 #else 498 if (lseek(input_file->Fd(), off, SEEK_SET) != off) { 499 return false; 500 } 501 constexpr size_t kMaxBufferSize = 4 * ::art::kPageSize; 502 const size_t buffer_size = std::min<uint64_t>(size, kMaxBufferSize); 503 art::UniqueCPtr<void> buffer(malloc(buffer_size)); 504 if (buffer == nullptr) { 505 errno = ENOMEM; 506 return false; 507 } 508 while (size != 0) { 509 size_t chunk_size = std::min<uint64_t>(buffer_size, size); 510 if (!input_file->ReadFully(buffer.get(), chunk_size) || 511 !WriteFully(buffer.get(), chunk_size)) { 512 return false; 513 } 514 size -= chunk_size; 515 } 516 #endif 517 return true; 518 } 519 520 bool FdFile::Unlink() { 521 if (file_path_.empty()) { 522 return false; 523 } 524 525 // Try to figure out whether this file is still referring to the one on disk. 526 bool is_current = false; 527 { 528 struct stat this_stat, current_stat; 529 int cur_fd = TEMP_FAILURE_RETRY(open(file_path_.c_str(), O_RDONLY | O_CLOEXEC)); 530 if (cur_fd > 0) { 531 // File still exists. 532 if (fstat(fd_, &this_stat) == 0 && fstat(cur_fd, ¤t_stat) == 0) { 533 is_current = (this_stat.st_dev == current_stat.st_dev) && 534 (this_stat.st_ino == current_stat.st_ino); 535 } 536 close(cur_fd); 537 } 538 } 539 540 if (is_current) { 541 unlink(file_path_.c_str()); 542 } 543 544 return is_current; 545 } 546 547 bool FdFile::Erase(bool unlink) { 548 DCHECK(!read_only_mode_); 549 550 bool ret_result = true; 551 if (unlink) { 552 ret_result = Unlink(); 553 } 554 555 int result; 556 result = SetLength(0); 557 result = Flush(); 558 result = Close(); 559 // Ignore the errors. 560 561 return ret_result; 562 } 563 564 int FdFile::FlushCloseOrErase() { 565 DCHECK(!read_only_mode_); 566 int flush_result = Flush(); 567 if (flush_result != 0) { 568 LOG(ERROR) << "CloseOrErase failed while flushing a file."; 569 Erase(); 570 return flush_result; 571 } 572 int close_result = Close(); 573 if (close_result != 0) { 574 LOG(ERROR) << "CloseOrErase failed while closing a file."; 575 Erase(); 576 return close_result; 577 } 578 return 0; 579 } 580 581 int FdFile::FlushClose() { 582 DCHECK(!read_only_mode_); 583 int flush_result = Flush(); 584 if (flush_result != 0) { 585 LOG(ERROR) << "FlushClose failed while flushing a file."; 586 } 587 int close_result = Close(); 588 if (close_result != 0) { 589 LOG(ERROR) << "FlushClose failed while closing a file."; 590 } 591 return (flush_result != 0) ? flush_result : close_result; 592 } 593 594 void FdFile::MarkUnchecked() { 595 guard_state_ = GuardState::kNoCheck; 596 } 597 598 bool FdFile::ClearContent() { 599 DCHECK(!read_only_mode_); 600 if (SetLength(0) < 0) { 601 PLOG(ERROR) << "Failed to reset the length"; 602 return false; 603 } 604 return ResetOffset(); 605 } 606 607 bool FdFile::ResetOffset() { 608 DCHECK(!read_only_mode_); 609 off_t rc = TEMP_FAILURE_RETRY(lseek(fd_, 0, SEEK_SET)); 610 if (rc == static_cast<off_t>(-1)) { 611 PLOG(ERROR) << "Failed to reset the offset"; 612 return false; 613 } 614 return true; 615 } 616 617 int FdFile::Compare(FdFile* other) { 618 int64_t length = GetLength(); 619 int64_t length2 = other->GetLength(); 620 if (length != length2) { 621 return length < length2 ? -1 : 1; 622 } 623 static const size_t kBufferSize = 4096; 624 std::unique_ptr<uint8_t[]> buffer1(new uint8_t[kBufferSize]); 625 std::unique_ptr<uint8_t[]> buffer2(new uint8_t[kBufferSize]); 626 size_t offset = 0; 627 while (length > 0) { 628 size_t len = std::min(kBufferSize, static_cast<size_t>(length)); 629 if (!PreadFully(&buffer1[0], len, offset)) { 630 return -1; 631 } 632 if (!other->PreadFully(&buffer2[0], len, offset)) { 633 return 1; 634 } 635 int result = memcmp(&buffer1[0], &buffer2[0], len); 636 if (result != 0) { 637 return result; 638 } 639 length -= len; 640 offset += len; 641 } 642 return 0; 643 } 644 645 } // namespace unix_file 646