1 //===-- File.cpp ------------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Host/File.h"
11 
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <limits.h>
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include <sys/stat.h>
18 
19 #ifdef _WIN32
20 #include "lldb/Host/windows/windows.h"
21 #else
22 #include <sys/ioctl.h>
23 #endif
24 
25 #include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()
26 
27 #include "lldb/Core/DataBufferHeap.h"
28 #include "lldb/Core/Error.h"
29 #include "lldb/Core/Log.h"
30 #include "lldb/Host/Config.h"
31 #include "lldb/Host/FileSpec.h"
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 
36 static const char *
37 GetStreamOpenModeFromOptions (uint32_t options)
38 {
39     if (options & File::eOpenOptionAppend)
40     {
41         if (options & File::eOpenOptionRead)
42         {
43             if (options & File::eOpenOptionCanCreateNewOnly)
44                 return "a+x";
45             else
46                 return "a+";
47         }
48         else if (options & File::eOpenOptionWrite)
49         {
50             if (options & File::eOpenOptionCanCreateNewOnly)
51                 return "ax";
52             else
53                 return "a";
54         }
55     }
56     else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite)
57     {
58         if (options & File::eOpenOptionCanCreate)
59         {
60             if (options & File::eOpenOptionCanCreateNewOnly)
61                 return "w+x";
62             else
63                 return "w+";
64         }
65         else
66             return "r+";
67     }
68     else if (options & File::eOpenOptionRead)
69     {
70         return "r";
71     }
72     else if (options & File::eOpenOptionWrite)
73     {
74         return "w";
75     }
76     return NULL;
77 }
78 
79 int File::kInvalidDescriptor = -1;
80 FILE * File::kInvalidStream = NULL;
81 
82 File::File(const char *path, uint32_t options, uint32_t permissions) :
83     IOObject(eFDTypeFile, false),
84     m_descriptor (kInvalidDescriptor),
85     m_stream (kInvalidStream),
86     m_options (),
87     m_own_stream (false),
88     m_is_interactive (eLazyBoolCalculate),
89     m_is_real_terminal (eLazyBoolCalculate)
90 {
91     Open (path, options, permissions);
92 }
93 
94 File::File (const FileSpec& filespec,
95             uint32_t options,
96             uint32_t permissions) :
97     IOObject(eFDTypeFile, false),
98     m_descriptor (kInvalidDescriptor),
99     m_stream (kInvalidStream),
100     m_options (0),
101     m_own_stream (false),
102     m_is_interactive (eLazyBoolCalculate),
103     m_is_real_terminal (eLazyBoolCalculate)
104 
105 {
106     if (filespec)
107     {
108         Open (filespec.GetPath().c_str(), options, permissions);
109     }
110 }
111 
112 File::File (const File &rhs) :
113     IOObject(eFDTypeFile, false),
114     m_descriptor (kInvalidDescriptor),
115     m_stream (kInvalidStream),
116     m_options (0),
117     m_own_stream (false),
118     m_is_interactive (eLazyBoolCalculate),
119     m_is_real_terminal (eLazyBoolCalculate)
120 {
121     Duplicate (rhs);
122 }
123 
124 
125 File &
126 File::operator = (const File &rhs)
127 {
128     if (this != &rhs)
129         Duplicate (rhs);
130     return *this;
131 }
132 
133 File::~File()
134 {
135     Close ();
136 }
137 
138 
139 int
140 File::GetDescriptor() const
141 {
142     if (DescriptorIsValid())
143         return m_descriptor;
144 
145     // Don't open the file descriptor if we don't need to, just get it from the
146     // stream if we have one.
147     if (StreamIsValid())
148     {
149 #if defined(LLVM_ON_WIN32)
150         return _fileno(m_stream);
151 #else
152         return fileno(m_stream);
153 #endif
154     }
155 
156     // Invalid descriptor and invalid stream, return invalid descriptor.
157     return kInvalidDescriptor;
158 }
159 
160 IOObject::WaitableHandle
161 File::GetWaitableHandle()
162 {
163     return m_descriptor;
164 }
165 
166 
167 void
168 File::SetDescriptor (int fd, bool transfer_ownership)
169 {
170     if (IsValid())
171         Close();
172     m_descriptor = fd;
173     m_should_close_fd = transfer_ownership;
174 }
175 
176 
177 FILE *
178 File::GetStream ()
179 {
180     if (!StreamIsValid())
181     {
182         if (DescriptorIsValid())
183         {
184             const char *mode = GetStreamOpenModeFromOptions (m_options);
185             if (mode)
186             {
187                 if (!m_should_close_fd)
188                 {
189                     // We must duplicate the file descriptor if we don't own it because
190                     // when you call fdopen, the stream will own the fd
191 #ifdef _WIN32
192                     m_descriptor = ::_dup(GetDescriptor());
193 #else
194                     m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD);
195 #endif
196                     m_should_close_fd = true;
197                 }
198 
199                 do
200                 {
201                     m_stream = ::fdopen (m_descriptor, mode);
202                 } while (m_stream == NULL && errno == EINTR);
203 
204                 // If we got a stream, then we own the stream and should no
205                 // longer own the descriptor because fclose() will close it for us
206 
207                 if (m_stream)
208                 {
209                     m_own_stream = true;
210                     m_should_close_fd = false;
211                 }
212             }
213         }
214     }
215     return m_stream;
216 }
217 
218 
219 void
220 File::SetStream (FILE *fh, bool transfer_ownership)
221 {
222     if (IsValid())
223         Close();
224     m_stream = fh;
225     m_own_stream = transfer_ownership;
226 }
227 
228 Error
229 File::Duplicate (const File &rhs)
230 {
231     Error error;
232     if (IsValid ())
233         Close();
234 
235     if (rhs.DescriptorIsValid())
236     {
237 #ifdef _WIN32
238         m_descriptor = ::_dup(rhs.GetDescriptor());
239 #else
240         m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD);
241 #endif
242         if (!DescriptorIsValid())
243             error.SetErrorToErrno();
244         else
245         {
246             m_options = rhs.m_options;
247             m_should_close_fd = true;
248         }
249     }
250     else
251     {
252         error.SetErrorString ("invalid file to duplicate");
253     }
254     return error;
255 }
256 
257 Error
258 File::Open (const char *path, uint32_t options, uint32_t permissions)
259 {
260     Error error;
261     if (IsValid())
262         Close ();
263 
264     int oflag = 0;
265     const bool read = options & eOpenOptionRead;
266     const bool write = options & eOpenOptionWrite;
267     if (write)
268     {
269         if (read)
270             oflag |= O_RDWR;
271         else
272             oflag |= O_WRONLY;
273 
274         if (options & eOpenOptionAppend)
275             oflag |= O_APPEND;
276 
277         if (options & eOpenOptionTruncate)
278             oflag |= O_TRUNC;
279 
280         if (options & eOpenOptionCanCreate)
281             oflag |= O_CREAT;
282 
283         if (options & eOpenOptionCanCreateNewOnly)
284             oflag |= O_CREAT | O_EXCL;
285     }
286     else if (read)
287     {
288         oflag |= O_RDONLY;
289 
290 #ifndef _WIN32
291         if (options & eOpenoptionDontFollowSymlinks)
292             oflag |= O_NOFOLLOW;
293 #endif
294     }
295 
296 #ifndef _WIN32
297     if (options & eOpenOptionNonBlocking)
298         oflag |= O_NONBLOCK;
299     if (options & eOpenOptionCloseOnExec)
300         oflag |= O_CLOEXEC;
301 #else
302     oflag |= O_BINARY;
303 #endif
304 
305     mode_t mode = 0;
306     if (oflag & O_CREAT)
307     {
308         if (permissions & lldb::eFilePermissionsUserRead)     mode |= S_IRUSR;
309         if (permissions & lldb::eFilePermissionsUserWrite)    mode |= S_IWUSR;
310         if (permissions & lldb::eFilePermissionsUserExecute)  mode |= S_IXUSR;
311         if (permissions & lldb::eFilePermissionsGroupRead)    mode |= S_IRGRP;
312         if (permissions & lldb::eFilePermissionsGroupWrite)   mode |= S_IWGRP;
313         if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP;
314         if (permissions & lldb::eFilePermissionsWorldRead)    mode |= S_IROTH;
315         if (permissions & lldb::eFilePermissionsWorldWrite)   mode |= S_IWOTH;
316         if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH;
317     }
318 
319     do
320     {
321         m_descriptor = ::open(path, oflag, mode);
322     } while (m_descriptor < 0 && errno == EINTR);
323 
324     if (!DescriptorIsValid())
325         error.SetErrorToErrno();
326     else
327     {
328         m_should_close_fd = true;
329         m_options = options;
330     }
331 
332     return error;
333 }
334 
335 uint32_t
336 File::GetPermissions(const FileSpec &file_spec, Error &error)
337 {
338     if (file_spec)
339     {
340         struct stat file_stats;
341         if (::stat(file_spec.GetCString(), &file_stats) == -1)
342             error.SetErrorToErrno();
343         else
344         {
345             error.Clear();
346             return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
347         }
348     }
349     else
350         error.SetErrorString ("empty file spec");
351     return 0;
352 }
353 
354 uint32_t
355 File::GetPermissions(Error &error) const
356 {
357     int fd = GetDescriptor();
358     if (fd != kInvalidDescriptor)
359     {
360         struct stat file_stats;
361         if (::fstat (fd, &file_stats) == -1)
362             error.SetErrorToErrno();
363         else
364         {
365             error.Clear();
366             return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
367         }
368     }
369     else
370     {
371         error.SetErrorString ("invalid file descriptor");
372     }
373     return 0;
374 }
375 
376 
377 Error
378 File::Close ()
379 {
380     Error error;
381     if (StreamIsValid() && m_own_stream)
382     {
383         if (::fclose (m_stream) == EOF)
384             error.SetErrorToErrno();
385     }
386 
387     if (DescriptorIsValid() && m_should_close_fd)
388     {
389         if (::close (m_descriptor) != 0)
390             error.SetErrorToErrno();
391     }
392     m_descriptor = kInvalidDescriptor;
393     m_stream = kInvalidStream;
394     m_options = 0;
395     m_own_stream = false;
396     m_should_close_fd = false;
397     m_is_interactive = eLazyBoolCalculate;
398     m_is_real_terminal = eLazyBoolCalculate;
399     return error;
400 }
401 
402 
403 Error
404 File::GetFileSpec (FileSpec &file_spec) const
405 {
406     Error error;
407 #ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
408     if (IsValid ())
409     {
410         char path[PATH_MAX];
411         if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
412             error.SetErrorToErrno();
413         else
414             file_spec.SetFile (path, false);
415     }
416     else
417     {
418         error.SetErrorString("invalid file handle");
419     }
420 #elif defined(__linux__)
421     char proc[64];
422     char path[PATH_MAX];
423     if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
424         error.SetErrorString ("cannot resolve file descriptor");
425     else
426     {
427         ssize_t len;
428         if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
429             error.SetErrorToErrno();
430         else
431         {
432             path[len] = '\0';
433             file_spec.SetFile (path, false);
434         }
435     }
436 #else
437     error.SetErrorString ("File::GetFileSpec is not supported on this platform");
438 #endif
439 
440     if (error.Fail())
441         file_spec.Clear();
442     return error;
443 }
444 
445 off_t
446 File::SeekFromStart (off_t offset, Error *error_ptr)
447 {
448     off_t result = 0;
449     if (DescriptorIsValid())
450     {
451         result = ::lseek (m_descriptor, offset, SEEK_SET);
452 
453         if (error_ptr)
454         {
455             if (result == -1)
456                 error_ptr->SetErrorToErrno();
457             else
458                 error_ptr->Clear();
459         }
460     }
461     else if (StreamIsValid ())
462     {
463         result = ::fseek(m_stream, offset, SEEK_SET);
464 
465         if (error_ptr)
466         {
467             if (result == -1)
468                 error_ptr->SetErrorToErrno();
469             else
470                 error_ptr->Clear();
471         }
472     }
473     else if (error_ptr)
474     {
475         error_ptr->SetErrorString("invalid file handle");
476     }
477     return result;
478 }
479 
480 off_t
481 File::SeekFromCurrent (off_t offset,  Error *error_ptr)
482 {
483     off_t result = -1;
484     if (DescriptorIsValid())
485     {
486         result = ::lseek (m_descriptor, offset, SEEK_CUR);
487 
488         if (error_ptr)
489         {
490             if (result == -1)
491                 error_ptr->SetErrorToErrno();
492             else
493                 error_ptr->Clear();
494         }
495     }
496     else if (StreamIsValid ())
497     {
498         result = ::fseek(m_stream, offset, SEEK_CUR);
499 
500         if (error_ptr)
501         {
502             if (result == -1)
503                 error_ptr->SetErrorToErrno();
504             else
505                 error_ptr->Clear();
506         }
507     }
508     else if (error_ptr)
509     {
510         error_ptr->SetErrorString("invalid file handle");
511     }
512     return result;
513 }
514 
515 off_t
516 File::SeekFromEnd (off_t offset, Error *error_ptr)
517 {
518     off_t result = -1;
519     if (DescriptorIsValid())
520     {
521         result = ::lseek (m_descriptor, offset, SEEK_END);
522 
523         if (error_ptr)
524         {
525             if (result == -1)
526                 error_ptr->SetErrorToErrno();
527             else
528                 error_ptr->Clear();
529         }
530     }
531     else if (StreamIsValid ())
532     {
533         result = ::fseek(m_stream, offset, SEEK_END);
534 
535         if (error_ptr)
536         {
537             if (result == -1)
538                 error_ptr->SetErrorToErrno();
539             else
540                 error_ptr->Clear();
541         }
542     }
543     else if (error_ptr)
544     {
545         error_ptr->SetErrorString("invalid file handle");
546     }
547     return result;
548 }
549 
550 Error
551 File::Flush ()
552 {
553     Error error;
554     if (StreamIsValid())
555     {
556         int err = 0;
557         do
558         {
559             err = ::fflush (m_stream);
560         } while (err == EOF && errno == EINTR);
561 
562         if (err == EOF)
563             error.SetErrorToErrno();
564     }
565     else if (!DescriptorIsValid())
566     {
567         error.SetErrorString("invalid file handle");
568     }
569     return error;
570 }
571 
572 
573 Error
574 File::Sync ()
575 {
576     Error error;
577     if (DescriptorIsValid())
578     {
579 #ifdef _WIN32
580         int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
581         if (err == 0)
582             error.SetErrorToGenericError();
583 #else
584         int err = 0;
585         do
586         {
587             err = ::fsync (m_descriptor);
588         } while (err == -1 && errno == EINTR);
589 
590         if (err == -1)
591             error.SetErrorToErrno();
592 #endif
593     }
594     else
595     {
596         error.SetErrorString("invalid file handle");
597     }
598     return error;
599 }
600 
601 #if defined (__APPLE__)
602 // Darwin kernels only can read/write <= INT_MAX bytes
603 #define MAX_READ_SIZE INT_MAX
604 #define MAX_WRITE_SIZE INT_MAX
605 #endif
606 
607 Error
608 File::Read (void *buf, size_t &num_bytes)
609 {
610     Error error;
611 
612 #if defined (MAX_READ_SIZE)
613     if (num_bytes > MAX_READ_SIZE)
614     {
615         uint8_t *p = (uint8_t *)buf;
616         size_t bytes_left = num_bytes;
617         // Init the num_bytes read to zero
618         num_bytes = 0;
619 
620         while (bytes_left > 0)
621         {
622             size_t curr_num_bytes;
623             if (bytes_left > MAX_READ_SIZE)
624                 curr_num_bytes = MAX_READ_SIZE;
625             else
626                 curr_num_bytes = bytes_left;
627 
628             error = Read (p + num_bytes, curr_num_bytes);
629 
630             // Update how many bytes were read
631             num_bytes += curr_num_bytes;
632             if (bytes_left < curr_num_bytes)
633                 bytes_left = 0;
634             else
635                 bytes_left -= curr_num_bytes;
636 
637             if (error.Fail())
638                 break;
639         }
640         return error;
641     }
642 #endif
643 
644     ssize_t bytes_read = -1;
645     if (DescriptorIsValid())
646     {
647         do
648         {
649             bytes_read = ::read (m_descriptor, buf, num_bytes);
650         } while (bytes_read < 0 && errno == EINTR);
651 
652         if (bytes_read == -1)
653         {
654             error.SetErrorToErrno();
655             num_bytes = 0;
656         }
657         else
658             num_bytes = bytes_read;
659     }
660     else if (StreamIsValid())
661     {
662         bytes_read = ::fread (buf, 1, num_bytes, m_stream);
663 
664         if (bytes_read == 0)
665         {
666             if (::feof(m_stream))
667                 error.SetErrorString ("feof");
668             else if (::ferror (m_stream))
669                 error.SetErrorString ("ferror");
670             num_bytes = 0;
671         }
672         else
673             num_bytes = bytes_read;
674     }
675     else
676     {
677         num_bytes = 0;
678         error.SetErrorString("invalid file handle");
679     }
680     return error;
681 }
682 
683 Error
684 File::Write (const void *buf, size_t &num_bytes)
685 {
686     Error error;
687 
688 #if defined (MAX_WRITE_SIZE)
689     if (num_bytes > MAX_WRITE_SIZE)
690     {
691         const uint8_t *p = (const uint8_t *)buf;
692         size_t bytes_left = num_bytes;
693         // Init the num_bytes written to zero
694         num_bytes = 0;
695 
696         while (bytes_left > 0)
697         {
698             size_t curr_num_bytes;
699             if (bytes_left > MAX_WRITE_SIZE)
700                 curr_num_bytes = MAX_WRITE_SIZE;
701             else
702                 curr_num_bytes = bytes_left;
703 
704             error = Write (p + num_bytes, curr_num_bytes);
705 
706             // Update how many bytes were read
707             num_bytes += curr_num_bytes;
708             if (bytes_left < curr_num_bytes)
709                 bytes_left = 0;
710             else
711                 bytes_left -= curr_num_bytes;
712 
713             if (error.Fail())
714                 break;
715         }
716         return error;
717     }
718 #endif
719 
720     ssize_t bytes_written = -1;
721     if (DescriptorIsValid())
722     {
723         do
724         {
725             bytes_written = ::write (m_descriptor, buf, num_bytes);
726         } while (bytes_written < 0 && errno == EINTR);
727 
728         if (bytes_written == -1)
729         {
730             error.SetErrorToErrno();
731             num_bytes = 0;
732         }
733         else
734             num_bytes = bytes_written;
735     }
736     else if (StreamIsValid())
737     {
738         bytes_written = ::fwrite (buf, 1, num_bytes, m_stream);
739 
740         if (bytes_written == 0)
741         {
742             if (::feof(m_stream))
743                 error.SetErrorString ("feof");
744             else if (::ferror (m_stream))
745                 error.SetErrorString ("ferror");
746             num_bytes = 0;
747         }
748         else
749             num_bytes = bytes_written;
750 
751     }
752     else
753     {
754         num_bytes = 0;
755         error.SetErrorString("invalid file handle");
756     }
757 
758     return error;
759 }
760 
761 
762 Error
763 File::Read (void *buf, size_t &num_bytes, off_t &offset)
764 {
765     Error error;
766 
767 #if defined (MAX_READ_SIZE)
768     if (num_bytes > MAX_READ_SIZE)
769     {
770         uint8_t *p = (uint8_t *)buf;
771         size_t bytes_left = num_bytes;
772         // Init the num_bytes read to zero
773         num_bytes = 0;
774 
775         while (bytes_left > 0)
776         {
777             size_t curr_num_bytes;
778             if (bytes_left > MAX_READ_SIZE)
779                 curr_num_bytes = MAX_READ_SIZE;
780             else
781                 curr_num_bytes = bytes_left;
782 
783             error = Read (p + num_bytes, curr_num_bytes, offset);
784 
785             // Update how many bytes were read
786             num_bytes += curr_num_bytes;
787             if (bytes_left < curr_num_bytes)
788                 bytes_left = 0;
789             else
790                 bytes_left -= curr_num_bytes;
791 
792             if (error.Fail())
793                 break;
794         }
795         return error;
796     }
797 #endif
798 
799 #ifndef _WIN32
800     int fd = GetDescriptor();
801     if (fd != kInvalidDescriptor)
802     {
803         ssize_t bytes_read = -1;
804         do
805         {
806             bytes_read = ::pread (fd, buf, num_bytes, offset);
807         } while (bytes_read < 0 && errno == EINTR);
808 
809         if (bytes_read < 0)
810         {
811             num_bytes = 0;
812             error.SetErrorToErrno();
813         }
814         else
815         {
816             offset += bytes_read;
817             num_bytes = bytes_read;
818         }
819     }
820     else
821     {
822         num_bytes = 0;
823         error.SetErrorString("invalid file handle");
824     }
825 #else
826     long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
827     SeekFromStart(offset);
828     error = Read(buf, num_bytes);
829     if (!error.Fail())
830         SeekFromStart(cur);
831 #endif
832     return error;
833 }
834 
835 Error
836 File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
837 {
838     Error error;
839 
840     if (num_bytes > 0)
841     {
842         int fd = GetDescriptor();
843         if (fd != kInvalidDescriptor)
844         {
845             struct stat file_stats;
846             if (::fstat (fd, &file_stats) == 0)
847             {
848                 if (file_stats.st_size > offset)
849                 {
850                     const size_t bytes_left = file_stats.st_size - offset;
851                     if (num_bytes > bytes_left)
852                         num_bytes = bytes_left;
853 
854                     size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
855                     std::unique_ptr<DataBufferHeap> data_heap_ap;
856                     data_heap_ap.reset(new DataBufferHeap());
857                     data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
858 
859                     if (data_heap_ap.get())
860                     {
861                         error = Read (data_heap_ap->GetBytes(), num_bytes, offset);
862                         if (error.Success())
863                         {
864                             // Make sure we read exactly what we asked for and if we got
865                             // less, adjust the array
866                             if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize())
867                                 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
868                             data_buffer_sp.reset(data_heap_ap.release());
869                             return error;
870                         }
871                     }
872                 }
873                 else
874                     error.SetErrorString("file is empty");
875             }
876             else
877                 error.SetErrorToErrno();
878         }
879         else
880             error.SetErrorString("invalid file handle");
881     }
882     else
883         error.SetErrorString("invalid file handle");
884 
885     num_bytes = 0;
886     data_buffer_sp.reset();
887     return error;
888 }
889 
890 Error
891 File::Write (const void *buf, size_t &num_bytes, off_t &offset)
892 {
893     Error error;
894 
895 #if defined (MAX_WRITE_SIZE)
896     if (num_bytes > MAX_WRITE_SIZE)
897     {
898         const uint8_t *p = (const uint8_t *)buf;
899         size_t bytes_left = num_bytes;
900         // Init the num_bytes written to zero
901         num_bytes = 0;
902 
903         while (bytes_left > 0)
904         {
905             size_t curr_num_bytes;
906             if (bytes_left > MAX_WRITE_SIZE)
907                 curr_num_bytes = MAX_WRITE_SIZE;
908             else
909                 curr_num_bytes = bytes_left;
910 
911             error = Write (p + num_bytes, curr_num_bytes, offset);
912 
913             // Update how many bytes were read
914             num_bytes += curr_num_bytes;
915             if (bytes_left < curr_num_bytes)
916                 bytes_left = 0;
917             else
918                 bytes_left -= curr_num_bytes;
919 
920             if (error.Fail())
921                 break;
922         }
923         return error;
924     }
925 #endif
926 
927     int fd = GetDescriptor();
928     if (fd != kInvalidDescriptor)
929     {
930 #ifndef _WIN32
931         ssize_t bytes_written = -1;
932         do
933         {
934             bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset);
935         } while (bytes_written < 0 && errno == EINTR);
936 
937         if (bytes_written < 0)
938         {
939             num_bytes = 0;
940             error.SetErrorToErrno();
941         }
942         else
943         {
944             offset += bytes_written;
945             num_bytes = bytes_written;
946         }
947 #else
948         long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
949         error = Write(buf, num_bytes);
950         long after = ::lseek(m_descriptor, 0, SEEK_CUR);
951 
952         if (!error.Fail())
953             SeekFromStart(cur);
954 
955         offset = after;
956 #endif
957     }
958     else
959     {
960         num_bytes = 0;
961         error.SetErrorString("invalid file handle");
962     }
963     return error;
964 }
965 
966 //------------------------------------------------------------------
967 // Print some formatted output to the stream.
968 //------------------------------------------------------------------
969 size_t
970 File::Printf (const char *format, ...)
971 {
972     va_list args;
973     va_start (args, format);
974     size_t result = PrintfVarArg (format, args);
975     va_end (args);
976     return result;
977 }
978 
979 //------------------------------------------------------------------
980 // Print some formatted output to the stream.
981 //------------------------------------------------------------------
982 size_t
983 File::PrintfVarArg (const char *format, va_list args)
984 {
985     size_t result = 0;
986     if (DescriptorIsValid())
987     {
988         char *s = NULL;
989         result = vasprintf(&s, format, args);
990         if (s != NULL)
991         {
992             if (result > 0)
993             {
994                 size_t s_len = result;
995                 Write (s, s_len);
996                 result = s_len;
997             }
998             free (s);
999         }
1000     }
1001     else if (StreamIsValid())
1002     {
1003         result = ::vfprintf (m_stream, format, args);
1004     }
1005     return result;
1006 }
1007 
1008 mode_t
1009 File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
1010 {
1011     mode_t mode = 0;
1012     if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
1013         mode |= O_RDWR;
1014     else if (open_options & eOpenOptionWrite)
1015         mode |= O_WRONLY;
1016 
1017     if (open_options & eOpenOptionAppend)
1018         mode |= O_APPEND;
1019 
1020     if (open_options & eOpenOptionTruncate)
1021         mode |= O_TRUNC;
1022 
1023     if (open_options & eOpenOptionNonBlocking)
1024         mode |= O_NONBLOCK;
1025 
1026     if (open_options & eOpenOptionCanCreateNewOnly)
1027         mode |= O_CREAT | O_EXCL;
1028     else if (open_options & eOpenOptionCanCreate)
1029         mode |= O_CREAT;
1030 
1031     return mode;
1032 }
1033 
1034 void
1035 File::CalculateInteractiveAndTerminal ()
1036 {
1037     const int fd = GetDescriptor();
1038     if (fd >= 0)
1039     {
1040         m_is_interactive = eLazyBoolNo;
1041         m_is_real_terminal = eLazyBoolNo;
1042 #if (defined(_WIN32) || defined(__ANDROID_NDK__))
1043         if (_isatty(fd))
1044         {
1045             m_is_interactive = eLazyBoolYes;
1046             m_is_real_terminal = eLazyBoolYes;
1047         }
1048 #else
1049         if (isatty(fd))
1050         {
1051             m_is_interactive = eLazyBoolYes;
1052             struct winsize window_size;
1053             if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
1054             {
1055                 if (window_size.ws_col > 0)
1056                 {
1057                     m_is_real_terminal = eLazyBoolYes;
1058                     if (llvm::sys::Process::FileDescriptorHasColors(fd))
1059                         m_supports_colors = eLazyBoolYes;
1060                 }
1061             }
1062         }
1063 #endif
1064     }
1065 }
1066 
1067 bool
1068 File::GetIsInteractive ()
1069 {
1070     if (m_is_interactive == eLazyBoolCalculate)
1071         CalculateInteractiveAndTerminal ();
1072     return m_is_interactive == eLazyBoolYes;
1073 }
1074 
1075 bool
1076 File::GetIsRealTerminal ()
1077 {
1078     if (m_is_real_terminal == eLazyBoolCalculate)
1079         CalculateInteractiveAndTerminal();
1080     return m_is_real_terminal == eLazyBoolYes;
1081 }
1082 
1083 bool
1084 File::GetIsTerminalWithColors ()
1085 {
1086     if (m_supports_colors == eLazyBoolCalculate)
1087         CalculateInteractiveAndTerminal();
1088     return m_supports_colors == eLazyBoolYes;
1089 }
1090 
1091