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