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