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