File.cpp revision 296417
1254219Scy//===-- File.cpp ------------------------------------------------*- C++ -*-===//
2254219Scy//
3254219Scy//                     The LLVM Compiler Infrastructure
4254219Scy//
5254219Scy// This file is distributed under the University of Illinois Open Source
6254219Scy// License. See LICENSE.TXT for details.
7254219Scy//
8254219Scy//===----------------------------------------------------------------------===//
9254219Scy
10254219Scy#include "lldb/Host/File.h"
11254219Scy
12254219Scy#include <errno.h>
13254219Scy#include <fcntl.h>
14254219Scy#include <limits.h>
15254219Scy#include <stdarg.h>
16254219Scy#include <stdio.h>
17254219Scy#include <sys/stat.h>
18254219Scy
19254219Scy#ifdef _WIN32
20254219Scy#include "lldb/Host/windows/windows.h"
21254219Scy#else
22254219Scy#include <sys/ioctl.h>
23254219Scy#endif
24254219Scy
25254219Scy#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()
26254219Scy
27254219Scy#include "lldb/Core/DataBufferHeap.h"
28254219Scy#include "lldb/Core/Error.h"
29254219Scy#include "lldb/Core/Log.h"
30254219Scy#include "lldb/Host/Config.h"
31254219Scy#include "lldb/Host/FileSpec.h"
32254219Scy
33254219Scyusing namespace lldb;
34254219Scyusing namespace lldb_private;
35254219Scy
36254219Scystatic const char *
37254219ScyGetStreamOpenModeFromOptions (uint32_t options)
38254219Scy{
39254219Scy    if (options & File::eOpenOptionAppend)
40254219Scy    {
41254219Scy        if (options & File::eOpenOptionRead)
42254219Scy        {
43254219Scy            if (options & File::eOpenOptionCanCreateNewOnly)
44254219Scy                return "a+x";
45254219Scy            else
46254219Scy                return "a+";
47254219Scy        }
48254219Scy        else if (options & File::eOpenOptionWrite)
49254219Scy        {
50254219Scy            if (options & File::eOpenOptionCanCreateNewOnly)
51254219Scy                return "ax";
52254219Scy            else
53254219Scy                return "a";
54254219Scy        }
55254219Scy    }
56254219Scy    else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite)
57254219Scy    {
58254219Scy        if (options & File::eOpenOptionCanCreate)
59254219Scy        {
60254219Scy            if (options & File::eOpenOptionCanCreateNewOnly)
61254219Scy                return "w+x";
62254219Scy            else
63254219Scy                return "w+";
64254219Scy        }
65254219Scy        else
66254219Scy            return "r+";
67254219Scy    }
68254219Scy    else if (options & File::eOpenOptionRead)
69254219Scy    {
70254219Scy        return "r";
71254219Scy    }
72254219Scy    else if (options & File::eOpenOptionWrite)
73254219Scy    {
74254219Scy        return "w";
75254219Scy    }
76254219Scy    return NULL;
77254219Scy}
78254219Scy
79254219Scyint File::kInvalidDescriptor = -1;
80254219ScyFILE * File::kInvalidStream = NULL;
81254219Scy
82254219ScyFile::File(const char *path, uint32_t options, uint32_t permissions) :
83254219Scy    IOObject(eFDTypeFile, false),
84254219Scy    m_descriptor (kInvalidDescriptor),
85254219Scy    m_stream (kInvalidStream),
86254219Scy    m_options (),
87254219Scy    m_own_stream (false),
88254219Scy    m_is_interactive (eLazyBoolCalculate),
89254219Scy    m_is_real_terminal (eLazyBoolCalculate)
90254219Scy{
91254219Scy    Open (path, options, permissions);
92254219Scy}
93254219Scy
94254219ScyFile::File (const FileSpec& filespec,
95254219Scy            uint32_t options,
96254219Scy            uint32_t permissions) :
97254219Scy    IOObject(eFDTypeFile, false),
98254219Scy    m_descriptor (kInvalidDescriptor),
99254219Scy    m_stream (kInvalidStream),
100254219Scy    m_options (0),
101254219Scy    m_own_stream (false),
102254219Scy    m_is_interactive (eLazyBoolCalculate),
103254219Scy    m_is_real_terminal (eLazyBoolCalculate)
104254219Scy
105254219Scy{
106254219Scy    if (filespec)
107254219Scy    {
108254219Scy        Open (filespec.GetPath().c_str(), options, permissions);
109254219Scy    }
110254219Scy}
111254219Scy
112254219ScyFile::File (const File &rhs) :
113254219Scy    IOObject(eFDTypeFile, false),
114254219Scy    m_descriptor (kInvalidDescriptor),
115254219Scy    m_stream (kInvalidStream),
116254219Scy    m_options (0),
117254219Scy    m_own_stream (false),
118254219Scy    m_is_interactive (eLazyBoolCalculate),
119254219Scy    m_is_real_terminal (eLazyBoolCalculate)
120254219Scy{
121254219Scy    Duplicate (rhs);
122254219Scy}
123254219Scy
124254219Scy
125254219ScyFile &
126254219ScyFile::operator = (const File &rhs)
127254219Scy{
128254219Scy    if (this != &rhs)
129254219Scy        Duplicate (rhs);
130254219Scy    return *this;
131254219Scy}
132254219Scy
133254219ScyFile::~File()
134254219Scy{
135254219Scy    Close ();
136254219Scy}
137254219Scy
138254219Scy
139254219Scyint
140254219ScyFile::GetDescriptor() const
141254219Scy{
142254219Scy    if (DescriptorIsValid())
143254219Scy        return m_descriptor;
144254219Scy
145254219Scy    // Don't open the file descriptor if we don't need to, just get it from the
146254219Scy    // stream if we have one.
147254219Scy    if (StreamIsValid())
148254219Scy    {
149254219Scy#if defined(LLVM_ON_WIN32)
150254219Scy        return _fileno(m_stream);
151254219Scy#else
152254219Scy        return fileno(m_stream);
153254219Scy#endif
154254219Scy    }
155254219Scy
156254219Scy    // Invalid descriptor and invalid stream, return invalid descriptor.
157254219Scy    return kInvalidDescriptor;
158254219Scy}
159254219Scy
160254219ScyIOObject::WaitableHandle
161254219ScyFile::GetWaitableHandle()
162254219Scy{
163254219Scy    return m_descriptor;
164254219Scy}
165254219Scy
166254219Scy
167254219Scyvoid
168254219ScyFile::SetDescriptor (int fd, bool transfer_ownership)
169254219Scy{
170254219Scy    if (IsValid())
171254219Scy        Close();
172254219Scy    m_descriptor = fd;
173254219Scy    m_should_close_fd = transfer_ownership;
174254219Scy}
175254219Scy
176254219Scy
177254219ScyFILE *
178254219ScyFile::GetStream ()
179254219Scy{
180254219Scy    if (!StreamIsValid())
181254219Scy    {
182254219Scy        if (DescriptorIsValid())
183254219Scy        {
184254219Scy            const char *mode = GetStreamOpenModeFromOptions (m_options);
185254219Scy            if (mode)
186254219Scy            {
187254219Scy                if (!m_should_close_fd)
188254219Scy                {
189254219Scy                    // We must duplicate the file descriptor if we don't own it because
190254219Scy                    // when you call fdopen, the stream will own the fd
191254219Scy#ifdef _WIN32
192254219Scy                    m_descriptor = ::_dup(GetDescriptor());
193254219Scy#else
194254219Scy                    m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD);
195254219Scy#endif
196254219Scy                    m_should_close_fd = true;
197254219Scy                }
198254219Scy
199254219Scy                do
200254219Scy                {
201254219Scy                    m_stream = ::fdopen (m_descriptor, mode);
202254219Scy                } while (m_stream == NULL && errno == EINTR);
203254219Scy
204254219Scy                // If we got a stream, then we own the stream and should no
205254219Scy                // longer own the descriptor because fclose() will close it for us
206254219Scy
207254219Scy                if (m_stream)
208254219Scy                {
209254219Scy                    m_own_stream = true;
210254219Scy                    m_should_close_fd = false;
211254219Scy                }
212254219Scy            }
213254219Scy        }
214254219Scy    }
215254219Scy    return m_stream;
216254219Scy}
217254219Scy
218254219Scy
219254219Scyvoid
220254219ScyFile::SetStream (FILE *fh, bool transfer_ownership)
221254219Scy{
222254219Scy    if (IsValid())
223254219Scy        Close();
224254219Scy    m_stream = fh;
225254219Scy    m_own_stream = transfer_ownership;
226254219Scy}
227254219Scy
228254219ScyError
229254219ScyFile::Duplicate (const File &rhs)
230254219Scy{
231254219Scy    Error error;
232254219Scy    if (IsValid ())
233254219Scy        Close();
234254219Scy
235254219Scy    if (rhs.DescriptorIsValid())
236254219Scy    {
237254219Scy#ifdef _WIN32
238254219Scy        m_descriptor = ::_dup(rhs.GetDescriptor());
239254219Scy#else
240254219Scy        m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD);
241254219Scy#endif
242254219Scy        if (!DescriptorIsValid())
243254219Scy            error.SetErrorToErrno();
244254219Scy        else
245254219Scy        {
246254219Scy            m_options = rhs.m_options;
247254219Scy            m_should_close_fd = true;
248254219Scy        }
249254219Scy    }
250254219Scy    else
251254219Scy    {
252254219Scy        error.SetErrorString ("invalid file to duplicate");
253254219Scy    }
254254219Scy    return error;
255254219Scy}
256254219Scy
257254219ScyError
258254219ScyFile::Open (const char *path, uint32_t options, uint32_t permissions)
259254219Scy{
260254219Scy    Error error;
261254219Scy    if (IsValid())
262254219Scy        Close ();
263254219Scy
264254219Scy    int oflag = 0;
265254219Scy    const bool read = options & eOpenOptionRead;
266254219Scy    const bool write = options & eOpenOptionWrite;
267254219Scy    if (write)
268254219Scy    {
269254219Scy        if (read)
270254219Scy            oflag |= O_RDWR;
271254219Scy        else
272254219Scy            oflag |= O_WRONLY;
273254219Scy
274254219Scy        if (options & eOpenOptionAppend)
275254219Scy            oflag |= O_APPEND;
276254219Scy
277254219Scy        if (options & eOpenOptionTruncate)
278254219Scy            oflag |= O_TRUNC;
279254219Scy
280254219Scy        if (options & eOpenOptionCanCreate)
281254219Scy            oflag |= O_CREAT;
282254219Scy
283254219Scy        if (options & eOpenOptionCanCreateNewOnly)
284            oflag |= O_CREAT | O_EXCL;
285    }
286    else if (read)
287    {
288        oflag |= O_RDONLY;
289
290#ifndef _WIN32
291        if (options & eOpenoptionDontFollowSymlinks)
292            oflag |= O_NOFOLLOW;
293#endif
294    }
295
296#ifndef _WIN32
297    if (options & eOpenOptionNonBlocking)
298        oflag |= O_NONBLOCK;
299    if (options & eOpenOptionCloseOnExec)
300        oflag |= O_CLOEXEC;
301#else
302    oflag |= O_BINARY;
303#endif
304
305    mode_t mode = 0;
306    if (oflag & O_CREAT)
307    {
308        if (permissions & lldb::eFilePermissionsUserRead)     mode |= S_IRUSR;
309        if (permissions & lldb::eFilePermissionsUserWrite)    mode |= S_IWUSR;
310        if (permissions & lldb::eFilePermissionsUserExecute)  mode |= S_IXUSR;
311        if (permissions & lldb::eFilePermissionsGroupRead)    mode |= S_IRGRP;
312        if (permissions & lldb::eFilePermissionsGroupWrite)   mode |= S_IWGRP;
313        if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP;
314        if (permissions & lldb::eFilePermissionsWorldRead)    mode |= S_IROTH;
315        if (permissions & lldb::eFilePermissionsWorldWrite)   mode |= S_IWOTH;
316        if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH;
317    }
318
319    do
320    {
321        m_descriptor = ::open(path, oflag, mode);
322    } while (m_descriptor < 0 && errno == EINTR);
323
324    if (!DescriptorIsValid())
325        error.SetErrorToErrno();
326    else
327    {
328        m_should_close_fd = true;
329        m_options = options;
330    }
331
332    return error;
333}
334
335uint32_t
336File::GetPermissions(const FileSpec &file_spec, Error &error)
337{
338    if (file_spec)
339    {
340        struct stat file_stats;
341        if (::stat(file_spec.GetCString(), &file_stats) == -1)
342            error.SetErrorToErrno();
343        else
344        {
345            error.Clear();
346            return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
347        }
348    }
349    else
350        error.SetErrorString ("empty file spec");
351    return 0;
352}
353
354uint32_t
355File::GetPermissions(Error &error) const
356{
357    int fd = GetDescriptor();
358    if (fd != kInvalidDescriptor)
359    {
360        struct stat file_stats;
361        if (::fstat (fd, &file_stats) == -1)
362            error.SetErrorToErrno();
363        else
364        {
365            error.Clear();
366            return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
367        }
368    }
369    else
370    {
371        error.SetErrorString ("invalid file descriptor");
372    }
373    return 0;
374}
375
376
377Error
378File::Close ()
379{
380    Error error;
381    if (StreamIsValid() && m_own_stream)
382    {
383        if (::fclose (m_stream) == EOF)
384            error.SetErrorToErrno();
385    }
386
387    if (DescriptorIsValid() && m_should_close_fd)
388    {
389        if (::close (m_descriptor) != 0)
390            error.SetErrorToErrno();
391    }
392    m_descriptor = kInvalidDescriptor;
393    m_stream = kInvalidStream;
394    m_options = 0;
395    m_own_stream = false;
396    m_should_close_fd = false;
397    m_is_interactive = eLazyBoolCalculate;
398    m_is_real_terminal = eLazyBoolCalculate;
399    return error;
400}
401
402
403Error
404File::GetFileSpec (FileSpec &file_spec) const
405{
406    Error error;
407#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
408    if (IsValid ())
409    {
410        char path[PATH_MAX];
411        if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
412            error.SetErrorToErrno();
413        else
414            file_spec.SetFile (path, false);
415    }
416    else
417    {
418        error.SetErrorString("invalid file handle");
419    }
420#elif defined(__linux__)
421    char proc[64];
422    char path[PATH_MAX];
423    if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
424        error.SetErrorString ("cannot resolve file descriptor");
425    else
426    {
427        ssize_t len;
428        if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
429            error.SetErrorToErrno();
430        else
431        {
432            path[len] = '\0';
433            file_spec.SetFile (path, false);
434        }
435    }
436#else
437    error.SetErrorString ("File::GetFileSpec is not supported on this platform");
438#endif
439
440    if (error.Fail())
441        file_spec.Clear();
442    return error;
443}
444
445off_t
446File::SeekFromStart (off_t offset, Error *error_ptr)
447{
448    off_t result = 0;
449    if (DescriptorIsValid())
450    {
451        result = ::lseek (m_descriptor, offset, SEEK_SET);
452
453        if (error_ptr)
454        {
455            if (result == -1)
456                error_ptr->SetErrorToErrno();
457            else
458                error_ptr->Clear();
459        }
460    }
461    else if (StreamIsValid ())
462    {
463        result = ::fseek(m_stream, offset, SEEK_SET);
464
465        if (error_ptr)
466        {
467            if (result == -1)
468                error_ptr->SetErrorToErrno();
469            else
470                error_ptr->Clear();
471        }
472    }
473    else if (error_ptr)
474    {
475        error_ptr->SetErrorString("invalid file handle");
476    }
477    return result;
478}
479
480off_t
481File::SeekFromCurrent (off_t offset,  Error *error_ptr)
482{
483    off_t result = -1;
484    if (DescriptorIsValid())
485    {
486        result = ::lseek (m_descriptor, offset, SEEK_CUR);
487
488        if (error_ptr)
489        {
490            if (result == -1)
491                error_ptr->SetErrorToErrno();
492            else
493                error_ptr->Clear();
494        }
495    }
496    else if (StreamIsValid ())
497    {
498        result = ::fseek(m_stream, offset, SEEK_CUR);
499
500        if (error_ptr)
501        {
502            if (result == -1)
503                error_ptr->SetErrorToErrno();
504            else
505                error_ptr->Clear();
506        }
507    }
508    else if (error_ptr)
509    {
510        error_ptr->SetErrorString("invalid file handle");
511    }
512    return result;
513}
514
515off_t
516File::SeekFromEnd (off_t offset, Error *error_ptr)
517{
518    off_t result = -1;
519    if (DescriptorIsValid())
520    {
521        result = ::lseek (m_descriptor, offset, SEEK_END);
522
523        if (error_ptr)
524        {
525            if (result == -1)
526                error_ptr->SetErrorToErrno();
527            else
528                error_ptr->Clear();
529        }
530    }
531    else if (StreamIsValid ())
532    {
533        result = ::fseek(m_stream, offset, SEEK_END);
534
535        if (error_ptr)
536        {
537            if (result == -1)
538                error_ptr->SetErrorToErrno();
539            else
540                error_ptr->Clear();
541        }
542    }
543    else if (error_ptr)
544    {
545        error_ptr->SetErrorString("invalid file handle");
546    }
547    return result;
548}
549
550Error
551File::Flush ()
552{
553    Error error;
554    if (StreamIsValid())
555    {
556        int err = 0;
557        do
558        {
559            err = ::fflush (m_stream);
560        } while (err == EOF && errno == EINTR);
561
562        if (err == EOF)
563            error.SetErrorToErrno();
564    }
565    else if (!DescriptorIsValid())
566    {
567        error.SetErrorString("invalid file handle");
568    }
569    return error;
570}
571
572
573Error
574File::Sync ()
575{
576    Error error;
577    if (DescriptorIsValid())
578    {
579#ifdef _WIN32
580        int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
581        if (err == 0)
582            error.SetErrorToGenericError();
583#else
584        int err = 0;
585        do
586        {
587            err = ::fsync (m_descriptor);
588        } while (err == -1 && errno == EINTR);
589
590        if (err == -1)
591            error.SetErrorToErrno();
592#endif
593    }
594    else
595    {
596        error.SetErrorString("invalid file handle");
597    }
598    return error;
599}
600
601#if defined (__APPLE__)
602// Darwin kernels only can read/write <= INT_MAX bytes
603#define MAX_READ_SIZE INT_MAX
604#define MAX_WRITE_SIZE INT_MAX
605#endif
606
607Error
608File::Read (void *buf, size_t &num_bytes)
609{
610    Error error;
611
612#if defined (MAX_READ_SIZE)
613    if (num_bytes > MAX_READ_SIZE)
614    {
615        uint8_t *p = (uint8_t *)buf;
616        size_t bytes_left = num_bytes;
617        // Init the num_bytes read to zero
618        num_bytes = 0;
619
620        while (bytes_left > 0)
621        {
622            size_t curr_num_bytes;
623            if (bytes_left > MAX_READ_SIZE)
624                curr_num_bytes = MAX_READ_SIZE;
625            else
626                curr_num_bytes = bytes_left;
627
628            error = Read (p + num_bytes, curr_num_bytes);
629
630            // Update how many bytes were read
631            num_bytes += curr_num_bytes;
632            if (bytes_left < curr_num_bytes)
633                bytes_left = 0;
634            else
635                bytes_left -= curr_num_bytes;
636
637            if (error.Fail())
638                break;
639        }
640        return error;
641    }
642#endif
643
644    ssize_t bytes_read = -1;
645    if (DescriptorIsValid())
646    {
647        do
648        {
649            bytes_read = ::read (m_descriptor, buf, num_bytes);
650        } while (bytes_read < 0 && errno == EINTR);
651
652        if (bytes_read == -1)
653        {
654            error.SetErrorToErrno();
655            num_bytes = 0;
656        }
657        else
658            num_bytes = bytes_read;
659    }
660    else if (StreamIsValid())
661    {
662        bytes_read = ::fread (buf, 1, num_bytes, m_stream);
663
664        if (bytes_read == 0)
665        {
666            if (::feof(m_stream))
667                error.SetErrorString ("feof");
668            else if (::ferror (m_stream))
669                error.SetErrorString ("ferror");
670            num_bytes = 0;
671        }
672        else
673            num_bytes = bytes_read;
674    }
675    else
676    {
677        num_bytes = 0;
678        error.SetErrorString("invalid file handle");
679    }
680    return error;
681}
682
683Error
684File::Write (const void *buf, size_t &num_bytes)
685{
686    Error error;
687
688#if defined (MAX_WRITE_SIZE)
689    if (num_bytes > MAX_WRITE_SIZE)
690    {
691        const uint8_t *p = (const uint8_t *)buf;
692        size_t bytes_left = num_bytes;
693        // Init the num_bytes written to zero
694        num_bytes = 0;
695
696        while (bytes_left > 0)
697        {
698            size_t curr_num_bytes;
699            if (bytes_left > MAX_WRITE_SIZE)
700                curr_num_bytes = MAX_WRITE_SIZE;
701            else
702                curr_num_bytes = bytes_left;
703
704            error = Write (p + num_bytes, curr_num_bytes);
705
706            // Update how many bytes were read
707            num_bytes += curr_num_bytes;
708            if (bytes_left < curr_num_bytes)
709                bytes_left = 0;
710            else
711                bytes_left -= curr_num_bytes;
712
713            if (error.Fail())
714                break;
715        }
716        return error;
717    }
718#endif
719
720    ssize_t bytes_written = -1;
721    if (DescriptorIsValid())
722    {
723        do
724        {
725            bytes_written = ::write (m_descriptor, buf, num_bytes);
726        } while (bytes_written < 0 && errno == EINTR);
727
728        if (bytes_written == -1)
729        {
730            error.SetErrorToErrno();
731            num_bytes = 0;
732        }
733        else
734            num_bytes = bytes_written;
735    }
736    else if (StreamIsValid())
737    {
738        bytes_written = ::fwrite (buf, 1, num_bytes, m_stream);
739
740        if (bytes_written == 0)
741        {
742            if (::feof(m_stream))
743                error.SetErrorString ("feof");
744            else if (::ferror (m_stream))
745                error.SetErrorString ("ferror");
746            num_bytes = 0;
747        }
748        else
749            num_bytes = bytes_written;
750
751    }
752    else
753    {
754        num_bytes = 0;
755        error.SetErrorString("invalid file handle");
756    }
757
758    return error;
759}
760
761
762Error
763File::Read (void *buf, size_t &num_bytes, off_t &offset)
764{
765    Error error;
766
767#if defined (MAX_READ_SIZE)
768    if (num_bytes > MAX_READ_SIZE)
769    {
770        uint8_t *p = (uint8_t *)buf;
771        size_t bytes_left = num_bytes;
772        // Init the num_bytes read to zero
773        num_bytes = 0;
774
775        while (bytes_left > 0)
776        {
777            size_t curr_num_bytes;
778            if (bytes_left > MAX_READ_SIZE)
779                curr_num_bytes = MAX_READ_SIZE;
780            else
781                curr_num_bytes = bytes_left;
782
783            error = Read (p + num_bytes, curr_num_bytes, offset);
784
785            // Update how many bytes were read
786            num_bytes += curr_num_bytes;
787            if (bytes_left < curr_num_bytes)
788                bytes_left = 0;
789            else
790                bytes_left -= curr_num_bytes;
791
792            if (error.Fail())
793                break;
794        }
795        return error;
796    }
797#endif
798
799#ifndef _WIN32
800    int fd = GetDescriptor();
801    if (fd != kInvalidDescriptor)
802    {
803        ssize_t bytes_read = -1;
804        do
805        {
806            bytes_read = ::pread (fd, buf, num_bytes, offset);
807        } while (bytes_read < 0 && errno == EINTR);
808
809        if (bytes_read < 0)
810        {
811            num_bytes = 0;
812            error.SetErrorToErrno();
813        }
814        else
815        {
816            offset += bytes_read;
817            num_bytes = bytes_read;
818        }
819    }
820    else
821    {
822        num_bytes = 0;
823        error.SetErrorString("invalid file handle");
824    }
825#else
826    long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
827    SeekFromStart(offset);
828    error = Read(buf, num_bytes);
829    if (!error.Fail())
830        SeekFromStart(cur);
831#endif
832    return error;
833}
834
835Error
836File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
837{
838    Error error;
839
840    if (num_bytes > 0)
841    {
842        int fd = GetDescriptor();
843        if (fd != kInvalidDescriptor)
844        {
845            struct stat file_stats;
846            if (::fstat (fd, &file_stats) == 0)
847            {
848                if (file_stats.st_size > offset)
849                {
850                    const size_t bytes_left = file_stats.st_size - offset;
851                    if (num_bytes > bytes_left)
852                        num_bytes = bytes_left;
853
854                    size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
855                    std::unique_ptr<DataBufferHeap> data_heap_ap;
856                    data_heap_ap.reset(new DataBufferHeap());
857                    data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
858
859                    if (data_heap_ap.get())
860                    {
861                        error = Read (data_heap_ap->GetBytes(), num_bytes, offset);
862                        if (error.Success())
863                        {
864                            // Make sure we read exactly what we asked for and if we got
865                            // less, adjust the array
866                            if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize())
867                                data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
868                            data_buffer_sp.reset(data_heap_ap.release());
869                            return error;
870                        }
871                    }
872                }
873                else
874                    error.SetErrorString("file is empty");
875            }
876            else
877                error.SetErrorToErrno();
878        }
879        else
880            error.SetErrorString("invalid file handle");
881    }
882    else
883        error.SetErrorString("invalid file handle");
884
885    num_bytes = 0;
886    data_buffer_sp.reset();
887    return error;
888}
889
890Error
891File::Write (const void *buf, size_t &num_bytes, off_t &offset)
892{
893    Error error;
894
895#if defined (MAX_WRITE_SIZE)
896    if (num_bytes > MAX_WRITE_SIZE)
897    {
898        const uint8_t *p = (const uint8_t *)buf;
899        size_t bytes_left = num_bytes;
900        // Init the num_bytes written to zero
901        num_bytes = 0;
902
903        while (bytes_left > 0)
904        {
905            size_t curr_num_bytes;
906            if (bytes_left > MAX_WRITE_SIZE)
907                curr_num_bytes = MAX_WRITE_SIZE;
908            else
909                curr_num_bytes = bytes_left;
910
911            error = Write (p + num_bytes, curr_num_bytes, offset);
912
913            // Update how many bytes were read
914            num_bytes += curr_num_bytes;
915            if (bytes_left < curr_num_bytes)
916                bytes_left = 0;
917            else
918                bytes_left -= curr_num_bytes;
919
920            if (error.Fail())
921                break;
922        }
923        return error;
924    }
925#endif
926
927    int fd = GetDescriptor();
928    if (fd != kInvalidDescriptor)
929    {
930#ifndef _WIN32
931        ssize_t bytes_written = -1;
932        do
933        {
934            bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset);
935        } while (bytes_written < 0 && errno == EINTR);
936
937        if (bytes_written < 0)
938        {
939            num_bytes = 0;
940            error.SetErrorToErrno();
941        }
942        else
943        {
944            offset += bytes_written;
945            num_bytes = bytes_written;
946        }
947#else
948        long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
949        error = Write(buf, num_bytes);
950        long after = ::lseek(m_descriptor, 0, SEEK_CUR);
951
952        if (!error.Fail())
953            SeekFromStart(cur);
954
955        offset = after;
956#endif
957    }
958    else
959    {
960        num_bytes = 0;
961        error.SetErrorString("invalid file handle");
962    }
963    return error;
964}
965
966//------------------------------------------------------------------
967// Print some formatted output to the stream.
968//------------------------------------------------------------------
969size_t
970File::Printf (const char *format, ...)
971{
972    va_list args;
973    va_start (args, format);
974    size_t result = PrintfVarArg (format, args);
975    va_end (args);
976    return result;
977}
978
979//------------------------------------------------------------------
980// Print some formatted output to the stream.
981//------------------------------------------------------------------
982size_t
983File::PrintfVarArg (const char *format, va_list args)
984{
985    size_t result = 0;
986    if (DescriptorIsValid())
987    {
988        char *s = NULL;
989        result = vasprintf(&s, format, args);
990        if (s != NULL)
991        {
992            if (result > 0)
993            {
994                size_t s_len = result;
995                Write (s, s_len);
996                result = s_len;
997            }
998            free (s);
999        }
1000    }
1001    else if (StreamIsValid())
1002    {
1003        result = ::vfprintf (m_stream, format, args);
1004    }
1005    return result;
1006}
1007
1008mode_t
1009File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
1010{
1011    mode_t mode = 0;
1012    if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
1013        mode |= O_RDWR;
1014    else if (open_options & eOpenOptionWrite)
1015        mode |= O_WRONLY;
1016
1017    if (open_options & eOpenOptionAppend)
1018        mode |= O_APPEND;
1019
1020    if (open_options & eOpenOptionTruncate)
1021        mode |= O_TRUNC;
1022
1023    if (open_options & eOpenOptionNonBlocking)
1024        mode |= O_NONBLOCK;
1025
1026    if (open_options & eOpenOptionCanCreateNewOnly)
1027        mode |= O_CREAT | O_EXCL;
1028    else if (open_options & eOpenOptionCanCreate)
1029        mode |= O_CREAT;
1030
1031    return mode;
1032}
1033
1034void
1035File::CalculateInteractiveAndTerminal ()
1036{
1037    const int fd = GetDescriptor();
1038    if (fd >= 0)
1039    {
1040        m_is_interactive = eLazyBoolNo;
1041        m_is_real_terminal = eLazyBoolNo;
1042#if (defined(_WIN32) || defined(__ANDROID_NDK__))
1043        if (_isatty(fd))
1044        {
1045            m_is_interactive = eLazyBoolYes;
1046            m_is_real_terminal = eLazyBoolYes;
1047        }
1048#else
1049        if (isatty(fd))
1050        {
1051            m_is_interactive = eLazyBoolYes;
1052            struct winsize window_size;
1053            if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
1054            {
1055                if (window_size.ws_col > 0)
1056                {
1057                    m_is_real_terminal = eLazyBoolYes;
1058                    if (llvm::sys::Process::FileDescriptorHasColors(fd))
1059                        m_supports_colors = eLazyBoolYes;
1060                }
1061            }
1062        }
1063#endif
1064    }
1065}
1066
1067bool
1068File::GetIsInteractive ()
1069{
1070    if (m_is_interactive == eLazyBoolCalculate)
1071        CalculateInteractiveAndTerminal ();
1072    return m_is_interactive == eLazyBoolYes;
1073}
1074
1075bool
1076File::GetIsRealTerminal ()
1077{
1078    if (m_is_real_terminal == eLazyBoolCalculate)
1079        CalculateInteractiveAndTerminal();
1080    return m_is_real_terminal == eLazyBoolYes;
1081}
1082
1083bool
1084File::GetIsTerminalWithColors ()
1085{
1086    if (m_supports_colors == eLazyBoolCalculate)
1087        CalculateInteractiveAndTerminal();
1088    return m_supports_colors == eLazyBoolYes;
1089}
1090
1091