blob: 4361eae78c8db85274f8fa811392ee6a1075ecf4 [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
Greg Clayton96c09682012-01-04 22:56:43 +000025#include "lldb/Core/DataBufferHeap.h"
Greg Clayton504f89a2011-02-08 17:49:02 +000026#include "lldb/Core/Error.h"
Zachary Turner98688922014-08-06 18:16:26 +000027#include "lldb/Core/Log.h"
Greg Clayton925137c2011-02-09 01:16:43 +000028#include "lldb/Host/Config.h"
Greg Clayton846b64b2011-02-08 19:54:44 +000029#include "lldb/Host/FileSpec.h"
Greg Clayton504f89a2011-02-08 17:49:02 +000030
31using namespace lldb;
32using namespace lldb_private;
33
Greg Clayton51b1e2d2011-02-09 01:08:52 +000034static const char *
35GetStreamOpenModeFromOptions (uint32_t options)
36{
37 if (options & File::eOpenOptionAppend)
38 {
39 if (options & File::eOpenOptionRead)
40 {
41 if (options & File::eOpenOptionCanCreateNewOnly)
42 return "a+x";
43 else
44 return "a+";
45 }
46 else if (options & File::eOpenOptionWrite)
47 {
48 if (options & File::eOpenOptionCanCreateNewOnly)
49 return "ax";
50 else
51 return "a";
52 }
53 }
54 else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite)
55 {
56 if (options & File::eOpenOptionCanCreate)
57 {
58 if (options & File::eOpenOptionCanCreateNewOnly)
59 return "w+x";
60 else
61 return "w+";
62 }
63 else
64 return "r+";
65 }
66 else if (options & File::eOpenOptionRead)
67 {
68 return "r";
69 }
70 else if (options & File::eOpenOptionWrite)
71 {
72 return "w";
73 }
74 return NULL;
75}
76
77int File::kInvalidDescriptor = -1;
78FILE * File::kInvalidStream = NULL;
79
Greg Clayton504f89a2011-02-08 17:49:02 +000080File::File(const char *path, uint32_t options, uint32_t permissions) :
Zachary Turner98688922014-08-06 18:16:26 +000081 IOObject(eFDTypeFile, false),
Greg Clayton51b1e2d2011-02-09 01:08:52 +000082 m_descriptor (kInvalidDescriptor),
83 m_stream (kInvalidStream),
Greg Clayton44d93782014-01-27 23:43:24 +000084 m_options (),
85 m_own_stream (false),
Greg Clayton340b0302014-02-05 17:57:57 +000086 m_is_interactive (eLazyBoolCalculate),
87 m_is_real_terminal (eLazyBoolCalculate)
Greg Clayton504f89a2011-02-08 17:49:02 +000088{
89 Open (path, options, permissions);
90}
91
Daniel Maleae0f8f572013-08-26 23:57:52 +000092File::File (const FileSpec& filespec,
93 uint32_t options,
94 uint32_t permissions) :
Zachary Turner98688922014-08-06 18:16:26 +000095 IOObject(eFDTypeFile, false),
Daniel Maleae0f8f572013-08-26 23:57:52 +000096 m_descriptor (kInvalidDescriptor),
97 m_stream (kInvalidStream),
98 m_options (0),
Greg Clayton44d93782014-01-27 23:43:24 +000099 m_own_stream (false),
Greg Clayton340b0302014-02-05 17:57:57 +0000100 m_is_interactive (eLazyBoolCalculate),
101 m_is_real_terminal (eLazyBoolCalculate)
102
Daniel Maleae0f8f572013-08-26 23:57:52 +0000103{
104 if (filespec)
105 {
106 Open (filespec.GetPath().c_str(), options, permissions);
107 }
108}
109
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000110File::File (const File &rhs) :
Zachary Turner98688922014-08-06 18:16:26 +0000111 IOObject(eFDTypeFile, false),
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000112 m_descriptor (kInvalidDescriptor),
113 m_stream (kInvalidStream),
114 m_options (0),
Greg Clayton44d93782014-01-27 23:43:24 +0000115 m_own_stream (false),
Greg Clayton340b0302014-02-05 17:57:57 +0000116 m_is_interactive (eLazyBoolCalculate),
117 m_is_real_terminal (eLazyBoolCalculate)
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000118{
119 Duplicate (rhs);
120}
121
122
123File &
124File::operator = (const File &rhs)
125{
126 if (this != &rhs)
127 Duplicate (rhs);
128 return *this;
129}
130
Greg Clayton504f89a2011-02-08 17:49:02 +0000131File::~File()
132{
133 Close ();
134}
135
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000136
137int
138File::GetDescriptor() const
139{
140 if (DescriptorIsValid())
141 return m_descriptor;
142
143 // Don't open the file descriptor if we don't need to, just get it from the
144 // stream if we have one.
145 if (StreamIsValid())
146 return fileno (m_stream);
147
148 // Invalid descriptor and invalid stream, return invalid descriptor.
149 return kInvalidDescriptor;
150}
151
Zachary Turner98688922014-08-06 18:16:26 +0000152IOObject::WaitableHandle
153File::GetWaitableHandle()
154{
155 return m_descriptor;
156}
157
158
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000159void
160File::SetDescriptor (int fd, bool transfer_ownership)
161{
162 if (IsValid())
163 Close();
164 m_descriptor = fd;
Zachary Turner98688922014-08-06 18:16:26 +0000165 m_should_close_fd = transfer_ownership;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000166}
167
168
169FILE *
170File::GetStream ()
171{
172 if (!StreamIsValid())
173 {
174 if (DescriptorIsValid())
175 {
176 const char *mode = GetStreamOpenModeFromOptions (m_options);
177 if (mode)
Greg Clayton96c09682012-01-04 22:56:43 +0000178 {
Zachary Turner98688922014-08-06 18:16:26 +0000179 if (!m_should_close_fd)
Greg Clayton44d93782014-01-27 23:43:24 +0000180 {
181 // We must duplicate the file descriptor if we don't own it because
182 // when you call fdopen, the stream will own the fd
183#ifdef _WIN32
184 m_descriptor = ::_dup(GetDescriptor());
185#else
186 m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD);
187#endif
Zachary Turner98688922014-08-06 18:16:26 +0000188 m_should_close_fd = true;
Greg Clayton44d93782014-01-27 23:43:24 +0000189 }
190
Greg Clayton96c09682012-01-04 22:56:43 +0000191 do
192 {
193 m_stream = ::fdopen (m_descriptor, mode);
194 } while (m_stream == NULL && errno == EINTR);
Greg Clayton44d93782014-01-27 23:43:24 +0000195
196 // If we got a stream, then we own the stream and should no
197 // longer own the descriptor because fclose() will close it for us
198
199 if (m_stream)
200 {
201 m_own_stream = true;
Zachary Turner98688922014-08-06 18:16:26 +0000202 m_should_close_fd = false;
Greg Clayton44d93782014-01-27 23:43:24 +0000203 }
Greg Clayton96c09682012-01-04 22:56:43 +0000204 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000205 }
206 }
207 return m_stream;
208}
209
210
211void
212File::SetStream (FILE *fh, bool transfer_ownership)
213{
214 if (IsValid())
215 Close();
216 m_stream = fh;
Greg Clayton44d93782014-01-27 23:43:24 +0000217 m_own_stream = transfer_ownership;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000218}
219
220Error
221File::Duplicate (const File &rhs)
222{
223 Error error;
224 if (IsValid ())
225 Close();
226
227 if (rhs.DescriptorIsValid())
228 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000229#ifdef _WIN32
230 m_descriptor = ::_dup(rhs.GetDescriptor());
231#else
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000232 m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000233#endif
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000234 if (!DescriptorIsValid())
235 error.SetErrorToErrno();
236 else
237 {
238 m_options = rhs.m_options;
Zachary Turner98688922014-08-06 18:16:26 +0000239 m_should_close_fd = true;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000240 }
241 }
242 else
243 {
244 error.SetErrorString ("invalid file to duplicate");
245 }
246 return error;
247}
248
Greg Clayton504f89a2011-02-08 17:49:02 +0000249Error
250File::Open (const char *path, uint32_t options, uint32_t permissions)
251{
252 Error error;
253 if (IsValid())
254 Close ();
255
256 int oflag = 0;
Greg Clayton96c09682012-01-04 22:56:43 +0000257 const bool read = options & eOpenOptionRead;
258 const bool write = options & eOpenOptionWrite;
259 if (write)
260 {
261 if (read)
262 oflag |= O_RDWR;
263 else
264 oflag |= O_WRONLY;
265
266 if (options & eOpenOptionAppend)
267 oflag |= O_APPEND;
268
269 if (options & eOpenOptionTruncate)
270 oflag |= O_TRUNC;
271
272 if (options & eOpenOptionCanCreate)
273 oflag |= O_CREAT;
274
275 if (options & eOpenOptionCanCreateNewOnly)
276 oflag |= O_CREAT | O_EXCL;
277 }
278 else if (read)
279 {
Greg Clayton504f89a2011-02-08 17:49:02 +0000280 oflag |= O_RDONLY;
Greg Claytonfbb76342013-11-20 21:07:01 +0000281
Colin Riley909bb7a2013-11-26 15:10:46 +0000282#ifndef _WIN32
Greg Claytonfbb76342013-11-20 21:07:01 +0000283 if (options & eOpenoptionDontFollowSymlinks)
284 oflag |= O_NOFOLLOW;
Colin Riley909bb7a2013-11-26 15:10:46 +0000285#endif
Greg Clayton96c09682012-01-04 22:56:43 +0000286 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000287
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000288#ifndef _WIN32
Greg Clayton504f89a2011-02-08 17:49:02 +0000289 if (options & eOpenOptionNonBlocking)
290 oflag |= O_NONBLOCK;
Pavel Labath97a9ac12015-02-05 16:44:42 +0000291 if (options & eOpenOptionCloseOnExec)
292 oflag |= O_CLOEXEC;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000293#else
294 oflag |= O_BINARY;
295#endif
Greg Clayton504f89a2011-02-08 17:49:02 +0000296
Greg Clayton504f89a2011-02-08 17:49:02 +0000297 mode_t mode = 0;
Greg Clayton96c09682012-01-04 22:56:43 +0000298 if (oflag & O_CREAT)
299 {
Greg Claytonfbb76342013-11-20 21:07:01 +0000300 if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR;
301 if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR;
302 if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR;
303 if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP;
304 if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP;
305 if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP;
306 if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH;
307 if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH;
308 if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH;
Greg Clayton96c09682012-01-04 22:56:43 +0000309 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000310
Greg Clayton96c09682012-01-04 22:56:43 +0000311 do
312 {
313 m_descriptor = ::open(path, oflag, mode);
314 } while (m_descriptor < 0 && errno == EINTR);
315
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000316 if (!DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000317 error.SetErrorToErrno();
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000318 else
Greg Clayton44d93782014-01-27 23:43:24 +0000319 {
Zachary Turner98688922014-08-06 18:16:26 +0000320 m_should_close_fd = true;
Greg Clayton44d93782014-01-27 23:43:24 +0000321 m_options = options;
322 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000323
324 return error;
325}
326
Daniel Maleae0f8f572013-08-26 23:57:52 +0000327uint32_t
328File::GetPermissions (const char *path, Error &error)
329{
330 if (path && path[0])
331 {
332 struct stat file_stats;
333 if (::stat (path, &file_stats) == -1)
334 error.SetErrorToErrno();
335 else
336 {
337 error.Clear();
Greg Claytonc0293822013-11-22 18:46:55 +0000338 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000339 }
340 }
341 else
342 {
343 if (path)
344 error.SetErrorString ("invalid path");
345 else
346 error.SetErrorString ("empty path");
347 }
348 return 0;
349}
350
351uint32_t
352File::GetPermissions(Error &error) const
353{
354 int fd = GetDescriptor();
355 if (fd != kInvalidDescriptor)
356 {
357 struct stat file_stats;
358 if (::fstat (fd, &file_stats) == -1)
359 error.SetErrorToErrno();
360 else
361 {
362 error.Clear();
Greg Claytonc0293822013-11-22 18:46:55 +0000363 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000364 }
365 }
366 else
367 {
368 error.SetErrorString ("invalid file descriptor");
369 }
370 return 0;
371}
372
373
Greg Clayton504f89a2011-02-08 17:49:02 +0000374Error
375File::Close ()
376{
377 Error error;
Greg Clayton44d93782014-01-27 23:43:24 +0000378 if (StreamIsValid() && m_own_stream)
Greg Clayton504f89a2011-02-08 17:49:02 +0000379 {
Greg Clayton44d93782014-01-27 23:43:24 +0000380 if (::fclose (m_stream) == EOF)
381 error.SetErrorToErrno();
Greg Clayton504f89a2011-02-08 17:49:02 +0000382 }
Greg Clayton44d93782014-01-27 23:43:24 +0000383
Zachary Turner98688922014-08-06 18:16:26 +0000384 if (DescriptorIsValid() && m_should_close_fd)
Greg Clayton44d93782014-01-27 23:43:24 +0000385 {
386 if (::close (m_descriptor) != 0)
387 error.SetErrorToErrno();
388 }
389 m_descriptor = kInvalidDescriptor;
390 m_stream = kInvalidStream;
391 m_options = 0;
392 m_own_stream = false;
Zachary Turner98688922014-08-06 18:16:26 +0000393 m_should_close_fd = false;
Greg Clayton340b0302014-02-05 17:57:57 +0000394 m_is_interactive = eLazyBoolCalculate;
395 m_is_real_terminal = eLazyBoolCalculate;
Greg Clayton504f89a2011-02-08 17:49:02 +0000396 return error;
397}
Greg Clayton968fa382011-02-08 19:10:53 +0000398
399
400Error
401File::GetFileSpec (FileSpec &file_spec) const
402{
403 Error error;
Greg Clayton925137c2011-02-09 01:16:43 +0000404#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
Greg Clayton968fa382011-02-08 19:10:53 +0000405 if (IsValid ())
406 {
407 char path[PATH_MAX];
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000408 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
Greg Clayton968fa382011-02-08 19:10:53 +0000409 error.SetErrorToErrno();
410 else
411 file_spec.SetFile (path, false);
412 }
413 else
Greg Clayton925137c2011-02-09 01:16:43 +0000414 {
Greg Clayton968fa382011-02-08 19:10:53 +0000415 error.SetErrorString("invalid file handle");
Greg Clayton925137c2011-02-09 01:16:43 +0000416 }
Greg Clayton94d08622011-02-09 07:19:18 +0000417#elif defined(__linux__)
418 char proc[64];
419 char path[PATH_MAX];
420 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
Greg Clayton86edbf42011-10-26 00:56:27 +0000421 error.SetErrorString ("cannot resolve file descriptor");
Greg Clayton94d08622011-02-09 07:19:18 +0000422 else
423 {
424 ssize_t len;
425 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
426 error.SetErrorToErrno();
427 else
428 {
429 path[len] = '\0';
430 file_spec.SetFile (path, false);
431 }
432 }
Greg Clayton925137c2011-02-09 01:16:43 +0000433#else
Greg Clayton94d08622011-02-09 07:19:18 +0000434 error.SetErrorString ("File::GetFileSpec is not supported on this platform");
Greg Clayton925137c2011-02-09 01:16:43 +0000435#endif
Greg Clayton968fa382011-02-08 19:10:53 +0000436
437 if (error.Fail())
438 file_spec.Clear();
439 return error;
440}
441
Greg Clayton43d82792013-05-22 23:30:09 +0000442off_t
443File::SeekFromStart (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000444{
Greg Clayton43d82792013-05-22 23:30:09 +0000445 off_t result = 0;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000446 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000447 {
Greg Clayton43d82792013-05-22 23:30:09 +0000448 result = ::lseek (m_descriptor, offset, SEEK_SET);
Greg Clayton968fa382011-02-08 19:10:53 +0000449
Greg Clayton43d82792013-05-22 23:30:09 +0000450 if (error_ptr)
451 {
452 if (result == -1)
453 error_ptr->SetErrorToErrno();
454 else
455 error_ptr->Clear();
456 }
Greg Clayton968fa382011-02-08 19:10:53 +0000457 }
Greg Clayton43d82792013-05-22 23:30:09 +0000458 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000459 {
Greg Clayton43d82792013-05-22 23:30:09 +0000460 result = ::fseek(m_stream, offset, SEEK_SET);
461
462 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 (error_ptr)
471 {
472 error_ptr->SetErrorString("invalid file handle");
473 }
474 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000475}
476
Greg Clayton43d82792013-05-22 23:30:09 +0000477off_t
478File::SeekFromCurrent (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000479{
Greg Clayton43d82792013-05-22 23:30:09 +0000480 off_t result = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000481 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000482 {
Greg Clayton43d82792013-05-22 23:30:09 +0000483 result = ::lseek (m_descriptor, offset, SEEK_CUR);
Greg Clayton968fa382011-02-08 19:10:53 +0000484
Greg Clayton43d82792013-05-22 23:30:09 +0000485 if (error_ptr)
486 {
487 if (result == -1)
488 error_ptr->SetErrorToErrno();
489 else
490 error_ptr->Clear();
491 }
Greg Clayton968fa382011-02-08 19:10:53 +0000492 }
Greg Clayton43d82792013-05-22 23:30:09 +0000493 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000494 {
Greg Clayton43d82792013-05-22 23:30:09 +0000495 result = ::fseek(m_stream, offset, SEEK_CUR);
496
497 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 (error_ptr)
506 {
507 error_ptr->SetErrorString("invalid file handle");
508 }
509 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000510}
511
Greg Clayton43d82792013-05-22 23:30:09 +0000512off_t
513File::SeekFromEnd (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000514{
Greg Clayton43d82792013-05-22 23:30:09 +0000515 off_t result = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000516 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000517 {
Greg Clayton43d82792013-05-22 23:30:09 +0000518 result = ::lseek (m_descriptor, offset, SEEK_END);
Greg Clayton968fa382011-02-08 19:10:53 +0000519
Greg Clayton43d82792013-05-22 23:30:09 +0000520 if (error_ptr)
521 {
522 if (result == -1)
523 error_ptr->SetErrorToErrno();
524 else
525 error_ptr->Clear();
526 }
Greg Clayton968fa382011-02-08 19:10:53 +0000527 }
Greg Clayton43d82792013-05-22 23:30:09 +0000528 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000529 {
Greg Clayton43d82792013-05-22 23:30:09 +0000530 result = ::fseek(m_stream, offset, SEEK_END);
531
532 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 (error_ptr)
541 {
542 error_ptr->SetErrorString("invalid file handle");
543 }
544 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000545}
546
547Error
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000548File::Flush ()
549{
550 Error error;
551 if (StreamIsValid())
552 {
Greg Clayton96c09682012-01-04 22:56:43 +0000553 int err = 0;
554 do
555 {
556 err = ::fflush (m_stream);
557 } while (err == EOF && errno == EINTR);
558
559 if (err == EOF)
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000560 error.SetErrorToErrno();
561 }
562 else if (!DescriptorIsValid())
563 {
564 error.SetErrorString("invalid file handle");
565 }
566 return error;
567}
568
569
570Error
Greg Clayton968fa382011-02-08 19:10:53 +0000571File::Sync ()
572{
573 Error error;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000574 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000575 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000576#ifdef _WIN32
577 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
578 if (err == 0)
579 error.SetErrorToGenericError();
580#else
Greg Clayton96c09682012-01-04 22:56:43 +0000581 int err = 0;
582 do
583 {
584 err = ::fsync (m_descriptor);
585 } while (err == -1 && errno == EINTR);
586
587 if (err == -1)
Greg Clayton968fa382011-02-08 19:10:53 +0000588 error.SetErrorToErrno();
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000589#endif
Greg Clayton968fa382011-02-08 19:10:53 +0000590 }
591 else
592 {
593 error.SetErrorString("invalid file handle");
594 }
595 return error;
596}
Greg Clayton846b64b2011-02-08 19:54:44 +0000597
Greg Clayton29aac9a2015-04-09 00:06:44 +0000598#if defined (__APPLE__)
599// Darwin kernels only can read/write <= INT_MAX bytes
600#define MAX_READ_SIZE INT_MAX
601#define MAX_WRITE_SIZE INT_MAX
602#endif
603
Greg Clayton504f89a2011-02-08 17:49:02 +0000604Error
605File::Read (void *buf, size_t &num_bytes)
606{
607 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000608
609#if defined (MAX_READ_SIZE)
610 if (num_bytes > MAX_READ_SIZE)
611 {
612 uint8_t *p = (uint8_t *)buf;
613 size_t bytes_left = num_bytes;
614 // Init the num_bytes read to zero
615 num_bytes = 0;
616
617 while (bytes_left > 0)
618 {
619 size_t curr_num_bytes;
620 if (bytes_left > MAX_READ_SIZE)
621 curr_num_bytes = MAX_READ_SIZE;
622 else
623 curr_num_bytes = bytes_left;
624
625 error = Read (p + num_bytes, curr_num_bytes);
626
627 // Update how many bytes were read
628 num_bytes += curr_num_bytes;
629 if (bytes_left < curr_num_bytes)
630 bytes_left = 0;
631 else
632 bytes_left -= curr_num_bytes;
633
634 if (error.Fail())
635 break;
636 }
637 return error;
638 }
639#endif
640
Greg Clayton96c09682012-01-04 22:56:43 +0000641 ssize_t bytes_read = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000642 if (DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000643 {
Greg Clayton96c09682012-01-04 22:56:43 +0000644 do
645 {
646 bytes_read = ::read (m_descriptor, buf, num_bytes);
647 } while (bytes_read < 0 && errno == EINTR);
648
Greg Clayton504f89a2011-02-08 17:49:02 +0000649 if (bytes_read == -1)
650 {
651 error.SetErrorToErrno();
652 num_bytes = 0;
653 }
654 else
655 num_bytes = bytes_read;
656 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000657 else if (StreamIsValid())
658 {
Greg Clayton96c09682012-01-04 22:56:43 +0000659 bytes_read = ::fread (buf, 1, num_bytes, m_stream);
660
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000661 if (bytes_read == 0)
662 {
663 if (::feof(m_stream))
664 error.SetErrorString ("feof");
665 else if (::ferror (m_stream))
666 error.SetErrorString ("ferror");
667 num_bytes = 0;
668 }
669 else
670 num_bytes = bytes_read;
671 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000672 else
673 {
674 num_bytes = 0;
675 error.SetErrorString("invalid file handle");
676 }
677 return error;
678}
679
680Error
681File::Write (const void *buf, size_t &num_bytes)
682{
683 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000684
685#if defined (MAX_WRITE_SIZE)
686 if (num_bytes > MAX_WRITE_SIZE)
687 {
688 const uint8_t *p = (const uint8_t *)buf;
689 size_t bytes_left = num_bytes;
690 // Init the num_bytes written to zero
691 num_bytes = 0;
692
693 while (bytes_left > 0)
694 {
695 size_t curr_num_bytes;
696 if (bytes_left > MAX_WRITE_SIZE)
697 curr_num_bytes = MAX_WRITE_SIZE;
698 else
699 curr_num_bytes = bytes_left;
700
701 error = Write (p + num_bytes, curr_num_bytes);
702
703 // Update how many bytes were read
704 num_bytes += curr_num_bytes;
705 if (bytes_left < curr_num_bytes)
706 bytes_left = 0;
707 else
708 bytes_left -= curr_num_bytes;
709
710 if (error.Fail())
711 break;
712 }
713 return error;
714 }
715#endif
716
Greg Clayton96c09682012-01-04 22:56:43 +0000717 ssize_t bytes_written = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000718 if (DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000719 {
Greg Clayton96c09682012-01-04 22:56:43 +0000720 do
721 {
722 bytes_written = ::write (m_descriptor, buf, num_bytes);
723 } while (bytes_written < 0 && errno == EINTR);
724
Greg Clayton504f89a2011-02-08 17:49:02 +0000725 if (bytes_written == -1)
726 {
727 error.SetErrorToErrno();
728 num_bytes = 0;
729 }
730 else
731 num_bytes = bytes_written;
732 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000733 else if (StreamIsValid())
734 {
Greg Clayton96c09682012-01-04 22:56:43 +0000735 bytes_written = ::fwrite (buf, 1, num_bytes, m_stream);
736
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000737 if (bytes_written == 0)
738 {
739 if (::feof(m_stream))
740 error.SetErrorString ("feof");
741 else if (::ferror (m_stream))
742 error.SetErrorString ("ferror");
743 num_bytes = 0;
744 }
745 else
746 num_bytes = bytes_written;
747
748 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000749 else
750 {
751 num_bytes = 0;
752 error.SetErrorString("invalid file handle");
753 }
Zachary Turner98688922014-08-06 18:16:26 +0000754
Greg Clayton504f89a2011-02-08 17:49:02 +0000755 return error;
756}
757
Greg Clayton846b64b2011-02-08 19:54:44 +0000758
759Error
760File::Read (void *buf, size_t &num_bytes, off_t &offset)
761{
762 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000763
764#if defined (MAX_READ_SIZE)
765 if (num_bytes > MAX_READ_SIZE)
766 {
767 uint8_t *p = (uint8_t *)buf;
768 size_t bytes_left = num_bytes;
769 // Init the num_bytes read to zero
770 num_bytes = 0;
771
772 while (bytes_left > 0)
773 {
774 size_t curr_num_bytes;
775 if (bytes_left > MAX_READ_SIZE)
776 curr_num_bytes = MAX_READ_SIZE;
777 else
778 curr_num_bytes = bytes_left;
779
780 error = Read (p + num_bytes, curr_num_bytes, offset);
781
782 // Update how many bytes were read
783 num_bytes += curr_num_bytes;
784 if (bytes_left < curr_num_bytes)
785 bytes_left = 0;
786 else
787 bytes_left -= curr_num_bytes;
788
789 if (error.Fail())
790 break;
791 }
792 return error;
793 }
794#endif
795
796#ifndef _WIN32
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000797 int fd = GetDescriptor();
798 if (fd != kInvalidDescriptor)
Greg Clayton846b64b2011-02-08 19:54:44 +0000799 {
Greg Clayton96c09682012-01-04 22:56:43 +0000800 ssize_t bytes_read = -1;
801 do
802 {
803 bytes_read = ::pread (fd, buf, num_bytes, offset);
804 } while (bytes_read < 0 && errno == EINTR);
805
Greg Clayton846b64b2011-02-08 19:54:44 +0000806 if (bytes_read < 0)
807 {
808 num_bytes = 0;
809 error.SetErrorToErrno();
810 }
811 else
812 {
813 offset += bytes_read;
814 num_bytes = bytes_read;
815 }
816 }
817 else
818 {
819 num_bytes = 0;
820 error.SetErrorString("invalid file handle");
821 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000822#else
823 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
824 SeekFromStart(offset);
Greg Clayton29aac9a2015-04-09 00:06:44 +0000825 error = Read(buf, num_bytes);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000826 if (!error.Fail())
827 SeekFromStart(cur);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000828#endif
Greg Clayton29aac9a2015-04-09 00:06:44 +0000829 return error;
Greg Clayton846b64b2011-02-08 19:54:44 +0000830}
831
832Error
Greg Clayton0b0b5122012-08-30 18:15:10 +0000833File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
Greg Clayton96c09682012-01-04 22:56:43 +0000834{
835 Error error;
836
837 if (num_bytes > 0)
838 {
839 int fd = GetDescriptor();
840 if (fd != kInvalidDescriptor)
841 {
842 struct stat file_stats;
843 if (::fstat (fd, &file_stats) == 0)
844 {
845 if (file_stats.st_size > offset)
846 {
847 const size_t bytes_left = file_stats.st_size - offset;
848 if (num_bytes > bytes_left)
849 num_bytes = bytes_left;
850
Jason Molenda03176d72015-01-22 00:41:05 +0000851 size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
Greg Clayton7b0992d2013-04-18 22:45:39 +0000852 std::unique_ptr<DataBufferHeap> data_heap_ap;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000853 data_heap_ap.reset(new DataBufferHeap());
854 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
Greg Clayton96c09682012-01-04 22:56:43 +0000855
856 if (data_heap_ap.get())
857 {
858 error = Read (data_heap_ap->GetBytes(), num_bytes, offset);
859 if (error.Success())
860 {
861 // Make sure we read exactly what we asked for and if we got
862 // less, adjust the array
Jason Molenda03176d72015-01-22 00:41:05 +0000863 if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize())
864 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
Greg Clayton96c09682012-01-04 22:56:43 +0000865 data_buffer_sp.reset(data_heap_ap.release());
866 return error;
867 }
868 }
869 }
870 else
871 error.SetErrorString("file is empty");
872 }
873 else
874 error.SetErrorToErrno();
875 }
876 else
877 error.SetErrorString("invalid file handle");
878 }
879 else
880 error.SetErrorString("invalid file handle");
881
882 num_bytes = 0;
883 data_buffer_sp.reset();
884 return error;
885}
886
887Error
Greg Clayton846b64b2011-02-08 19:54:44 +0000888File::Write (const void *buf, size_t &num_bytes, off_t &offset)
889{
Greg Clayton7965e542015-04-09 00:12:33 +0000890 Error error;
891
Greg Clayton29aac9a2015-04-09 00:06:44 +0000892#if defined (MAX_WRITE_SIZE)
893 if (num_bytes > MAX_WRITE_SIZE)
894 {
895 const uint8_t *p = (const uint8_t *)buf;
896 size_t bytes_left = num_bytes;
897 // Init the num_bytes written to zero
898 num_bytes = 0;
899
900 while (bytes_left > 0)
901 {
902 size_t curr_num_bytes;
903 if (bytes_left > MAX_WRITE_SIZE)
904 curr_num_bytes = MAX_WRITE_SIZE;
905 else
906 curr_num_bytes = bytes_left;
907
908 error = Write (p + num_bytes, curr_num_bytes, offset);
909
910 // Update how many bytes were read
911 num_bytes += curr_num_bytes;
912 if (bytes_left < curr_num_bytes)
913 bytes_left = 0;
914 else
915 bytes_left -= curr_num_bytes;
916
917 if (error.Fail())
918 break;
919 }
920 return error;
921 }
922#endif
923
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000924 int fd = GetDescriptor();
925 if (fd != kInvalidDescriptor)
Greg Clayton846b64b2011-02-08 19:54:44 +0000926 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000927#ifndef _WIN32
Greg Clayton96c09682012-01-04 22:56:43 +0000928 ssize_t bytes_written = -1;
929 do
930 {
931 bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset);
932 } while (bytes_written < 0 && errno == EINTR);
933
Greg Clayton846b64b2011-02-08 19:54:44 +0000934 if (bytes_written < 0)
935 {
936 num_bytes = 0;
937 error.SetErrorToErrno();
938 }
939 else
940 {
941 offset += bytes_written;
942 num_bytes = bytes_written;
943 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000944#else
945 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
946 error = Write(buf, num_bytes);
947 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
948
949 if (!error.Fail())
950 SeekFromStart(cur);
951
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000952 offset = after;
953#endif
Greg Clayton846b64b2011-02-08 19:54:44 +0000954 }
955 else
956 {
957 num_bytes = 0;
958 error.SetErrorString("invalid file handle");
959 }
960 return error;
961}
962
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000963//------------------------------------------------------------------
964// Print some formatted output to the stream.
965//------------------------------------------------------------------
Greg Claytonc7bece562013-01-25 18:06:21 +0000966size_t
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000967File::Printf (const char *format, ...)
968{
969 va_list args;
970 va_start (args, format);
Greg Claytonc7bece562013-01-25 18:06:21 +0000971 size_t result = PrintfVarArg (format, args);
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000972 va_end (args);
973 return result;
974}
Greg Clayton846b64b2011-02-08 19:54:44 +0000975
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000976//------------------------------------------------------------------
977// Print some formatted output to the stream.
978//------------------------------------------------------------------
Greg Claytonc7bece562013-01-25 18:06:21 +0000979size_t
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000980File::PrintfVarArg (const char *format, va_list args)
981{
Greg Claytonc7bece562013-01-25 18:06:21 +0000982 size_t result = 0;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000983 if (DescriptorIsValid())
984 {
985 char *s = NULL;
986 result = vasprintf(&s, format, args);
987 if (s != NULL)
988 {
989 if (result > 0)
990 {
991 size_t s_len = result;
992 Write (s, s_len);
993 result = s_len;
994 }
995 free (s);
996 }
997 }
998 else if (StreamIsValid())
999 {
1000 result = ::vfprintf (m_stream, format, args);
1001 }
1002 return result;
1003}
Daniel Maleae0f8f572013-08-26 23:57:52 +00001004
1005mode_t
1006File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
1007{
1008 mode_t mode = 0;
1009 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
1010 mode |= O_RDWR;
1011 else if (open_options & eOpenOptionWrite)
1012 mode |= O_WRONLY;
1013
1014 if (open_options & eOpenOptionAppend)
1015 mode |= O_APPEND;
1016
1017 if (open_options & eOpenOptionTruncate)
1018 mode |= O_TRUNC;
1019
1020 if (open_options & eOpenOptionNonBlocking)
1021 mode |= O_NONBLOCK;
1022
1023 if (open_options & eOpenOptionCanCreateNewOnly)
1024 mode |= O_CREAT | O_EXCL;
1025 else if (open_options & eOpenOptionCanCreate)
1026 mode |= O_CREAT;
1027
1028 return mode;
1029}
Greg Clayton340b0302014-02-05 17:57:57 +00001030
1031void
1032File::CalculateInteractiveAndTerminal ()
1033{
1034 const int fd = GetDescriptor();
1035 if (fd >= 0)
1036 {
1037 m_is_interactive = eLazyBoolNo;
1038 m_is_real_terminal = eLazyBoolNo;
Shawn Best8da0bf32014-11-08 01:41:49 +00001039#if (defined(_WIN32) || defined(__ANDROID_NDK__))
Deepak Panickal6419e982014-03-03 15:53:37 +00001040 if (_isatty(fd))
1041 {
1042 m_is_interactive = eLazyBoolYes;
1043 m_is_real_terminal = eLazyBoolYes;
1044 }
1045#else
Greg Clayton340b0302014-02-05 17:57:57 +00001046 if (isatty(fd))
1047 {
1048 m_is_interactive = eLazyBoolYes;
1049 struct winsize window_size;
1050 if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
1051 {
1052 if (window_size.ws_col > 0)
1053 m_is_real_terminal = eLazyBoolYes;
1054 }
1055 }
Deepak Panickal94667bc2014-02-17 17:43:39 +00001056#endif
Greg Clayton340b0302014-02-05 17:57:57 +00001057 }
1058}
1059
1060bool
1061File::GetIsInteractive ()
1062{
1063 if (m_is_interactive == eLazyBoolCalculate)
1064 CalculateInteractiveAndTerminal ();
1065 return m_is_interactive == eLazyBoolYes;
1066}
1067
1068bool
1069File::GetIsRealTerminal ()
1070{
1071 if (m_is_real_terminal == eLazyBoolCalculate)
1072 CalculateInteractiveAndTerminal();
1073 return m_is_real_terminal == eLazyBoolYes;
1074}
1075