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