blob: 3446c28e06d4e8aa0334738448bd9a2ed01257e6 [file] [log] [blame]
Michael J. Spencerdffde992010-11-29 22:28:51 +00001//===- llvm/Support/Unix/PathV2.cpp - Unix Path Implementation --*- C++ -*-===//
2//
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//
10// This file implements the Unix specific implementation of the PathV2 API.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15//=== WARNING: Implementation here must contain only generic UNIX code that
16//=== is guaranteed to work on *all* UNIX variants.
17//===----------------------------------------------------------------------===//
18
19#include "Unix.h"
Daniel Dunbar92bb5142012-05-05 16:36:24 +000020#include "llvm/Support/Process.h"
Michael J. Spencerbee0c382010-12-01 19:32:01 +000021#if HAVE_SYS_STAT_H
22#include <sys/stat.h>
23#endif
24#if HAVE_FCNTL_H
25#include <fcntl.h>
26#endif
Michael J. Spencerda7c1ca2011-01-05 16:38:57 +000027#if HAVE_DIRENT_H
28# include <dirent.h>
29# define NAMLEN(dirent) strlen((dirent)->d_name)
30#else
31# define dirent direct
32# define NAMLEN(dirent) (dirent)->d_namlen
33# if HAVE_SYS_NDIR_H
34# include <sys/ndir.h>
35# endif
36# if HAVE_SYS_DIR_H
37# include <sys/dir.h>
38# endif
39# if HAVE_NDIR_H
40# include <ndir.h>
41# endif
42#endif
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +000043#if HAVE_STDIO_H
44#include <stdio.h>
Michael J. Spencerbee0c382010-12-01 19:32:01 +000045#endif
Bill Wendling544e4122011-09-14 21:49:42 +000046#if HAVE_LIMITS_H
47#include <limits.h>
48#endif
Michael J. Spencerbee0c382010-12-01 19:32:01 +000049
Sylvestre Ledru6fc30c22012-04-11 15:35:36 +000050// For GNU Hurd
51#if defined(__GNU__) && !defined(PATH_MAX)
52# define PATH_MAX 4096
53#endif
54
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +000055using namespace llvm;
56
Michael J. Spencerbee0c382010-12-01 19:32:01 +000057namespace {
Michael J. Spencerad8a14f2010-12-07 01:23:08 +000058 /// This class automatically closes the given file descriptor when it goes out
59 /// of scope. You can take back explicit ownership of the file descriptor by
60 /// calling take(). The destructor does not verify that close was successful.
61 /// Therefore, never allow this class to call close on a file descriptor that
62 /// has been read from or written to.
Michael J. Spencerbee0c382010-12-01 19:32:01 +000063 struct AutoFD {
64 int FileDescriptor;
65
66 AutoFD(int fd) : FileDescriptor(fd) {}
67 ~AutoFD() {
68 if (FileDescriptor >= 0)
69 ::close(FileDescriptor);
70 }
71
72 int take() {
73 int ret = FileDescriptor;
74 FileDescriptor = -1;
75 return ret;
76 }
77
78 operator int() const {return FileDescriptor;}
79 };
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +000080
81 error_code TempDir(SmallVectorImpl<char> &result) {
82 // FIXME: Don't use TMPDIR if program is SUID or SGID enabled.
83 const char *dir = 0;
84 (dir = std::getenv("TMPDIR" )) ||
85 (dir = std::getenv("TMP" )) ||
86 (dir = std::getenv("TEMP" )) ||
87 (dir = std::getenv("TEMPDIR")) ||
88#ifdef P_tmpdir
89 (dir = P_tmpdir) ||
90#endif
91 (dir = "/tmp");
92
Michael J. Spencerfbd1bbd2010-12-07 01:23:19 +000093 result.clear();
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +000094 StringRef d(dir);
95 result.append(d.begin(), d.end());
David Blaikie58604cd2012-02-09 19:24:12 +000096 return error_code::success();
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +000097 }
Michael J. Spencerbee0c382010-12-01 19:32:01 +000098}
Michael J. Spencerdffde992010-11-29 22:28:51 +000099
100namespace llvm {
101namespace sys {
Michael J. Spencer1522fce2010-12-07 01:22:31 +0000102namespace fs {
Michael J. Spencerdffde992010-11-29 22:28:51 +0000103
104error_code current_path(SmallVectorImpl<char> &result) {
Sylvestre Ledru6fc30c22012-04-11 15:35:36 +0000105#ifdef MAXPATHLEN
Andrew Trick0a828fd2011-03-24 16:43:37 +0000106 result.reserve(MAXPATHLEN);
Sylvestre Ledru6fc30c22012-04-11 15:35:36 +0000107#else
108// For GNU Hurd
109 result.reserve(1024);
110#endif
Michael J. Spencerdffde992010-11-29 22:28:51 +0000111
Michael J. Spencer1522fce2010-12-07 01:22:31 +0000112 while (true) {
113 if (::getcwd(result.data(), result.capacity()) == 0) {
114 // See if there was a real error.
115 if (errno != errc::not_enough_memory)
116 return error_code(errno, system_category());
117 // Otherwise there just wasn't enough space.
118 result.reserve(result.capacity() * 2);
119 } else
120 break;
121 }
Michael J. Spencerdffde992010-11-29 22:28:51 +0000122
123 result.set_size(strlen(result.data()));
David Blaikie58604cd2012-02-09 19:24:12 +0000124 return error_code::success();
Michael J. Spencerdffde992010-11-29 22:28:51 +0000125}
126
Michael J. Spencerbee0c382010-12-01 19:32:01 +0000127error_code copy_file(const Twine &from, const Twine &to, copy_option copt) {
128 // Get arguments.
129 SmallString<128> from_storage;
130 SmallString<128> to_storage;
Michael J. Spencer871498e2010-12-01 20:37:42 +0000131 StringRef f = from.toNullTerminatedStringRef(from_storage);
132 StringRef t = to.toNullTerminatedStringRef(to_storage);
Michael J. Spencerbee0c382010-12-01 19:32:01 +0000133
134 const size_t buf_sz = 32768;
135 char buffer[buf_sz];
136 int from_file = -1, to_file = -1;
137
138 // Open from.
139 if ((from_file = ::open(f.begin(), O_RDONLY)) < 0)
140 return error_code(errno, system_category());
141 AutoFD from_fd(from_file);
142
143 // Stat from.
144 struct stat from_stat;
145 if (::stat(f.begin(), &from_stat) != 0)
146 return error_code(errno, system_category());
147
148 // Setup to flags.
149 int to_flags = O_CREAT | O_WRONLY;
150 if (copt == copy_option::fail_if_exists)
151 to_flags |= O_EXCL;
152
153 // Open to.
154 if ((to_file = ::open(t.begin(), to_flags, from_stat.st_mode)) < 0)
155 return error_code(errno, system_category());
156 AutoFD to_fd(to_file);
157
158 // Copy!
159 ssize_t sz, sz_read = 1, sz_write;
160 while (sz_read > 0 &&
161 (sz_read = ::read(from_fd, buffer, buf_sz)) > 0) {
162 // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
163 // Marc Rochkind, Addison-Wesley, 2004, page 94
164 sz_write = 0;
165 do {
166 if ((sz = ::write(to_fd, buffer + sz_write, sz_read - sz_write)) < 0) {
167 sz_read = sz; // cause read loop termination.
168 break; // error.
169 }
170 sz_write += sz;
171 } while (sz_write < sz_read);
172 }
173
174 // After all the file operations above the return value of close actually
175 // matters.
176 if (::close(from_fd.take()) < 0) sz_read = -1;
177 if (::close(to_fd.take()) < 0) sz_read = -1;
178
179 // Check for errors.
180 if (sz_read < 0)
181 return error_code(errno, system_category());
182
David Blaikie58604cd2012-02-09 19:24:12 +0000183 return error_code::success();
Michael J. Spencerbee0c382010-12-01 19:32:01 +0000184}
185
Michael J. Spencerb83769f2010-12-03 05:42:11 +0000186error_code create_directory(const Twine &path, bool &existed) {
187 SmallString<128> path_storage;
188 StringRef p = path.toNullTerminatedStringRef(path_storage);
189
Michael J. Spencer79c3c3a2010-12-07 01:23:29 +0000190 if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) {
Michael J. Spencer9d425e72010-12-04 18:45:32 +0000191 if (errno != errc::file_exists)
Michael J. Spencerb83769f2010-12-03 05:42:11 +0000192 return error_code(errno, system_category());
193 existed = true;
194 } else
195 existed = false;
196
David Blaikie58604cd2012-02-09 19:24:12 +0000197 return error_code::success();
Michael J. Spencerb83769f2010-12-03 05:42:11 +0000198}
199
Michael J. Spencerd7b305f2010-12-03 05:58:41 +0000200error_code create_hard_link(const Twine &to, const Twine &from) {
201 // Get arguments.
202 SmallString<128> from_storage;
203 SmallString<128> to_storage;
204 StringRef f = from.toNullTerminatedStringRef(from_storage);
205 StringRef t = to.toNullTerminatedStringRef(to_storage);
206
207 if (::link(t.begin(), f.begin()) == -1)
208 return error_code(errno, system_category());
209
David Blaikie58604cd2012-02-09 19:24:12 +0000210 return error_code::success();
Michael J. Spencerd7b305f2010-12-03 05:58:41 +0000211}
212
Michael J. Spencer9b391c52010-12-03 07:41:25 +0000213error_code create_symlink(const Twine &to, const Twine &from) {
214 // Get arguments.
215 SmallString<128> from_storage;
216 SmallString<128> to_storage;
217 StringRef f = from.toNullTerminatedStringRef(from_storage);
218 StringRef t = to.toNullTerminatedStringRef(to_storage);
219
220 if (::symlink(t.begin(), f.begin()) == -1)
221 return error_code(errno, system_category());
222
David Blaikie58604cd2012-02-09 19:24:12 +0000223 return error_code::success();
Michael J. Spencer9b391c52010-12-03 07:41:25 +0000224}
225
Michael J. Spencer106aa732010-12-03 17:53:43 +0000226error_code remove(const Twine &path, bool &existed) {
227 SmallString<128> path_storage;
228 StringRef p = path.toNullTerminatedStringRef(path_storage);
229
230 if (::remove(p.begin()) == -1) {
Michael J. Spencer9d425e72010-12-04 18:45:32 +0000231 if (errno != errc::no_such_file_or_directory)
Michael J. Spencer106aa732010-12-03 17:53:43 +0000232 return error_code(errno, system_category());
233 existed = false;
234 } else
235 existed = true;
236
David Blaikie58604cd2012-02-09 19:24:12 +0000237 return error_code::success();
Michael J. Spencer106aa732010-12-03 17:53:43 +0000238}
239
Michael J. Spencera50b98c2010-12-03 17:53:55 +0000240error_code rename(const Twine &from, const Twine &to) {
241 // Get arguments.
242 SmallString<128> from_storage;
243 SmallString<128> to_storage;
244 StringRef f = from.toNullTerminatedStringRef(from_storage);
245 StringRef t = to.toNullTerminatedStringRef(to_storage);
246
Michael J. Spencer283d49c2011-01-16 22:18:41 +0000247 if (::rename(f.begin(), t.begin()) == -1) {
248 // If it's a cross device link, copy then delete, otherwise return the error
249 if (errno == EXDEV) {
250 if (error_code ec = copy_file(from, to, copy_option::overwrite_if_exists))
251 return ec;
252 bool Existed;
253 if (error_code ec = remove(from, Existed))
254 return ec;
255 } else
256 return error_code(errno, system_category());
257 }
Michael J. Spencera50b98c2010-12-03 17:53:55 +0000258
David Blaikie58604cd2012-02-09 19:24:12 +0000259 return error_code::success();
Michael J. Spencera50b98c2010-12-03 17:53:55 +0000260}
261
Michael J. Spencer3920d3b2010-12-03 17:54:07 +0000262error_code resize_file(const Twine &path, uint64_t size) {
263 SmallString<128> path_storage;
264 StringRef p = path.toNullTerminatedStringRef(path_storage);
265
266 if (::truncate(p.begin(), size) == -1)
267 return error_code(errno, system_category());
268
David Blaikie58604cd2012-02-09 19:24:12 +0000269 return error_code::success();
Michael J. Spencer3920d3b2010-12-03 17:54:07 +0000270}
271
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000272error_code exists(const Twine &path, bool &result) {
273 SmallString<128> path_storage;
274 StringRef p = path.toNullTerminatedStringRef(path_storage);
275
276 struct stat status;
277 if (::stat(p.begin(), &status) == -1) {
Michael J. Spencer9d425e72010-12-04 18:45:32 +0000278 if (errno != errc::no_such_file_or_directory)
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000279 return error_code(errno, system_category());
280 result = false;
281 } else
282 result = true;
283
David Blaikie58604cd2012-02-09 19:24:12 +0000284 return error_code::success();
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000285}
286
Michael J. Spencerd45fbe62011-12-12 06:04:28 +0000287bool equivalent(file_status A, file_status B) {
288 assert(status_known(A) && status_known(B));
Sylvestre Ledru9dc06bd2012-04-23 16:37:23 +0000289 return A.fs_st_dev == B.fs_st_dev &&
290 A.fs_st_ino == B.fs_st_ino;
Michael J. Spencerd45fbe62011-12-12 06:04:28 +0000291}
292
Michael J. Spencerb531f452010-12-03 18:49:13 +0000293error_code equivalent(const Twine &A, const Twine &B, bool &result) {
Michael J. Spencerd45fbe62011-12-12 06:04:28 +0000294 file_status fsA, fsB;
295 if (error_code ec = status(A, fsA)) return ec;
296 if (error_code ec = status(B, fsB)) return ec;
297 result = equivalent(fsA, fsB);
David Blaikie58604cd2012-02-09 19:24:12 +0000298 return error_code::success();
Michael J. Spencerb531f452010-12-03 18:49:13 +0000299}
300
Michael J. Spencer01a87c42010-12-04 00:31:48 +0000301error_code file_size(const Twine &path, uint64_t &result) {
302 SmallString<128> path_storage;
303 StringRef p = path.toNullTerminatedStringRef(path_storage);
304
305 struct stat status;
306 if (::stat(p.begin(), &status) == -1)
307 return error_code(errno, system_category());
308 if (!S_ISREG(status.st_mode))
Michael J. Spencer9d425e72010-12-04 18:45:32 +0000309 return make_error_code(errc::operation_not_permitted);
Michael J. Spencer01a87c42010-12-04 00:31:48 +0000310
311 result = status.st_size;
David Blaikie58604cd2012-02-09 19:24:12 +0000312 return error_code::success();
Michael J. Spencer01a87c42010-12-04 00:31:48 +0000313}
314
Michael J. Spencer470ae132010-12-04 00:32:40 +0000315error_code status(const Twine &path, file_status &result) {
316 SmallString<128> path_storage;
317 StringRef p = path.toNullTerminatedStringRef(path_storage);
318
319 struct stat status;
320 if (::stat(p.begin(), &status) != 0) {
321 error_code ec(errno, system_category());
322 if (ec == errc::no_such_file_or_directory)
323 result = file_status(file_type::file_not_found);
324 else
325 result = file_status(file_type::status_error);
326 return ec;
327 }
328
329 if (S_ISDIR(status.st_mode))
330 result = file_status(file_type::directory_file);
331 else if (S_ISREG(status.st_mode))
332 result = file_status(file_type::regular_file);
333 else if (S_ISBLK(status.st_mode))
334 result = file_status(file_type::block_file);
335 else if (S_ISCHR(status.st_mode))
336 result = file_status(file_type::character_file);
337 else if (S_ISFIFO(status.st_mode))
338 result = file_status(file_type::fifo_file);
339 else if (S_ISSOCK(status.st_mode))
340 result = file_status(file_type::socket_file);
341 else
342 result = file_status(file_type::type_unknown);
343
Sylvestre Ledru9dc06bd2012-04-23 16:37:23 +0000344 result.fs_st_dev = status.st_dev;
345 result.fs_st_ino = status.st_ino;
Michael J. Spencerd45fbe62011-12-12 06:04:28 +0000346
David Blaikie58604cd2012-02-09 19:24:12 +0000347 return error_code::success();
Michael J. Spencer470ae132010-12-04 00:32:40 +0000348}
349
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000350error_code unique_file(const Twine &model, int &result_fd,
Argyrios Kyrtzidis814450a2011-07-28 00:29:20 +0000351 SmallVectorImpl<char> &result_path,
352 bool makeAbsolute) {
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000353 SmallString<128> Model;
354 model.toVector(Model);
355 // Null terminate.
356 Model.c_str();
357
Argyrios Kyrtzidis814450a2011-07-28 00:29:20 +0000358 if (makeAbsolute) {
359 // Make model absolute by prepending a temp directory if it's not already.
360 bool absolute = path::is_absolute(Twine(Model));
361 if (!absolute) {
362 SmallString<128> TDir;
363 if (error_code ec = TempDir(TDir)) return ec;
364 path::append(TDir, Twine(Model));
365 Model.swap(TDir);
366 }
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000367 }
368
Daniel Dunbar463a7192012-05-05 16:39:22 +0000369 // From here on, DO NOT modify model. It may be needed if the randomly chosen
370 // path already exists.
Daniel Dunbar92bb5142012-05-05 16:36:24 +0000371 SmallString<128> RandomPath = Model;
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000372
373retry_random_path:
Daniel Dunbar463a7192012-05-05 16:39:22 +0000374 // Replace '%' with random chars.
Daniel Dunbar92bb5142012-05-05 16:36:24 +0000375 for (unsigned i = 0, e = Model.size(); i != e; ++i) {
376 if (Model[i] == '%')
377 RandomPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000378 }
379
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000380 // Try to open + create the file.
381rety_open_create:
382 int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
383 if (RandomFD == -1) {
384 // If the file existed, try again, otherwise, error.
Michael J. Spencer9d425e72010-12-04 18:45:32 +0000385 if (errno == errc::file_exists)
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000386 goto retry_random_path;
387 // The path prefix doesn't exist.
Michael J. Spencer9d425e72010-12-04 18:45:32 +0000388 if (errno == errc::no_such_file_or_directory) {
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000389 StringRef p(RandomPath.begin(), RandomPath.size());
390 SmallString<64> dir_to_create;
391 for (path::const_iterator i = path::begin(p),
392 e = --path::end(p); i != e; ++i) {
Michael J. Spencer936671b2010-12-07 03:57:37 +0000393 path::append(dir_to_create, *i);
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000394 bool Exists;
395 if (error_code ec = exists(Twine(dir_to_create), Exists)) return ec;
396 if (!Exists) {
397 // Don't try to create network paths.
398 if (i->size() > 2 && (*i)[0] == '/' &&
399 (*i)[1] == '/' &&
400 (*i)[2] != '/')
Michael J. Spencer9d425e72010-12-04 18:45:32 +0000401 return make_error_code(errc::no_such_file_or_directory);
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000402 if (::mkdir(dir_to_create.c_str(), 0700) == -1)
403 return error_code(errno, system_category());
404 }
405 }
406 goto rety_open_create;
407 }
408 return error_code(errno, system_category());
409 }
410
Michael J. Spencer9d425e72010-12-04 18:45:32 +0000411 // Make the path absolute.
Andrew Trick0a828fd2011-03-24 16:43:37 +0000412 char real_path_buff[PATH_MAX + 1];
413 if (realpath(RandomPath.c_str(), real_path_buff) == NULL) {
414 int error = errno;
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000415 ::close(RandomFD);
416 ::unlink(RandomPath.c_str());
Andrew Trick0a828fd2011-03-24 16:43:37 +0000417 return error_code(error, system_category());
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000418 }
419
Andrew Trick0a828fd2011-03-24 16:43:37 +0000420 result_path.clear();
421 StringRef d(real_path_buff);
422 result_path.append(d.begin(), d.end());
423
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000424 result_fd = RandomFD;
David Blaikie58604cd2012-02-09 19:24:12 +0000425 return error_code::success();
Michael J. Spencer3cb84ef2010-12-03 01:21:28 +0000426}
427
Michael J. Spencera81ac8f2011-12-08 22:50:09 +0000428error_code detail::directory_iterator_construct(detail::DirIterState &it,
429 StringRef path){
Michael J. Spencerda7c1ca2011-01-05 16:38:57 +0000430 SmallString<128> path_null(path);
431 DIR *directory = ::opendir(path_null.c_str());
432 if (directory == 0)
433 return error_code(errno, system_category());
434
435 it.IterationHandle = reinterpret_cast<intptr_t>(directory);
436 // Add something for replace_filename to replace.
437 path::append(path_null, ".");
438 it.CurrentEntry = directory_entry(path_null.str());
439 return directory_iterator_increment(it);
440}
441
Michael J. Spencera81ac8f2011-12-08 22:50:09 +0000442error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
Michael J. Spencerda7c1ca2011-01-05 16:38:57 +0000443 if (it.IterationHandle)
444 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle));
445 it.IterationHandle = 0;
446 it.CurrentEntry = directory_entry();
David Blaikie58604cd2012-02-09 19:24:12 +0000447 return error_code::success();
Michael J. Spencerda7c1ca2011-01-05 16:38:57 +0000448}
449
Michael J. Spencera81ac8f2011-12-08 22:50:09 +0000450error_code detail::directory_iterator_increment(detail::DirIterState &it) {
Michael J. Spencerda7c1ca2011-01-05 16:38:57 +0000451 errno = 0;
452 dirent *cur_dir = ::readdir(reinterpret_cast<DIR *>(it.IterationHandle));
453 if (cur_dir == 0 && errno != 0) {
454 return error_code(errno, system_category());
455 } else if (cur_dir != 0) {
456 StringRef name(cur_dir->d_name, NAMLEN(cur_dir));
457 if ((name.size() == 1 && name[0] == '.') ||
458 (name.size() == 2 && name[0] == '.' && name[1] == '.'))
459 return directory_iterator_increment(it);
460 it.CurrentEntry.replace_filename(name);
461 } else
462 return directory_iterator_destruct(it);
463
David Blaikie58604cd2012-02-09 19:24:12 +0000464 return error_code::success();
Michael J. Spencerda7c1ca2011-01-05 16:38:57 +0000465}
466
Michael J. Spencerd6cdf1d2011-01-15 18:52:33 +0000467error_code get_magic(const Twine &path, uint32_t len,
468 SmallVectorImpl<char> &result) {
469 SmallString<128> PathStorage;
470 StringRef Path = path.toNullTerminatedStringRef(PathStorage);
471 result.set_size(0);
472
473 // Open path.
474 std::FILE *file = std::fopen(Path.data(), "rb");
475 if (file == 0)
476 return error_code(errno, system_category());
477
478 // Reserve storage.
479 result.reserve(len);
480
481 // Read magic!
482 size_t size = std::fread(result.data(), 1, len, file);
483 if (std::ferror(file) != 0) {
484 std::fclose(file);
485 return error_code(errno, system_category());
486 } else if (size != result.size()) {
487 if (std::feof(file) != 0) {
488 std::fclose(file);
489 result.set_size(size);
490 return make_error_code(errc::value_too_large);
491 }
492 }
493 std::fclose(file);
494 result.set_size(len);
David Blaikie58604cd2012-02-09 19:24:12 +0000495 return error_code::success();
Michael J. Spencerd6cdf1d2011-01-15 18:52:33 +0000496}
497
Michael J. Spencerbee0c382010-12-01 19:32:01 +0000498} // end namespace fs
Michael J. Spencerdffde992010-11-29 22:28:51 +0000499} // end namespace sys
500} // end namespace llvm