blob: a862f2cd433f4961f75747acdfd3abcde05c8ece [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 Clayton2b4d9b72011-04-01 18:18:34 +000017#include <sys/stat.h>
Greg Clayton504f89a2011-02-08 17:49:02 +000018
Virgile Bellob2f1fb22013-08-23 12:44:05 +000019#ifdef _WIN32
20#include "lldb/Host/windows/windows.h"
Deepak Panickal94667bc2014-02-17 17:43:39 +000021#else
22#include <sys/ioctl.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000023#endif
24
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"
Greg Clayton504f89a2011-02-08 17:49:02 +000032
33using namespace lldb;
34using namespace lldb_private;
35
Greg Clayton51b1e2d2011-02-09 01:08:52 +000036static const char *
37GetStreamOpenModeFromOptions (uint32_t options)
38{
39 if (options & File::eOpenOptionAppend)
40 {
41 if (options & File::eOpenOptionRead)
42 {
43 if (options & File::eOpenOptionCanCreateNewOnly)
44 return "a+x";
45 else
46 return "a+";
47 }
48 else if (options & File::eOpenOptionWrite)
49 {
50 if (options & File::eOpenOptionCanCreateNewOnly)
51 return "ax";
52 else
53 return "a";
54 }
55 }
56 else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite)
57 {
58 if (options & File::eOpenOptionCanCreate)
59 {
60 if (options & File::eOpenOptionCanCreateNewOnly)
61 return "w+x";
62 else
63 return "w+";
64 }
65 else
66 return "r+";
67 }
68 else if (options & File::eOpenOptionRead)
69 {
70 return "r";
71 }
72 else if (options & File::eOpenOptionWrite)
73 {
74 return "w";
75 }
76 return NULL;
77}
78
79int File::kInvalidDescriptor = -1;
80FILE * File::kInvalidStream = NULL;
81
Greg Clayton504f89a2011-02-08 17:49:02 +000082File::File(const char *path, uint32_t options, uint32_t permissions) :
Zachary Turner98688922014-08-06 18:16:26 +000083 IOObject(eFDTypeFile, false),
Greg Clayton51b1e2d2011-02-09 01:08:52 +000084 m_descriptor (kInvalidDescriptor),
85 m_stream (kInvalidStream),
Greg Clayton44d93782014-01-27 23:43:24 +000086 m_options (),
87 m_own_stream (false),
Greg Clayton340b0302014-02-05 17:57:57 +000088 m_is_interactive (eLazyBoolCalculate),
89 m_is_real_terminal (eLazyBoolCalculate)
Greg Clayton504f89a2011-02-08 17:49:02 +000090{
91 Open (path, options, permissions);
92}
93
Daniel Maleae0f8f572013-08-26 23:57:52 +000094File::File (const FileSpec& filespec,
95 uint32_t options,
96 uint32_t permissions) :
Zachary Turner98688922014-08-06 18:16:26 +000097 IOObject(eFDTypeFile, false),
Daniel Maleae0f8f572013-08-26 23:57:52 +000098 m_descriptor (kInvalidDescriptor),
99 m_stream (kInvalidStream),
100 m_options (0),
Greg Clayton44d93782014-01-27 23:43:24 +0000101 m_own_stream (false),
Greg Clayton340b0302014-02-05 17:57:57 +0000102 m_is_interactive (eLazyBoolCalculate),
103 m_is_real_terminal (eLazyBoolCalculate)
104
Daniel Maleae0f8f572013-08-26 23:57:52 +0000105{
106 if (filespec)
107 {
108 Open (filespec.GetPath().c_str(), options, permissions);
109 }
110}
111
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000112File::File (const File &rhs) :
Zachary Turner98688922014-08-06 18:16:26 +0000113 IOObject(eFDTypeFile, false),
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000114 m_descriptor (kInvalidDescriptor),
115 m_stream (kInvalidStream),
116 m_options (0),
Greg Clayton44d93782014-01-27 23:43:24 +0000117 m_own_stream (false),
Greg Clayton340b0302014-02-05 17:57:57 +0000118 m_is_interactive (eLazyBoolCalculate),
119 m_is_real_terminal (eLazyBoolCalculate)
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000120{
121 Duplicate (rhs);
122}
123
124
125File &
126File::operator = (const File &rhs)
127{
128 if (this != &rhs)
129 Duplicate (rhs);
130 return *this;
131}
132
Greg Clayton504f89a2011-02-08 17:49:02 +0000133File::~File()
134{
135 Close ();
136}
137
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000138
139int
140File::GetDescriptor() const
141{
142 if (DescriptorIsValid())
143 return m_descriptor;
144
145 // Don't open the file descriptor if we don't need to, just get it from the
146 // stream if we have one.
147 if (StreamIsValid())
Zachary Turner9c402642015-10-15 19:35:48 +0000148 {
149#if defined(LLVM_ON_WIN32)
150 return _fileno(m_stream);
151#else
152 return fileno(m_stream);
153#endif
154 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000155
156 // Invalid descriptor and invalid stream, return invalid descriptor.
157 return kInvalidDescriptor;
158}
159
Zachary Turner98688922014-08-06 18:16:26 +0000160IOObject::WaitableHandle
161File::GetWaitableHandle()
162{
163 return m_descriptor;
164}
165
166
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000167void
168File::SetDescriptor (int fd, bool transfer_ownership)
169{
170 if (IsValid())
171 Close();
172 m_descriptor = fd;
Zachary Turner98688922014-08-06 18:16:26 +0000173 m_should_close_fd = transfer_ownership;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000174}
175
176
177FILE *
178File::GetStream ()
179{
180 if (!StreamIsValid())
181 {
182 if (DescriptorIsValid())
183 {
184 const char *mode = GetStreamOpenModeFromOptions (m_options);
185 if (mode)
Greg Clayton96c09682012-01-04 22:56:43 +0000186 {
Zachary Turner98688922014-08-06 18:16:26 +0000187 if (!m_should_close_fd)
Greg Clayton44d93782014-01-27 23:43:24 +0000188 {
189 // We must duplicate the file descriptor if we don't own it because
190 // when you call fdopen, the stream will own the fd
191#ifdef _WIN32
192 m_descriptor = ::_dup(GetDescriptor());
193#else
194 m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD);
195#endif
Zachary Turner98688922014-08-06 18:16:26 +0000196 m_should_close_fd = true;
Greg Clayton44d93782014-01-27 23:43:24 +0000197 }
198
Greg Clayton96c09682012-01-04 22:56:43 +0000199 do
200 {
201 m_stream = ::fdopen (m_descriptor, mode);
202 } while (m_stream == NULL && errno == EINTR);
Greg Clayton44d93782014-01-27 23:43:24 +0000203
204 // If we got a stream, then we own the stream and should no
205 // longer own the descriptor because fclose() will close it for us
206
207 if (m_stream)
208 {
209 m_own_stream = true;
Zachary Turner98688922014-08-06 18:16:26 +0000210 m_should_close_fd = false;
Greg Clayton44d93782014-01-27 23:43:24 +0000211 }
Greg Clayton96c09682012-01-04 22:56:43 +0000212 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000213 }
214 }
215 return m_stream;
216}
217
218
219void
220File::SetStream (FILE *fh, bool transfer_ownership)
221{
222 if (IsValid())
223 Close();
224 m_stream = fh;
Greg Clayton44d93782014-01-27 23:43:24 +0000225 m_own_stream = transfer_ownership;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000226}
227
228Error
229File::Duplicate (const File &rhs)
230{
231 Error error;
232 if (IsValid ())
233 Close();
234
235 if (rhs.DescriptorIsValid())
236 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000237#ifdef _WIN32
238 m_descriptor = ::_dup(rhs.GetDescriptor());
239#else
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000240 m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000241#endif
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000242 if (!DescriptorIsValid())
243 error.SetErrorToErrno();
244 else
245 {
246 m_options = rhs.m_options;
Zachary Turner98688922014-08-06 18:16:26 +0000247 m_should_close_fd = true;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000248 }
249 }
250 else
251 {
252 error.SetErrorString ("invalid file to duplicate");
253 }
254 return error;
255}
256
Greg Clayton504f89a2011-02-08 17:49:02 +0000257Error
258File::Open (const char *path, uint32_t options, uint32_t permissions)
259{
260 Error error;
261 if (IsValid())
262 Close ();
263
264 int oflag = 0;
Greg Clayton96c09682012-01-04 22:56:43 +0000265 const bool read = options & eOpenOptionRead;
266 const bool write = options & eOpenOptionWrite;
267 if (write)
268 {
269 if (read)
270 oflag |= O_RDWR;
271 else
272 oflag |= O_WRONLY;
273
274 if (options & eOpenOptionAppend)
275 oflag |= O_APPEND;
276
277 if (options & eOpenOptionTruncate)
278 oflag |= O_TRUNC;
279
280 if (options & eOpenOptionCanCreate)
281 oflag |= O_CREAT;
282
283 if (options & eOpenOptionCanCreateNewOnly)
284 oflag |= O_CREAT | O_EXCL;
285 }
286 else if (read)
287 {
Greg Clayton504f89a2011-02-08 17:49:02 +0000288 oflag |= O_RDONLY;
Greg Claytonfbb76342013-11-20 21:07:01 +0000289
Colin Riley909bb7a2013-11-26 15:10:46 +0000290#ifndef _WIN32
Greg Claytonfbb76342013-11-20 21:07:01 +0000291 if (options & eOpenoptionDontFollowSymlinks)
292 oflag |= O_NOFOLLOW;
Colin Riley909bb7a2013-11-26 15:10:46 +0000293#endif
Greg Clayton96c09682012-01-04 22:56:43 +0000294 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000295
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000296#ifndef _WIN32
Greg Clayton504f89a2011-02-08 17:49:02 +0000297 if (options & eOpenOptionNonBlocking)
298 oflag |= O_NONBLOCK;
Pavel Labath97a9ac12015-02-05 16:44:42 +0000299 if (options & eOpenOptionCloseOnExec)
300 oflag |= O_CLOEXEC;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000301#else
302 oflag |= O_BINARY;
303#endif
Greg Clayton504f89a2011-02-08 17:49:02 +0000304
Greg Clayton504f89a2011-02-08 17:49:02 +0000305 mode_t mode = 0;
Greg Clayton96c09682012-01-04 22:56:43 +0000306 if (oflag & O_CREAT)
307 {
Greg Claytonfbb76342013-11-20 21:07:01 +0000308 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;
Greg Clayton96c09682012-01-04 22:56:43 +0000317 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000318
Greg Clayton96c09682012-01-04 22:56:43 +0000319 do
320 {
321 m_descriptor = ::open(path, oflag, mode);
322 } while (m_descriptor < 0 && errno == EINTR);
323
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000324 if (!DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000325 error.SetErrorToErrno();
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000326 else
Greg Clayton44d93782014-01-27 23:43:24 +0000327 {
Zachary Turner98688922014-08-06 18:16:26 +0000328 m_should_close_fd = true;
Greg Clayton44d93782014-01-27 23:43:24 +0000329 m_options = options;
330 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000331
332 return error;
333}
334
Daniel Maleae0f8f572013-08-26 23:57:52 +0000335uint32_t
Chaoren Lind3173f32015-05-29 19:52:29 +0000336File::GetPermissions(const FileSpec &file_spec, Error &error)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000337{
Chaoren Lind3173f32015-05-29 19:52:29 +0000338 if (file_spec)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000339 {
340 struct stat file_stats;
Chaoren Lind3173f32015-05-29 19:52:29 +0000341 if (::stat(file_spec.GetCString(), &file_stats) == -1)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000342 error.SetErrorToErrno();
343 else
344 {
345 error.Clear();
Greg Claytonc0293822013-11-22 18:46:55 +0000346 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000347 }
348 }
349 else
Chaoren Lind3173f32015-05-29 19:52:29 +0000350 error.SetErrorString ("empty file spec");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000351 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();
Greg Claytonc0293822013-11-22 18:46:55 +0000366 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000367 }
368 }
369 else
370 {
371 error.SetErrorString ("invalid file descriptor");
372 }
373 return 0;
374}
375
376
Greg Clayton504f89a2011-02-08 17:49:02 +0000377Error
378File::Close ()
379{
380 Error error;
Greg Clayton44d93782014-01-27 23:43:24 +0000381 if (StreamIsValid() && m_own_stream)
Greg Clayton504f89a2011-02-08 17:49:02 +0000382 {
Greg Clayton44d93782014-01-27 23:43:24 +0000383 if (::fclose (m_stream) == EOF)
384 error.SetErrorToErrno();
Greg Clayton504f89a2011-02-08 17:49:02 +0000385 }
Greg Clayton44d93782014-01-27 23:43:24 +0000386
Zachary Turner98688922014-08-06 18:16:26 +0000387 if (DescriptorIsValid() && m_should_close_fd)
Greg Clayton44d93782014-01-27 23:43:24 +0000388 {
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;
Zachary Turner98688922014-08-06 18:16:26 +0000396 m_should_close_fd = false;
Greg Clayton340b0302014-02-05 17:57:57 +0000397 m_is_interactive = eLazyBoolCalculate;
398 m_is_real_terminal = eLazyBoolCalculate;
Greg Clayton504f89a2011-02-08 17:49:02 +0000399 return error;
400}
Greg Clayton968fa382011-02-08 19:10:53 +0000401
Enrico Granata744959b2016-01-13 18:11:45 +0000402void
403File::Clear ()
404{
405 m_stream = nullptr;
406 m_descriptor = -1;
407 m_options = 0;
408 m_own_stream = false;
409 m_is_interactive = m_supports_colors = m_is_real_terminal = eLazyBoolCalculate;
410}
Greg Clayton968fa382011-02-08 19:10:53 +0000411
412Error
413File::GetFileSpec (FileSpec &file_spec) const
414{
415 Error error;
Greg Clayton925137c2011-02-09 01:16:43 +0000416#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
Greg Clayton968fa382011-02-08 19:10:53 +0000417 if (IsValid ())
418 {
419 char path[PATH_MAX];
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000420 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
Greg Clayton968fa382011-02-08 19:10:53 +0000421 error.SetErrorToErrno();
422 else
423 file_spec.SetFile (path, false);
424 }
425 else
Greg Clayton925137c2011-02-09 01:16:43 +0000426 {
Greg Clayton968fa382011-02-08 19:10:53 +0000427 error.SetErrorString("invalid file handle");
Greg Clayton925137c2011-02-09 01:16:43 +0000428 }
Greg Clayton94d08622011-02-09 07:19:18 +0000429#elif defined(__linux__)
430 char proc[64];
431 char path[PATH_MAX];
432 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
Greg Clayton86edbf42011-10-26 00:56:27 +0000433 error.SetErrorString ("cannot resolve file descriptor");
Greg Clayton94d08622011-02-09 07:19:18 +0000434 else
435 {
436 ssize_t len;
437 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
438 error.SetErrorToErrno();
439 else
440 {
441 path[len] = '\0';
442 file_spec.SetFile (path, false);
443 }
444 }
Greg Clayton925137c2011-02-09 01:16:43 +0000445#else
Greg Clayton94d08622011-02-09 07:19:18 +0000446 error.SetErrorString ("File::GetFileSpec is not supported on this platform");
Greg Clayton925137c2011-02-09 01:16:43 +0000447#endif
Greg Clayton968fa382011-02-08 19:10:53 +0000448
449 if (error.Fail())
450 file_spec.Clear();
451 return error;
452}
453
Greg Clayton43d82792013-05-22 23:30:09 +0000454off_t
455File::SeekFromStart (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000456{
Greg Clayton43d82792013-05-22 23:30:09 +0000457 off_t result = 0;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000458 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000459 {
Greg Clayton43d82792013-05-22 23:30:09 +0000460 result = ::lseek (m_descriptor, offset, SEEK_SET);
Greg Clayton968fa382011-02-08 19:10:53 +0000461
Greg Clayton43d82792013-05-22 23:30:09 +0000462 if (error_ptr)
463 {
464 if (result == -1)
465 error_ptr->SetErrorToErrno();
466 else
467 error_ptr->Clear();
468 }
Greg Clayton968fa382011-02-08 19:10:53 +0000469 }
Greg Clayton43d82792013-05-22 23:30:09 +0000470 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000471 {
Greg Clayton43d82792013-05-22 23:30:09 +0000472 result = ::fseek(m_stream, offset, SEEK_SET);
473
474 if (error_ptr)
475 {
476 if (result == -1)
477 error_ptr->SetErrorToErrno();
478 else
479 error_ptr->Clear();
480 }
Greg Clayton968fa382011-02-08 19:10:53 +0000481 }
Greg Clayton43d82792013-05-22 23:30:09 +0000482 else if (error_ptr)
483 {
484 error_ptr->SetErrorString("invalid file handle");
485 }
486 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000487}
488
Greg Clayton43d82792013-05-22 23:30:09 +0000489off_t
490File::SeekFromCurrent (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000491{
Greg Clayton43d82792013-05-22 23:30:09 +0000492 off_t result = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000493 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000494 {
Greg Clayton43d82792013-05-22 23:30:09 +0000495 result = ::lseek (m_descriptor, offset, SEEK_CUR);
Greg Clayton968fa382011-02-08 19:10:53 +0000496
Greg Clayton43d82792013-05-22 23:30:09 +0000497 if (error_ptr)
498 {
499 if (result == -1)
500 error_ptr->SetErrorToErrno();
501 else
502 error_ptr->Clear();
503 }
Greg Clayton968fa382011-02-08 19:10:53 +0000504 }
Greg Clayton43d82792013-05-22 23:30:09 +0000505 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000506 {
Greg Clayton43d82792013-05-22 23:30:09 +0000507 result = ::fseek(m_stream, offset, SEEK_CUR);
508
509 if (error_ptr)
510 {
511 if (result == -1)
512 error_ptr->SetErrorToErrno();
513 else
514 error_ptr->Clear();
515 }
Greg Clayton968fa382011-02-08 19:10:53 +0000516 }
Greg Clayton43d82792013-05-22 23:30:09 +0000517 else if (error_ptr)
518 {
519 error_ptr->SetErrorString("invalid file handle");
520 }
521 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000522}
523
Greg Clayton43d82792013-05-22 23:30:09 +0000524off_t
525File::SeekFromEnd (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000526{
Greg Clayton43d82792013-05-22 23:30:09 +0000527 off_t result = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000528 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000529 {
Greg Clayton43d82792013-05-22 23:30:09 +0000530 result = ::lseek (m_descriptor, offset, SEEK_END);
Greg Clayton968fa382011-02-08 19:10:53 +0000531
Greg Clayton43d82792013-05-22 23:30:09 +0000532 if (error_ptr)
533 {
534 if (result == -1)
535 error_ptr->SetErrorToErrno();
536 else
537 error_ptr->Clear();
538 }
Greg Clayton968fa382011-02-08 19:10:53 +0000539 }
Greg Clayton43d82792013-05-22 23:30:09 +0000540 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000541 {
Greg Clayton43d82792013-05-22 23:30:09 +0000542 result = ::fseek(m_stream, offset, SEEK_END);
543
544 if (error_ptr)
545 {
546 if (result == -1)
547 error_ptr->SetErrorToErrno();
548 else
549 error_ptr->Clear();
550 }
Greg Clayton968fa382011-02-08 19:10:53 +0000551 }
Greg Clayton43d82792013-05-22 23:30:09 +0000552 else if (error_ptr)
553 {
554 error_ptr->SetErrorString("invalid file handle");
555 }
556 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000557}
558
559Error
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000560File::Flush ()
561{
562 Error error;
563 if (StreamIsValid())
564 {
Greg Clayton96c09682012-01-04 22:56:43 +0000565 int err = 0;
566 do
567 {
568 err = ::fflush (m_stream);
569 } while (err == EOF && errno == EINTR);
570
571 if (err == EOF)
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000572 error.SetErrorToErrno();
573 }
574 else if (!DescriptorIsValid())
575 {
576 error.SetErrorString("invalid file handle");
577 }
578 return error;
579}
580
581
582Error
Greg Clayton968fa382011-02-08 19:10:53 +0000583File::Sync ()
584{
585 Error error;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000586 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000587 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000588#ifdef _WIN32
589 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
590 if (err == 0)
591 error.SetErrorToGenericError();
592#else
Greg Clayton96c09682012-01-04 22:56:43 +0000593 int err = 0;
594 do
595 {
596 err = ::fsync (m_descriptor);
597 } while (err == -1 && errno == EINTR);
598
599 if (err == -1)
Greg Clayton968fa382011-02-08 19:10:53 +0000600 error.SetErrorToErrno();
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000601#endif
Greg Clayton968fa382011-02-08 19:10:53 +0000602 }
603 else
604 {
605 error.SetErrorString("invalid file handle");
606 }
607 return error;
608}
Greg Clayton846b64b2011-02-08 19:54:44 +0000609
Greg Clayton29aac9a2015-04-09 00:06:44 +0000610#if defined (__APPLE__)
611// Darwin kernels only can read/write <= INT_MAX bytes
612#define MAX_READ_SIZE INT_MAX
613#define MAX_WRITE_SIZE INT_MAX
614#endif
615
Greg Clayton504f89a2011-02-08 17:49:02 +0000616Error
617File::Read (void *buf, size_t &num_bytes)
618{
619 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000620
621#if defined (MAX_READ_SIZE)
622 if (num_bytes > MAX_READ_SIZE)
623 {
624 uint8_t *p = (uint8_t *)buf;
625 size_t bytes_left = num_bytes;
626 // Init the num_bytes read to zero
627 num_bytes = 0;
628
629 while (bytes_left > 0)
630 {
631 size_t curr_num_bytes;
632 if (bytes_left > MAX_READ_SIZE)
633 curr_num_bytes = MAX_READ_SIZE;
634 else
635 curr_num_bytes = bytes_left;
636
637 error = Read (p + num_bytes, curr_num_bytes);
638
639 // Update how many bytes were read
640 num_bytes += curr_num_bytes;
641 if (bytes_left < curr_num_bytes)
642 bytes_left = 0;
643 else
644 bytes_left -= curr_num_bytes;
645
646 if (error.Fail())
647 break;
648 }
649 return error;
650 }
651#endif
652
Greg Clayton96c09682012-01-04 22:56:43 +0000653 ssize_t bytes_read = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000654 if (DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000655 {
Greg Clayton96c09682012-01-04 22:56:43 +0000656 do
657 {
658 bytes_read = ::read (m_descriptor, buf, num_bytes);
659 } while (bytes_read < 0 && errno == EINTR);
660
Greg Clayton504f89a2011-02-08 17:49:02 +0000661 if (bytes_read == -1)
662 {
663 error.SetErrorToErrno();
664 num_bytes = 0;
665 }
666 else
667 num_bytes = bytes_read;
668 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000669 else if (StreamIsValid())
670 {
Greg Clayton96c09682012-01-04 22:56:43 +0000671 bytes_read = ::fread (buf, 1, num_bytes, m_stream);
672
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000673 if (bytes_read == 0)
674 {
675 if (::feof(m_stream))
676 error.SetErrorString ("feof");
677 else if (::ferror (m_stream))
678 error.SetErrorString ("ferror");
679 num_bytes = 0;
680 }
681 else
682 num_bytes = bytes_read;
683 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000684 else
685 {
686 num_bytes = 0;
687 error.SetErrorString("invalid file handle");
688 }
689 return error;
690}
691
692Error
693File::Write (const void *buf, size_t &num_bytes)
694{
695 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000696
697#if defined (MAX_WRITE_SIZE)
698 if (num_bytes > MAX_WRITE_SIZE)
699 {
700 const uint8_t *p = (const uint8_t *)buf;
701 size_t bytes_left = num_bytes;
702 // Init the num_bytes written to zero
703 num_bytes = 0;
704
705 while (bytes_left > 0)
706 {
707 size_t curr_num_bytes;
708 if (bytes_left > MAX_WRITE_SIZE)
709 curr_num_bytes = MAX_WRITE_SIZE;
710 else
711 curr_num_bytes = bytes_left;
712
713 error = Write (p + num_bytes, curr_num_bytes);
714
715 // Update how many bytes were read
716 num_bytes += curr_num_bytes;
717 if (bytes_left < curr_num_bytes)
718 bytes_left = 0;
719 else
720 bytes_left -= curr_num_bytes;
721
722 if (error.Fail())
723 break;
724 }
725 return error;
726 }
727#endif
728
Greg Clayton96c09682012-01-04 22:56:43 +0000729 ssize_t bytes_written = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000730 if (DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000731 {
Greg Clayton96c09682012-01-04 22:56:43 +0000732 do
733 {
734 bytes_written = ::write (m_descriptor, buf, num_bytes);
735 } while (bytes_written < 0 && errno == EINTR);
736
Greg Clayton504f89a2011-02-08 17:49:02 +0000737 if (bytes_written == -1)
738 {
739 error.SetErrorToErrno();
740 num_bytes = 0;
741 }
742 else
743 num_bytes = bytes_written;
744 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000745 else if (StreamIsValid())
746 {
Greg Clayton96c09682012-01-04 22:56:43 +0000747 bytes_written = ::fwrite (buf, 1, num_bytes, m_stream);
748
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000749 if (bytes_written == 0)
750 {
751 if (::feof(m_stream))
752 error.SetErrorString ("feof");
753 else if (::ferror (m_stream))
754 error.SetErrorString ("ferror");
755 num_bytes = 0;
756 }
757 else
758 num_bytes = bytes_written;
759
760 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000761 else
762 {
763 num_bytes = 0;
764 error.SetErrorString("invalid file handle");
765 }
Zachary Turner98688922014-08-06 18:16:26 +0000766
Greg Clayton504f89a2011-02-08 17:49:02 +0000767 return error;
768}
769
Greg Clayton846b64b2011-02-08 19:54:44 +0000770
771Error
772File::Read (void *buf, size_t &num_bytes, off_t &offset)
773{
774 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000775
776#if defined (MAX_READ_SIZE)
777 if (num_bytes > MAX_READ_SIZE)
778 {
779 uint8_t *p = (uint8_t *)buf;
780 size_t bytes_left = num_bytes;
781 // Init the num_bytes read to zero
782 num_bytes = 0;
783
784 while (bytes_left > 0)
785 {
786 size_t curr_num_bytes;
787 if (bytes_left > MAX_READ_SIZE)
788 curr_num_bytes = MAX_READ_SIZE;
789 else
790 curr_num_bytes = bytes_left;
791
792 error = Read (p + num_bytes, curr_num_bytes, offset);
793
794 // Update how many bytes were read
795 num_bytes += curr_num_bytes;
796 if (bytes_left < curr_num_bytes)
797 bytes_left = 0;
798 else
799 bytes_left -= curr_num_bytes;
800
801 if (error.Fail())
802 break;
803 }
804 return error;
805 }
806#endif
807
808#ifndef _WIN32
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000809 int fd = GetDescriptor();
810 if (fd != kInvalidDescriptor)
Greg Clayton846b64b2011-02-08 19:54:44 +0000811 {
Greg Clayton96c09682012-01-04 22:56:43 +0000812 ssize_t bytes_read = -1;
813 do
814 {
815 bytes_read = ::pread (fd, buf, num_bytes, offset);
816 } while (bytes_read < 0 && errno == EINTR);
817
Greg Clayton846b64b2011-02-08 19:54:44 +0000818 if (bytes_read < 0)
819 {
820 num_bytes = 0;
821 error.SetErrorToErrno();
822 }
823 else
824 {
825 offset += bytes_read;
826 num_bytes = bytes_read;
827 }
828 }
829 else
830 {
831 num_bytes = 0;
832 error.SetErrorString("invalid file handle");
833 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000834#else
835 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
836 SeekFromStart(offset);
Greg Clayton29aac9a2015-04-09 00:06:44 +0000837 error = Read(buf, num_bytes);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000838 if (!error.Fail())
839 SeekFromStart(cur);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000840#endif
Greg Clayton29aac9a2015-04-09 00:06:44 +0000841 return error;
Greg Clayton846b64b2011-02-08 19:54:44 +0000842}
843
844Error
Greg Clayton0b0b5122012-08-30 18:15:10 +0000845File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
Greg Clayton96c09682012-01-04 22:56:43 +0000846{
847 Error error;
848
849 if (num_bytes > 0)
850 {
851 int fd = GetDescriptor();
852 if (fd != kInvalidDescriptor)
853 {
854 struct stat file_stats;
855 if (::fstat (fd, &file_stats) == 0)
856 {
857 if (file_stats.st_size > offset)
858 {
859 const size_t bytes_left = file_stats.st_size - offset;
860 if (num_bytes > bytes_left)
861 num_bytes = bytes_left;
862
Jason Molenda03176d72015-01-22 00:41:05 +0000863 size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
Greg Clayton7b0992d2013-04-18 22:45:39 +0000864 std::unique_ptr<DataBufferHeap> data_heap_ap;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000865 data_heap_ap.reset(new DataBufferHeap());
866 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
Greg Clayton96c09682012-01-04 22:56:43 +0000867
868 if (data_heap_ap.get())
869 {
870 error = Read (data_heap_ap->GetBytes(), num_bytes, offset);
871 if (error.Success())
872 {
873 // Make sure we read exactly what we asked for and if we got
874 // less, adjust the array
Jason Molenda03176d72015-01-22 00:41:05 +0000875 if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize())
876 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
Greg Clayton96c09682012-01-04 22:56:43 +0000877 data_buffer_sp.reset(data_heap_ap.release());
878 return error;
879 }
880 }
881 }
882 else
883 error.SetErrorString("file is empty");
884 }
885 else
886 error.SetErrorToErrno();
887 }
888 else
889 error.SetErrorString("invalid file handle");
890 }
891 else
892 error.SetErrorString("invalid file handle");
893
894 num_bytes = 0;
895 data_buffer_sp.reset();
896 return error;
897}
898
899Error
Greg Clayton846b64b2011-02-08 19:54:44 +0000900File::Write (const void *buf, size_t &num_bytes, off_t &offset)
901{
Greg Clayton7965e542015-04-09 00:12:33 +0000902 Error error;
903
Greg Clayton29aac9a2015-04-09 00:06:44 +0000904#if defined (MAX_WRITE_SIZE)
905 if (num_bytes > MAX_WRITE_SIZE)
906 {
907 const uint8_t *p = (const uint8_t *)buf;
908 size_t bytes_left = num_bytes;
909 // Init the num_bytes written to zero
910 num_bytes = 0;
911
912 while (bytes_left > 0)
913 {
914 size_t curr_num_bytes;
915 if (bytes_left > MAX_WRITE_SIZE)
916 curr_num_bytes = MAX_WRITE_SIZE;
917 else
918 curr_num_bytes = bytes_left;
919
920 error = Write (p + num_bytes, curr_num_bytes, offset);
921
922 // Update how many bytes were read
923 num_bytes += curr_num_bytes;
924 if (bytes_left < curr_num_bytes)
925 bytes_left = 0;
926 else
927 bytes_left -= curr_num_bytes;
928
929 if (error.Fail())
930 break;
931 }
932 return error;
933 }
934#endif
935
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000936 int fd = GetDescriptor();
937 if (fd != kInvalidDescriptor)
Greg Clayton846b64b2011-02-08 19:54:44 +0000938 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000939#ifndef _WIN32
Greg Clayton96c09682012-01-04 22:56:43 +0000940 ssize_t bytes_written = -1;
941 do
942 {
943 bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset);
944 } while (bytes_written < 0 && errno == EINTR);
945
Greg Clayton846b64b2011-02-08 19:54:44 +0000946 if (bytes_written < 0)
947 {
948 num_bytes = 0;
949 error.SetErrorToErrno();
950 }
951 else
952 {
953 offset += bytes_written;
954 num_bytes = bytes_written;
955 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000956#else
957 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
958 error = Write(buf, num_bytes);
959 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
960
961 if (!error.Fail())
962 SeekFromStart(cur);
963
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000964 offset = after;
965#endif
Greg Clayton846b64b2011-02-08 19:54:44 +0000966 }
967 else
968 {
969 num_bytes = 0;
970 error.SetErrorString("invalid file handle");
971 }
972 return error;
973}
974
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000975//------------------------------------------------------------------
976// Print some formatted output to the stream.
977//------------------------------------------------------------------
Greg Claytonc7bece562013-01-25 18:06:21 +0000978size_t
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000979File::Printf (const char *format, ...)
980{
981 va_list args;
982 va_start (args, format);
Greg Claytonc7bece562013-01-25 18:06:21 +0000983 size_t result = PrintfVarArg (format, args);
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000984 va_end (args);
985 return result;
986}
Greg Clayton846b64b2011-02-08 19:54:44 +0000987
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000988//------------------------------------------------------------------
989// Print some formatted output to the stream.
990//------------------------------------------------------------------
Greg Claytonc7bece562013-01-25 18:06:21 +0000991size_t
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000992File::PrintfVarArg (const char *format, va_list args)
993{
Greg Claytonc7bece562013-01-25 18:06:21 +0000994 size_t result = 0;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000995 if (DescriptorIsValid())
996 {
997 char *s = NULL;
998 result = vasprintf(&s, format, args);
999 if (s != NULL)
1000 {
1001 if (result > 0)
1002 {
1003 size_t s_len = result;
1004 Write (s, s_len);
1005 result = s_len;
1006 }
1007 free (s);
1008 }
1009 }
1010 else if (StreamIsValid())
1011 {
1012 result = ::vfprintf (m_stream, format, args);
1013 }
1014 return result;
1015}
Daniel Maleae0f8f572013-08-26 23:57:52 +00001016
1017mode_t
1018File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
1019{
1020 mode_t mode = 0;
1021 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
1022 mode |= O_RDWR;
1023 else if (open_options & eOpenOptionWrite)
1024 mode |= O_WRONLY;
1025
1026 if (open_options & eOpenOptionAppend)
1027 mode |= O_APPEND;
1028
1029 if (open_options & eOpenOptionTruncate)
1030 mode |= O_TRUNC;
1031
1032 if (open_options & eOpenOptionNonBlocking)
1033 mode |= O_NONBLOCK;
1034
1035 if (open_options & eOpenOptionCanCreateNewOnly)
1036 mode |= O_CREAT | O_EXCL;
1037 else if (open_options & eOpenOptionCanCreate)
1038 mode |= O_CREAT;
1039
1040 return mode;
1041}
Greg Clayton340b0302014-02-05 17:57:57 +00001042
1043void
1044File::CalculateInteractiveAndTerminal ()
1045{
1046 const int fd = GetDescriptor();
1047 if (fd >= 0)
1048 {
1049 m_is_interactive = eLazyBoolNo;
1050 m_is_real_terminal = eLazyBoolNo;
Shawn Best8da0bf32014-11-08 01:41:49 +00001051#if (defined(_WIN32) || defined(__ANDROID_NDK__))
Deepak Panickal6419e982014-03-03 15:53:37 +00001052 if (_isatty(fd))
1053 {
1054 m_is_interactive = eLazyBoolYes;
1055 m_is_real_terminal = eLazyBoolYes;
1056 }
1057#else
Greg Clayton340b0302014-02-05 17:57:57 +00001058 if (isatty(fd))
1059 {
1060 m_is_interactive = eLazyBoolYes;
1061 struct winsize window_size;
1062 if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
1063 {
1064 if (window_size.ws_col > 0)
Sean Callanan66810412015-10-19 23:11:07 +00001065 {
Greg Clayton340b0302014-02-05 17:57:57 +00001066 m_is_real_terminal = eLazyBoolYes;
Sean Callanan66810412015-10-19 23:11:07 +00001067 if (llvm::sys::Process::FileDescriptorHasColors(fd))
1068 m_supports_colors = eLazyBoolYes;
1069 }
Greg Clayton340b0302014-02-05 17:57:57 +00001070 }
1071 }
Deepak Panickal94667bc2014-02-17 17:43:39 +00001072#endif
Greg Clayton340b0302014-02-05 17:57:57 +00001073 }
1074}
1075
1076bool
1077File::GetIsInteractive ()
1078{
1079 if (m_is_interactive == eLazyBoolCalculate)
1080 CalculateInteractiveAndTerminal ();
1081 return m_is_interactive == eLazyBoolYes;
1082}
1083
1084bool
1085File::GetIsRealTerminal ()
1086{
1087 if (m_is_real_terminal == eLazyBoolCalculate)
1088 CalculateInteractiveAndTerminal();
1089 return m_is_real_terminal == eLazyBoolYes;
1090}
1091
Sean Callanan66810412015-10-19 23:11:07 +00001092bool
1093File::GetIsTerminalWithColors ()
1094{
1095 if (m_supports_colors == eLazyBoolCalculate)
1096 CalculateInteractiveAndTerminal();
1097 return m_supports_colors == eLazyBoolYes;
1098}
1099