1 //===-- File.cpp ------------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Host/File.h"
20 #include "lldb/Host/windows/windows.h"
22 #include <sys/ioctl.h>
25 #include "lldb/Core/DataBufferHeap.h"
26 #include "lldb/Core/Error.h"
27 #include "lldb/Core/Log.h"
28 #include "lldb/Host/Config.h"
29 #include "lldb/Host/FileSpec.h"
32 using namespace lldb_private;
35 GetStreamOpenModeFromOptions (uint32_t options)
37 if (options & File::eOpenOptionAppend)
39 if (options & File::eOpenOptionRead)
41 if (options & File::eOpenOptionCanCreateNewOnly)
46 else if (options & File::eOpenOptionWrite)
48 if (options & File::eOpenOptionCanCreateNewOnly)
54 else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite)
56 if (options & File::eOpenOptionCanCreate)
58 if (options & File::eOpenOptionCanCreateNewOnly)
66 else if (options & File::eOpenOptionRead)
70 else if (options & File::eOpenOptionWrite)
77 int File::kInvalidDescriptor = -1;
78 FILE * File::kInvalidStream = NULL;
80 File::File(const char *path, uint32_t options, uint32_t permissions) :
81 IOObject(eFDTypeFile, false),
82 m_descriptor (kInvalidDescriptor),
83 m_stream (kInvalidStream),
86 m_is_interactive (eLazyBoolCalculate),
87 m_is_real_terminal (eLazyBoolCalculate)
89 Open (path, options, permissions);
92 File::File (const FileSpec& filespec,
94 uint32_t permissions) :
95 IOObject(eFDTypeFile, false),
96 m_descriptor (kInvalidDescriptor),
97 m_stream (kInvalidStream),
100 m_is_interactive (eLazyBoolCalculate),
101 m_is_real_terminal (eLazyBoolCalculate)
106 Open (filespec.GetPath().c_str(), options, permissions);
110 File::File (const File &rhs) :
111 IOObject(eFDTypeFile, false),
112 m_descriptor (kInvalidDescriptor),
113 m_stream (kInvalidStream),
115 m_own_stream (false),
116 m_is_interactive (eLazyBoolCalculate),
117 m_is_real_terminal (eLazyBoolCalculate)
124 File::operator = (const File &rhs)
138 File::GetDescriptor() const
140 if (DescriptorIsValid())
143 // Don't open the file descriptor if we don't need to, just get it from the
144 // stream if we have one.
146 return fileno (m_stream);
148 // Invalid descriptor and invalid stream, return invalid descriptor.
149 return kInvalidDescriptor;
152 IOObject::WaitableHandle
153 File::GetWaitableHandle()
160 File::SetDescriptor (int fd, bool transfer_ownership)
165 m_should_close_fd = transfer_ownership;
172 if (!StreamIsValid())
174 if (DescriptorIsValid())
176 const char *mode = GetStreamOpenModeFromOptions (m_options);
179 if (!m_should_close_fd)
181 // We must duplicate the file descriptor if we don't own it because
182 // when you call fdopen, the stream will own the fd
184 m_descriptor = ::_dup(GetDescriptor());
186 m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD);
188 m_should_close_fd = true;
193 m_stream = ::fdopen (m_descriptor, mode);
194 } while (m_stream == NULL && errno == EINTR);
196 // If we got a stream, then we own the stream and should no
197 // longer own the descriptor because fclose() will close it for us
202 m_should_close_fd = false;
212 File::SetStream (FILE *fh, bool transfer_ownership)
217 m_own_stream = transfer_ownership;
221 File::Duplicate (const File &rhs)
227 if (rhs.DescriptorIsValid())
230 m_descriptor = ::_dup(rhs.GetDescriptor());
232 m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD);
234 if (!DescriptorIsValid())
235 error.SetErrorToErrno();
238 m_options = rhs.m_options;
239 m_should_close_fd = true;
244 error.SetErrorString ("invalid file to duplicate");
250 File::Open (const char *path, uint32_t options, uint32_t permissions)
257 const bool read = options & eOpenOptionRead;
258 const bool write = options & eOpenOptionWrite;
266 if (options & eOpenOptionAppend)
269 if (options & eOpenOptionTruncate)
272 if (options & eOpenOptionCanCreate)
275 if (options & eOpenOptionCanCreateNewOnly)
276 oflag |= O_CREAT | O_EXCL;
283 if (options & eOpenoptionDontFollowSymlinks)
289 if (options & eOpenOptionNonBlocking)
298 if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR;
299 if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR;
300 if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR;
301 if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP;
302 if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP;
303 if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP;
304 if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH;
305 if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH;
306 if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH;
311 m_descriptor = ::open(path, oflag, mode);
312 } while (m_descriptor < 0 && errno == EINTR);
314 if (!DescriptorIsValid())
315 error.SetErrorToErrno();
318 m_should_close_fd = true;
326 File::GetPermissions (const char *path, Error &error)
330 struct stat file_stats;
331 if (::stat (path, &file_stats) == -1)
332 error.SetErrorToErrno();
336 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
342 error.SetErrorString ("invalid path");
344 error.SetErrorString ("empty path");
350 File::GetPermissions(Error &error) const
352 int fd = GetDescriptor();
353 if (fd != kInvalidDescriptor)
355 struct stat file_stats;
356 if (::fstat (fd, &file_stats) == -1)
357 error.SetErrorToErrno();
361 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
366 error.SetErrorString ("invalid file descriptor");
376 if (StreamIsValid() && m_own_stream)
378 if (::fclose (m_stream) == EOF)
379 error.SetErrorToErrno();
382 if (DescriptorIsValid() && m_should_close_fd)
384 if (::close (m_descriptor) != 0)
385 error.SetErrorToErrno();
387 m_descriptor = kInvalidDescriptor;
388 m_stream = kInvalidStream;
390 m_own_stream = false;
391 m_should_close_fd = false;
392 m_is_interactive = eLazyBoolCalculate;
393 m_is_real_terminal = eLazyBoolCalculate;
399 File::GetFileSpec (FileSpec &file_spec) const
402 #ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
406 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
407 error.SetErrorToErrno();
409 file_spec.SetFile (path, false);
413 error.SetErrorString("invalid file handle");
415 #elif defined(__linux__)
418 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
419 error.SetErrorString ("cannot resolve file descriptor");
423 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
424 error.SetErrorToErrno();
428 file_spec.SetFile (path, false);
432 error.SetErrorString ("File::GetFileSpec is not supported on this platform");
441 File::SeekFromStart (off_t offset, Error *error_ptr)
444 if (DescriptorIsValid())
446 result = ::lseek (m_descriptor, offset, SEEK_SET);
451 error_ptr->SetErrorToErrno();
456 else if (StreamIsValid ())
458 result = ::fseek(m_stream, offset, SEEK_SET);
463 error_ptr->SetErrorToErrno();
470 error_ptr->SetErrorString("invalid file handle");
476 File::SeekFromCurrent (off_t offset, Error *error_ptr)
479 if (DescriptorIsValid())
481 result = ::lseek (m_descriptor, offset, SEEK_CUR);
486 error_ptr->SetErrorToErrno();
491 else if (StreamIsValid ())
493 result = ::fseek(m_stream, offset, SEEK_CUR);
498 error_ptr->SetErrorToErrno();
505 error_ptr->SetErrorString("invalid file handle");
511 File::SeekFromEnd (off_t offset, Error *error_ptr)
514 if (DescriptorIsValid())
516 result = ::lseek (m_descriptor, offset, SEEK_END);
521 error_ptr->SetErrorToErrno();
526 else if (StreamIsValid ())
528 result = ::fseek(m_stream, offset, SEEK_END);
533 error_ptr->SetErrorToErrno();
540 error_ptr->SetErrorString("invalid file handle");
554 err = ::fflush (m_stream);
555 } while (err == EOF && errno == EINTR);
558 error.SetErrorToErrno();
560 else if (!DescriptorIsValid())
562 error.SetErrorString("invalid file handle");
572 if (DescriptorIsValid())
575 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
577 error.SetErrorToGenericError();
582 err = ::fsync (m_descriptor);
583 } while (err == -1 && errno == EINTR);
586 error.SetErrorToErrno();
591 error.SetErrorString("invalid file handle");
597 File::Read (void *buf, size_t &num_bytes)
600 ssize_t bytes_read = -1;
601 if (DescriptorIsValid())
605 bytes_read = ::read (m_descriptor, buf, num_bytes);
606 } while (bytes_read < 0 && errno == EINTR);
608 if (bytes_read == -1)
610 error.SetErrorToErrno();
614 num_bytes = bytes_read;
616 else if (StreamIsValid())
618 bytes_read = ::fread (buf, 1, num_bytes, m_stream);
622 if (::feof(m_stream))
623 error.SetErrorString ("feof");
624 else if (::ferror (m_stream))
625 error.SetErrorString ("ferror");
629 num_bytes = bytes_read;
634 error.SetErrorString("invalid file handle");
640 File::Write (const void *buf, size_t &num_bytes)
643 ssize_t bytes_written = -1;
644 if (DescriptorIsValid())
648 bytes_written = ::write (m_descriptor, buf, num_bytes);
649 } while (bytes_written < 0 && errno == EINTR);
651 if (bytes_written == -1)
653 error.SetErrorToErrno();
657 num_bytes = bytes_written;
659 else if (StreamIsValid())
661 bytes_written = ::fwrite (buf, 1, num_bytes, m_stream);
663 if (bytes_written == 0)
665 if (::feof(m_stream))
666 error.SetErrorString ("feof");
667 else if (::ferror (m_stream))
668 error.SetErrorString ("ferror");
672 num_bytes = bytes_written;
678 error.SetErrorString("invalid file handle");
686 File::Read (void *buf, size_t &num_bytes, off_t &offset)
690 int fd = GetDescriptor();
691 if (fd != kInvalidDescriptor)
693 ssize_t bytes_read = -1;
696 bytes_read = ::pread (fd, buf, num_bytes, offset);
697 } while (bytes_read < 0 && errno == EINTR);
702 error.SetErrorToErrno();
706 offset += bytes_read;
707 num_bytes = bytes_read;
713 error.SetErrorString("invalid file handle");
717 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
718 SeekFromStart(offset);
719 Error error = Read(buf, num_bytes);
727 File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
733 int fd = GetDescriptor();
734 if (fd != kInvalidDescriptor)
736 struct stat file_stats;
737 if (::fstat (fd, &file_stats) == 0)
739 if (file_stats.st_size > offset)
741 const size_t bytes_left = file_stats.st_size - offset;
742 if (num_bytes > bytes_left)
743 num_bytes = bytes_left;
745 std::unique_ptr<DataBufferHeap> data_heap_ap;
746 data_heap_ap.reset(new DataBufferHeap(num_bytes + (null_terminate ? 1 : 0), '\0'));
748 if (data_heap_ap.get())
750 error = Read (data_heap_ap->GetBytes(), num_bytes, offset);
753 // Make sure we read exactly what we asked for and if we got
754 // less, adjust the array
755 if (num_bytes < data_heap_ap->GetByteSize())
756 data_heap_ap->SetByteSize(num_bytes);
757 data_buffer_sp.reset(data_heap_ap.release());
763 error.SetErrorString("file is empty");
766 error.SetErrorToErrno();
769 error.SetErrorString("invalid file handle");
772 error.SetErrorString("invalid file handle");
775 data_buffer_sp.reset();
780 File::Write (const void *buf, size_t &num_bytes, off_t &offset)
783 int fd = GetDescriptor();
784 if (fd != kInvalidDescriptor)
787 ssize_t bytes_written = -1;
790 bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset);
791 } while (bytes_written < 0 && errno == EINTR);
793 if (bytes_written < 0)
796 error.SetErrorToErrno();
800 offset += bytes_written;
801 num_bytes = bytes_written;
804 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
805 error = Write(buf, num_bytes);
806 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
811 ssize_t bytes_written = after - cur;
818 error.SetErrorString("invalid file handle");
823 //------------------------------------------------------------------
824 // Print some formatted output to the stream.
825 //------------------------------------------------------------------
827 File::Printf (const char *format, ...)
830 va_start (args, format);
831 size_t result = PrintfVarArg (format, args);
836 //------------------------------------------------------------------
837 // Print some formatted output to the stream.
838 //------------------------------------------------------------------
840 File::PrintfVarArg (const char *format, va_list args)
843 if (DescriptorIsValid())
846 result = vasprintf(&s, format, args);
851 size_t s_len = result;
858 else if (StreamIsValid())
860 result = ::vfprintf (m_stream, format, args);
866 File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
869 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
871 else if (open_options & eOpenOptionWrite)
874 if (open_options & eOpenOptionAppend)
877 if (open_options & eOpenOptionTruncate)
880 if (open_options & eOpenOptionNonBlocking)
883 if (open_options & eOpenOptionCanCreateNewOnly)
884 mode |= O_CREAT | O_EXCL;
885 else if (open_options & eOpenOptionCanCreate)
892 File::CalculateInteractiveAndTerminal ()
894 const int fd = GetDescriptor();
897 m_is_interactive = eLazyBoolNo;
898 m_is_real_terminal = eLazyBoolNo;
902 m_is_interactive = eLazyBoolYes;
903 m_is_real_terminal = eLazyBoolYes;
908 m_is_interactive = eLazyBoolYes;
909 struct winsize window_size;
910 if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
912 if (window_size.ws_col > 0)
913 m_is_real_terminal = eLazyBoolYes;
921 File::GetIsInteractive ()
923 if (m_is_interactive == eLazyBoolCalculate)
924 CalculateInteractiveAndTerminal ();
925 return m_is_interactive == eLazyBoolYes;
929 File::GetIsRealTerminal ()
931 if (m_is_real_terminal == eLazyBoolCalculate)
932 CalculateInteractiveAndTerminal();
933 return m_is_real_terminal == eLazyBoolYes;