]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Host/common/File.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / source / Host / common / File.cpp
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
18 #ifdef _WIN32
19 #include "lldb/Host/windows/windows.h"
20 #else
21 #include <sys/ioctl.h>
22 #endif
23
24 #include "llvm/Support/ConvertUTF.h"
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 #include "lldb/Host/FileSystem.h"
33
34 using namespace lldb;
35 using namespace lldb_private;
36
37 static const char *GetStreamOpenModeFromOptions(uint32_t options) {
38   if (options & File::eOpenOptionAppend) {
39     if (options & File::eOpenOptionRead) {
40       if (options & File::eOpenOptionCanCreateNewOnly)
41         return "a+x";
42       else
43         return "a+";
44     } else if (options & File::eOpenOptionWrite) {
45       if (options & File::eOpenOptionCanCreateNewOnly)
46         return "ax";
47       else
48         return "a";
49     }
50   } else if (options & File::eOpenOptionRead &&
51              options & File::eOpenOptionWrite) {
52     if (options & File::eOpenOptionCanCreate) {
53       if (options & File::eOpenOptionCanCreateNewOnly)
54         return "w+x";
55       else
56         return "w+";
57     } else
58       return "r+";
59   } else if (options & File::eOpenOptionRead) {
60     return "r";
61   } else if (options & File::eOpenOptionWrite) {
62     return "w";
63   }
64   return NULL;
65 }
66
67 int File::kInvalidDescriptor = -1;
68 FILE *File::kInvalidStream = NULL;
69
70 File::File(const char *path, uint32_t options, uint32_t permissions)
71     : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
72       m_stream(kInvalidStream), m_options(), m_own_stream(false),
73       m_is_interactive(eLazyBoolCalculate),
74       m_is_real_terminal(eLazyBoolCalculate) {
75   Open(path, options, permissions);
76 }
77
78 File::File(const FileSpec &filespec, uint32_t options, uint32_t permissions)
79     : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
80       m_stream(kInvalidStream), m_options(0), m_own_stream(false),
81       m_is_interactive(eLazyBoolCalculate),
82       m_is_real_terminal(eLazyBoolCalculate)
83
84 {
85   if (filespec) {
86     Open(filespec.GetPath().c_str(), options, permissions);
87   }
88 }
89
90 File::~File() { Close(); }
91
92 int File::GetDescriptor() const {
93   if (DescriptorIsValid())
94     return m_descriptor;
95
96   // Don't open the file descriptor if we don't need to, just get it from the
97   // stream if we have one.
98   if (StreamIsValid()) {
99 #if defined(LLVM_ON_WIN32)
100     return _fileno(m_stream);
101 #else
102     return fileno(m_stream);
103 #endif
104   }
105
106   // Invalid descriptor and invalid stream, return invalid descriptor.
107   return kInvalidDescriptor;
108 }
109
110 IOObject::WaitableHandle File::GetWaitableHandle() { return m_descriptor; }
111
112 void File::SetDescriptor(int fd, bool transfer_ownership) {
113   if (IsValid())
114     Close();
115   m_descriptor = fd;
116   m_should_close_fd = transfer_ownership;
117 }
118
119 FILE *File::GetStream() {
120   if (!StreamIsValid()) {
121     if (DescriptorIsValid()) {
122       const char *mode = GetStreamOpenModeFromOptions(m_options);
123       if (mode) {
124         if (!m_should_close_fd) {
125 // We must duplicate the file descriptor if we don't own it because
126 // when you call fdopen, the stream will own the fd
127 #ifdef _WIN32
128           m_descriptor = ::_dup(GetDescriptor());
129 #else
130           m_descriptor = dup(GetDescriptor());
131 #endif
132           m_should_close_fd = true;
133         }
134
135         do {
136           m_stream = ::fdopen(m_descriptor, mode);
137         } while (m_stream == NULL && errno == EINTR);
138
139         // If we got a stream, then we own the stream and should no
140         // longer own the descriptor because fclose() will close it for us
141
142         if (m_stream) {
143           m_own_stream = true;
144           m_should_close_fd = false;
145         }
146       }
147     }
148   }
149   return m_stream;
150 }
151
152 void File::SetStream(FILE *fh, bool transfer_ownership) {
153   if (IsValid())
154     Close();
155   m_stream = fh;
156   m_own_stream = transfer_ownership;
157 }
158
159 Error File::Open(const char *path, uint32_t options, uint32_t permissions) {
160   Error error;
161   if (IsValid())
162     Close();
163
164   int oflag = 0;
165   const bool read = options & eOpenOptionRead;
166   const bool write = options & eOpenOptionWrite;
167   if (write) {
168     if (read)
169       oflag |= O_RDWR;
170     else
171       oflag |= O_WRONLY;
172
173     if (options & eOpenOptionAppend)
174       oflag |= O_APPEND;
175
176     if (options & eOpenOptionTruncate)
177       oflag |= O_TRUNC;
178
179     if (options & eOpenOptionCanCreate)
180       oflag |= O_CREAT;
181
182     if (options & eOpenOptionCanCreateNewOnly)
183       oflag |= O_CREAT | O_EXCL;
184   } else if (read) {
185     oflag |= O_RDONLY;
186
187 #ifndef _WIN32
188     if (options & eOpenOptionDontFollowSymlinks)
189       oflag |= O_NOFOLLOW;
190 #endif
191   }
192
193 #ifndef _WIN32
194   if (options & eOpenOptionNonBlocking)
195     oflag |= O_NONBLOCK;
196   if (options & eOpenOptionCloseOnExec)
197     oflag |= O_CLOEXEC;
198 #else
199   oflag |= O_BINARY;
200 #endif
201
202   mode_t mode = 0;
203   if (oflag & O_CREAT) {
204     if (permissions & lldb::eFilePermissionsUserRead)
205       mode |= S_IRUSR;
206     if (permissions & lldb::eFilePermissionsUserWrite)
207       mode |= S_IWUSR;
208     if (permissions & lldb::eFilePermissionsUserExecute)
209       mode |= S_IXUSR;
210     if (permissions & lldb::eFilePermissionsGroupRead)
211       mode |= S_IRGRP;
212     if (permissions & lldb::eFilePermissionsGroupWrite)
213       mode |= S_IWGRP;
214     if (permissions & lldb::eFilePermissionsGroupExecute)
215       mode |= S_IXGRP;
216     if (permissions & lldb::eFilePermissionsWorldRead)
217       mode |= S_IROTH;
218     if (permissions & lldb::eFilePermissionsWorldWrite)
219       mode |= S_IWOTH;
220     if (permissions & lldb::eFilePermissionsWorldExecute)
221       mode |= S_IXOTH;
222   }
223
224   do {
225 #ifdef _MSC_VER
226     std::wstring wpath;
227     if (!llvm::ConvertUTF8toWide(path, wpath)) {
228       m_descriptor = -1;
229       error.SetErrorString("Error converting path to UTF-16");
230       return error;
231     }
232     ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode);
233 #else
234     m_descriptor = ::open(path, oflag, mode);
235 #endif
236   } while (m_descriptor < 0 && errno == EINTR);
237
238   if (!DescriptorIsValid())
239     error.SetErrorToErrno();
240   else {
241     m_should_close_fd = true;
242     m_options = options;
243   }
244
245   return error;
246 }
247
248 uint32_t File::GetPermissions(const FileSpec &file_spec, Error &error) {
249   if (file_spec) {
250     struct stat file_stats;
251     int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats);
252     if (stat_result == -1)
253       error.SetErrorToErrno();
254     else {
255       error.Clear();
256       return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
257     }
258   } else
259     error.SetErrorString("empty file spec");
260   return 0;
261 }
262
263 uint32_t File::GetPermissions(Error &error) const {
264   int fd = GetDescriptor();
265   if (fd != kInvalidDescriptor) {
266     struct stat file_stats;
267     if (::fstat(fd, &file_stats) == -1)
268       error.SetErrorToErrno();
269     else {
270       error.Clear();
271       return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
272     }
273   } else {
274     error.SetErrorString("invalid file descriptor");
275   }
276   return 0;
277 }
278
279 Error File::Close() {
280   Error error;
281   if (StreamIsValid() && m_own_stream) {
282     if (::fclose(m_stream) == EOF)
283       error.SetErrorToErrno();
284   }
285
286   if (DescriptorIsValid() && m_should_close_fd) {
287     if (::close(m_descriptor) != 0)
288       error.SetErrorToErrno();
289   }
290   m_descriptor = kInvalidDescriptor;
291   m_stream = kInvalidStream;
292   m_options = 0;
293   m_own_stream = false;
294   m_should_close_fd = false;
295   m_is_interactive = eLazyBoolCalculate;
296   m_is_real_terminal = eLazyBoolCalculate;
297   return error;
298 }
299
300 void File::Clear() {
301   m_stream = nullptr;
302   m_descriptor = -1;
303   m_options = 0;
304   m_own_stream = false;
305   m_is_interactive = m_supports_colors = m_is_real_terminal =
306       eLazyBoolCalculate;
307 }
308
309 Error File::GetFileSpec(FileSpec &file_spec) const {
310   Error error;
311 #ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
312   if (IsValid()) {
313     char path[PATH_MAX];
314     if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
315       error.SetErrorToErrno();
316     else
317       file_spec.SetFile(path, false);
318   } else {
319     error.SetErrorString("invalid file handle");
320   }
321 #elif defined(__linux__)
322   char proc[64];
323   char path[PATH_MAX];
324   if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
325     error.SetErrorString("cannot resolve file descriptor");
326   else {
327     ssize_t len;
328     if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
329       error.SetErrorToErrno();
330     else {
331       path[len] = '\0';
332       file_spec.SetFile(path, false);
333     }
334   }
335 #else
336   error.SetErrorString("File::GetFileSpec is not supported on this platform");
337 #endif
338
339   if (error.Fail())
340     file_spec.Clear();
341   return error;
342 }
343
344 off_t File::SeekFromStart(off_t offset, Error *error_ptr) {
345   off_t result = 0;
346   if (DescriptorIsValid()) {
347     result = ::lseek(m_descriptor, offset, SEEK_SET);
348
349     if (error_ptr) {
350       if (result == -1)
351         error_ptr->SetErrorToErrno();
352       else
353         error_ptr->Clear();
354     }
355   } else if (StreamIsValid()) {
356     result = ::fseek(m_stream, offset, SEEK_SET);
357
358     if (error_ptr) {
359       if (result == -1)
360         error_ptr->SetErrorToErrno();
361       else
362         error_ptr->Clear();
363     }
364   } else if (error_ptr) {
365     error_ptr->SetErrorString("invalid file handle");
366   }
367   return result;
368 }
369
370 off_t File::SeekFromCurrent(off_t offset, Error *error_ptr) {
371   off_t result = -1;
372   if (DescriptorIsValid()) {
373     result = ::lseek(m_descriptor, offset, SEEK_CUR);
374
375     if (error_ptr) {
376       if (result == -1)
377         error_ptr->SetErrorToErrno();
378       else
379         error_ptr->Clear();
380     }
381   } else if (StreamIsValid()) {
382     result = ::fseek(m_stream, offset, SEEK_CUR);
383
384     if (error_ptr) {
385       if (result == -1)
386         error_ptr->SetErrorToErrno();
387       else
388         error_ptr->Clear();
389     }
390   } else if (error_ptr) {
391     error_ptr->SetErrorString("invalid file handle");
392   }
393   return result;
394 }
395
396 off_t File::SeekFromEnd(off_t offset, Error *error_ptr) {
397   off_t result = -1;
398   if (DescriptorIsValid()) {
399     result = ::lseek(m_descriptor, offset, SEEK_END);
400
401     if (error_ptr) {
402       if (result == -1)
403         error_ptr->SetErrorToErrno();
404       else
405         error_ptr->Clear();
406     }
407   } else if (StreamIsValid()) {
408     result = ::fseek(m_stream, offset, SEEK_END);
409
410     if (error_ptr) {
411       if (result == -1)
412         error_ptr->SetErrorToErrno();
413       else
414         error_ptr->Clear();
415     }
416   } else if (error_ptr) {
417     error_ptr->SetErrorString("invalid file handle");
418   }
419   return result;
420 }
421
422 Error File::Flush() {
423   Error error;
424   if (StreamIsValid()) {
425     int err = 0;
426     do {
427       err = ::fflush(m_stream);
428     } while (err == EOF && errno == EINTR);
429
430     if (err == EOF)
431       error.SetErrorToErrno();
432   } else if (!DescriptorIsValid()) {
433     error.SetErrorString("invalid file handle");
434   }
435   return error;
436 }
437
438 Error File::Sync() {
439   Error error;
440   if (DescriptorIsValid()) {
441 #ifdef _WIN32
442     int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
443     if (err == 0)
444       error.SetErrorToGenericError();
445 #else
446     int err = 0;
447     do {
448       err = ::fsync(m_descriptor);
449     } while (err == -1 && errno == EINTR);
450
451     if (err == -1)
452       error.SetErrorToErrno();
453 #endif
454   } else {
455     error.SetErrorString("invalid file handle");
456   }
457   return error;
458 }
459
460 #if defined(__APPLE__)
461 // Darwin kernels only can read/write <= INT_MAX bytes
462 #define MAX_READ_SIZE INT_MAX
463 #define MAX_WRITE_SIZE INT_MAX
464 #endif
465
466 Error File::Read(void *buf, size_t &num_bytes) {
467   Error error;
468
469 #if defined(MAX_READ_SIZE)
470   if (num_bytes > MAX_READ_SIZE) {
471     uint8_t *p = (uint8_t *)buf;
472     size_t bytes_left = num_bytes;
473     // Init the num_bytes read to zero
474     num_bytes = 0;
475
476     while (bytes_left > 0) {
477       size_t curr_num_bytes;
478       if (bytes_left > MAX_READ_SIZE)
479         curr_num_bytes = MAX_READ_SIZE;
480       else
481         curr_num_bytes = bytes_left;
482
483       error = Read(p + num_bytes, curr_num_bytes);
484
485       // Update how many bytes were read
486       num_bytes += curr_num_bytes;
487       if (bytes_left < curr_num_bytes)
488         bytes_left = 0;
489       else
490         bytes_left -= curr_num_bytes;
491
492       if (error.Fail())
493         break;
494     }
495     return error;
496   }
497 #endif
498
499   ssize_t bytes_read = -1;
500   if (DescriptorIsValid()) {
501     do {
502       bytes_read = ::read(m_descriptor, buf, num_bytes);
503     } while (bytes_read < 0 && errno == EINTR);
504
505     if (bytes_read == -1) {
506       error.SetErrorToErrno();
507       num_bytes = 0;
508     } else
509       num_bytes = bytes_read;
510   } else if (StreamIsValid()) {
511     bytes_read = ::fread(buf, 1, num_bytes, m_stream);
512
513     if (bytes_read == 0) {
514       if (::feof(m_stream))
515         error.SetErrorString("feof");
516       else if (::ferror(m_stream))
517         error.SetErrorString("ferror");
518       num_bytes = 0;
519     } else
520       num_bytes = bytes_read;
521   } else {
522     num_bytes = 0;
523     error.SetErrorString("invalid file handle");
524   }
525   return error;
526 }
527
528 Error File::Write(const void *buf, size_t &num_bytes) {
529   Error error;
530
531 #if defined(MAX_WRITE_SIZE)
532   if (num_bytes > MAX_WRITE_SIZE) {
533     const uint8_t *p = (const uint8_t *)buf;
534     size_t bytes_left = num_bytes;
535     // Init the num_bytes written to zero
536     num_bytes = 0;
537
538     while (bytes_left > 0) {
539       size_t curr_num_bytes;
540       if (bytes_left > MAX_WRITE_SIZE)
541         curr_num_bytes = MAX_WRITE_SIZE;
542       else
543         curr_num_bytes = bytes_left;
544
545       error = Write(p + num_bytes, curr_num_bytes);
546
547       // Update how many bytes were read
548       num_bytes += curr_num_bytes;
549       if (bytes_left < curr_num_bytes)
550         bytes_left = 0;
551       else
552         bytes_left -= curr_num_bytes;
553
554       if (error.Fail())
555         break;
556     }
557     return error;
558   }
559 #endif
560
561   ssize_t bytes_written = -1;
562   if (DescriptorIsValid()) {
563     do {
564       bytes_written = ::write(m_descriptor, buf, num_bytes);
565     } while (bytes_written < 0 && errno == EINTR);
566
567     if (bytes_written == -1) {
568       error.SetErrorToErrno();
569       num_bytes = 0;
570     } else
571       num_bytes = bytes_written;
572   } else if (StreamIsValid()) {
573     bytes_written = ::fwrite(buf, 1, num_bytes, m_stream);
574
575     if (bytes_written == 0) {
576       if (::feof(m_stream))
577         error.SetErrorString("feof");
578       else if (::ferror(m_stream))
579         error.SetErrorString("ferror");
580       num_bytes = 0;
581     } else
582       num_bytes = bytes_written;
583
584   } else {
585     num_bytes = 0;
586     error.SetErrorString("invalid file handle");
587   }
588
589   return error;
590 }
591
592 Error File::Read(void *buf, size_t &num_bytes, off_t &offset) {
593   Error error;
594
595 #if defined(MAX_READ_SIZE)
596   if (num_bytes > MAX_READ_SIZE) {
597     uint8_t *p = (uint8_t *)buf;
598     size_t bytes_left = num_bytes;
599     // Init the num_bytes read to zero
600     num_bytes = 0;
601
602     while (bytes_left > 0) {
603       size_t curr_num_bytes;
604       if (bytes_left > MAX_READ_SIZE)
605         curr_num_bytes = MAX_READ_SIZE;
606       else
607         curr_num_bytes = bytes_left;
608
609       error = Read(p + num_bytes, curr_num_bytes, offset);
610
611       // Update how many bytes were read
612       num_bytes += curr_num_bytes;
613       if (bytes_left < curr_num_bytes)
614         bytes_left = 0;
615       else
616         bytes_left -= curr_num_bytes;
617
618       if (error.Fail())
619         break;
620     }
621     return error;
622   }
623 #endif
624
625 #ifndef _WIN32
626   int fd = GetDescriptor();
627   if (fd != kInvalidDescriptor) {
628     ssize_t bytes_read = -1;
629     do {
630       bytes_read = ::pread(fd, buf, num_bytes, offset);
631     } while (bytes_read < 0 && errno == EINTR);
632
633     if (bytes_read < 0) {
634       num_bytes = 0;
635       error.SetErrorToErrno();
636     } else {
637       offset += bytes_read;
638       num_bytes = bytes_read;
639     }
640   } else {
641     num_bytes = 0;
642     error.SetErrorString("invalid file handle");
643   }
644 #else
645   long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
646   SeekFromStart(offset);
647   error = Read(buf, num_bytes);
648   if (!error.Fail())
649     SeekFromStart(cur);
650 #endif
651   return error;
652 }
653
654 Error File::Read(size_t &num_bytes, off_t &offset, bool null_terminate,
655                  DataBufferSP &data_buffer_sp) {
656   Error error;
657
658   if (num_bytes > 0) {
659     int fd = GetDescriptor();
660     if (fd != kInvalidDescriptor) {
661       struct stat file_stats;
662       if (::fstat(fd, &file_stats) == 0) {
663         if (file_stats.st_size > offset) {
664           const size_t bytes_left = file_stats.st_size - offset;
665           if (num_bytes > bytes_left)
666             num_bytes = bytes_left;
667
668           size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
669           std::unique_ptr<DataBufferHeap> data_heap_ap;
670           data_heap_ap.reset(new DataBufferHeap());
671           data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
672
673           if (data_heap_ap.get()) {
674             error = Read(data_heap_ap->GetBytes(), num_bytes, offset);
675             if (error.Success()) {
676               // Make sure we read exactly what we asked for and if we got
677               // less, adjust the array
678               if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize())
679                 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
680               data_buffer_sp.reset(data_heap_ap.release());
681               return error;
682             }
683           }
684         } else
685           error.SetErrorString("file is empty");
686       } else
687         error.SetErrorToErrno();
688     } else
689       error.SetErrorString("invalid file handle");
690   } else
691     error.SetErrorString("invalid file handle");
692
693   num_bytes = 0;
694   data_buffer_sp.reset();
695   return error;
696 }
697
698 Error File::Write(const void *buf, size_t &num_bytes, off_t &offset) {
699   Error error;
700
701 #if defined(MAX_WRITE_SIZE)
702   if (num_bytes > MAX_WRITE_SIZE) {
703     const uint8_t *p = (const uint8_t *)buf;
704     size_t bytes_left = num_bytes;
705     // Init the num_bytes written to zero
706     num_bytes = 0;
707
708     while (bytes_left > 0) {
709       size_t curr_num_bytes;
710       if (bytes_left > MAX_WRITE_SIZE)
711         curr_num_bytes = MAX_WRITE_SIZE;
712       else
713         curr_num_bytes = bytes_left;
714
715       error = Write(p + num_bytes, curr_num_bytes, offset);
716
717       // Update how many bytes were read
718       num_bytes += curr_num_bytes;
719       if (bytes_left < curr_num_bytes)
720         bytes_left = 0;
721       else
722         bytes_left -= curr_num_bytes;
723
724       if (error.Fail())
725         break;
726     }
727     return error;
728   }
729 #endif
730
731   int fd = GetDescriptor();
732   if (fd != kInvalidDescriptor) {
733 #ifndef _WIN32
734     ssize_t bytes_written = -1;
735     do {
736       bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset);
737     } while (bytes_written < 0 && errno == EINTR);
738
739     if (bytes_written < 0) {
740       num_bytes = 0;
741       error.SetErrorToErrno();
742     } else {
743       offset += bytes_written;
744       num_bytes = bytes_written;
745     }
746 #else
747     long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
748     error = Write(buf, num_bytes);
749     long after = ::lseek(m_descriptor, 0, SEEK_CUR);
750
751     if (!error.Fail())
752       SeekFromStart(cur);
753
754     offset = after;
755 #endif
756   } else {
757     num_bytes = 0;
758     error.SetErrorString("invalid file handle");
759   }
760   return error;
761 }
762
763 //------------------------------------------------------------------
764 // Print some formatted output to the stream.
765 //------------------------------------------------------------------
766 size_t File::Printf(const char *format, ...) {
767   va_list args;
768   va_start(args, format);
769   size_t result = PrintfVarArg(format, args);
770   va_end(args);
771   return result;
772 }
773
774 //------------------------------------------------------------------
775 // Print some formatted output to the stream.
776 //------------------------------------------------------------------
777 size_t File::PrintfVarArg(const char *format, va_list args) {
778   size_t result = 0;
779   if (DescriptorIsValid()) {
780     char *s = NULL;
781     result = vasprintf(&s, format, args);
782     if (s != NULL) {
783       if (result > 0) {
784         size_t s_len = result;
785         Write(s, s_len);
786         result = s_len;
787       }
788       free(s);
789     }
790   } else if (StreamIsValid()) {
791     result = ::vfprintf(m_stream, format, args);
792   }
793   return result;
794 }
795
796 mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) {
797   mode_t mode = 0;
798   if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
799     mode |= O_RDWR;
800   else if (open_options & eOpenOptionWrite)
801     mode |= O_WRONLY;
802
803   if (open_options & eOpenOptionAppend)
804     mode |= O_APPEND;
805
806   if (open_options & eOpenOptionTruncate)
807     mode |= O_TRUNC;
808
809   if (open_options & eOpenOptionNonBlocking)
810     mode |= O_NONBLOCK;
811
812   if (open_options & eOpenOptionCanCreateNewOnly)
813     mode |= O_CREAT | O_EXCL;
814   else if (open_options & eOpenOptionCanCreate)
815     mode |= O_CREAT;
816
817   return mode;
818 }
819
820 void File::CalculateInteractiveAndTerminal() {
821   const int fd = GetDescriptor();
822   if (fd >= 0) {
823     m_is_interactive = eLazyBoolNo;
824     m_is_real_terminal = eLazyBoolNo;
825 #if defined(_WIN32)
826     if (_isatty(fd)) {
827       m_is_interactive = eLazyBoolYes;
828       m_is_real_terminal = eLazyBoolYes;
829     }
830 #else
831     if (isatty(fd)) {
832       m_is_interactive = eLazyBoolYes;
833       struct winsize window_size;
834       if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) {
835         if (window_size.ws_col > 0) {
836           m_is_real_terminal = eLazyBoolYes;
837           if (llvm::sys::Process::FileDescriptorHasColors(fd))
838             m_supports_colors = eLazyBoolYes;
839         }
840       }
841     }
842 #endif
843   }
844 }
845
846 bool File::GetIsInteractive() {
847   if (m_is_interactive == eLazyBoolCalculate)
848     CalculateInteractiveAndTerminal();
849   return m_is_interactive == eLazyBoolYes;
850 }
851
852 bool File::GetIsRealTerminal() {
853   if (m_is_real_terminal == eLazyBoolCalculate)
854     CalculateInteractiveAndTerminal();
855   return m_is_real_terminal == eLazyBoolYes;
856 }
857
858 bool File::GetIsTerminalWithColors() {
859   if (m_supports_colors == eLazyBoolCalculate)
860     CalculateInteractiveAndTerminal();
861   return m_supports_colors == eLazyBoolYes;
862 }