1 //===-- File.cpp ------------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Host/File.h" 10 11 #include <errno.h> 12 #include <fcntl.h> 13 #include <limits.h> 14 #include <stdarg.h> 15 #include <stdio.h> 16 17 #ifdef _WIN32 18 #include "lldb/Host/windows/windows.h" 19 #else 20 #include <sys/ioctl.h> 21 #include <sys/stat.h> 22 #include <termios.h> 23 #include <unistd.h> 24 #endif 25 26 #include "llvm/Support/ConvertUTF.h" 27 #include "llvm/Support/Errno.h" 28 #include "llvm/Support/FileSystem.h" 29 #include "llvm/Support/Process.h" 30 31 #include "lldb/Host/Config.h" 32 #include "lldb/Host/FileSystem.h" 33 #include "lldb/Host/Host.h" 34 #include "lldb/Utility/DataBufferHeap.h" 35 #include "lldb/Utility/FileSpec.h" 36 #include "lldb/Utility/Log.h" 37 38 using namespace lldb; 39 using namespace lldb_private; 40 41 static const char *GetStreamOpenModeFromOptions(uint32_t options) { 42 if (options & File::eOpenOptionAppend) { 43 if (options & File::eOpenOptionRead) { 44 if (options & File::eOpenOptionCanCreateNewOnly) 45 return "a+x"; 46 else 47 return "a+"; 48 } else if (options & File::eOpenOptionWrite) { 49 if (options & File::eOpenOptionCanCreateNewOnly) 50 return "ax"; 51 else 52 return "a"; 53 } 54 } else if (options & File::eOpenOptionRead && 55 options & File::eOpenOptionWrite) { 56 if (options & File::eOpenOptionCanCreate) { 57 if (options & File::eOpenOptionCanCreateNewOnly) 58 return "w+x"; 59 else 60 return "w+"; 61 } else 62 return "r+"; 63 } else if (options & File::eOpenOptionRead) { 64 return "r"; 65 } else if (options & File::eOpenOptionWrite) { 66 return "w"; 67 } 68 return nullptr; 69 } 70 71 int File::kInvalidDescriptor = -1; 72 FILE *File::kInvalidStream = nullptr; 73 74 File::~File() { Close(); } 75 76 int File::GetDescriptor() const { 77 if (DescriptorIsValid()) 78 return m_descriptor; 79 80 // Don't open the file descriptor if we don't need to, just get it from the 81 // stream if we have one. 82 if (StreamIsValid()) { 83 #if defined(_WIN32) 84 return _fileno(m_stream); 85 #else 86 return fileno(m_stream); 87 #endif 88 } 89 90 // Invalid descriptor and invalid stream, return invalid descriptor. 91 return kInvalidDescriptor; 92 } 93 94 IOObject::WaitableHandle File::GetWaitableHandle() { return GetDescriptor(); } 95 96 void File::SetDescriptor(int fd, bool transfer_ownership) { 97 if (IsValid()) 98 Close(); 99 m_descriptor = fd; 100 m_should_close_fd = transfer_ownership; 101 } 102 103 FILE *File::GetStream() { 104 if (!StreamIsValid()) { 105 if (DescriptorIsValid()) { 106 const char *mode = GetStreamOpenModeFromOptions(m_options); 107 if (mode) { 108 if (!m_should_close_fd) { 109 // We must duplicate the file descriptor if we don't own it because when you 110 // call fdopen, the stream will own the fd 111 #ifdef _WIN32 112 m_descriptor = ::_dup(GetDescriptor()); 113 #else 114 m_descriptor = dup(GetDescriptor()); 115 #endif 116 m_should_close_fd = true; 117 } 118 119 m_stream = 120 llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, mode); 121 122 // If we got a stream, then we own the stream and should no longer own 123 // the descriptor because fclose() will close it for us 124 125 if (m_stream) { 126 m_own_stream = true; 127 m_should_close_fd = false; 128 } 129 } 130 } 131 } 132 return m_stream; 133 } 134 135 void File::SetStream(FILE *fh, bool transfer_ownership) { 136 if (IsValid()) 137 Close(); 138 m_stream = fh; 139 m_own_stream = transfer_ownership; 140 } 141 142 uint32_t File::GetPermissions(Status &error) const { 143 int fd = GetDescriptor(); 144 if (fd != kInvalidDescriptor) { 145 struct stat file_stats; 146 if (::fstat(fd, &file_stats) == -1) 147 error.SetErrorToErrno(); 148 else { 149 error.Clear(); 150 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 151 } 152 } else { 153 error.SetErrorString("invalid file descriptor"); 154 } 155 return 0; 156 } 157 158 Status File::Close() { 159 Status error; 160 if (StreamIsValid() && m_own_stream) { 161 if (::fclose(m_stream) == EOF) 162 error.SetErrorToErrno(); 163 } 164 165 if (DescriptorIsValid() && m_should_close_fd) { 166 if (::close(m_descriptor) != 0) 167 error.SetErrorToErrno(); 168 } 169 m_descriptor = kInvalidDescriptor; 170 m_stream = kInvalidStream; 171 m_options = 0; 172 m_own_stream = false; 173 m_should_close_fd = false; 174 m_is_interactive = eLazyBoolCalculate; 175 m_is_real_terminal = eLazyBoolCalculate; 176 return error; 177 } 178 179 void File::Clear() { 180 m_stream = nullptr; 181 m_descriptor = kInvalidDescriptor; 182 m_options = 0; 183 m_own_stream = false; 184 m_is_interactive = m_supports_colors = m_is_real_terminal = 185 eLazyBoolCalculate; 186 } 187 188 Status File::GetFileSpec(FileSpec &file_spec) const { 189 Status error; 190 #ifdef F_GETPATH 191 if (IsValid()) { 192 char path[PATH_MAX]; 193 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) 194 error.SetErrorToErrno(); 195 else 196 file_spec.SetFile(path, FileSpec::Style::native); 197 } else { 198 error.SetErrorString("invalid file handle"); 199 } 200 #elif defined(__linux__) 201 char proc[64]; 202 char path[PATH_MAX]; 203 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) 204 error.SetErrorString("cannot resolve file descriptor"); 205 else { 206 ssize_t len; 207 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) 208 error.SetErrorToErrno(); 209 else { 210 path[len] = '\0'; 211 file_spec.SetFile(path, FileSpec::Style::native); 212 } 213 } 214 #else 215 error.SetErrorString("File::GetFileSpec is not supported on this platform"); 216 #endif 217 218 if (error.Fail()) 219 file_spec.Clear(); 220 return error; 221 } 222 223 off_t File::SeekFromStart(off_t offset, Status *error_ptr) { 224 off_t result = 0; 225 if (DescriptorIsValid()) { 226 result = ::lseek(m_descriptor, offset, SEEK_SET); 227 228 if (error_ptr) { 229 if (result == -1) 230 error_ptr->SetErrorToErrno(); 231 else 232 error_ptr->Clear(); 233 } 234 } else if (StreamIsValid()) { 235 result = ::fseek(m_stream, offset, SEEK_SET); 236 237 if (error_ptr) { 238 if (result == -1) 239 error_ptr->SetErrorToErrno(); 240 else 241 error_ptr->Clear(); 242 } 243 } else if (error_ptr) { 244 error_ptr->SetErrorString("invalid file handle"); 245 } 246 return result; 247 } 248 249 off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) { 250 off_t result = -1; 251 if (DescriptorIsValid()) { 252 result = ::lseek(m_descriptor, offset, SEEK_CUR); 253 254 if (error_ptr) { 255 if (result == -1) 256 error_ptr->SetErrorToErrno(); 257 else 258 error_ptr->Clear(); 259 } 260 } else if (StreamIsValid()) { 261 result = ::fseek(m_stream, offset, SEEK_CUR); 262 263 if (error_ptr) { 264 if (result == -1) 265 error_ptr->SetErrorToErrno(); 266 else 267 error_ptr->Clear(); 268 } 269 } else if (error_ptr) { 270 error_ptr->SetErrorString("invalid file handle"); 271 } 272 return result; 273 } 274 275 off_t File::SeekFromEnd(off_t offset, Status *error_ptr) { 276 off_t result = -1; 277 if (DescriptorIsValid()) { 278 result = ::lseek(m_descriptor, offset, SEEK_END); 279 280 if (error_ptr) { 281 if (result == -1) 282 error_ptr->SetErrorToErrno(); 283 else 284 error_ptr->Clear(); 285 } 286 } else if (StreamIsValid()) { 287 result = ::fseek(m_stream, offset, SEEK_END); 288 289 if (error_ptr) { 290 if (result == -1) 291 error_ptr->SetErrorToErrno(); 292 else 293 error_ptr->Clear(); 294 } 295 } else if (error_ptr) { 296 error_ptr->SetErrorString("invalid file handle"); 297 } 298 return result; 299 } 300 301 Status File::Flush() { 302 Status error; 303 if (StreamIsValid()) { 304 if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF) 305 error.SetErrorToErrno(); 306 } else if (!DescriptorIsValid()) { 307 error.SetErrorString("invalid file handle"); 308 } 309 return error; 310 } 311 312 Status File::Sync() { 313 Status error; 314 if (DescriptorIsValid()) { 315 #ifdef _WIN32 316 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); 317 if (err == 0) 318 error.SetErrorToGenericError(); 319 #else 320 if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1) 321 error.SetErrorToErrno(); 322 #endif 323 } else { 324 error.SetErrorString("invalid file handle"); 325 } 326 return error; 327 } 328 329 #if defined(__APPLE__) 330 // Darwin kernels only can read/write <= INT_MAX bytes 331 #define MAX_READ_SIZE INT_MAX 332 #define MAX_WRITE_SIZE INT_MAX 333 #endif 334 335 Status File::Read(void *buf, size_t &num_bytes) { 336 Status error; 337 338 #if defined(MAX_READ_SIZE) 339 if (num_bytes > MAX_READ_SIZE) { 340 uint8_t *p = (uint8_t *)buf; 341 size_t bytes_left = num_bytes; 342 // Init the num_bytes read to zero 343 num_bytes = 0; 344 345 while (bytes_left > 0) { 346 size_t curr_num_bytes; 347 if (bytes_left > MAX_READ_SIZE) 348 curr_num_bytes = MAX_READ_SIZE; 349 else 350 curr_num_bytes = bytes_left; 351 352 error = Read(p + num_bytes, curr_num_bytes); 353 354 // Update how many bytes were read 355 num_bytes += curr_num_bytes; 356 if (bytes_left < curr_num_bytes) 357 bytes_left = 0; 358 else 359 bytes_left -= curr_num_bytes; 360 361 if (error.Fail()) 362 break; 363 } 364 return error; 365 } 366 #endif 367 368 ssize_t bytes_read = -1; 369 if (DescriptorIsValid()) { 370 bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes); 371 if (bytes_read == -1) { 372 error.SetErrorToErrno(); 373 num_bytes = 0; 374 } else 375 num_bytes = bytes_read; 376 } else if (StreamIsValid()) { 377 bytes_read = ::fread(buf, 1, num_bytes, m_stream); 378 379 if (bytes_read == 0) { 380 if (::feof(m_stream)) 381 error.SetErrorString("feof"); 382 else if (::ferror(m_stream)) 383 error.SetErrorString("ferror"); 384 num_bytes = 0; 385 } else 386 num_bytes = bytes_read; 387 } else { 388 num_bytes = 0; 389 error.SetErrorString("invalid file handle"); 390 } 391 return error; 392 } 393 394 Status File::Write(const void *buf, size_t &num_bytes) { 395 Status error; 396 397 #if defined(MAX_WRITE_SIZE) 398 if (num_bytes > MAX_WRITE_SIZE) { 399 const uint8_t *p = (const uint8_t *)buf; 400 size_t bytes_left = num_bytes; 401 // Init the num_bytes written to zero 402 num_bytes = 0; 403 404 while (bytes_left > 0) { 405 size_t curr_num_bytes; 406 if (bytes_left > MAX_WRITE_SIZE) 407 curr_num_bytes = MAX_WRITE_SIZE; 408 else 409 curr_num_bytes = bytes_left; 410 411 error = Write(p + num_bytes, curr_num_bytes); 412 413 // Update how many bytes were read 414 num_bytes += curr_num_bytes; 415 if (bytes_left < curr_num_bytes) 416 bytes_left = 0; 417 else 418 bytes_left -= curr_num_bytes; 419 420 if (error.Fail()) 421 break; 422 } 423 return error; 424 } 425 #endif 426 427 ssize_t bytes_written = -1; 428 if (DescriptorIsValid()) { 429 bytes_written = 430 llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes); 431 if (bytes_written == -1) { 432 error.SetErrorToErrno(); 433 num_bytes = 0; 434 } else 435 num_bytes = bytes_written; 436 } else if (StreamIsValid()) { 437 bytes_written = ::fwrite(buf, 1, num_bytes, m_stream); 438 439 if (bytes_written == 0) { 440 if (::feof(m_stream)) 441 error.SetErrorString("feof"); 442 else if (::ferror(m_stream)) 443 error.SetErrorString("ferror"); 444 num_bytes = 0; 445 } else 446 num_bytes = bytes_written; 447 448 } else { 449 num_bytes = 0; 450 error.SetErrorString("invalid file handle"); 451 } 452 453 return error; 454 } 455 456 Status File::Read(void *buf, size_t &num_bytes, off_t &offset) { 457 Status error; 458 459 #if defined(MAX_READ_SIZE) 460 if (num_bytes > MAX_READ_SIZE) { 461 uint8_t *p = (uint8_t *)buf; 462 size_t bytes_left = num_bytes; 463 // Init the num_bytes read to zero 464 num_bytes = 0; 465 466 while (bytes_left > 0) { 467 size_t curr_num_bytes; 468 if (bytes_left > MAX_READ_SIZE) 469 curr_num_bytes = MAX_READ_SIZE; 470 else 471 curr_num_bytes = bytes_left; 472 473 error = Read(p + num_bytes, curr_num_bytes, offset); 474 475 // Update how many bytes were read 476 num_bytes += curr_num_bytes; 477 if (bytes_left < curr_num_bytes) 478 bytes_left = 0; 479 else 480 bytes_left -= curr_num_bytes; 481 482 if (error.Fail()) 483 break; 484 } 485 return error; 486 } 487 #endif 488 489 #ifndef _WIN32 490 int fd = GetDescriptor(); 491 if (fd != kInvalidDescriptor) { 492 ssize_t bytes_read = 493 llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset); 494 if (bytes_read < 0) { 495 num_bytes = 0; 496 error.SetErrorToErrno(); 497 } else { 498 offset += bytes_read; 499 num_bytes = bytes_read; 500 } 501 } else { 502 num_bytes = 0; 503 error.SetErrorString("invalid file handle"); 504 } 505 #else 506 std::lock_guard<std::mutex> guard(offset_access_mutex); 507 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 508 SeekFromStart(offset); 509 error = Read(buf, num_bytes); 510 if (!error.Fail()) 511 SeekFromStart(cur); 512 #endif 513 return error; 514 } 515 516 Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) { 517 Status error; 518 519 #if defined(MAX_WRITE_SIZE) 520 if (num_bytes > MAX_WRITE_SIZE) { 521 const uint8_t *p = (const uint8_t *)buf; 522 size_t bytes_left = num_bytes; 523 // Init the num_bytes written to zero 524 num_bytes = 0; 525 526 while (bytes_left > 0) { 527 size_t curr_num_bytes; 528 if (bytes_left > MAX_WRITE_SIZE) 529 curr_num_bytes = MAX_WRITE_SIZE; 530 else 531 curr_num_bytes = bytes_left; 532 533 error = Write(p + num_bytes, curr_num_bytes, offset); 534 535 // Update how many bytes were read 536 num_bytes += curr_num_bytes; 537 if (bytes_left < curr_num_bytes) 538 bytes_left = 0; 539 else 540 bytes_left -= curr_num_bytes; 541 542 if (error.Fail()) 543 break; 544 } 545 return error; 546 } 547 #endif 548 549 int fd = GetDescriptor(); 550 if (fd != kInvalidDescriptor) { 551 #ifndef _WIN32 552 ssize_t bytes_written = 553 llvm::sys::RetryAfterSignal(-1, ::pwrite, m_descriptor, buf, num_bytes, offset); 554 if (bytes_written < 0) { 555 num_bytes = 0; 556 error.SetErrorToErrno(); 557 } else { 558 offset += bytes_written; 559 num_bytes = bytes_written; 560 } 561 #else 562 std::lock_guard<std::mutex> guard(offset_access_mutex); 563 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 564 SeekFromStart(offset); 565 error = Write(buf, num_bytes); 566 long after = ::lseek(m_descriptor, 0, SEEK_CUR); 567 568 if (!error.Fail()) 569 SeekFromStart(cur); 570 571 offset = after; 572 #endif 573 } else { 574 num_bytes = 0; 575 error.SetErrorString("invalid file handle"); 576 } 577 return error; 578 } 579 580 // Print some formatted output to the stream. 581 size_t File::Printf(const char *format, ...) { 582 va_list args; 583 va_start(args, format); 584 size_t result = PrintfVarArg(format, args); 585 va_end(args); 586 return result; 587 } 588 589 // Print some formatted output to the stream. 590 size_t File::PrintfVarArg(const char *format, va_list args) { 591 size_t result = 0; 592 if (DescriptorIsValid()) { 593 char *s = nullptr; 594 result = vasprintf(&s, format, args); 595 if (s != nullptr) { 596 if (result > 0) { 597 size_t s_len = result; 598 Write(s, s_len); 599 result = s_len; 600 } 601 free(s); 602 } 603 } else if (StreamIsValid()) { 604 result = ::vfprintf(m_stream, format, args); 605 } 606 return result; 607 } 608 609 mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) { 610 mode_t mode = 0; 611 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) 612 mode |= O_RDWR; 613 else if (open_options & eOpenOptionWrite) 614 mode |= O_WRONLY; 615 616 if (open_options & eOpenOptionAppend) 617 mode |= O_APPEND; 618 619 if (open_options & eOpenOptionTruncate) 620 mode |= O_TRUNC; 621 622 if (open_options & eOpenOptionNonBlocking) 623 mode |= O_NONBLOCK; 624 625 if (open_options & eOpenOptionCanCreateNewOnly) 626 mode |= O_CREAT | O_EXCL; 627 else if (open_options & eOpenOptionCanCreate) 628 mode |= O_CREAT; 629 630 return mode; 631 } 632 633 void File::CalculateInteractiveAndTerminal() { 634 const int fd = GetDescriptor(); 635 if (fd >= 0) { 636 m_is_interactive = eLazyBoolNo; 637 m_is_real_terminal = eLazyBoolNo; 638 #if defined(_WIN32) 639 if (_isatty(fd)) { 640 m_is_interactive = eLazyBoolYes; 641 m_is_real_terminal = eLazyBoolYes; 642 #if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) 643 m_supports_colors = eLazyBoolYes; 644 #endif 645 } 646 #else 647 if (isatty(fd)) { 648 m_is_interactive = eLazyBoolYes; 649 struct winsize window_size; 650 if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) { 651 if (window_size.ws_col > 0) { 652 m_is_real_terminal = eLazyBoolYes; 653 if (llvm::sys::Process::FileDescriptorHasColors(fd)) 654 m_supports_colors = eLazyBoolYes; 655 } 656 } 657 } 658 #endif 659 } 660 } 661 662 bool File::GetIsInteractive() { 663 if (m_is_interactive == eLazyBoolCalculate) 664 CalculateInteractiveAndTerminal(); 665 return m_is_interactive == eLazyBoolYes; 666 } 667 668 bool File::GetIsRealTerminal() { 669 if (m_is_real_terminal == eLazyBoolCalculate) 670 CalculateInteractiveAndTerminal(); 671 return m_is_real_terminal == eLazyBoolYes; 672 } 673 674 bool File::GetIsTerminalWithColors() { 675 if (m_supports_colors == eLazyBoolCalculate) 676 CalculateInteractiveAndTerminal(); 677 return m_supports_colors == eLazyBoolYes; 678 } 679