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