blob: a3d7bf5940c557a263dc7aa43c67492da68c538e [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())
Zachary Turner9c402642015-10-15 19:35:48 +0000146 {
147#if defined(LLVM_ON_WIN32)
148 return _fileno(m_stream);
149#else
150 return fileno(m_stream);
151#endif
152 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000153
154 // Invalid descriptor and invalid stream, return invalid descriptor.
155 return kInvalidDescriptor;
156}
157
Zachary Turner98688922014-08-06 18:16:26 +0000158IOObject::WaitableHandle
159File::GetWaitableHandle()
160{
161 return m_descriptor;
162}
163
164
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000165void
166File::SetDescriptor (int fd, bool transfer_ownership)
167{
168 if (IsValid())
169 Close();
170 m_descriptor = fd;
Zachary Turner98688922014-08-06 18:16:26 +0000171 m_should_close_fd = transfer_ownership;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000172}
173
174
175FILE *
176File::GetStream ()
177{
178 if (!StreamIsValid())
179 {
180 if (DescriptorIsValid())
181 {
182 const char *mode = GetStreamOpenModeFromOptions (m_options);
183 if (mode)
Greg Clayton96c09682012-01-04 22:56:43 +0000184 {
Zachary Turner98688922014-08-06 18:16:26 +0000185 if (!m_should_close_fd)
Greg Clayton44d93782014-01-27 23:43:24 +0000186 {
187 // We must duplicate the file descriptor if we don't own it because
188 // when you call fdopen, the stream will own the fd
189#ifdef _WIN32
190 m_descriptor = ::_dup(GetDescriptor());
191#else
192 m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD);
193#endif
Zachary Turner98688922014-08-06 18:16:26 +0000194 m_should_close_fd = true;
Greg Clayton44d93782014-01-27 23:43:24 +0000195 }
196
Greg Clayton96c09682012-01-04 22:56:43 +0000197 do
198 {
199 m_stream = ::fdopen (m_descriptor, mode);
200 } while (m_stream == NULL && errno == EINTR);
Greg Clayton44d93782014-01-27 23:43:24 +0000201
202 // If we got a stream, then we own the stream and should no
203 // longer own the descriptor because fclose() will close it for us
204
205 if (m_stream)
206 {
207 m_own_stream = true;
Zachary Turner98688922014-08-06 18:16:26 +0000208 m_should_close_fd = false;
Greg Clayton44d93782014-01-27 23:43:24 +0000209 }
Greg Clayton96c09682012-01-04 22:56:43 +0000210 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000211 }
212 }
213 return m_stream;
214}
215
216
217void
218File::SetStream (FILE *fh, bool transfer_ownership)
219{
220 if (IsValid())
221 Close();
222 m_stream = fh;
Greg Clayton44d93782014-01-27 23:43:24 +0000223 m_own_stream = transfer_ownership;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000224}
225
226Error
227File::Duplicate (const File &rhs)
228{
229 Error error;
230 if (IsValid ())
231 Close();
232
233 if (rhs.DescriptorIsValid())
234 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000235#ifdef _WIN32
236 m_descriptor = ::_dup(rhs.GetDescriptor());
237#else
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000238 m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000239#endif
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000240 if (!DescriptorIsValid())
241 error.SetErrorToErrno();
242 else
243 {
244 m_options = rhs.m_options;
Zachary Turner98688922014-08-06 18:16:26 +0000245 m_should_close_fd = true;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000246 }
247 }
248 else
249 {
250 error.SetErrorString ("invalid file to duplicate");
251 }
252 return error;
253}
254
Greg Clayton504f89a2011-02-08 17:49:02 +0000255Error
256File::Open (const char *path, uint32_t options, uint32_t permissions)
257{
258 Error error;
259 if (IsValid())
260 Close ();
261
262 int oflag = 0;
Greg Clayton96c09682012-01-04 22:56:43 +0000263 const bool read = options & eOpenOptionRead;
264 const bool write = options & eOpenOptionWrite;
265 if (write)
266 {
267 if (read)
268 oflag |= O_RDWR;
269 else
270 oflag |= O_WRONLY;
271
272 if (options & eOpenOptionAppend)
273 oflag |= O_APPEND;
274
275 if (options & eOpenOptionTruncate)
276 oflag |= O_TRUNC;
277
278 if (options & eOpenOptionCanCreate)
279 oflag |= O_CREAT;
280
281 if (options & eOpenOptionCanCreateNewOnly)
282 oflag |= O_CREAT | O_EXCL;
283 }
284 else if (read)
285 {
Greg Clayton504f89a2011-02-08 17:49:02 +0000286 oflag |= O_RDONLY;
Greg Claytonfbb76342013-11-20 21:07:01 +0000287
Colin Riley909bb7a2013-11-26 15:10:46 +0000288#ifndef _WIN32
Greg Claytonfbb76342013-11-20 21:07:01 +0000289 if (options & eOpenoptionDontFollowSymlinks)
290 oflag |= O_NOFOLLOW;
Colin Riley909bb7a2013-11-26 15:10:46 +0000291#endif
Greg Clayton96c09682012-01-04 22:56:43 +0000292 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000293
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000294#ifndef _WIN32
Greg Clayton504f89a2011-02-08 17:49:02 +0000295 if (options & eOpenOptionNonBlocking)
296 oflag |= O_NONBLOCK;
Pavel Labath97a9ac12015-02-05 16:44:42 +0000297 if (options & eOpenOptionCloseOnExec)
298 oflag |= O_CLOEXEC;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000299#else
300 oflag |= O_BINARY;
301#endif
Greg Clayton504f89a2011-02-08 17:49:02 +0000302
Greg Clayton504f89a2011-02-08 17:49:02 +0000303 mode_t mode = 0;
Greg Clayton96c09682012-01-04 22:56:43 +0000304 if (oflag & O_CREAT)
305 {
Greg Claytonfbb76342013-11-20 21:07:01 +0000306 if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR;
307 if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR;
308 if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR;
309 if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP;
310 if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP;
311 if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP;
312 if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH;
313 if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH;
314 if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH;
Greg Clayton96c09682012-01-04 22:56:43 +0000315 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000316
Greg Clayton96c09682012-01-04 22:56:43 +0000317 do
318 {
319 m_descriptor = ::open(path, oflag, mode);
320 } while (m_descriptor < 0 && errno == EINTR);
321
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000322 if (!DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000323 error.SetErrorToErrno();
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000324 else
Greg Clayton44d93782014-01-27 23:43:24 +0000325 {
Zachary Turner98688922014-08-06 18:16:26 +0000326 m_should_close_fd = true;
Greg Clayton44d93782014-01-27 23:43:24 +0000327 m_options = options;
328 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000329
330 return error;
331}
332
Daniel Maleae0f8f572013-08-26 23:57:52 +0000333uint32_t
Chaoren Lind3173f32015-05-29 19:52:29 +0000334File::GetPermissions(const FileSpec &file_spec, Error &error)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000335{
Chaoren Lind3173f32015-05-29 19:52:29 +0000336 if (file_spec)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000337 {
338 struct stat file_stats;
Chaoren Lind3173f32015-05-29 19:52:29 +0000339 if (::stat(file_spec.GetCString(), &file_stats) == -1)
Daniel Maleae0f8f572013-08-26 23:57:52 +0000340 error.SetErrorToErrno();
341 else
342 {
343 error.Clear();
Greg Claytonc0293822013-11-22 18:46:55 +0000344 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000345 }
346 }
347 else
Chaoren Lind3173f32015-05-29 19:52:29 +0000348 error.SetErrorString ("empty file spec");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000349 return 0;
350}
351
352uint32_t
353File::GetPermissions(Error &error) const
354{
355 int fd = GetDescriptor();
356 if (fd != kInvalidDescriptor)
357 {
358 struct stat file_stats;
359 if (::fstat (fd, &file_stats) == -1)
360 error.SetErrorToErrno();
361 else
362 {
363 error.Clear();
Greg Claytonc0293822013-11-22 18:46:55 +0000364 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000365 }
366 }
367 else
368 {
369 error.SetErrorString ("invalid file descriptor");
370 }
371 return 0;
372}
373
374
Greg Clayton504f89a2011-02-08 17:49:02 +0000375Error
376File::Close ()
377{
378 Error error;
Greg Clayton44d93782014-01-27 23:43:24 +0000379 if (StreamIsValid() && m_own_stream)
Greg Clayton504f89a2011-02-08 17:49:02 +0000380 {
Greg Clayton44d93782014-01-27 23:43:24 +0000381 if (::fclose (m_stream) == EOF)
382 error.SetErrorToErrno();
Greg Clayton504f89a2011-02-08 17:49:02 +0000383 }
Greg Clayton44d93782014-01-27 23:43:24 +0000384
Zachary Turner98688922014-08-06 18:16:26 +0000385 if (DescriptorIsValid() && m_should_close_fd)
Greg Clayton44d93782014-01-27 23:43:24 +0000386 {
387 if (::close (m_descriptor) != 0)
388 error.SetErrorToErrno();
389 }
390 m_descriptor = kInvalidDescriptor;
391 m_stream = kInvalidStream;
392 m_options = 0;
393 m_own_stream = false;
Zachary Turner98688922014-08-06 18:16:26 +0000394 m_should_close_fd = false;
Greg Clayton340b0302014-02-05 17:57:57 +0000395 m_is_interactive = eLazyBoolCalculate;
396 m_is_real_terminal = eLazyBoolCalculate;
Greg Clayton504f89a2011-02-08 17:49:02 +0000397 return error;
398}
Greg Clayton968fa382011-02-08 19:10:53 +0000399
400
401Error
402File::GetFileSpec (FileSpec &file_spec) const
403{
404 Error error;
Greg Clayton925137c2011-02-09 01:16:43 +0000405#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED
Greg Clayton968fa382011-02-08 19:10:53 +0000406 if (IsValid ())
407 {
408 char path[PATH_MAX];
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000409 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
Greg Clayton968fa382011-02-08 19:10:53 +0000410 error.SetErrorToErrno();
411 else
412 file_spec.SetFile (path, false);
413 }
414 else
Greg Clayton925137c2011-02-09 01:16:43 +0000415 {
Greg Clayton968fa382011-02-08 19:10:53 +0000416 error.SetErrorString("invalid file handle");
Greg Clayton925137c2011-02-09 01:16:43 +0000417 }
Greg Clayton94d08622011-02-09 07:19:18 +0000418#elif defined(__linux__)
419 char proc[64];
420 char path[PATH_MAX];
421 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
Greg Clayton86edbf42011-10-26 00:56:27 +0000422 error.SetErrorString ("cannot resolve file descriptor");
Greg Clayton94d08622011-02-09 07:19:18 +0000423 else
424 {
425 ssize_t len;
426 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
427 error.SetErrorToErrno();
428 else
429 {
430 path[len] = '\0';
431 file_spec.SetFile (path, false);
432 }
433 }
Greg Clayton925137c2011-02-09 01:16:43 +0000434#else
Greg Clayton94d08622011-02-09 07:19:18 +0000435 error.SetErrorString ("File::GetFileSpec is not supported on this platform");
Greg Clayton925137c2011-02-09 01:16:43 +0000436#endif
Greg Clayton968fa382011-02-08 19:10:53 +0000437
438 if (error.Fail())
439 file_spec.Clear();
440 return error;
441}
442
Greg Clayton43d82792013-05-22 23:30:09 +0000443off_t
444File::SeekFromStart (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000445{
Greg Clayton43d82792013-05-22 23:30:09 +0000446 off_t result = 0;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000447 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000448 {
Greg Clayton43d82792013-05-22 23:30:09 +0000449 result = ::lseek (m_descriptor, offset, SEEK_SET);
Greg Clayton968fa382011-02-08 19:10:53 +0000450
Greg Clayton43d82792013-05-22 23:30:09 +0000451 if (error_ptr)
452 {
453 if (result == -1)
454 error_ptr->SetErrorToErrno();
455 else
456 error_ptr->Clear();
457 }
Greg Clayton968fa382011-02-08 19:10:53 +0000458 }
Greg Clayton43d82792013-05-22 23:30:09 +0000459 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000460 {
Greg Clayton43d82792013-05-22 23:30:09 +0000461 result = ::fseek(m_stream, offset, SEEK_SET);
462
463 if (error_ptr)
464 {
465 if (result == -1)
466 error_ptr->SetErrorToErrno();
467 else
468 error_ptr->Clear();
469 }
Greg Clayton968fa382011-02-08 19:10:53 +0000470 }
Greg Clayton43d82792013-05-22 23:30:09 +0000471 else if (error_ptr)
472 {
473 error_ptr->SetErrorString("invalid file handle");
474 }
475 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000476}
477
Greg Clayton43d82792013-05-22 23:30:09 +0000478off_t
479File::SeekFromCurrent (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000480{
Greg Clayton43d82792013-05-22 23:30:09 +0000481 off_t result = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000482 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000483 {
Greg Clayton43d82792013-05-22 23:30:09 +0000484 result = ::lseek (m_descriptor, offset, SEEK_CUR);
Greg Clayton968fa382011-02-08 19:10:53 +0000485
Greg Clayton43d82792013-05-22 23:30:09 +0000486 if (error_ptr)
487 {
488 if (result == -1)
489 error_ptr->SetErrorToErrno();
490 else
491 error_ptr->Clear();
492 }
Greg Clayton968fa382011-02-08 19:10:53 +0000493 }
Greg Clayton43d82792013-05-22 23:30:09 +0000494 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000495 {
Greg Clayton43d82792013-05-22 23:30:09 +0000496 result = ::fseek(m_stream, offset, SEEK_CUR);
497
498 if (error_ptr)
499 {
500 if (result == -1)
501 error_ptr->SetErrorToErrno();
502 else
503 error_ptr->Clear();
504 }
Greg Clayton968fa382011-02-08 19:10:53 +0000505 }
Greg Clayton43d82792013-05-22 23:30:09 +0000506 else if (error_ptr)
507 {
508 error_ptr->SetErrorString("invalid file handle");
509 }
510 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000511}
512
Greg Clayton43d82792013-05-22 23:30:09 +0000513off_t
514File::SeekFromEnd (off_t offset, Error *error_ptr)
Greg Clayton968fa382011-02-08 19:10:53 +0000515{
Greg Clayton43d82792013-05-22 23:30:09 +0000516 off_t result = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000517 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000518 {
Greg Clayton43d82792013-05-22 23:30:09 +0000519 result = ::lseek (m_descriptor, offset, SEEK_END);
Greg Clayton968fa382011-02-08 19:10:53 +0000520
Greg Clayton43d82792013-05-22 23:30:09 +0000521 if (error_ptr)
522 {
523 if (result == -1)
524 error_ptr->SetErrorToErrno();
525 else
526 error_ptr->Clear();
527 }
Greg Clayton968fa382011-02-08 19:10:53 +0000528 }
Greg Clayton43d82792013-05-22 23:30:09 +0000529 else if (StreamIsValid ())
Greg Clayton968fa382011-02-08 19:10:53 +0000530 {
Greg Clayton43d82792013-05-22 23:30:09 +0000531 result = ::fseek(m_stream, offset, SEEK_END);
532
533 if (error_ptr)
534 {
535 if (result == -1)
536 error_ptr->SetErrorToErrno();
537 else
538 error_ptr->Clear();
539 }
Greg Clayton968fa382011-02-08 19:10:53 +0000540 }
Greg Clayton43d82792013-05-22 23:30:09 +0000541 else if (error_ptr)
542 {
543 error_ptr->SetErrorString("invalid file handle");
544 }
545 return result;
Greg Clayton968fa382011-02-08 19:10:53 +0000546}
547
548Error
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000549File::Flush ()
550{
551 Error error;
552 if (StreamIsValid())
553 {
Greg Clayton96c09682012-01-04 22:56:43 +0000554 int err = 0;
555 do
556 {
557 err = ::fflush (m_stream);
558 } while (err == EOF && errno == EINTR);
559
560 if (err == EOF)
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000561 error.SetErrorToErrno();
562 }
563 else if (!DescriptorIsValid())
564 {
565 error.SetErrorString("invalid file handle");
566 }
567 return error;
568}
569
570
571Error
Greg Clayton968fa382011-02-08 19:10:53 +0000572File::Sync ()
573{
574 Error error;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000575 if (DescriptorIsValid())
Greg Clayton968fa382011-02-08 19:10:53 +0000576 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000577#ifdef _WIN32
578 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
579 if (err == 0)
580 error.SetErrorToGenericError();
581#else
Greg Clayton96c09682012-01-04 22:56:43 +0000582 int err = 0;
583 do
584 {
585 err = ::fsync (m_descriptor);
586 } while (err == -1 && errno == EINTR);
587
588 if (err == -1)
Greg Clayton968fa382011-02-08 19:10:53 +0000589 error.SetErrorToErrno();
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000590#endif
Greg Clayton968fa382011-02-08 19:10:53 +0000591 }
592 else
593 {
594 error.SetErrorString("invalid file handle");
595 }
596 return error;
597}
Greg Clayton846b64b2011-02-08 19:54:44 +0000598
Greg Clayton29aac9a2015-04-09 00:06:44 +0000599#if defined (__APPLE__)
600// Darwin kernels only can read/write <= INT_MAX bytes
601#define MAX_READ_SIZE INT_MAX
602#define MAX_WRITE_SIZE INT_MAX
603#endif
604
Greg Clayton504f89a2011-02-08 17:49:02 +0000605Error
606File::Read (void *buf, size_t &num_bytes)
607{
608 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000609
610#if defined (MAX_READ_SIZE)
611 if (num_bytes > MAX_READ_SIZE)
612 {
613 uint8_t *p = (uint8_t *)buf;
614 size_t bytes_left = num_bytes;
615 // Init the num_bytes read to zero
616 num_bytes = 0;
617
618 while (bytes_left > 0)
619 {
620 size_t curr_num_bytes;
621 if (bytes_left > MAX_READ_SIZE)
622 curr_num_bytes = MAX_READ_SIZE;
623 else
624 curr_num_bytes = bytes_left;
625
626 error = Read (p + num_bytes, curr_num_bytes);
627
628 // Update how many bytes were read
629 num_bytes += curr_num_bytes;
630 if (bytes_left < curr_num_bytes)
631 bytes_left = 0;
632 else
633 bytes_left -= curr_num_bytes;
634
635 if (error.Fail())
636 break;
637 }
638 return error;
639 }
640#endif
641
Greg Clayton96c09682012-01-04 22:56:43 +0000642 ssize_t bytes_read = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000643 if (DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000644 {
Greg Clayton96c09682012-01-04 22:56:43 +0000645 do
646 {
647 bytes_read = ::read (m_descriptor, buf, num_bytes);
648 } while (bytes_read < 0 && errno == EINTR);
649
Greg Clayton504f89a2011-02-08 17:49:02 +0000650 if (bytes_read == -1)
651 {
652 error.SetErrorToErrno();
653 num_bytes = 0;
654 }
655 else
656 num_bytes = bytes_read;
657 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000658 else if (StreamIsValid())
659 {
Greg Clayton96c09682012-01-04 22:56:43 +0000660 bytes_read = ::fread (buf, 1, num_bytes, m_stream);
661
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000662 if (bytes_read == 0)
663 {
664 if (::feof(m_stream))
665 error.SetErrorString ("feof");
666 else if (::ferror (m_stream))
667 error.SetErrorString ("ferror");
668 num_bytes = 0;
669 }
670 else
671 num_bytes = bytes_read;
672 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000673 else
674 {
675 num_bytes = 0;
676 error.SetErrorString("invalid file handle");
677 }
678 return error;
679}
680
681Error
682File::Write (const void *buf, size_t &num_bytes)
683{
684 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000685
686#if defined (MAX_WRITE_SIZE)
687 if (num_bytes > MAX_WRITE_SIZE)
688 {
689 const uint8_t *p = (const uint8_t *)buf;
690 size_t bytes_left = num_bytes;
691 // Init the num_bytes written to zero
692 num_bytes = 0;
693
694 while (bytes_left > 0)
695 {
696 size_t curr_num_bytes;
697 if (bytes_left > MAX_WRITE_SIZE)
698 curr_num_bytes = MAX_WRITE_SIZE;
699 else
700 curr_num_bytes = bytes_left;
701
702 error = Write (p + num_bytes, curr_num_bytes);
703
704 // Update how many bytes were read
705 num_bytes += curr_num_bytes;
706 if (bytes_left < curr_num_bytes)
707 bytes_left = 0;
708 else
709 bytes_left -= curr_num_bytes;
710
711 if (error.Fail())
712 break;
713 }
714 return error;
715 }
716#endif
717
Greg Clayton96c09682012-01-04 22:56:43 +0000718 ssize_t bytes_written = -1;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000719 if (DescriptorIsValid())
Greg Clayton504f89a2011-02-08 17:49:02 +0000720 {
Greg Clayton96c09682012-01-04 22:56:43 +0000721 do
722 {
723 bytes_written = ::write (m_descriptor, buf, num_bytes);
724 } while (bytes_written < 0 && errno == EINTR);
725
Greg Clayton504f89a2011-02-08 17:49:02 +0000726 if (bytes_written == -1)
727 {
728 error.SetErrorToErrno();
729 num_bytes = 0;
730 }
731 else
732 num_bytes = bytes_written;
733 }
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000734 else if (StreamIsValid())
735 {
Greg Clayton96c09682012-01-04 22:56:43 +0000736 bytes_written = ::fwrite (buf, 1, num_bytes, m_stream);
737
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000738 if (bytes_written == 0)
739 {
740 if (::feof(m_stream))
741 error.SetErrorString ("feof");
742 else if (::ferror (m_stream))
743 error.SetErrorString ("ferror");
744 num_bytes = 0;
745 }
746 else
747 num_bytes = bytes_written;
748
749 }
Greg Clayton504f89a2011-02-08 17:49:02 +0000750 else
751 {
752 num_bytes = 0;
753 error.SetErrorString("invalid file handle");
754 }
Zachary Turner98688922014-08-06 18:16:26 +0000755
Greg Clayton504f89a2011-02-08 17:49:02 +0000756 return error;
757}
758
Greg Clayton846b64b2011-02-08 19:54:44 +0000759
760Error
761File::Read (void *buf, size_t &num_bytes, off_t &offset)
762{
763 Error error;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000764
765#if defined (MAX_READ_SIZE)
766 if (num_bytes > MAX_READ_SIZE)
767 {
768 uint8_t *p = (uint8_t *)buf;
769 size_t bytes_left = num_bytes;
770 // Init the num_bytes read to zero
771 num_bytes = 0;
772
773 while (bytes_left > 0)
774 {
775 size_t curr_num_bytes;
776 if (bytes_left > MAX_READ_SIZE)
777 curr_num_bytes = MAX_READ_SIZE;
778 else
779 curr_num_bytes = bytes_left;
780
781 error = Read (p + num_bytes, curr_num_bytes, offset);
782
783 // Update how many bytes were read
784 num_bytes += curr_num_bytes;
785 if (bytes_left < curr_num_bytes)
786 bytes_left = 0;
787 else
788 bytes_left -= curr_num_bytes;
789
790 if (error.Fail())
791 break;
792 }
793 return error;
794 }
795#endif
796
797#ifndef _WIN32
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000798 int fd = GetDescriptor();
799 if (fd != kInvalidDescriptor)
Greg Clayton846b64b2011-02-08 19:54:44 +0000800 {
Greg Clayton96c09682012-01-04 22:56:43 +0000801 ssize_t bytes_read = -1;
802 do
803 {
804 bytes_read = ::pread (fd, buf, num_bytes, offset);
805 } while (bytes_read < 0 && errno == EINTR);
806
Greg Clayton846b64b2011-02-08 19:54:44 +0000807 if (bytes_read < 0)
808 {
809 num_bytes = 0;
810 error.SetErrorToErrno();
811 }
812 else
813 {
814 offset += bytes_read;
815 num_bytes = bytes_read;
816 }
817 }
818 else
819 {
820 num_bytes = 0;
821 error.SetErrorString("invalid file handle");
822 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000823#else
824 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
825 SeekFromStart(offset);
Greg Clayton29aac9a2015-04-09 00:06:44 +0000826 error = Read(buf, num_bytes);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000827 if (!error.Fail())
828 SeekFromStart(cur);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000829#endif
Greg Clayton29aac9a2015-04-09 00:06:44 +0000830 return error;
Greg Clayton846b64b2011-02-08 19:54:44 +0000831}
832
833Error
Greg Clayton0b0b5122012-08-30 18:15:10 +0000834File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
Greg Clayton96c09682012-01-04 22:56:43 +0000835{
836 Error error;
837
838 if (num_bytes > 0)
839 {
840 int fd = GetDescriptor();
841 if (fd != kInvalidDescriptor)
842 {
843 struct stat file_stats;
844 if (::fstat (fd, &file_stats) == 0)
845 {
846 if (file_stats.st_size > offset)
847 {
848 const size_t bytes_left = file_stats.st_size - offset;
849 if (num_bytes > bytes_left)
850 num_bytes = bytes_left;
851
Jason Molenda03176d72015-01-22 00:41:05 +0000852 size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
Greg Clayton7b0992d2013-04-18 22:45:39 +0000853 std::unique_ptr<DataBufferHeap> data_heap_ap;
Greg Clayton29aac9a2015-04-09 00:06:44 +0000854 data_heap_ap.reset(new DataBufferHeap());
855 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
Greg Clayton96c09682012-01-04 22:56:43 +0000856
857 if (data_heap_ap.get())
858 {
859 error = Read (data_heap_ap->GetBytes(), num_bytes, offset);
860 if (error.Success())
861 {
862 // Make sure we read exactly what we asked for and if we got
863 // less, adjust the array
Jason Molenda03176d72015-01-22 00:41:05 +0000864 if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize())
865 data_heap_ap->SetByteSize(num_bytes_plus_nul_char);
Greg Clayton96c09682012-01-04 22:56:43 +0000866 data_buffer_sp.reset(data_heap_ap.release());
867 return error;
868 }
869 }
870 }
871 else
872 error.SetErrorString("file is empty");
873 }
874 else
875 error.SetErrorToErrno();
876 }
877 else
878 error.SetErrorString("invalid file handle");
879 }
880 else
881 error.SetErrorString("invalid file handle");
882
883 num_bytes = 0;
884 data_buffer_sp.reset();
885 return error;
886}
887
888Error
Greg Clayton846b64b2011-02-08 19:54:44 +0000889File::Write (const void *buf, size_t &num_bytes, off_t &offset)
890{
Greg Clayton7965e542015-04-09 00:12:33 +0000891 Error error;
892
Greg Clayton29aac9a2015-04-09 00:06:44 +0000893#if defined (MAX_WRITE_SIZE)
894 if (num_bytes > MAX_WRITE_SIZE)
895 {
896 const uint8_t *p = (const uint8_t *)buf;
897 size_t bytes_left = num_bytes;
898 // Init the num_bytes written to zero
899 num_bytes = 0;
900
901 while (bytes_left > 0)
902 {
903 size_t curr_num_bytes;
904 if (bytes_left > MAX_WRITE_SIZE)
905 curr_num_bytes = MAX_WRITE_SIZE;
906 else
907 curr_num_bytes = bytes_left;
908
909 error = Write (p + num_bytes, curr_num_bytes, offset);
910
911 // Update how many bytes were read
912 num_bytes += curr_num_bytes;
913 if (bytes_left < curr_num_bytes)
914 bytes_left = 0;
915 else
916 bytes_left -= curr_num_bytes;
917
918 if (error.Fail())
919 break;
920 }
921 return error;
922 }
923#endif
924
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000925 int fd = GetDescriptor();
926 if (fd != kInvalidDescriptor)
Greg Clayton846b64b2011-02-08 19:54:44 +0000927 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000928#ifndef _WIN32
Greg Clayton96c09682012-01-04 22:56:43 +0000929 ssize_t bytes_written = -1;
930 do
931 {
932 bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset);
933 } while (bytes_written < 0 && errno == EINTR);
934
Greg Clayton846b64b2011-02-08 19:54:44 +0000935 if (bytes_written < 0)
936 {
937 num_bytes = 0;
938 error.SetErrorToErrno();
939 }
940 else
941 {
942 offset += bytes_written;
943 num_bytes = bytes_written;
944 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000945#else
946 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
947 error = Write(buf, num_bytes);
948 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
949
950 if (!error.Fail())
951 SeekFromStart(cur);
952
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000953 offset = after;
954#endif
Greg Clayton846b64b2011-02-08 19:54:44 +0000955 }
956 else
957 {
958 num_bytes = 0;
959 error.SetErrorString("invalid file handle");
960 }
961 return error;
962}
963
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000964//------------------------------------------------------------------
965// Print some formatted output to the stream.
966//------------------------------------------------------------------
Greg Claytonc7bece562013-01-25 18:06:21 +0000967size_t
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000968File::Printf (const char *format, ...)
969{
970 va_list args;
971 va_start (args, format);
Greg Claytonc7bece562013-01-25 18:06:21 +0000972 size_t result = PrintfVarArg (format, args);
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000973 va_end (args);
974 return result;
975}
Greg Clayton846b64b2011-02-08 19:54:44 +0000976
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000977//------------------------------------------------------------------
978// Print some formatted output to the stream.
979//------------------------------------------------------------------
Greg Claytonc7bece562013-01-25 18:06:21 +0000980size_t
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000981File::PrintfVarArg (const char *format, va_list args)
982{
Greg Claytonc7bece562013-01-25 18:06:21 +0000983 size_t result = 0;
Greg Clayton51b1e2d2011-02-09 01:08:52 +0000984 if (DescriptorIsValid())
985 {
986 char *s = NULL;
987 result = vasprintf(&s, format, args);
988 if (s != NULL)
989 {
990 if (result > 0)
991 {
992 size_t s_len = result;
993 Write (s, s_len);
994 result = s_len;
995 }
996 free (s);
997 }
998 }
999 else if (StreamIsValid())
1000 {
1001 result = ::vfprintf (m_stream, format, args);
1002 }
1003 return result;
1004}
Daniel Maleae0f8f572013-08-26 23:57:52 +00001005
1006mode_t
1007File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
1008{
1009 mode_t mode = 0;
1010 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
1011 mode |= O_RDWR;
1012 else if (open_options & eOpenOptionWrite)
1013 mode |= O_WRONLY;
1014
1015 if (open_options & eOpenOptionAppend)
1016 mode |= O_APPEND;
1017
1018 if (open_options & eOpenOptionTruncate)
1019 mode |= O_TRUNC;
1020
1021 if (open_options & eOpenOptionNonBlocking)
1022 mode |= O_NONBLOCK;
1023
1024 if (open_options & eOpenOptionCanCreateNewOnly)
1025 mode |= O_CREAT | O_EXCL;
1026 else if (open_options & eOpenOptionCanCreate)
1027 mode |= O_CREAT;
1028
1029 return mode;
1030}
Greg Clayton340b0302014-02-05 17:57:57 +00001031
1032void
1033File::CalculateInteractiveAndTerminal ()
1034{
1035 const int fd = GetDescriptor();
1036 if (fd >= 0)
1037 {
1038 m_is_interactive = eLazyBoolNo;
1039 m_is_real_terminal = eLazyBoolNo;
Shawn Best8da0bf32014-11-08 01:41:49 +00001040#if (defined(_WIN32) || defined(__ANDROID_NDK__))
Deepak Panickal6419e982014-03-03 15:53:37 +00001041 if (_isatty(fd))
1042 {
1043 m_is_interactive = eLazyBoolYes;
1044 m_is_real_terminal = eLazyBoolYes;
1045 }
1046#else
Greg Clayton340b0302014-02-05 17:57:57 +00001047 if (isatty(fd))
1048 {
1049 m_is_interactive = eLazyBoolYes;
1050 struct winsize window_size;
1051 if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
1052 {
1053 if (window_size.ws_col > 0)
1054 m_is_real_terminal = eLazyBoolYes;
1055 }
1056 }
Deepak Panickal94667bc2014-02-17 17:43:39 +00001057#endif
Greg Clayton340b0302014-02-05 17:57:57 +00001058 }
1059}
1060
1061bool
1062File::GetIsInteractive ()
1063{
1064 if (m_is_interactive == eLazyBoolCalculate)
1065 CalculateInteractiveAndTerminal ();
1066 return m_is_interactive == eLazyBoolYes;
1067}
1068
1069bool
1070File::GetIsRealTerminal ()
1071{
1072 if (m_is_real_terminal == eLazyBoolCalculate)
1073 CalculateInteractiveAndTerminal();
1074 return m_is_real_terminal == eLazyBoolYes;
1075}
1076