blob: fd0454bb1fc32ff08a381132f82982d4dee637a2 [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>
Zachary Turner5821a3b2017-03-20 23:55:20 +000022#include <sys/stat.h>
Pavel Labathb8ad0152017-01-24 14:05:23 +000023#include <termios.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000024#endif
25
Zachary Turner190fadc2016-03-22 17:58:09 +000026#include "llvm/Support/ConvertUTF.h"
Zachary Turner07db3f72017-03-21 05:47:57 +000027#include "llvm/Support/FileSystem.h"
Sean Callanan66810412015-10-19 23:11:07 +000028#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()
29
Greg Clayton925137c2011-02-09 01:16:43 +000030#include "lldb/Host/Config.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000031#include "lldb/Utility/DataBufferHeap.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000032#include "lldb/Utility/Error.h"
Zachary Turner5713a052017-03-22 18:40:07 +000033#include "lldb/Utility/FileSpec.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000034#include "lldb/Utility/Log.h"
Greg Clayton504f89a2011-02-08 17:49:02 +000035
36using namespace lldb;
37using namespace lldb_private;
38
Kate Stoneb9c1b512016-09-06 20:57:50 +000039static const char *GetStreamOpenModeFromOptions(uint32_t options) {
40 if (options & File::eOpenOptionAppend) {
41 if (options & File::eOpenOptionRead) {
42 if (options & File::eOpenOptionCanCreateNewOnly)
43 return "a+x";
44 else
45 return "a+";
46 } else if (options & File::eOpenOptionWrite) {
47 if (options & File::eOpenOptionCanCreateNewOnly)
48 return "ax";
49 else
50 return "a";
Greg Clayton51b1e2d2011-02-09 01:08:52 +000051 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 } else if (options & File::eOpenOptionRead &&
53 options & File::eOpenOptionWrite) {
54 if (options & File::eOpenOptionCanCreate) {
55 if (options & File::eOpenOptionCanCreateNewOnly)
56 return "w+x";
57 else
58 return "w+";
59 } else
60 return "r+";
61 } else if (options & File::eOpenOptionRead) {
62 return "r";
63 } else if (options & File::eOpenOptionWrite) {
64 return "w";
65 }
66 return NULL;
Greg Clayton51b1e2d2011-02-09 01:08:52 +000067}
68
69int File::kInvalidDescriptor = -1;
Kate Stoneb9c1b512016-09-06 20:57:50 +000070FILE *File::kInvalidStream = NULL;
Greg Clayton51b1e2d2011-02-09 01:08:52 +000071
Kate Stoneb9c1b512016-09-06 20:57:50 +000072File::File(const char *path, uint32_t options, uint32_t permissions)
73 : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
74 m_stream(kInvalidStream), m_options(), m_own_stream(false),
75 m_is_interactive(eLazyBoolCalculate),
76 m_is_real_terminal(eLazyBoolCalculate) {
77 Open(path, options, permissions);
Greg Clayton504f89a2011-02-08 17:49:02 +000078}
79
Kate Stoneb9c1b512016-09-06 20:57:50 +000080File::File(const FileSpec &filespec, uint32_t options, uint32_t permissions)
81 : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
82 m_stream(kInvalidStream), m_options(0), m_own_stream(false),
83 m_is_interactive(eLazyBoolCalculate),
84 m_is_real_terminal(eLazyBoolCalculate)
Greg Clayton340b0302014-02-05 17:57:57 +000085
Daniel Maleae0f8f572013-08-26 23:57:52 +000086{
Kate Stoneb9c1b512016-09-06 20:57:50 +000087 if (filespec) {
88 Open(filespec.GetPath().c_str(), options, permissions);
89 }
Daniel Maleae0f8f572013-08-26 23:57:52 +000090}
91
Kate Stoneb9c1b512016-09-06 20:57:50 +000092File::~File() { Close(); }
Greg Clayton504f89a2011-02-08 17:49:02 +000093
Kate Stoneb9c1b512016-09-06 20:57:50 +000094int File::GetDescriptor() const {
95 if (DescriptorIsValid())
Zachary Turner98688922014-08-06 18:16:26 +000096 return m_descriptor;
Zachary Turner98688922014-08-06 18:16:26 +000097
Kate Stoneb9c1b512016-09-06 20:57:50 +000098 // Don't open the file descriptor if we don't need to, just get it from the
99 // stream if we have one.
100 if (StreamIsValid()) {
101#if defined(LLVM_ON_WIN32)
102 return _fileno(m_stream);
Greg Clayton44d93782014-01-27 23:43:24 +0000103#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 return fileno(m_stream);
Greg Clayton44d93782014-01-27 23:43:24 +0000105#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106 }
Greg Clayton44d93782014-01-27 23:43:24 +0000107
Kate Stoneb9c1b512016-09-06 20:57:50 +0000108 // Invalid descriptor and invalid stream, return invalid descriptor.
109 return kInvalidDescriptor;
110}
Greg Clayton44d93782014-01-27 23:43:24 +0000111
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112IOObject::WaitableHandle File::GetWaitableHandle() { return m_descriptor; }
Greg Clayton44d93782014-01-27 23:43:24 +0000113
Kate Stoneb9c1b512016-09-06 20:57:50 +0000114void File::SetDescriptor(int fd, bool transfer_ownership) {
115 if (IsValid())
116 Close();
117 m_descriptor = fd;
118 m_should_close_fd = transfer_ownership;
119}
120
121FILE *File::GetStream() {
122 if (!StreamIsValid()) {
123 if (DescriptorIsValid()) {
124 const char *mode = GetStreamOpenModeFromOptions(m_options);
125 if (mode) {
126 if (!m_should_close_fd) {
127// We must duplicate the file descriptor if we don't own it because
128// when you call fdopen, the stream will own the fd
129#ifdef _WIN32
130 m_descriptor = ::_dup(GetDescriptor());
131#else
132 m_descriptor = dup(GetDescriptor());
133#endif
134 m_should_close_fd = true;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000135 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000136
137 do {
138 m_stream = ::fdopen(m_descriptor, mode);
139 } while (m_stream == NULL && errno == EINTR);
140
141 // If we got a stream, then we own the stream and should no
142 // longer own the descriptor because fclose() will close it for us
143
144 if (m_stream) {
145 m_own_stream = true;
146 m_should_close_fd = false;
147 }
148 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000149 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000150 }
151 return m_stream;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000152}
153
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154void File::SetStream(FILE *fh, bool transfer_ownership) {
155 if (IsValid())
156 Close();
157 m_stream = fh;
158 m_own_stream = transfer_ownership;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000159}
160
Kate Stoneb9c1b512016-09-06 20:57:50 +0000161Error File::Open(const char *path, uint32_t options, uint32_t permissions) {
162 Error error;
163 if (IsValid())
164 Close();
Greg Clayton504f89a2011-02-08 17:49:02 +0000165
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166 int oflag = 0;
167 const bool read = options & eOpenOptionRead;
168 const bool write = options & eOpenOptionWrite;
169 if (write) {
170 if (read)
171 oflag |= O_RDWR;
172 else
173 oflag |= O_WRONLY;
Greg Clayton96c09682012-01-04 22:56:43 +0000174
Kate Stoneb9c1b512016-09-06 20:57:50 +0000175 if (options & eOpenOptionAppend)
176 oflag |= O_APPEND;
Greg Clayton96c09682012-01-04 22:56:43 +0000177
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178 if (options & eOpenOptionTruncate)
179 oflag |= O_TRUNC;
180
181 if (options & eOpenOptionCanCreate)
182 oflag |= O_CREAT;
183
184 if (options & eOpenOptionCanCreateNewOnly)
185 oflag |= O_CREAT | O_EXCL;
186 } else if (read) {
187 oflag |= O_RDONLY;
Greg Claytonfbb76342013-11-20 21:07:01 +0000188
Colin Riley909bb7a2013-11-26 15:10:46 +0000189#ifndef _WIN32
Kate Stoneb9c1b512016-09-06 20:57:50 +0000190 if (options & eOpenOptionDontFollowSymlinks)
191 oflag |= O_NOFOLLOW;
Colin Riley909bb7a2013-11-26 15:10:46 +0000192#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000193 }
194
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000195#ifndef _WIN32
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 if (options & eOpenOptionNonBlocking)
197 oflag |= O_NONBLOCK;
198 if (options & eOpenOptionCloseOnExec)
199 oflag |= O_CLOEXEC;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000200#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000201 oflag |= O_BINARY;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000202#endif
Greg Clayton504f89a2011-02-08 17:49:02 +0000203
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204 mode_t mode = 0;
205 if (oflag & O_CREAT) {
206 if (permissions & lldb::eFilePermissionsUserRead)
207 mode |= S_IRUSR;
208 if (permissions & lldb::eFilePermissionsUserWrite)
209 mode |= S_IWUSR;
210 if (permissions & lldb::eFilePermissionsUserExecute)
211 mode |= S_IXUSR;
212 if (permissions & lldb::eFilePermissionsGroupRead)
213 mode |= S_IRGRP;
214 if (permissions & lldb::eFilePermissionsGroupWrite)
215 mode |= S_IWGRP;
216 if (permissions & lldb::eFilePermissionsGroupExecute)
217 mode |= S_IXGRP;
218 if (permissions & lldb::eFilePermissionsWorldRead)
219 mode |= S_IROTH;
220 if (permissions & lldb::eFilePermissionsWorldWrite)
221 mode |= S_IWOTH;
222 if (permissions & lldb::eFilePermissionsWorldExecute)
223 mode |= S_IXOTH;
224 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000225
Kate Stoneb9c1b512016-09-06 20:57:50 +0000226 do {
Hafiz Abid Qadeerf6ee79c2016-12-15 15:00:41 +0000227#ifdef _MSC_VER
Kate Stoneb9c1b512016-09-06 20:57:50 +0000228 std::wstring wpath;
229 if (!llvm::ConvertUTF8toWide(path, wpath)) {
230 m_descriptor = -1;
231 error.SetErrorString("Error converting path to UTF-16");
232 return error;
233 }
234 ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode);
Zachary Turner190fadc2016-03-22 17:58:09 +0000235#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000236 m_descriptor = ::open(path, oflag, mode);
Zachary Turner190fadc2016-03-22 17:58:09 +0000237#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000238 } while (m_descriptor < 0 && errno == EINTR);
Greg Clayton96c09682012-01-04 22:56:43 +0000239
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240 if (!DescriptorIsValid())
241 error.SetErrorToErrno();
242 else {
243 m_should_close_fd = true;
244 m_options = options;
245 }
246
247 return error;
Greg Clayton504f89a2011-02-08 17:49:02 +0000248}
249
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250uint32_t File::GetPermissions(const FileSpec &file_spec, Error &error) {
251 if (file_spec) {
Zachary Turner07db3f72017-03-21 05:47:57 +0000252 error.Clear();
253 auto Perms = llvm::sys::fs::getPermissions(file_spec.GetPath());
254 if (Perms)
255 return *Perms;
256 error = Error(Perms.getError());
257 return 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258 } else
259 error.SetErrorString("empty file spec");
260 return 0;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000261}
262
Kate Stoneb9c1b512016-09-06 20:57:50 +0000263uint32_t File::GetPermissions(Error &error) const {
264 int fd = GetDescriptor();
265 if (fd != kInvalidDescriptor) {
266 struct stat file_stats;
267 if (::fstat(fd, &file_stats) == -1)
268 error.SetErrorToErrno();
269 else {
270 error.Clear();
271 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000272 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000273 } else {
274 error.SetErrorString("invalid file descriptor");
275 }
276 return 0;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000277}
278
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279Error File::Close() {
280 Error error;
281 if (StreamIsValid() && m_own_stream) {
282 if (::fclose(m_stream) == EOF)
283 error.SetErrorToErrno();
284 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000285
Kate Stoneb9c1b512016-09-06 20:57:50 +0000286 if (DescriptorIsValid() && m_should_close_fd) {
287 if (::close(m_descriptor) != 0)
288 error.SetErrorToErrno();
289 }
290 m_descriptor = kInvalidDescriptor;
291 m_stream = kInvalidStream;
292 m_options = 0;
293 m_own_stream = false;
294 m_should_close_fd = false;
295 m_is_interactive = eLazyBoolCalculate;
296 m_is_real_terminal = eLazyBoolCalculate;
297 return error;
Greg Clayton504f89a2011-02-08 17:49:02 +0000298}
Greg Clayton968fa382011-02-08 19:10:53 +0000299
Kate Stoneb9c1b512016-09-06 20:57:50 +0000300void File::Clear() {
301 m_stream = nullptr;
302 m_descriptor = -1;
303 m_options = 0;
304 m_own_stream = false;
305 m_is_interactive = m_supports_colors = m_is_real_terminal =
306 eLazyBoolCalculate;
Enrico Granata744959b2016-01-13 18:11:45 +0000307}
Greg Clayton968fa382011-02-08 19:10:53 +0000308
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309Error File::GetFileSpec(FileSpec &file_spec) const {
310 Error error;
Greg Clayton925137c2011-02-09 01:16:43 +0000311#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
Kate Stoneb9c1b512016-09-06 20:57:50 +0000312 if (IsValid()) {
Greg Clayton94d08622011-02-09 07:19:18 +0000313 char path[PATH_MAX];
Kate Stoneb9c1b512016-09-06 20:57:50 +0000314 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
315 error.SetErrorToErrno();
Greg Clayton94d08622011-02-09 07:19:18 +0000316 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000317 file_spec.SetFile(path, false);
318 } else {
319 error.SetErrorString("invalid file handle");
320 }
321#elif defined(__linux__)
322 char proc[64];
323 char path[PATH_MAX];
324 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
325 error.SetErrorString("cannot resolve file descriptor");
326 else {
327 ssize_t len;
328 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
329 error.SetErrorToErrno();
330 else {
331 path[len] = '\0';
332 file_spec.SetFile(path, false);
Greg Clayton94d08622011-02-09 07:19:18 +0000333 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000334 }
Greg Clayton925137c2011-02-09 01:16:43 +0000335#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000336 error.SetErrorString("File::GetFileSpec is not supported on this platform");
Greg Clayton925137c2011-02-09 01:16:43 +0000337#endif
Greg Clayton968fa382011-02-08 19:10:53 +0000338
Kate Stoneb9c1b512016-09-06 20:57:50 +0000339 if (error.Fail())
340 file_spec.Clear();
341 return error;
Greg Clayton968fa382011-02-08 19:10:53 +0000342}
343
Kate Stoneb9c1b512016-09-06 20:57:50 +0000344off_t File::SeekFromStart(off_t offset, Error *error_ptr) {
345 off_t result = 0;
346 if (DescriptorIsValid()) {
347 result = ::lseek(m_descriptor, offset, SEEK_SET);
Greg Clayton968fa382011-02-08 19:10:53 +0000348
Kate Stoneb9c1b512016-09-06 20:57:50 +0000349 if (error_ptr) {
350 if (result == -1)
351 error_ptr->SetErrorToErrno();
352 else
353 error_ptr->Clear();
Greg Clayton968fa382011-02-08 19:10:53 +0000354 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000355 } else if (StreamIsValid()) {
356 result = ::fseek(m_stream, offset, SEEK_SET);
357
358 if (error_ptr) {
359 if (result == -1)
360 error_ptr->SetErrorToErrno();
361 else
362 error_ptr->Clear();
Greg Clayton968fa382011-02-08 19:10:53 +0000363 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000364 } else if (error_ptr) {
365 error_ptr->SetErrorString("invalid file handle");
366 }
367 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000368}
369
Kate Stoneb9c1b512016-09-06 20:57:50 +0000370off_t File::SeekFromCurrent(off_t offset, Error *error_ptr) {
371 off_t result = -1;
372 if (DescriptorIsValid()) {
373 result = ::lseek(m_descriptor, offset, SEEK_CUR);
374
375 if (error_ptr) {
376 if (result == -1)
377 error_ptr->SetErrorToErrno();
378 else
379 error_ptr->Clear();
Greg Clayton968fa382011-02-08 19:10:53 +0000380 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000381 } else if (StreamIsValid()) {
382 result = ::fseek(m_stream, offset, SEEK_CUR);
383
384 if (error_ptr) {
385 if (result == -1)
386 error_ptr->SetErrorToErrno();
387 else
388 error_ptr->Clear();
Greg Clayton968fa382011-02-08 19:10:53 +0000389 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000390 } else if (error_ptr) {
391 error_ptr->SetErrorString("invalid file handle");
392 }
393 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000394}
395
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396off_t File::SeekFromEnd(off_t offset, Error *error_ptr) {
397 off_t result = -1;
398 if (DescriptorIsValid()) {
399 result = ::lseek(m_descriptor, offset, SEEK_END);
400
401 if (error_ptr) {
402 if (result == -1)
403 error_ptr->SetErrorToErrno();
404 else
405 error_ptr->Clear();
Greg Clayton968fa382011-02-08 19:10:53 +0000406 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000407 } else if (StreamIsValid()) {
408 result = ::fseek(m_stream, offset, SEEK_END);
409
410 if (error_ptr) {
411 if (result == -1)
412 error_ptr->SetErrorToErrno();
413 else
414 error_ptr->Clear();
Greg Clayton968fa382011-02-08 19:10:53 +0000415 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000416 } else if (error_ptr) {
417 error_ptr->SetErrorString("invalid file handle");
418 }
419 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000420}
421
Kate Stoneb9c1b512016-09-06 20:57:50 +0000422Error File::Flush() {
423 Error error;
424 if (StreamIsValid()) {
425 int err = 0;
426 do {
427 err = ::fflush(m_stream);
428 } while (err == EOF && errno == EINTR);
429
430 if (err == EOF)
431 error.SetErrorToErrno();
432 } else if (!DescriptorIsValid()) {
433 error.SetErrorString("invalid file handle");
434 }
435 return error;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000436}
437
Kate Stoneb9c1b512016-09-06 20:57:50 +0000438Error File::Sync() {
439 Error error;
440 if (DescriptorIsValid()) {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000441#ifdef _WIN32
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
443 if (err == 0)
444 error.SetErrorToGenericError();
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000445#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446 int err = 0;
447 do {
448 err = ::fsync(m_descriptor);
449 } while (err == -1 && errno == EINTR);
450
451 if (err == -1)
452 error.SetErrorToErrno();
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000453#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000454 } else {
455 error.SetErrorString("invalid file handle");
456 }
457 return error;
Greg Clayton968fa382011-02-08 19:10:53 +0000458}
Greg Clayton846b64b2011-02-08 19:54:44 +0000459
Kate Stoneb9c1b512016-09-06 20:57:50 +0000460#if defined(__APPLE__)
Greg Clayton29aac9a2015-04-09 00:06:44 +0000461// Darwin kernels only can read/write <= INT_MAX bytes
462#define MAX_READ_SIZE INT_MAX
463#define MAX_WRITE_SIZE INT_MAX
464#endif
465
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466Error File::Read(void *buf, size_t &num_bytes) {
467 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000468
Kate Stoneb9c1b512016-09-06 20:57:50 +0000469#if defined(MAX_READ_SIZE)
470 if (num_bytes > MAX_READ_SIZE) {
471 uint8_t *p = (uint8_t *)buf;
472 size_t bytes_left = num_bytes;
473 // Init the num_bytes read to zero
474 num_bytes = 0;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000475
Kate Stoneb9c1b512016-09-06 20:57:50 +0000476 while (bytes_left > 0) {
477 size_t curr_num_bytes;
478 if (bytes_left > MAX_READ_SIZE)
479 curr_num_bytes = MAX_READ_SIZE;
480 else
481 curr_num_bytes = bytes_left;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000482
Kate Stoneb9c1b512016-09-06 20:57:50 +0000483 error = Read(p + num_bytes, curr_num_bytes);
Greg Clayton29aac9a2015-04-09 00:06:44 +0000484
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485 // Update how many bytes were read
486 num_bytes += curr_num_bytes;
487 if (bytes_left < curr_num_bytes)
488 bytes_left = 0;
489 else
490 bytes_left -= curr_num_bytes;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000491
Kate Stoneb9c1b512016-09-06 20:57:50 +0000492 if (error.Fail())
493 break;
Greg Clayton504f89a2011-02-08 17:49:02 +0000494 }
495 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000496 }
Greg Clayton29aac9a2015-04-09 00:06:44 +0000497#endif
498
Kate Stoneb9c1b512016-09-06 20:57:50 +0000499 ssize_t bytes_read = -1;
500 if (DescriptorIsValid()) {
501 do {
502 bytes_read = ::read(m_descriptor, buf, num_bytes);
503 } while (bytes_read < 0 && errno == EINTR);
Greg Clayton96c09682012-01-04 22:56:43 +0000504
Kate Stoneb9c1b512016-09-06 20:57:50 +0000505 if (bytes_read == -1) {
506 error.SetErrorToErrno();
507 num_bytes = 0;
508 } else
509 num_bytes = bytes_read;
510 } else if (StreamIsValid()) {
511 bytes_read = ::fread(buf, 1, num_bytes, m_stream);
Greg Clayton96c09682012-01-04 22:56:43 +0000512
Kate Stoneb9c1b512016-09-06 20:57:50 +0000513 if (bytes_read == 0) {
514 if (::feof(m_stream))
515 error.SetErrorString("feof");
516 else if (::ferror(m_stream))
517 error.SetErrorString("ferror");
518 num_bytes = 0;
519 } else
520 num_bytes = bytes_read;
521 } else {
522 num_bytes = 0;
523 error.SetErrorString("invalid file handle");
524 }
525 return error;
Greg Clayton504f89a2011-02-08 17:49:02 +0000526}
527
Kate Stoneb9c1b512016-09-06 20:57:50 +0000528Error File::Write(const void *buf, size_t &num_bytes) {
529 Error error;
Greg Clayton846b64b2011-02-08 19:54:44 +0000530
Kate Stoneb9c1b512016-09-06 20:57:50 +0000531#if defined(MAX_WRITE_SIZE)
532 if (num_bytes > MAX_WRITE_SIZE) {
533 const uint8_t *p = (const uint8_t *)buf;
534 size_t bytes_left = num_bytes;
535 // Init the num_bytes written to zero
536 num_bytes = 0;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000537
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538 while (bytes_left > 0) {
539 size_t curr_num_bytes;
540 if (bytes_left > MAX_WRITE_SIZE)
541 curr_num_bytes = MAX_WRITE_SIZE;
542 else
543 curr_num_bytes = bytes_left;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000544
Kate Stoneb9c1b512016-09-06 20:57:50 +0000545 error = Write(p + num_bytes, curr_num_bytes);
Greg Clayton29aac9a2015-04-09 00:06:44 +0000546
Kate Stoneb9c1b512016-09-06 20:57:50 +0000547 // Update how many bytes were read
548 num_bytes += curr_num_bytes;
549 if (bytes_left < curr_num_bytes)
550 bytes_left = 0;
551 else
552 bytes_left -= curr_num_bytes;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000553
Kate Stoneb9c1b512016-09-06 20:57:50 +0000554 if (error.Fail())
555 break;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000556 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000557 return error;
558 }
559#endif
560
561 ssize_t bytes_written = -1;
562 if (DescriptorIsValid()) {
563 do {
564 bytes_written = ::write(m_descriptor, buf, num_bytes);
565 } while (bytes_written < 0 && errno == EINTR);
566
567 if (bytes_written == -1) {
568 error.SetErrorToErrno();
569 num_bytes = 0;
570 } else
571 num_bytes = bytes_written;
572 } else if (StreamIsValid()) {
573 bytes_written = ::fwrite(buf, 1, num_bytes, m_stream);
574
575 if (bytes_written == 0) {
576 if (::feof(m_stream))
577 error.SetErrorString("feof");
578 else if (::ferror(m_stream))
579 error.SetErrorString("ferror");
580 num_bytes = 0;
581 } else
582 num_bytes = bytes_written;
583
584 } else {
585 num_bytes = 0;
586 error.SetErrorString("invalid file handle");
587 }
588
589 return error;
590}
591
592Error File::Read(void *buf, size_t &num_bytes, off_t &offset) {
593 Error error;
594
595#if defined(MAX_READ_SIZE)
596 if (num_bytes > MAX_READ_SIZE) {
597 uint8_t *p = (uint8_t *)buf;
598 size_t bytes_left = num_bytes;
599 // Init the num_bytes read to zero
600 num_bytes = 0;
601
602 while (bytes_left > 0) {
603 size_t curr_num_bytes;
604 if (bytes_left > MAX_READ_SIZE)
605 curr_num_bytes = MAX_READ_SIZE;
606 else
607 curr_num_bytes = bytes_left;
608
609 error = Read(p + num_bytes, curr_num_bytes, offset);
610
611 // Update how many bytes were read
612 num_bytes += curr_num_bytes;
613 if (bytes_left < curr_num_bytes)
614 bytes_left = 0;
615 else
616 bytes_left -= curr_num_bytes;
617
618 if (error.Fail())
619 break;
620 }
621 return error;
622 }
Greg Clayton29aac9a2015-04-09 00:06:44 +0000623#endif
624
625#ifndef _WIN32
Kate Stoneb9c1b512016-09-06 20:57:50 +0000626 int fd = GetDescriptor();
627 if (fd != kInvalidDescriptor) {
628 ssize_t bytes_read = -1;
629 do {
630 bytes_read = ::pread(fd, buf, num_bytes, offset);
631 } while (bytes_read < 0 && errno == EINTR);
Greg Clayton96c09682012-01-04 22:56:43 +0000632
Kate Stoneb9c1b512016-09-06 20:57:50 +0000633 if (bytes_read < 0) {
634 num_bytes = 0;
635 error.SetErrorToErrno();
636 } else {
637 offset += bytes_read;
638 num_bytes = bytes_read;
Greg Clayton846b64b2011-02-08 19:54:44 +0000639 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000640 } else {
641 num_bytes = 0;
642 error.SetErrorString("invalid file handle");
643 }
644#else
645 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
646 SeekFromStart(offset);
647 error = Read(buf, num_bytes);
648 if (!error.Fail())
649 SeekFromStart(cur);
650#endif
651 return error;
652}
653
654Error File::Read(size_t &num_bytes, off_t &offset, bool null_terminate,
655 DataBufferSP &data_buffer_sp) {
656 Error error;
657
658 if (num_bytes > 0) {
659 int fd = GetDescriptor();
660 if (fd != kInvalidDescriptor) {
661 struct stat file_stats;
662 if (::fstat(fd, &file_stats) == 0) {
663 if (file_stats.st_size > offset) {
664 const size_t bytes_left = file_stats.st_size - offset;
665 if (num_bytes > bytes_left)
666 num_bytes = bytes_left;
667
668 size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
669 std::unique_ptr<DataBufferHeap> data_heap_ap;
670 data_heap_ap.reset(new DataBufferHeap());
671 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
672
673 if (data_heap_ap.get()) {
674 error = Read(data_heap_ap->GetBytes(), num_bytes, offset);
675 if (error.Success()) {
676 // Make sure we read exactly what we asked for and if we got
677 // less, adjust the array
678 if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize())
679 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
680 data_buffer_sp.reset(data_heap_ap.release());
681 return error;
682 }
683 }
684 } else
685 error.SetErrorString("file is empty");
686 } else
687 error.SetErrorToErrno();
688 } else
689 error.SetErrorString("invalid file handle");
690 } else
691 error.SetErrorString("invalid file handle");
692
693 num_bytes = 0;
694 data_buffer_sp.reset();
695 return error;
696}
697
698Error File::Write(const void *buf, size_t &num_bytes, off_t &offset) {
699 Error error;
700
701#if defined(MAX_WRITE_SIZE)
702 if (num_bytes > MAX_WRITE_SIZE) {
703 const uint8_t *p = (const uint8_t *)buf;
704 size_t bytes_left = num_bytes;
705 // Init the num_bytes written to zero
706 num_bytes = 0;
707
708 while (bytes_left > 0) {
709 size_t curr_num_bytes;
710 if (bytes_left > MAX_WRITE_SIZE)
711 curr_num_bytes = MAX_WRITE_SIZE;
712 else
713 curr_num_bytes = bytes_left;
714
715 error = Write(p + num_bytes, curr_num_bytes, offset);
716
717 // Update how many bytes were read
718 num_bytes += curr_num_bytes;
719 if (bytes_left < curr_num_bytes)
720 bytes_left = 0;
721 else
722 bytes_left -= curr_num_bytes;
723
724 if (error.Fail())
725 break;
726 }
727 return error;
728 }
729#endif
730
731 int fd = GetDescriptor();
732 if (fd != kInvalidDescriptor) {
733#ifndef _WIN32
734 ssize_t bytes_written = -1;
735 do {
736 bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset);
737 } while (bytes_written < 0 && errno == EINTR);
738
739 if (bytes_written < 0) {
740 num_bytes = 0;
741 error.SetErrorToErrno();
742 } else {
743 offset += bytes_written;
744 num_bytes = bytes_written;
Greg Clayton846b64b2011-02-08 19:54:44 +0000745 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000746#else
747 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000748 error = Write(buf, num_bytes);
749 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
750
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000751 if (!error.Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +0000752 SeekFromStart(cur);
753
754 offset = after;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000755#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000756 } else {
Greg Clayton96c09682012-01-04 22:56:43 +0000757 num_bytes = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000758 error.SetErrorString("invalid file handle");
759 }
760 return error;
Greg Clayton846b64b2011-02-08 19:54:44 +0000761}
762
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000763//------------------------------------------------------------------
764// Print some formatted output to the stream.
765//------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000766size_t File::Printf(const char *format, ...) {
767 va_list args;
768 va_start(args, format);
769 size_t result = PrintfVarArg(format, args);
770 va_end(args);
771 return result;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000772}
Greg Clayton846b64b2011-02-08 19:54:44 +0000773
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000774//------------------------------------------------------------------
775// Print some formatted output to the stream.
776//------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000777size_t File::PrintfVarArg(const char *format, va_list args) {
778 size_t result = 0;
779 if (DescriptorIsValid()) {
780 char *s = NULL;
781 result = vasprintf(&s, format, args);
782 if (s != NULL) {
783 if (result > 0) {
784 size_t s_len = result;
785 Write(s, s_len);
786 result = s_len;
787 }
788 free(s);
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000789 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000790 } else if (StreamIsValid()) {
791 result = ::vfprintf(m_stream, format, args);
792 }
793 return result;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000794}
Daniel Maleae0f8f572013-08-26 23:57:52 +0000795
Kate Stoneb9c1b512016-09-06 20:57:50 +0000796mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) {
797 mode_t mode = 0;
798 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
799 mode |= O_RDWR;
800 else if (open_options & eOpenOptionWrite)
801 mode |= O_WRONLY;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000802
Kate Stoneb9c1b512016-09-06 20:57:50 +0000803 if (open_options & eOpenOptionAppend)
804 mode |= O_APPEND;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000805
Kate Stoneb9c1b512016-09-06 20:57:50 +0000806 if (open_options & eOpenOptionTruncate)
807 mode |= O_TRUNC;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000808
Kate Stoneb9c1b512016-09-06 20:57:50 +0000809 if (open_options & eOpenOptionNonBlocking)
810 mode |= O_NONBLOCK;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000811
Kate Stoneb9c1b512016-09-06 20:57:50 +0000812 if (open_options & eOpenOptionCanCreateNewOnly)
813 mode |= O_CREAT | O_EXCL;
814 else if (open_options & eOpenOptionCanCreate)
815 mode |= O_CREAT;
816
817 return mode;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000818}
Greg Clayton340b0302014-02-05 17:57:57 +0000819
Kate Stoneb9c1b512016-09-06 20:57:50 +0000820void File::CalculateInteractiveAndTerminal() {
821 const int fd = GetDescriptor();
822 if (fd >= 0) {
823 m_is_interactive = eLazyBoolNo;
824 m_is_real_terminal = eLazyBoolNo;
Pavel Labath6b734562016-08-08 12:26:57 +0000825#if defined(_WIN32)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000826 if (_isatty(fd)) {
827 m_is_interactive = eLazyBoolYes;
828 m_is_real_terminal = eLazyBoolYes;
Greg Clayton340b0302014-02-05 17:57:57 +0000829 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000830#else
831 if (isatty(fd)) {
832 m_is_interactive = eLazyBoolYes;
833 struct winsize window_size;
834 if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) {
835 if (window_size.ws_col > 0) {
836 m_is_real_terminal = eLazyBoolYes;
837 if (llvm::sys::Process::FileDescriptorHasColors(fd))
838 m_supports_colors = eLazyBoolYes;
839 }
840 }
841 }
842#endif
843 }
Greg Clayton340b0302014-02-05 17:57:57 +0000844}
845
Kate Stoneb9c1b512016-09-06 20:57:50 +0000846bool File::GetIsInteractive() {
847 if (m_is_interactive == eLazyBoolCalculate)
848 CalculateInteractiveAndTerminal();
849 return m_is_interactive == eLazyBoolYes;
Greg Clayton340b0302014-02-05 17:57:57 +0000850}
851
Kate Stoneb9c1b512016-09-06 20:57:50 +0000852bool File::GetIsRealTerminal() {
853 if (m_is_real_terminal == eLazyBoolCalculate)
854 CalculateInteractiveAndTerminal();
855 return m_is_real_terminal == eLazyBoolYes;
Greg Clayton340b0302014-02-05 17:57:57 +0000856}
857
Kate Stoneb9c1b512016-09-06 20:57:50 +0000858bool File::GetIsTerminalWithColors() {
859 if (m_supports_colors == eLazyBoolCalculate)
860 CalculateInteractiveAndTerminal();
861 return m_supports_colors == eLazyBoolYes;
Sean Callanan66810412015-10-19 23:11:07 +0000862}