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 = dup(GetDescriptor());
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 = dup(rhs.GetDescriptor());
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 void
403 File::Clear ()
404 {
405     m_stream = nullptr;
406     m_descriptor = -1;
407     m_options = 0;
408     m_own_stream = false;
409     m_is_interactive = m_supports_colors = m_is_real_terminal = eLazyBoolCalculate;
410 }
411 
412 Error
413 File::GetFileSpec (FileSpec &file_spec) const
414 {
415     Error error;
416 #ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
417     if (IsValid ())
418     {
419         char path[PATH_MAX];
420         if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
421             error.SetErrorToErrno();
422         else
423             file_spec.SetFile (path, false);
424     }
425     else
426     {
427         error.SetErrorString("invalid file handle");
428     }
429 #elif defined(__linux__)
430     char proc[64];
431     char path[PATH_MAX];
432     if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
433         error.SetErrorString ("cannot resolve file descriptor");
434     else
435     {
436         ssize_t len;
437         if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
438             error.SetErrorToErrno();
439         else
440         {
441             path[len] = '\0';
442             file_spec.SetFile (path, false);
443         }
444     }
445 #else
446     error.SetErrorString ("File::GetFileSpec is not supported on this platform");
447 #endif
448 
449     if (error.Fail())
450         file_spec.Clear();
451     return error;
452 }
453 
454 off_t
455 File::SeekFromStart (off_t offset, Error *error_ptr)
456 {
457     off_t result = 0;
458     if (DescriptorIsValid())
459     {
460         result = ::lseek (m_descriptor, offset, SEEK_SET);
461 
462         if (error_ptr)
463         {
464             if (result == -1)
465                 error_ptr->SetErrorToErrno();
466             else
467                 error_ptr->Clear();
468         }
469     }
470     else if (StreamIsValid ())
471     {
472         result = ::fseek(m_stream, offset, SEEK_SET);
473 
474         if (error_ptr)
475         {
476             if (result == -1)
477                 error_ptr->SetErrorToErrno();
478             else
479                 error_ptr->Clear();
480         }
481     }
482     else if (error_ptr)
483     {
484         error_ptr->SetErrorString("invalid file handle");
485     }
486     return result;
487 }
488 
489 off_t
490 File::SeekFromCurrent (off_t offset,  Error *error_ptr)
491 {
492     off_t result = -1;
493     if (DescriptorIsValid())
494     {
495         result = ::lseek (m_descriptor, offset, SEEK_CUR);
496 
497         if (error_ptr)
498         {
499             if (result == -1)
500                 error_ptr->SetErrorToErrno();
501             else
502                 error_ptr->Clear();
503         }
504     }
505     else if (StreamIsValid ())
506     {
507         result = ::fseek(m_stream, offset, SEEK_CUR);
508 
509         if (error_ptr)
510         {
511             if (result == -1)
512                 error_ptr->SetErrorToErrno();
513             else
514                 error_ptr->Clear();
515         }
516     }
517     else if (error_ptr)
518     {
519         error_ptr->SetErrorString("invalid file handle");
520     }
521     return result;
522 }
523 
524 off_t
525 File::SeekFromEnd (off_t offset, Error *error_ptr)
526 {
527     off_t result = -1;
528     if (DescriptorIsValid())
529     {
530         result = ::lseek (m_descriptor, offset, SEEK_END);
531 
532         if (error_ptr)
533         {
534             if (result == -1)
535                 error_ptr->SetErrorToErrno();
536             else
537                 error_ptr->Clear();
538         }
539     }
540     else if (StreamIsValid ())
541     {
542         result = ::fseek(m_stream, offset, SEEK_END);
543 
544         if (error_ptr)
545         {
546             if (result == -1)
547                 error_ptr->SetErrorToErrno();
548             else
549                 error_ptr->Clear();
550         }
551     }
552     else if (error_ptr)
553     {
554         error_ptr->SetErrorString("invalid file handle");
555     }
556     return result;
557 }
558 
559 Error
560 File::Flush ()
561 {
562     Error error;
563     if (StreamIsValid())
564     {
565         int err = 0;
566         do
567         {
568             err = ::fflush (m_stream);
569         } while (err == EOF && errno == EINTR);
570 
571         if (err == EOF)
572             error.SetErrorToErrno();
573     }
574     else if (!DescriptorIsValid())
575     {
576         error.SetErrorString("invalid file handle");
577     }
578     return error;
579 }
580 
581 
582 Error
583 File::Sync ()
584 {
585     Error error;
586     if (DescriptorIsValid())
587     {
588 #ifdef _WIN32
589         int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
590         if (err == 0)
591             error.SetErrorToGenericError();
592 #else
593         int err = 0;
594         do
595         {
596             err = ::fsync (m_descriptor);
597         } while (err == -1 && errno == EINTR);
598 
599         if (err == -1)
600             error.SetErrorToErrno();
601 #endif
602     }
603     else
604     {
605         error.SetErrorString("invalid file handle");
606     }
607     return error;
608 }
609 
610 #if defined (__APPLE__)
611 // Darwin kernels only can read/write <= INT_MAX bytes
612 #define MAX_READ_SIZE INT_MAX
613 #define MAX_WRITE_SIZE INT_MAX
614 #endif
615 
616 Error
617 File::Read (void *buf, size_t &num_bytes)
618 {
619     Error error;
620 
621 #if defined (MAX_READ_SIZE)
622     if (num_bytes > MAX_READ_SIZE)
623     {
624         uint8_t *p = (uint8_t *)buf;
625         size_t bytes_left = num_bytes;
626         // Init the num_bytes read to zero
627         num_bytes = 0;
628 
629         while (bytes_left > 0)
630         {
631             size_t curr_num_bytes;
632             if (bytes_left > MAX_READ_SIZE)
633                 curr_num_bytes = MAX_READ_SIZE;
634             else
635                 curr_num_bytes = bytes_left;
636 
637             error = Read (p + num_bytes, curr_num_bytes);
638 
639             // Update how many bytes were read
640             num_bytes += curr_num_bytes;
641             if (bytes_left < curr_num_bytes)
642                 bytes_left = 0;
643             else
644                 bytes_left -= curr_num_bytes;
645 
646             if (error.Fail())
647                 break;
648         }
649         return error;
650     }
651 #endif
652 
653     ssize_t bytes_read = -1;
654     if (DescriptorIsValid())
655     {
656         do
657         {
658             bytes_read = ::read (m_descriptor, buf, num_bytes);
659         } while (bytes_read < 0 && errno == EINTR);
660 
661         if (bytes_read == -1)
662         {
663             error.SetErrorToErrno();
664             num_bytes = 0;
665         }
666         else
667             num_bytes = bytes_read;
668     }
669     else if (StreamIsValid())
670     {
671         bytes_read = ::fread (buf, 1, num_bytes, m_stream);
672 
673         if (bytes_read == 0)
674         {
675             if (::feof(m_stream))
676                 error.SetErrorString ("feof");
677             else if (::ferror (m_stream))
678                 error.SetErrorString ("ferror");
679             num_bytes = 0;
680         }
681         else
682             num_bytes = bytes_read;
683     }
684     else
685     {
686         num_bytes = 0;
687         error.SetErrorString("invalid file handle");
688     }
689     return error;
690 }
691 
692 Error
693 File::Write (const void *buf, size_t &num_bytes)
694 {
695     Error error;
696 
697 #if defined (MAX_WRITE_SIZE)
698     if (num_bytes > MAX_WRITE_SIZE)
699     {
700         const uint8_t *p = (const uint8_t *)buf;
701         size_t bytes_left = num_bytes;
702         // Init the num_bytes written to zero
703         num_bytes = 0;
704 
705         while (bytes_left > 0)
706         {
707             size_t curr_num_bytes;
708             if (bytes_left > MAX_WRITE_SIZE)
709                 curr_num_bytes = MAX_WRITE_SIZE;
710             else
711                 curr_num_bytes = bytes_left;
712 
713             error = Write (p + num_bytes, curr_num_bytes);
714 
715             // Update how many bytes were read
716             num_bytes += curr_num_bytes;
717             if (bytes_left < curr_num_bytes)
718                 bytes_left = 0;
719             else
720                 bytes_left -= curr_num_bytes;
721 
722             if (error.Fail())
723                 break;
724         }
725         return error;
726     }
727 #endif
728 
729     ssize_t bytes_written = -1;
730     if (DescriptorIsValid())
731     {
732         do
733         {
734             bytes_written = ::write (m_descriptor, buf, num_bytes);
735         } while (bytes_written < 0 && errno == EINTR);
736 
737         if (bytes_written == -1)
738         {
739             error.SetErrorToErrno();
740             num_bytes = 0;
741         }
742         else
743             num_bytes = bytes_written;
744     }
745     else if (StreamIsValid())
746     {
747         bytes_written = ::fwrite (buf, 1, num_bytes, m_stream);
748 
749         if (bytes_written == 0)
750         {
751             if (::feof(m_stream))
752                 error.SetErrorString ("feof");
753             else if (::ferror (m_stream))
754                 error.SetErrorString ("ferror");
755             num_bytes = 0;
756         }
757         else
758             num_bytes = bytes_written;
759 
760     }
761     else
762     {
763         num_bytes = 0;
764         error.SetErrorString("invalid file handle");
765     }
766 
767     return error;
768 }
769 
770 
771 Error
772 File::Read (void *buf, size_t &num_bytes, off_t &offset)
773 {
774     Error error;
775 
776 #if defined (MAX_READ_SIZE)
777     if (num_bytes > MAX_READ_SIZE)
778     {
779         uint8_t *p = (uint8_t *)buf;
780         size_t bytes_left = num_bytes;
781         // Init the num_bytes read to zero
782         num_bytes = 0;
783 
784         while (bytes_left > 0)
785         {
786             size_t curr_num_bytes;
787             if (bytes_left > MAX_READ_SIZE)
788                 curr_num_bytes = MAX_READ_SIZE;
789             else
790                 curr_num_bytes = bytes_left;
791 
792             error = Read (p + num_bytes, curr_num_bytes, offset);
793 
794             // Update how many bytes were read
795             num_bytes += curr_num_bytes;
796             if (bytes_left < curr_num_bytes)
797                 bytes_left = 0;
798             else
799                 bytes_left -= curr_num_bytes;
800 
801             if (error.Fail())
802                 break;
803         }
804         return error;
805     }
806 #endif
807 
808 #ifndef _WIN32
809     int fd = GetDescriptor();
810     if (fd != kInvalidDescriptor)
811     {
812         ssize_t bytes_read = -1;
813         do
814         {
815             bytes_read = ::pread (fd, buf, num_bytes, offset);
816         } while (bytes_read < 0 && errno == EINTR);
817 
818         if (bytes_read < 0)
819         {
820             num_bytes = 0;
821             error.SetErrorToErrno();
822         }
823         else
824         {
825             offset += bytes_read;
826             num_bytes = bytes_read;
827         }
828     }
829     else
830     {
831         num_bytes = 0;
832         error.SetErrorString("invalid file handle");
833     }
834 #else
835     long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
836     SeekFromStart(offset);
837     error = Read(buf, num_bytes);
838     if (!error.Fail())
839         SeekFromStart(cur);
840 #endif
841     return error;
842 }
843 
844 Error
845 File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
846 {
847     Error error;
848 
849     if (num_bytes > 0)
850     {
851         int fd = GetDescriptor();
852         if (fd != kInvalidDescriptor)
853         {
854             struct stat file_stats;
855             if (::fstat (fd, &file_stats) == 0)
856             {
857                 if (file_stats.st_size > offset)
858                 {
859                     const size_t bytes_left = file_stats.st_size - offset;
860                     if (num_bytes > bytes_left)
861                         num_bytes = bytes_left;
862 
863                     size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
864                     std::unique_ptr<DataBufferHeap> data_heap_ap;
865                     data_heap_ap.reset(new DataBufferHeap());
866                     data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
867 
868                     if (data_heap_ap.get())
869                     {
870                         error = Read (data_heap_ap->GetBytes(), num_bytes, offset);
871                         if (error.Success())
872                         {
873                             // Make sure we read exactly what we asked for and if we got
874                             // less, adjust the array
875                             if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize())
876                                 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
877                             data_buffer_sp.reset(data_heap_ap.release());
878                             return error;
879                         }
880                     }
881                 }
882                 else
883                     error.SetErrorString("file is empty");
884             }
885             else
886                 error.SetErrorToErrno();
887         }
888         else
889             error.SetErrorString("invalid file handle");
890     }
891     else
892         error.SetErrorString("invalid file handle");
893 
894     num_bytes = 0;
895     data_buffer_sp.reset();
896     return error;
897 }
898 
899 Error
900 File::Write (const void *buf, size_t &num_bytes, off_t &offset)
901 {
902     Error error;
903 
904 #if defined (MAX_WRITE_SIZE)
905     if (num_bytes > MAX_WRITE_SIZE)
906     {
907         const uint8_t *p = (const uint8_t *)buf;
908         size_t bytes_left = num_bytes;
909         // Init the num_bytes written to zero
910         num_bytes = 0;
911 
912         while (bytes_left > 0)
913         {
914             size_t curr_num_bytes;
915             if (bytes_left > MAX_WRITE_SIZE)
916                 curr_num_bytes = MAX_WRITE_SIZE;
917             else
918                 curr_num_bytes = bytes_left;
919 
920             error = Write (p + num_bytes, curr_num_bytes, offset);
921 
922             // Update how many bytes were read
923             num_bytes += curr_num_bytes;
924             if (bytes_left < curr_num_bytes)
925                 bytes_left = 0;
926             else
927                 bytes_left -= curr_num_bytes;
928 
929             if (error.Fail())
930                 break;
931         }
932         return error;
933     }
934 #endif
935 
936     int fd = GetDescriptor();
937     if (fd != kInvalidDescriptor)
938     {
939 #ifndef _WIN32
940         ssize_t bytes_written = -1;
941         do
942         {
943             bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset);
944         } while (bytes_written < 0 && errno == EINTR);
945 
946         if (bytes_written < 0)
947         {
948             num_bytes = 0;
949             error.SetErrorToErrno();
950         }
951         else
952         {
953             offset += bytes_written;
954             num_bytes = bytes_written;
955         }
956 #else
957         long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
958         error = Write(buf, num_bytes);
959         long after = ::lseek(m_descriptor, 0, SEEK_CUR);
960 
961         if (!error.Fail())
962             SeekFromStart(cur);
963 
964         offset = after;
965 #endif
966     }
967     else
968     {
969         num_bytes = 0;
970         error.SetErrorString("invalid file handle");
971     }
972     return error;
973 }
974 
975 //------------------------------------------------------------------
976 // Print some formatted output to the stream.
977 //------------------------------------------------------------------
978 size_t
979 File::Printf (const char *format, ...)
980 {
981     va_list args;
982     va_start (args, format);
983     size_t result = PrintfVarArg (format, args);
984     va_end (args);
985     return result;
986 }
987 
988 //------------------------------------------------------------------
989 // Print some formatted output to the stream.
990 //------------------------------------------------------------------
991 size_t
992 File::PrintfVarArg (const char *format, va_list args)
993 {
994     size_t result = 0;
995     if (DescriptorIsValid())
996     {
997         char *s = NULL;
998         result = vasprintf(&s, format, args);
999         if (s != NULL)
1000         {
1001             if (result > 0)
1002             {
1003                 size_t s_len = result;
1004                 Write (s, s_len);
1005                 result = s_len;
1006             }
1007             free (s);
1008         }
1009     }
1010     else if (StreamIsValid())
1011     {
1012         result = ::vfprintf (m_stream, format, args);
1013     }
1014     return result;
1015 }
1016 
1017 mode_t
1018 File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
1019 {
1020     mode_t mode = 0;
1021     if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
1022         mode |= O_RDWR;
1023     else if (open_options & eOpenOptionWrite)
1024         mode |= O_WRONLY;
1025 
1026     if (open_options & eOpenOptionAppend)
1027         mode |= O_APPEND;
1028 
1029     if (open_options & eOpenOptionTruncate)
1030         mode |= O_TRUNC;
1031 
1032     if (open_options & eOpenOptionNonBlocking)
1033         mode |= O_NONBLOCK;
1034 
1035     if (open_options & eOpenOptionCanCreateNewOnly)
1036         mode |= O_CREAT | O_EXCL;
1037     else if (open_options & eOpenOptionCanCreate)
1038         mode |= O_CREAT;
1039 
1040     return mode;
1041 }
1042 
1043 void
1044 File::CalculateInteractiveAndTerminal ()
1045 {
1046     const int fd = GetDescriptor();
1047     if (fd >= 0)
1048     {
1049         m_is_interactive = eLazyBoolNo;
1050         m_is_real_terminal = eLazyBoolNo;
1051 #if (defined(_WIN32) || defined(__ANDROID_NDK__))
1052         if (_isatty(fd))
1053         {
1054             m_is_interactive = eLazyBoolYes;
1055             m_is_real_terminal = eLazyBoolYes;
1056         }
1057 #else
1058         if (isatty(fd))
1059         {
1060             m_is_interactive = eLazyBoolYes;
1061             struct winsize window_size;
1062             if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
1063             {
1064                 if (window_size.ws_col > 0)
1065                 {
1066                     m_is_real_terminal = eLazyBoolYes;
1067                     if (llvm::sys::Process::FileDescriptorHasColors(fd))
1068                         m_supports_colors = eLazyBoolYes;
1069                 }
1070             }
1071         }
1072 #endif
1073     }
1074 }
1075 
1076 bool
1077 File::GetIsInteractive ()
1078 {
1079     if (m_is_interactive == eLazyBoolCalculate)
1080         CalculateInteractiveAndTerminal ();
1081     return m_is_interactive == eLazyBoolYes;
1082 }
1083 
1084 bool
1085 File::GetIsRealTerminal ()
1086 {
1087     if (m_is_real_terminal == eLazyBoolCalculate)
1088         CalculateInteractiveAndTerminal();
1089     return m_is_real_terminal == eLazyBoolYes;
1090 }
1091 
1092 bool
1093 File::GetIsTerminalWithColors ()
1094 {
1095     if (m_supports_colors == eLazyBoolCalculate)
1096         CalculateInteractiveAndTerminal();
1097     return m_supports_colors == eLazyBoolYes;
1098 }
1099 
1100