blob: adf04cce2a1342bc0b63f469250f49baa0099a91 [file] [log] [blame]
Greg Claytonfbb76342013-11-20 21:07:01 +00001//===-- File.cpp ------------------------------------------------*- C++ -*-===//
Greg Clayton504f89a2011-02-08 17:49:02 +00002//
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
Greg Clayton504f89a2011-02-08 17:49:02 +000010#include "lldb/Host/File.h"
11
Greg Clayton96c09682012-01-04 22:56:43 +000012#include <errno.h>
Greg Clayton504f89a2011-02-08 17:49:02 +000013#include <fcntl.h>
Stephen Wilson8acdbb82011-04-08 13:36:44 +000014#include <limits.h>
Greg Claytonf4dd5432011-02-09 21:12:40 +000015#include <stdarg.h>
Greg Clayton340b0302014-02-05 17:57:57 +000016#include <stdio.h>
Greg Clayton504f89a2011-02-08 17:49:02 +000017
Virgile Bellob2f1fb22013-08-23 12:44:05 +000018#ifdef _WIN32
19#include "lldb/Host/windows/windows.h"
Deepak Panickal94667bc2014-02-17 17:43:39 +000020#else
21#include <sys/ioctl.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000022#endif
23
Zachary Turner190fadc2016-03-22 17:58:09 +000024#include "llvm/Support/ConvertUTF.h"
Sean Callanan66810412015-10-19 23:11:07 +000025#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()
26
Greg Clayton96c09682012-01-04 22:56:43 +000027#include "lldb/Core/DataBufferHeap.h"
Greg Clayton504f89a2011-02-08 17:49:02 +000028#include "lldb/Core/Error.h"
Zachary Turner98688922014-08-06 18:16:26 +000029#include "lldb/Core/Log.h"
Greg Clayton925137c2011-02-09 01:16:43 +000030#include "lldb/Host/Config.h"
Greg Clayton846b64b2011-02-08 19:54:44 +000031#include "lldb/Host/FileSpec.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000032#include "lldb/Host/FileSystem.h"
Greg Clayton504f89a2011-02-08 17:49:02 +000033
34using namespace lldb;
35using namespace lldb_private;
36
Greg Clayton51b1e2d2011-02-09 01:08:52 +000037static const char *
38GetStreamOpenModeFromOptions (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
80int File::kInvalidDescriptor = -1;
81FILE * File::kInvalidStream = NULL;
82
Greg Clayton504f89a2011-02-08 17:49:02 +000083File::File(const char *path, uint32_t options, uint32_t permissions) :
Zachary Turner98688922014-08-06 18:16:26 +000084 IOObject(eFDTypeFile, false),
Greg Clayton51b1e2d2011-02-09 01:08:52 +000085 m_descriptor (kInvalidDescriptor),
86 m_stream (kInvalidStream),
Greg Clayton44d93782014-01-27 23:43:24 +000087 m_options (),
88 m_own_stream (false),
Greg Clayton340b0302014-02-05 17:57:57 +000089 m_is_interactive (eLazyBoolCalculate),
90 m_is_real_terminal (eLazyBoolCalculate)
Greg Clayton504f89a2011-02-08 17:49:02 +000091{
92 Open (path, options, permissions);
93}
94
Daniel Maleae0f8f572013-08-26 23:57:52 +000095File::File (const FileSpec& filespec,
96 uint32_t options,
97 uint32_t permissions) :
Zachary Turner98688922014-08-06 18:16:26 +000098 IOObject(eFDTypeFile, false),
Daniel Maleae0f8f572013-08-26 23:57:52 +000099 m_descriptor (kInvalidDescriptor),
100 m_stream (kInvalidStream),
101 m_options (0),
Greg Clayton44d93782014-01-27 23:43:24 +0000102 m_own_stream (false),
Greg Clayton340b0302014-02-05 17:57:57 +0000103 m_is_interactive (eLazyBoolCalculate),
104 m_is_real_terminal (eLazyBoolCalculate)
105
Daniel Maleae0f8f572013-08-26 23:57:52 +0000106{
107 if (filespec)
108 {
109 Open (filespec.GetPath().c_str(), options, permissions);
110 }
111}
112
Greg Clayton504f89a2011-02-08 17:49:02 +0000113File::~File()
114{
115 Close ();
116}
117
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000118
119int
120File::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())
Zachary Turner9c402642015-10-15 19:35:48 +0000128 {
129#if defined(LLVM_ON_WIN32)
130 return _fileno(m_stream);
131#else
132 return fileno(m_stream);
133#endif
134 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000135
136 // Invalid descriptor and invalid stream, return invalid descriptor.
137 return kInvalidDescriptor;
138}
139
Zachary Turner98688922014-08-06 18:16:26 +0000140IOObject::WaitableHandle
141File::GetWaitableHandle()
142{
143 return m_descriptor;
144}
145
146
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000147void
148File::SetDescriptor (int fd, bool transfer_ownership)
149{
150 if (IsValid())
151 Close();
152 m_descriptor = fd;
Zachary Turner98688922014-08-06 18:16:26 +0000153 m_should_close_fd = transfer_ownership;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000154}
155
156
157FILE *
158File::GetStream ()
159{
160 if (!StreamIsValid())
161 {
162 if (DescriptorIsValid())
163 {
164 const char *mode = GetStreamOpenModeFromOptions (m_options);
165 if (mode)
Greg Clayton96c09682012-01-04 22:56:43 +0000166 {
Zachary Turner98688922014-08-06 18:16:26 +0000167 if (!m_should_close_fd)
Greg Clayton44d93782014-01-27 23:43:24 +0000168 {
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
Enrico Granata35e06392016-01-20 23:20:10 +0000174 m_descriptor = dup(GetDescriptor());
Greg Clayton44d93782014-01-27 23:43:24 +0000175#endif
Zachary Turner98688922014-08-06 18:16:26 +0000176 m_should_close_fd = true;
Greg Clayton44d93782014-01-27 23:43:24 +0000177 }
178
Greg Clayton96c09682012-01-04 22:56:43 +0000179 do
180 {
181 m_stream = ::fdopen (m_descriptor, mode);
182 } while (m_stream == NULL && errno == EINTR);
Greg Clayton44d93782014-01-27 23:43:24 +0000183
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;
Zachary Turner98688922014-08-06 18:16:26 +0000190 m_should_close_fd = false;
Greg Clayton44d93782014-01-27 23:43:24 +0000191 }
Greg Clayton96c09682012-01-04 22:56:43 +0000192 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000193 }
194 }
195 return m_stream;
196}
197
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000198void
199File::SetStream (FILE *fh, bool transfer_ownership)
200{
201 if (IsValid())
202 Close();
203 m_stream = fh;
Greg Clayton44d93782014-01-27 23:43:24 +0000204 m_own_stream = transfer_ownership;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000205}
206
207Error
Greg Clayton504f89a2011-02-08 17:49:02 +0000208File::Open (const char *path, uint32_t options, uint32_t permissions)
209{
210 Error error;
211 if (IsValid())
212 Close ();
213
214 int oflag = 0;
Greg Clayton96c09682012-01-04 22:56:43 +0000215 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 {
Greg Clayton504f89a2011-02-08 17:49:02 +0000238 oflag |= O_RDONLY;
Greg Claytonfbb76342013-11-20 21:07:01 +0000239
Colin Riley909bb7a2013-11-26 15:10:46 +0000240#ifndef _WIN32
Greg Claytonfbb76342013-11-20 21:07:01 +0000241 if (options & eOpenoptionDontFollowSymlinks)
242 oflag |= O_NOFOLLOW;
Colin Riley909bb7a2013-11-26 15:10:46 +0000243#endif
Greg Clayton96c09682012-01-04 22:56:43 +0000244 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000245
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000246#ifndef _WIN32
Greg Clayton504f89a2011-02-08 17:49:02 +0000247 if (options & eOpenOptionNonBlocking)
248 oflag |= O_NONBLOCK;
Pavel Labath97a9ac12015-02-05 16:44:42 +0000249 if (options & eOpenOptionCloseOnExec)
250 oflag |= O_CLOEXEC;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000251#else
252 oflag |= O_BINARY;
253#endif
Greg Clayton504f89a2011-02-08 17:49:02 +0000254
Greg Clayton504f89a2011-02-08 17:49:02 +0000255 mode_t mode = 0;
Greg Clayton96c09682012-01-04 22:56:43 +0000256 if (oflag & O_CREAT)
257 {
Greg Claytonfbb76342013-11-20 21:07:01 +0000258 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;
Greg Clayton96c09682012-01-04 22:56:43 +0000267 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000268
Greg Clayton96c09682012-01-04 22:56:43 +0000269 do
270 {
Zachary Turner190fadc2016-03-22 17:58:09 +0000271#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
Greg Clayton96c09682012-01-04 22:56:43 +0000281 m_descriptor = ::open(path, oflag, mode);
Zachary Turner190fadc2016-03-22 17:58:09 +0000282#endif
Greg Clayton96c09682012-01-04 22:56:43 +0000283 } while (m_descriptor < 0 && errno == EINTR);
284
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000285 if (!DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000286 error.SetErrorToErrno();
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000287 else
Greg Clayton44d93782014-01-27 23:43:24 +0000288 {
Zachary Turner98688922014-08-06 18:16:26 +0000289 m_should_close_fd = true;
Greg Clayton44d93782014-01-27 23:43:24 +0000290 m_options = options;
291 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000292
293 return error;
294}
295
Daniel Maleae0f8f572013-08-26 23:57:52 +0000296uint32_t
Chaoren Lind3173f32015-05-29 19:52:29 +0000297File::GetPermissions(const FileSpec &file_spec, Error &error)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000298{
Chaoren Lind3173f32015-05-29 19:52:29 +0000299 if (file_spec)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000300 {
301 struct stat file_stats;
Zachary Turner190fadc2016-03-22 17:58:09 +0000302 int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats);
303 if (stat_result == -1)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000304 error.SetErrorToErrno();
305 else
306 {
307 error.Clear();
Greg Claytonc0293822013-11-22 18:46:55 +0000308 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000309 }
310 }
311 else
Chaoren Lind3173f32015-05-29 19:52:29 +0000312 error.SetErrorString ("empty file spec");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000313 return 0;
314}
315
316uint32_t
317File::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();
Greg Claytonc0293822013-11-22 18:46:55 +0000328 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000329 }
330 }
331 else
332 {
333 error.SetErrorString ("invalid file descriptor");
334 }
335 return 0;
336}
337
338
Greg Clayton504f89a2011-02-08 17:49:02 +0000339Error
340File::Close ()
341{
342 Error error;
Greg Clayton44d93782014-01-27 23:43:24 +0000343 if (StreamIsValid() && m_own_stream)
Greg Clayton504f89a2011-02-08 17:49:02 +0000344 {
Greg Clayton44d93782014-01-27 23:43:24 +0000345 if (::fclose (m_stream) == EOF)
346 error.SetErrorToErrno();
Greg Clayton504f89a2011-02-08 17:49:02 +0000347 }
Greg Clayton44d93782014-01-27 23:43:24 +0000348
Zachary Turner98688922014-08-06 18:16:26 +0000349 if (DescriptorIsValid() && m_should_close_fd)
Greg Clayton44d93782014-01-27 23:43:24 +0000350 {
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;
Zachary Turner98688922014-08-06 18:16:26 +0000358 m_should_close_fd = false;
Greg Clayton340b0302014-02-05 17:57:57 +0000359 m_is_interactive = eLazyBoolCalculate;
360 m_is_real_terminal = eLazyBoolCalculate;
Greg Clayton504f89a2011-02-08 17:49:02 +0000361 return error;
362}
Greg Clayton968fa382011-02-08 19:10:53 +0000363
Enrico Granata744959b2016-01-13 18:11:45 +0000364void
365File::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}
Greg Clayton968fa382011-02-08 19:10:53 +0000373
374Error
375File::GetFileSpec (FileSpec &file_spec) const
376{
377 Error error;
Greg Clayton925137c2011-02-09 01:16:43 +0000378#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
Greg Clayton968fa382011-02-08 19:10:53 +0000379 if (IsValid ())
380 {
381 char path[PATH_MAX];
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000382 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
Greg Clayton968fa382011-02-08 19:10:53 +0000383 error.SetErrorToErrno();
384 else
385 file_spec.SetFile (path, false);
386 }
387 else
Greg Clayton925137c2011-02-09 01:16:43 +0000388 {
Greg Clayton968fa382011-02-08 19:10:53 +0000389 error.SetErrorString("invalid file handle");
Greg Clayton925137c2011-02-09 01:16:43 +0000390 }
Greg Clayton94d08622011-02-09 07:19:18 +0000391#elif defined(__linux__)
392 char proc[64];
393 char path[PATH_MAX];
394 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
Greg Clayton86edbf42011-10-26 00:56:27 +0000395 error.SetErrorString ("cannot resolve file descriptor");
Greg Clayton94d08622011-02-09 07:19:18 +0000396 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 }
Greg Clayton925137c2011-02-09 01:16:43 +0000407#else
Greg Clayton94d08622011-02-09 07:19:18 +0000408 error.SetErrorString ("File::GetFileSpec is not supported on this platform");
Greg Clayton925137c2011-02-09 01:16:43 +0000409#endif
Greg Clayton968fa382011-02-08 19:10:53 +0000410
411 if (error.Fail())
412 file_spec.Clear();
413 return error;
414}
415
Greg Clayton43d82792013-05-22 23:30:09 +0000416off_t
417File::SeekFromStart (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000418{
Greg Clayton43d82792013-05-22 23:30:09 +0000419 off_t result = 0;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000420 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000421 {
Greg Clayton43d82792013-05-22 23:30:09 +0000422 result = ::lseek (m_descriptor, offset, SEEK_SET);
Greg Clayton968fa382011-02-08 19:10:53 +0000423
Greg Clayton43d82792013-05-22 23:30:09 +0000424 if (error_ptr)
425 {
426 if (result == -1)
427 error_ptr->SetErrorToErrno();
428 else
429 error_ptr->Clear();
430 }
Greg Clayton968fa382011-02-08 19:10:53 +0000431 }
Greg Clayton43d82792013-05-22 23:30:09 +0000432 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000433 {
Greg Clayton43d82792013-05-22 23:30:09 +0000434 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 }
Greg Clayton968fa382011-02-08 19:10:53 +0000443 }
Greg Clayton43d82792013-05-22 23:30:09 +0000444 else if (error_ptr)
445 {
446 error_ptr->SetErrorString("invalid file handle");
447 }
448 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000449}
450
Greg Clayton43d82792013-05-22 23:30:09 +0000451off_t
452File::SeekFromCurrent (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000453{
Greg Clayton43d82792013-05-22 23:30:09 +0000454 off_t result = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000455 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000456 {
Greg Clayton43d82792013-05-22 23:30:09 +0000457 result = ::lseek (m_descriptor, offset, SEEK_CUR);
Greg Clayton968fa382011-02-08 19:10:53 +0000458
Greg Clayton43d82792013-05-22 23:30:09 +0000459 if (error_ptr)
460 {
461 if (result == -1)
462 error_ptr->SetErrorToErrno();
463 else
464 error_ptr->Clear();
465 }
Greg Clayton968fa382011-02-08 19:10:53 +0000466 }
Greg Clayton43d82792013-05-22 23:30:09 +0000467 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000468 {
Greg Clayton43d82792013-05-22 23:30:09 +0000469 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 }
Greg Clayton968fa382011-02-08 19:10:53 +0000478 }
Greg Clayton43d82792013-05-22 23:30:09 +0000479 else if (error_ptr)
480 {
481 error_ptr->SetErrorString("invalid file handle");
482 }
483 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000484}
485
Greg Clayton43d82792013-05-22 23:30:09 +0000486off_t
487File::SeekFromEnd (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000488{
Greg Clayton43d82792013-05-22 23:30:09 +0000489 off_t result = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000490 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000491 {
Greg Clayton43d82792013-05-22 23:30:09 +0000492 result = ::lseek (m_descriptor, offset, SEEK_END);
Greg Clayton968fa382011-02-08 19:10:53 +0000493
Greg Clayton43d82792013-05-22 23:30:09 +0000494 if (error_ptr)
495 {
496 if (result == -1)
497 error_ptr->SetErrorToErrno();
498 else
499 error_ptr->Clear();
500 }
Greg Clayton968fa382011-02-08 19:10:53 +0000501 }
Greg Clayton43d82792013-05-22 23:30:09 +0000502 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000503 {
Greg Clayton43d82792013-05-22 23:30:09 +0000504 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 }
Greg Clayton968fa382011-02-08 19:10:53 +0000513 }
Greg Clayton43d82792013-05-22 23:30:09 +0000514 else if (error_ptr)
515 {
516 error_ptr->SetErrorString("invalid file handle");
517 }
518 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000519}
520
521Error
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000522File::Flush ()
523{
524 Error error;
525 if (StreamIsValid())
526 {
Greg Clayton96c09682012-01-04 22:56:43 +0000527 int err = 0;
528 do
529 {
530 err = ::fflush (m_stream);
531 } while (err == EOF && errno == EINTR);
532
533 if (err == EOF)
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000534 error.SetErrorToErrno();
535 }
536 else if (!DescriptorIsValid())
537 {
538 error.SetErrorString("invalid file handle");
539 }
540 return error;
541}
542
543
544Error
Greg Clayton968fa382011-02-08 19:10:53 +0000545File::Sync ()
546{
547 Error error;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000548 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000549 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000550#ifdef _WIN32
551 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
552 if (err == 0)
553 error.SetErrorToGenericError();
554#else
Greg Clayton96c09682012-01-04 22:56:43 +0000555 int err = 0;
556 do
557 {
558 err = ::fsync (m_descriptor);
559 } while (err == -1 && errno == EINTR);
560
561 if (err == -1)
Greg Clayton968fa382011-02-08 19:10:53 +0000562 error.SetErrorToErrno();
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000563#endif
Greg Clayton968fa382011-02-08 19:10:53 +0000564 }
565 else
566 {
567 error.SetErrorString("invalid file handle");
568 }
569 return error;
570}
Greg Clayton846b64b2011-02-08 19:54:44 +0000571
Greg Clayton29aac9a2015-04-09 00:06:44 +0000572#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
Greg Clayton504f89a2011-02-08 17:49:02 +0000578Error
579File::Read (void *buf, size_t &num_bytes)
580{
581 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000582
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
Greg Clayton96c09682012-01-04 22:56:43 +0000615 ssize_t bytes_read = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000616 if (DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000617 {
Greg Clayton96c09682012-01-04 22:56:43 +0000618 do
619 {
620 bytes_read = ::read (m_descriptor, buf, num_bytes);
621 } while (bytes_read < 0 && errno == EINTR);
622
Greg Clayton504f89a2011-02-08 17:49:02 +0000623 if (bytes_read == -1)
624 {
625 error.SetErrorToErrno();
626 num_bytes = 0;
627 }
628 else
629 num_bytes = bytes_read;
630 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000631 else if (StreamIsValid())
632 {
Greg Clayton96c09682012-01-04 22:56:43 +0000633 bytes_read = ::fread (buf, 1, num_bytes, m_stream);
634
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000635 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 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000646 else
647 {
648 num_bytes = 0;
649 error.SetErrorString("invalid file handle");
650 }
651 return error;
652}
653
654Error
655File::Write (const void *buf, size_t &num_bytes)
656{
657 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000658
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
Greg Clayton96c09682012-01-04 22:56:43 +0000691 ssize_t bytes_written = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000692 if (DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000693 {
Greg Clayton96c09682012-01-04 22:56:43 +0000694 do
695 {
696 bytes_written = ::write (m_descriptor, buf, num_bytes);
697 } while (bytes_written < 0 && errno == EINTR);
698
Greg Clayton504f89a2011-02-08 17:49:02 +0000699 if (bytes_written == -1)
700 {
701 error.SetErrorToErrno();
702 num_bytes = 0;
703 }
704 else
705 num_bytes = bytes_written;
706 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000707 else if (StreamIsValid())
708 {
Greg Clayton96c09682012-01-04 22:56:43 +0000709 bytes_written = ::fwrite (buf, 1, num_bytes, m_stream);
710
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000711 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 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000723 else
724 {
725 num_bytes = 0;
726 error.SetErrorString("invalid file handle");
727 }
Zachary Turner98688922014-08-06 18:16:26 +0000728
Greg Clayton504f89a2011-02-08 17:49:02 +0000729 return error;
730}
731
Greg Clayton846b64b2011-02-08 19:54:44 +0000732
733Error
734File::Read (void *buf, size_t &num_bytes, off_t &offset)
735{
736 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000737
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
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000771 int fd = GetDescriptor();
772 if (fd != kInvalidDescriptor)
Greg Clayton846b64b2011-02-08 19:54:44 +0000773 {
Greg Clayton96c09682012-01-04 22:56:43 +0000774 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
Greg Clayton846b64b2011-02-08 19:54:44 +0000780 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 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000796#else
797 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
798 SeekFromStart(offset);
Greg Clayton29aac9a2015-04-09 00:06:44 +0000799 error = Read(buf, num_bytes);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000800 if (!error.Fail())
801 SeekFromStart(cur);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000802#endif
Greg Clayton29aac9a2015-04-09 00:06:44 +0000803 return error;
Greg Clayton846b64b2011-02-08 19:54:44 +0000804}
805
806Error
Greg Clayton0b0b5122012-08-30 18:15:10 +0000807File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
Greg Clayton96c09682012-01-04 22:56:43 +0000808{
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
Jason Molenda03176d72015-01-22 00:41:05 +0000825 size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
Greg Clayton7b0992d2013-04-18 22:45:39 +0000826 std::unique_ptr<DataBufferHeap> data_heap_ap;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000827 data_heap_ap.reset(new DataBufferHeap());
828 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
Greg Clayton96c09682012-01-04 22:56:43 +0000829
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
Jason Molenda03176d72015-01-22 00:41:05 +0000837 if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize())
838 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
Greg Clayton96c09682012-01-04 22:56:43 +0000839 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
861Error
Greg Clayton846b64b2011-02-08 19:54:44 +0000862File::Write (const void *buf, size_t &num_bytes, off_t &offset)
863{
Greg Clayton7965e542015-04-09 00:12:33 +0000864 Error error;
865
Greg Clayton29aac9a2015-04-09 00:06:44 +0000866#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
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000898 int fd = GetDescriptor();
899 if (fd != kInvalidDescriptor)
Greg Clayton846b64b2011-02-08 19:54:44 +0000900 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000901#ifndef _WIN32
Greg Clayton96c09682012-01-04 22:56:43 +0000902 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
Greg Clayton846b64b2011-02-08 19:54:44 +0000908 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 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000918#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
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000926 offset = after;
927#endif
Greg Clayton846b64b2011-02-08 19:54:44 +0000928 }
929 else
930 {
931 num_bytes = 0;
932 error.SetErrorString("invalid file handle");
933 }
934 return error;
935}
936
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000937//------------------------------------------------------------------
938// Print some formatted output to the stream.
939//------------------------------------------------------------------
Greg Claytonc7bece562013-01-25 18:06:21 +0000940size_t
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000941File::Printf (const char *format, ...)
942{
943 va_list args;
944 va_start (args, format);
Greg Claytonc7bece562013-01-25 18:06:21 +0000945 size_t result = PrintfVarArg (format, args);
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000946 va_end (args);
947 return result;
948}
Greg Clayton846b64b2011-02-08 19:54:44 +0000949
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000950//------------------------------------------------------------------
951// Print some formatted output to the stream.
952//------------------------------------------------------------------
Greg Claytonc7bece562013-01-25 18:06:21 +0000953size_t
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000954File::PrintfVarArg (const char *format, va_list args)
955{
Greg Claytonc7bece562013-01-25 18:06:21 +0000956 size_t result = 0;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000957 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}
Daniel Maleae0f8f572013-08-26 23:57:52 +0000978
979mode_t
980File::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}
Greg Clayton340b0302014-02-05 17:57:57 +00001004
1005void
1006File::CalculateInteractiveAndTerminal ()
1007{
1008 const int fd = GetDescriptor();
1009 if (fd >= 0)
1010 {
1011 m_is_interactive = eLazyBoolNo;
1012 m_is_real_terminal = eLazyBoolNo;
Shawn Best8da0bf32014-11-08 01:41:49 +00001013#if (defined(_WIN32) || defined(__ANDROID_NDK__))
Deepak Panickal6419e982014-03-03 15:53:37 +00001014 if (_isatty(fd))
1015 {
1016 m_is_interactive = eLazyBoolYes;
1017 m_is_real_terminal = eLazyBoolYes;
1018 }
1019#else
Greg Clayton340b0302014-02-05 17:57:57 +00001020 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)
Sean Callanan66810412015-10-19 23:11:07 +00001027 {
Greg Clayton340b0302014-02-05 17:57:57 +00001028 m_is_real_terminal = eLazyBoolYes;
Sean Callanan66810412015-10-19 23:11:07 +00001029 if (llvm::sys::Process::FileDescriptorHasColors(fd))
1030 m_supports_colors = eLazyBoolYes;
1031 }
Greg Clayton340b0302014-02-05 17:57:57 +00001032 }
1033 }
Deepak Panickal94667bc2014-02-17 17:43:39 +00001034#endif
Greg Clayton340b0302014-02-05 17:57:57 +00001035 }
1036}
1037
1038bool
1039File::GetIsInteractive ()
1040{
1041 if (m_is_interactive == eLazyBoolCalculate)
1042 CalculateInteractiveAndTerminal ();
1043 return m_is_interactive == eLazyBoolYes;
1044}
1045
1046bool
1047File::GetIsRealTerminal ()
1048{
1049 if (m_is_real_terminal == eLazyBoolCalculate)
1050 CalculateInteractiveAndTerminal();
1051 return m_is_real_terminal == eLazyBoolYes;
1052}
1053
Sean Callanan66810412015-10-19 23:11:07 +00001054bool
1055File::GetIsTerminalWithColors ()
1056{
1057 if (m_supports_colors == eLazyBoolCalculate)
1058 CalculateInteractiveAndTerminal();
1059 return m_supports_colors == eLazyBoolYes;
1060}
1061