blob: c7a1c92d46dbe62f5df33a674b07b1cb47551c71 [file] [log] [blame]
Michael J. Spencerebad2f92010-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 Dunbar3f0fa192012-05-05 16:36:24 +000020#include "llvm/Support/Process.h"
Michael J. Spencer9fc1d9d2010-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
Nick Kledzik18497e92012-06-20 00:28:54 +000027#ifdef HAVE_SYS_MMAN_H
28#include <sys/mman.h>
29#endif
Michael J. Spencer52714862011-01-05 16:38:57 +000030#if HAVE_DIRENT_H
31# include <dirent.h>
32# define NAMLEN(dirent) strlen((dirent)->d_name)
33#else
34# define dirent direct
35# define NAMLEN(dirent) (dirent)->d_namlen
36# if HAVE_SYS_NDIR_H
37# include <sys/ndir.h>
38# endif
39# if HAVE_SYS_DIR_H
40# include <sys/dir.h>
41# endif
42# if HAVE_NDIR_H
43# include <ndir.h>
44# endif
45#endif
Michael J. Spencer45710402010-12-03 01:21:28 +000046#if HAVE_STDIO_H
47#include <stdio.h>
Michael J. Spencer9fc1d9d2010-12-01 19:32:01 +000048#endif
Bill Wendlingbdaa57f2011-09-14 21:49:42 +000049#if HAVE_LIMITS_H
50#include <limits.h>
51#endif
Michael J. Spencer9fc1d9d2010-12-01 19:32:01 +000052
Joerg Sonnenbergerc0697302012-08-10 10:56:09 +000053// Both stdio.h and cstdio are included via different pathes and
54// stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros
55// either.
56#undef ferror
57#undef feof
58
Sylvestre Ledru14ada942012-04-11 15:35:36 +000059// For GNU Hurd
60#if defined(__GNU__) && !defined(PATH_MAX)
61# define PATH_MAX 4096
62#endif
63
Michael J. Spencer45710402010-12-03 01:21:28 +000064using namespace llvm;
65
Michael J. Spencer9fc1d9d2010-12-01 19:32:01 +000066namespace {
Michael J. Spencer5529c572010-12-07 01:23:08 +000067 /// This class automatically closes the given file descriptor when it goes out
68 /// of scope. You can take back explicit ownership of the file descriptor by
69 /// calling take(). The destructor does not verify that close was successful.
70 /// Therefore, never allow this class to call close on a file descriptor that
71 /// has been read from or written to.
Michael J. Spencer9fc1d9d2010-12-01 19:32:01 +000072 struct AutoFD {
73 int FileDescriptor;
74
75 AutoFD(int fd) : FileDescriptor(fd) {}
76 ~AutoFD() {
77 if (FileDescriptor >= 0)
78 ::close(FileDescriptor);
79 }
80
81 int take() {
82 int ret = FileDescriptor;
83 FileDescriptor = -1;
84 return ret;
85 }
86
87 operator int() const {return FileDescriptor;}
88 };
Michael J. Spencer45710402010-12-03 01:21:28 +000089
90 error_code TempDir(SmallVectorImpl<char> &result) {
91 // FIXME: Don't use TMPDIR if program is SUID or SGID enabled.
92 const char *dir = 0;
93 (dir = std::getenv("TMPDIR" )) ||
94 (dir = std::getenv("TMP" )) ||
95 (dir = std::getenv("TEMP" )) ||
96 (dir = std::getenv("TEMPDIR")) ||
97#ifdef P_tmpdir
98 (dir = P_tmpdir) ||
99#endif
100 (dir = "/tmp");
101
Michael J. Spencer98c7a112010-12-07 01:23:19 +0000102 result.clear();
Michael J. Spencer45710402010-12-03 01:21:28 +0000103 StringRef d(dir);
104 result.append(d.begin(), d.end());
David Blaikie18544b92012-02-09 19:24:12 +0000105 return error_code::success();
Michael J. Spencer45710402010-12-03 01:21:28 +0000106 }
Michael J. Spencer9fc1d9d2010-12-01 19:32:01 +0000107}
Michael J. Spencerebad2f92010-11-29 22:28:51 +0000108
109namespace llvm {
110namespace sys {
Michael J. Spencer20daa282010-12-07 01:22:31 +0000111namespace fs {
Rafael Espindolae03dfd92013-06-26 05:01:35 +0000112#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
113 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \
114 defined(__linux__) || defined(__CYGWIN__)
115static int
116test_dir(char buf[PATH_MAX], char ret[PATH_MAX],
117 const char *dir, const char *bin)
118{
119 struct stat sb;
120
121 snprintf(buf, PATH_MAX, "%s/%s", dir, bin);
122 if (realpath(buf, ret) == NULL)
123 return (1);
124 if (stat(buf, &sb) != 0)
125 return (1);
126
127 return (0);
128}
129
130static char *
131getprogpath(char ret[PATH_MAX], const char *bin)
132{
133 char *pv, *s, *t, buf[PATH_MAX];
134
135 /* First approach: absolute path. */
136 if (bin[0] == '/') {
137 if (test_dir(buf, ret, "/", bin) == 0)
138 return (ret);
139 return (NULL);
140 }
141
142 /* Second approach: relative path. */
143 if (strchr(bin, '/') != NULL) {
144 if (getcwd(buf, PATH_MAX) == NULL)
145 return (NULL);
146 if (test_dir(buf, ret, buf, bin) == 0)
147 return (ret);
148 return (NULL);
149 }
150
151 /* Third approach: $PATH */
152 if ((pv = getenv("PATH")) == NULL)
153 return (NULL);
154 s = pv = strdup(pv);
155 if (pv == NULL)
156 return (NULL);
157 while ((t = strsep(&s, ":")) != NULL) {
158 if (test_dir(buf, ret, t, bin) == 0) {
159 free(pv);
160 return (ret);
161 }
162 }
163 free(pv);
164 return (NULL);
165}
166#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__
167
168/// GetMainExecutable - Return the path to the main executable, given the
169/// value of argv[0] from program startup.
170std::string getMainExecutable(const char *argv0, void *MainAddr) {
171#if defined(__APPLE__)
172 // On OS X the executable path is saved to the stack by dyld. Reading it
173 // from there is much faster than calling dladdr, especially for large
174 // binaries with symbols.
175 char exe_path[MAXPATHLEN];
176 uint32_t size = sizeof(exe_path);
177 if (_NSGetExecutablePath(exe_path, &size) == 0) {
178 char link_path[MAXPATHLEN];
179 if (realpath(exe_path, link_path))
180 return Path(link_path);
181 }
182#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
183 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__)
184 char exe_path[PATH_MAX];
185
186 if (getprogpath(exe_path, argv0) != NULL)
187 return Path(exe_path);
188#elif defined(__linux__) || defined(__CYGWIN__)
189 char exe_path[MAXPATHLEN];
190 StringRef aPath("/proc/self/exe");
191 if (sys::fs::exists(aPath)) {
192 // /proc is not always mounted under Linux (chroot for example).
193 ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path));
194 if (len >= 0)
195 return StringRef(exe_path, len);
196 } else {
197 // Fall back to the classical detection.
198 if (getprogpath(exe_path, argv0) != NULL)
199 return exe_path;
200 }
201#elif defined(HAVE_DLFCN_H)
202 // Use dladdr to get executable path if available.
203 Dl_info DLInfo;
204 int err = dladdr(MainAddr, &DLInfo);
205 if (err == 0)
206 return Path();
207
208 // If the filename is a symlink, we need to resolve and return the location of
209 // the actual executable.
210 char link_path[MAXPATHLEN];
211 if (realpath(DLInfo.dli_fname, link_path))
212 return Path(link_path);
213#else
214#error GetMainExecutable is not implemented on this host yet.
215#endif
216 return "";
217}
Michael J. Spencerebad2f92010-11-29 22:28:51 +0000218
Rafael Espindolabe3ede72013-06-20 21:51:49 +0000219TimeValue file_status::getLastModificationTime() const {
Rafael Espindoladb5d8fe2013-06-20 18:42:04 +0000220 TimeValue Ret;
221 Ret.fromEpochTime(fs_st_mtime);
222 return Ret;
223}
224
Michael J. Spencerebad2f92010-11-29 22:28:51 +0000225error_code current_path(SmallVectorImpl<char> &result) {
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000226#ifdef MAXPATHLEN
Andrew Tricka4ec5b22011-03-24 16:43:37 +0000227 result.reserve(MAXPATHLEN);
Sylvestre Ledru14ada942012-04-11 15:35:36 +0000228#else
229// For GNU Hurd
230 result.reserve(1024);
231#endif
Michael J. Spencerebad2f92010-11-29 22:28:51 +0000232
Michael J. Spencer20daa282010-12-07 01:22:31 +0000233 while (true) {
234 if (::getcwd(result.data(), result.capacity()) == 0) {
235 // See if there was a real error.
236 if (errno != errc::not_enough_memory)
237 return error_code(errno, system_category());
238 // Otherwise there just wasn't enough space.
239 result.reserve(result.capacity() * 2);
240 } else
241 break;
242 }
Michael J. Spencerebad2f92010-11-29 22:28:51 +0000243
244 result.set_size(strlen(result.data()));
David Blaikie18544b92012-02-09 19:24:12 +0000245 return error_code::success();
Michael J. Spencerebad2f92010-11-29 22:28:51 +0000246}
247
Michael J. Spencer9fc1d9d2010-12-01 19:32:01 +0000248error_code copy_file(const Twine &from, const Twine &to, copy_option copt) {
249 // Get arguments.
250 SmallString<128> from_storage;
251 SmallString<128> to_storage;
Michael J. Spencer795adf52010-12-01 20:37:42 +0000252 StringRef f = from.toNullTerminatedStringRef(from_storage);
253 StringRef t = to.toNullTerminatedStringRef(to_storage);
Michael J. Spencer9fc1d9d2010-12-01 19:32:01 +0000254
255 const size_t buf_sz = 32768;
256 char buffer[buf_sz];
257 int from_file = -1, to_file = -1;
258
259 // Open from.
260 if ((from_file = ::open(f.begin(), O_RDONLY)) < 0)
261 return error_code(errno, system_category());
262 AutoFD from_fd(from_file);
263
264 // Stat from.
265 struct stat from_stat;
266 if (::stat(f.begin(), &from_stat) != 0)
267 return error_code(errno, system_category());
268
269 // Setup to flags.
270 int to_flags = O_CREAT | O_WRONLY;
271 if (copt == copy_option::fail_if_exists)
272 to_flags |= O_EXCL;
273
274 // Open to.
275 if ((to_file = ::open(t.begin(), to_flags, from_stat.st_mode)) < 0)
276 return error_code(errno, system_category());
277 AutoFD to_fd(to_file);
278
279 // Copy!
280 ssize_t sz, sz_read = 1, sz_write;
281 while (sz_read > 0 &&
282 (sz_read = ::read(from_fd, buffer, buf_sz)) > 0) {
283 // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
284 // Marc Rochkind, Addison-Wesley, 2004, page 94
285 sz_write = 0;
286 do {
287 if ((sz = ::write(to_fd, buffer + sz_write, sz_read - sz_write)) < 0) {
288 sz_read = sz; // cause read loop termination.
289 break; // error.
290 }
291 sz_write += sz;
292 } while (sz_write < sz_read);
293 }
294
295 // After all the file operations above the return value of close actually
296 // matters.
297 if (::close(from_fd.take()) < 0) sz_read = -1;
298 if (::close(to_fd.take()) < 0) sz_read = -1;
299
300 // Check for errors.
301 if (sz_read < 0)
302 return error_code(errno, system_category());
303
David Blaikie18544b92012-02-09 19:24:12 +0000304 return error_code::success();
Michael J. Spencer9fc1d9d2010-12-01 19:32:01 +0000305}
306
Michael J. Spencer31e310c2010-12-03 05:42:11 +0000307error_code create_directory(const Twine &path, bool &existed) {
308 SmallString<128> path_storage;
309 StringRef p = path.toNullTerminatedStringRef(path_storage);
310
Michael J. Spencere5755be2010-12-07 01:23:29 +0000311 if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) {
Michael J. Spencer66a1f862010-12-04 18:45:32 +0000312 if (errno != errc::file_exists)
Michael J. Spencer31e310c2010-12-03 05:42:11 +0000313 return error_code(errno, system_category());
314 existed = true;
315 } else
316 existed = false;
317
David Blaikie18544b92012-02-09 19:24:12 +0000318 return error_code::success();
Michael J. Spencer31e310c2010-12-03 05:42:11 +0000319}
320
Michael J. Spencere0c45602010-12-03 05:58:41 +0000321error_code create_hard_link(const Twine &to, const Twine &from) {
322 // Get arguments.
323 SmallString<128> from_storage;
324 SmallString<128> to_storage;
325 StringRef f = from.toNullTerminatedStringRef(from_storage);
326 StringRef t = to.toNullTerminatedStringRef(to_storage);
327
328 if (::link(t.begin(), f.begin()) == -1)
329 return error_code(errno, system_category());
330
David Blaikie18544b92012-02-09 19:24:12 +0000331 return error_code::success();
Michael J. Spencere0c45602010-12-03 05:58:41 +0000332}
333
Michael J. Spencer7ee6d5d2010-12-03 07:41:25 +0000334error_code create_symlink(const Twine &to, const Twine &from) {
335 // Get arguments.
336 SmallString<128> from_storage;
337 SmallString<128> to_storage;
338 StringRef f = from.toNullTerminatedStringRef(from_storage);
339 StringRef t = to.toNullTerminatedStringRef(to_storage);
340
341 if (::symlink(t.begin(), f.begin()) == -1)
342 return error_code(errno, system_category());
343
David Blaikie18544b92012-02-09 19:24:12 +0000344 return error_code::success();
Michael J. Spencer7ee6d5d2010-12-03 07:41:25 +0000345}
346
Michael J. Spencer6e74e112010-12-03 17:53:43 +0000347error_code remove(const Twine &path, bool &existed) {
348 SmallString<128> path_storage;
349 StringRef p = path.toNullTerminatedStringRef(path_storage);
350
Rafael Espindola8cd62b02013-06-17 20:35:51 +0000351 struct stat buf;
352 if (stat(p.begin(), &buf) != 0) {
353 if (errno != errc::no_such_file_or_directory)
354 return error_code(errno, system_category());
355 existed = false;
356 return error_code::success();
357 }
358
359 // Note: this check catches strange situations. In all cases, LLVM should
360 // only be involved in the creation and deletion of regular files. This
361 // check ensures that what we're trying to erase is a regular file. It
362 // effectively prevents LLVM from erasing things like /dev/null, any block
363 // special file, or other things that aren't "regular" files.
364 if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode))
365 return make_error_code(errc::operation_not_permitted);
366
Michael J. Spencer6e74e112010-12-03 17:53:43 +0000367 if (::remove(p.begin()) == -1) {
Michael J. Spencer66a1f862010-12-04 18:45:32 +0000368 if (errno != errc::no_such_file_or_directory)
Michael J. Spencer6e74e112010-12-03 17:53:43 +0000369 return error_code(errno, system_category());
370 existed = false;
371 } else
372 existed = true;
373
David Blaikie18544b92012-02-09 19:24:12 +0000374 return error_code::success();
Michael J. Spencer6e74e112010-12-03 17:53:43 +0000375}
376
Michael J. Spencer409f5562010-12-03 17:53:55 +0000377error_code rename(const Twine &from, const Twine &to) {
378 // Get arguments.
379 SmallString<128> from_storage;
380 SmallString<128> to_storage;
381 StringRef f = from.toNullTerminatedStringRef(from_storage);
382 StringRef t = to.toNullTerminatedStringRef(to_storage);
383
Michael J. Spencerec202ee2011-01-16 22:18:41 +0000384 if (::rename(f.begin(), t.begin()) == -1) {
385 // If it's a cross device link, copy then delete, otherwise return the error
386 if (errno == EXDEV) {
387 if (error_code ec = copy_file(from, to, copy_option::overwrite_if_exists))
388 return ec;
389 bool Existed;
390 if (error_code ec = remove(from, Existed))
391 return ec;
392 } else
393 return error_code(errno, system_category());
394 }
Michael J. Spencer409f5562010-12-03 17:53:55 +0000395
David Blaikie18544b92012-02-09 19:24:12 +0000396 return error_code::success();
Michael J. Spencer409f5562010-12-03 17:53:55 +0000397}
398
Michael J. Spencerc20a0322010-12-03 17:54:07 +0000399error_code resize_file(const Twine &path, uint64_t size) {
400 SmallString<128> path_storage;
401 StringRef p = path.toNullTerminatedStringRef(path_storage);
402
403 if (::truncate(p.begin(), size) == -1)
404 return error_code(errno, system_category());
405
David Blaikie18544b92012-02-09 19:24:12 +0000406 return error_code::success();
Michael J. Spencerc20a0322010-12-03 17:54:07 +0000407}
408
Michael J. Spencer45710402010-12-03 01:21:28 +0000409error_code exists(const Twine &path, bool &result) {
410 SmallString<128> path_storage;
411 StringRef p = path.toNullTerminatedStringRef(path_storage);
412
Benjamin Kramer172f8082012-06-02 16:28:09 +0000413 if (::access(p.begin(), F_OK) == -1) {
Michael J. Spencer66a1f862010-12-04 18:45:32 +0000414 if (errno != errc::no_such_file_or_directory)
Michael J. Spencer45710402010-12-03 01:21:28 +0000415 return error_code(errno, system_category());
416 result = false;
417 } else
418 result = true;
419
David Blaikie18544b92012-02-09 19:24:12 +0000420 return error_code::success();
Michael J. Spencer45710402010-12-03 01:21:28 +0000421}
422
Rafael Espindolaa1280c12013-06-18 20:56:38 +0000423bool can_write(const Twine &Path) {
424 SmallString<128> PathStorage;
425 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
426 return 0 == access(P.begin(), W_OK);
427}
428
Rafael Espindolab0a5c962013-06-14 19:38:45 +0000429bool can_execute(const Twine &Path) {
430 SmallString<128> PathStorage;
431 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
432
Manuel Klimek52772bf2013-06-17 10:48:34 +0000433 if (0 != access(P.begin(), R_OK | X_OK))
434 return false;
435 struct stat buf;
436 if (0 != stat(P.begin(), &buf))
437 return false;
438 if (!S_ISREG(buf.st_mode))
439 return false;
440 return true;
Rafael Espindolab0a5c962013-06-14 19:38:45 +0000441}
442
Michael J. Spencer203d7802011-12-12 06:04:28 +0000443bool equivalent(file_status A, file_status B) {
444 assert(status_known(A) && status_known(B));
Sylvestre Ledru3099f4bd2012-04-23 16:37:23 +0000445 return A.fs_st_dev == B.fs_st_dev &&
446 A.fs_st_ino == B.fs_st_ino;
Michael J. Spencer203d7802011-12-12 06:04:28 +0000447}
448
Michael J. Spencer376d3872010-12-03 18:49:13 +0000449error_code equivalent(const Twine &A, const Twine &B, bool &result) {
Michael J. Spencer203d7802011-12-12 06:04:28 +0000450 file_status fsA, fsB;
451 if (error_code ec = status(A, fsA)) return ec;
452 if (error_code ec = status(B, fsB)) return ec;
453 result = equivalent(fsA, fsB);
David Blaikie18544b92012-02-09 19:24:12 +0000454 return error_code::success();
Michael J. Spencer376d3872010-12-03 18:49:13 +0000455}
456
Michael J. Spencer818ab4a2010-12-04 00:31:48 +0000457error_code file_size(const Twine &path, uint64_t &result) {
458 SmallString<128> path_storage;
459 StringRef p = path.toNullTerminatedStringRef(path_storage);
460
461 struct stat status;
462 if (::stat(p.begin(), &status) == -1)
463 return error_code(errno, system_category());
464 if (!S_ISREG(status.st_mode))
Michael J. Spencer66a1f862010-12-04 18:45:32 +0000465 return make_error_code(errc::operation_not_permitted);
Michael J. Spencer818ab4a2010-12-04 00:31:48 +0000466
467 result = status.st_size;
David Blaikie18544b92012-02-09 19:24:12 +0000468 return error_code::success();
Michael J. Spencer818ab4a2010-12-04 00:31:48 +0000469}
470
Rafael Espindola7cf7c512013-06-20 15:06:35 +0000471error_code getUniqueID(const Twine Path, uint64_t &Result) {
Rafael Espindola45e6c242013-06-18 19:34:49 +0000472 SmallString<128> Storage;
473 StringRef P = Path.toNullTerminatedStringRef(Storage);
474
475 struct stat Status;
476 if (::stat(P.begin(), &Status) != 0)
477 return error_code(errno, system_category());
478
479 Result = Status.st_ino;
480 return error_code::success();
481}
482
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000483error_code status(const Twine &path, file_status &result) {
484 SmallString<128> path_storage;
485 StringRef p = path.toNullTerminatedStringRef(path_storage);
486
487 struct stat status;
488 if (::stat(p.begin(), &status) != 0) {
489 error_code ec(errno, system_category());
490 if (ec == errc::no_such_file_or_directory)
491 result = file_status(file_type::file_not_found);
492 else
493 result = file_status(file_type::status_error);
494 return ec;
495 }
496
Nick Kledzik18497e92012-06-20 00:28:54 +0000497 perms prms = static_cast<perms>(status.st_mode & perms_mask);
498
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000499 if (S_ISDIR(status.st_mode))
Nick Kledzik18497e92012-06-20 00:28:54 +0000500 result = file_status(file_type::directory_file, prms);
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000501 else if (S_ISREG(status.st_mode))
Nick Kledzik18497e92012-06-20 00:28:54 +0000502 result = file_status(file_type::regular_file, prms);
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000503 else if (S_ISBLK(status.st_mode))
Nick Kledzik18497e92012-06-20 00:28:54 +0000504 result = file_status(file_type::block_file, prms);
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000505 else if (S_ISCHR(status.st_mode))
Nick Kledzik18497e92012-06-20 00:28:54 +0000506 result = file_status(file_type::character_file, prms);
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000507 else if (S_ISFIFO(status.st_mode))
Nick Kledzik18497e92012-06-20 00:28:54 +0000508 result = file_status(file_type::fifo_file, prms);
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000509 else if (S_ISSOCK(status.st_mode))
Nick Kledzik18497e92012-06-20 00:28:54 +0000510 result = file_status(file_type::socket_file, prms);
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000511 else
Nick Kledzik18497e92012-06-20 00:28:54 +0000512 result = file_status(file_type::type_unknown, prms);
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000513
Sylvestre Ledru3099f4bd2012-04-23 16:37:23 +0000514 result.fs_st_dev = status.st_dev;
515 result.fs_st_ino = status.st_ino;
Rafael Espindoladb5d8fe2013-06-20 18:42:04 +0000516 result.fs_st_mtime = status.st_mtime;
Rafael Espindolae34d6a52013-06-20 22:02:10 +0000517 result.fs_st_uid = status.st_uid;
518 result.fs_st_gid = status.st_gid;
Michael J. Spencer203d7802011-12-12 06:04:28 +0000519
David Blaikie18544b92012-02-09 19:24:12 +0000520 return error_code::success();
Michael J. Spencerdb5576a2010-12-04 00:32:40 +0000521}
522
Nick Kledzik18497e92012-06-20 00:28:54 +0000523// Modifies permissions on a file.
524error_code permissions(const Twine &path, perms prms) {
525 if ((prms & add_perms) && (prms & remove_perms))
526 llvm_unreachable("add_perms and remove_perms are mutually exclusive");
527
528 // Get current permissions
Rafael Espindola1efb69c2013-06-20 22:07:53 +0000529 // FIXME: We only need this stat for add_perms and remove_perms.
Nick Kledzik18497e92012-06-20 00:28:54 +0000530 file_status info;
531 if (error_code ec = status(path, info)) {
532 return ec;
533 }
534
535 // Set updated permissions.
536 SmallString<128> path_storage;
537 StringRef p = path.toNullTerminatedStringRef(path_storage);
538 perms permsToSet;
539 if (prms & add_perms) {
540 permsToSet = (info.permissions() | prms) & perms_mask;
541 } else if (prms & remove_perms) {
542 permsToSet = (info.permissions() & ~prms) & perms_mask;
543 } else {
544 permsToSet = prms & perms_mask;
545 }
546 if (::chmod(p.begin(), static_cast<mode_t>(permsToSet))) {
547 return error_code(errno, system_category());
548 }
549
550 return error_code::success();
551}
552
Rafael Espindola4a3365c2013-06-20 20:56:14 +0000553error_code setLastModificationAndAccessTime(int FD, TimeValue Time) {
554 timeval Times[2];
555 Times[0].tv_sec = Time.toPosixTime();
556 Times[0].tv_usec = 0;
557 Times[1] = Times[0];
558 if (::futimes(FD, Times))
559 return error_code(errno, system_category());
560 return error_code::success();
561}
562
Eric Christopherb6148ed2012-05-11 00:07:44 +0000563// Since this is most often used for temporary files, mode defaults to 0600.
Michael J. Spencer45710402010-12-03 01:21:28 +0000564error_code unique_file(const Twine &model, int &result_fd,
Eric Christopherb6148ed2012-05-11 00:07:44 +0000565 SmallVectorImpl<char> &result_path,
566 bool makeAbsolute, unsigned mode) {
Michael J. Spencer45710402010-12-03 01:21:28 +0000567 SmallString<128> Model;
568 model.toVector(Model);
569 // Null terminate.
570 Model.c_str();
571
Argyrios Kyrtzidis348937d2011-07-28 00:29:20 +0000572 if (makeAbsolute) {
573 // Make model absolute by prepending a temp directory if it's not already.
574 bool absolute = path::is_absolute(Twine(Model));
575 if (!absolute) {
576 SmallString<128> TDir;
577 if (error_code ec = TempDir(TDir)) return ec;
578 path::append(TDir, Twine(Model));
579 Model.swap(TDir);
580 }
Michael J. Spencer45710402010-12-03 01:21:28 +0000581 }
582
Daniel Dunbar58ed0c62012-05-05 16:39:22 +0000583 // From here on, DO NOT modify model. It may be needed if the randomly chosen
584 // path already exists.
Daniel Dunbar3f0fa192012-05-05 16:36:24 +0000585 SmallString<128> RandomPath = Model;
Michael J. Spencer45710402010-12-03 01:21:28 +0000586
587retry_random_path:
Daniel Dunbar58ed0c62012-05-05 16:39:22 +0000588 // Replace '%' with random chars.
Daniel Dunbar3f0fa192012-05-05 16:36:24 +0000589 for (unsigned i = 0, e = Model.size(); i != e; ++i) {
590 if (Model[i] == '%')
591 RandomPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
Michael J. Spencer45710402010-12-03 01:21:28 +0000592 }
593
Argyrios Kyrtzidiseed2dc52013-02-28 00:38:19 +0000594 // Make sure we don't fall into an infinite loop by constantly trying
595 // to create the parent path.
596 bool TriedToCreateParent = false;
597
Michael J. Spencer45710402010-12-03 01:21:28 +0000598 // Try to open + create the file.
599rety_open_create:
Eric Christopherb6148ed2012-05-11 00:07:44 +0000600 int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, mode);
Michael J. Spencer45710402010-12-03 01:21:28 +0000601 if (RandomFD == -1) {
Douglas Gregor95585ab2013-01-10 01:58:46 +0000602 int SavedErrno = errno;
Michael J. Spencer45710402010-12-03 01:21:28 +0000603 // If the file existed, try again, otherwise, error.
Douglas Gregor95585ab2013-01-10 01:58:46 +0000604 if (SavedErrno == errc::file_exists)
Michael J. Spencer45710402010-12-03 01:21:28 +0000605 goto retry_random_path;
Daniel Dunbar61d59f22012-11-15 20:24:52 +0000606 // If path prefix doesn't exist, try to create it.
Douglas Gregor6bd4d8c2013-04-05 20:48:36 +0000607 if (SavedErrno == errc::no_such_file_or_directory && !TriedToCreateParent) {
Argyrios Kyrtzidiseed2dc52013-02-28 00:38:19 +0000608 TriedToCreateParent = true;
Daniel Dunbar61d59f22012-11-15 20:24:52 +0000609 StringRef p(RandomPath);
Michael J. Spencer45710402010-12-03 01:21:28 +0000610 SmallString<64> dir_to_create;
611 for (path::const_iterator i = path::begin(p),
612 e = --path::end(p); i != e; ++i) {
Michael J. Spencer1e090f02010-12-07 03:57:37 +0000613 path::append(dir_to_create, *i);
Michael J. Spencer45710402010-12-03 01:21:28 +0000614 bool Exists;
615 if (error_code ec = exists(Twine(dir_to_create), Exists)) return ec;
616 if (!Exists) {
617 // Don't try to create network paths.
618 if (i->size() > 2 && (*i)[0] == '/' &&
619 (*i)[1] == '/' &&
620 (*i)[2] != '/')
Michael J. Spencer66a1f862010-12-04 18:45:32 +0000621 return make_error_code(errc::no_such_file_or_directory);
Douglas Gregor95585ab2013-01-10 01:58:46 +0000622 if (::mkdir(dir_to_create.c_str(), 0700) == -1 &&
623 errno != errc::file_exists)
Michael J. Spencer45710402010-12-03 01:21:28 +0000624 return error_code(errno, system_category());
625 }
626 }
627 goto rety_open_create;
628 }
Douglas Gregor95585ab2013-01-10 01:58:46 +0000629
630 return error_code(SavedErrno, system_category());
Michael J. Spencer45710402010-12-03 01:21:28 +0000631 }
632
Michael J. Spencer66a1f862010-12-04 18:45:32 +0000633 // Make the path absolute.
Andrew Tricka4ec5b22011-03-24 16:43:37 +0000634 char real_path_buff[PATH_MAX + 1];
635 if (realpath(RandomPath.c_str(), real_path_buff) == NULL) {
636 int error = errno;
Michael J. Spencer45710402010-12-03 01:21:28 +0000637 ::close(RandomFD);
638 ::unlink(RandomPath.c_str());
Andrew Tricka4ec5b22011-03-24 16:43:37 +0000639 return error_code(error, system_category());
Michael J. Spencer45710402010-12-03 01:21:28 +0000640 }
641
Andrew Tricka4ec5b22011-03-24 16:43:37 +0000642 result_path.clear();
643 StringRef d(real_path_buff);
644 result_path.append(d.begin(), d.end());
645
Michael J. Spencer45710402010-12-03 01:21:28 +0000646 result_fd = RandomFD;
David Blaikie18544b92012-02-09 19:24:12 +0000647 return error_code::success();
Michael J. Spencer45710402010-12-03 01:21:28 +0000648}
649
Michael J. Spencer42ad29f2013-03-14 00:20:10 +0000650error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) {
651 AutoFD ScopedFD(FD);
652 if (!CloseFD)
653 ScopedFD.take();
Michael J. Spenceref2284f2012-08-15 19:05:47 +0000654
655 // Figure out how large the file is.
656 struct stat FileInfo;
Michael J. Spencer42ad29f2013-03-14 00:20:10 +0000657 if (fstat(FD, &FileInfo) == -1)
Michael J. Spenceref2284f2012-08-15 19:05:47 +0000658 return error_code(errno, system_category());
659 uint64_t FileSize = FileInfo.st_size;
660
661 if (Size == 0)
662 Size = FileSize;
663 else if (FileSize < Size) {
664 // We need to grow the file.
Michael J. Spencer42ad29f2013-03-14 00:20:10 +0000665 if (ftruncate(FD, Size) == -1)
Michael J. Spenceref2284f2012-08-15 19:05:47 +0000666 return error_code(errno, system_category());
667 }
668
669 int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE;
670 int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE);
671#ifdef MAP_FILE
672 flags |= MAP_FILE;
673#endif
Michael J. Spencer42ad29f2013-03-14 00:20:10 +0000674 Mapping = ::mmap(0, Size, prot, flags, FD, Offset);
Michael J. Spenceref2284f2012-08-15 19:05:47 +0000675 if (Mapping == MAP_FAILED)
676 return error_code(errno, system_category());
677 return error_code::success();
678}
679
680mapped_file_region::mapped_file_region(const Twine &path,
681 mapmode mode,
682 uint64_t length,
683 uint64_t offset,
684 error_code &ec)
685 : Mode(mode)
686 , Size(length)
687 , Mapping() {
688 // Make sure that the requested size fits within SIZE_T.
689 if (length > std::numeric_limits<size_t>::max()) {
690 ec = make_error_code(errc::invalid_argument);
691 return;
692 }
693
694 SmallString<128> path_storage;
695 StringRef name = path.toNullTerminatedStringRef(path_storage);
696 int oflags = (mode == readonly) ? O_RDONLY : O_RDWR;
697 int ofd = ::open(name.begin(), oflags);
698 if (ofd == -1) {
699 ec = error_code(errno, system_category());
700 return;
701 }
702
Michael J. Spencer42ad29f2013-03-14 00:20:10 +0000703 ec = init(ofd, true, offset);
Michael J. Spenceref2284f2012-08-15 19:05:47 +0000704 if (ec)
705 Mapping = 0;
706}
707
708mapped_file_region::mapped_file_region(int fd,
Michael J. Spencer42ad29f2013-03-14 00:20:10 +0000709 bool closefd,
Michael J. Spenceref2284f2012-08-15 19:05:47 +0000710 mapmode mode,
711 uint64_t length,
712 uint64_t offset,
713 error_code &ec)
714 : Mode(mode)
715 , Size(length)
716 , Mapping() {
717 // Make sure that the requested size fits within SIZE_T.
718 if (length > std::numeric_limits<size_t>::max()) {
719 ec = make_error_code(errc::invalid_argument);
720 return;
721 }
722
Michael J. Spencer42ad29f2013-03-14 00:20:10 +0000723 ec = init(fd, closefd, offset);
Michael J. Spenceref2284f2012-08-15 19:05:47 +0000724 if (ec)
725 Mapping = 0;
726}
727
728mapped_file_region::~mapped_file_region() {
729 if (Mapping)
730 ::munmap(Mapping, Size);
731}
732
Chandler Carruthf12e3a62012-11-30 11:45:22 +0000733#if LLVM_HAS_RVALUE_REFERENCES
Michael J. Spenceref2284f2012-08-15 19:05:47 +0000734mapped_file_region::mapped_file_region(mapped_file_region &&other)
735 : Mode(other.Mode), Size(other.Size), Mapping(other.Mapping) {
736 other.Mapping = 0;
737}
738#endif
739
740mapped_file_region::mapmode mapped_file_region::flags() const {
741 assert(Mapping && "Mapping failed but used anyway!");
742 return Mode;
743}
744
745uint64_t mapped_file_region::size() const {
746 assert(Mapping && "Mapping failed but used anyway!");
747 return Size;
748}
749
750char *mapped_file_region::data() const {
751 assert(Mapping && "Mapping failed but used anyway!");
752 assert(Mode != readonly && "Cannot get non const data for readonly mapping!");
753 return reinterpret_cast<char*>(Mapping);
754}
755
756const char *mapped_file_region::const_data() const {
757 assert(Mapping && "Mapping failed but used anyway!");
758 return reinterpret_cast<const char*>(Mapping);
759}
760
761int mapped_file_region::alignment() {
Chandler Carruthacd64be2012-12-31 23:31:56 +0000762 return process::get_self()->page_size();
Michael J. Spenceref2284f2012-08-15 19:05:47 +0000763}
764
Michael J. Spencer0a7625d2011-12-08 22:50:09 +0000765error_code detail::directory_iterator_construct(detail::DirIterState &it,
766 StringRef path){
Michael J. Spencer52714862011-01-05 16:38:57 +0000767 SmallString<128> path_null(path);
768 DIR *directory = ::opendir(path_null.c_str());
769 if (directory == 0)
770 return error_code(errno, system_category());
771
772 it.IterationHandle = reinterpret_cast<intptr_t>(directory);
773 // Add something for replace_filename to replace.
774 path::append(path_null, ".");
775 it.CurrentEntry = directory_entry(path_null.str());
776 return directory_iterator_increment(it);
777}
778
Michael J. Spencer0a7625d2011-12-08 22:50:09 +0000779error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
Michael J. Spencer52714862011-01-05 16:38:57 +0000780 if (it.IterationHandle)
781 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle));
782 it.IterationHandle = 0;
783 it.CurrentEntry = directory_entry();
David Blaikie18544b92012-02-09 19:24:12 +0000784 return error_code::success();
Michael J. Spencer52714862011-01-05 16:38:57 +0000785}
786
Michael J. Spencer0a7625d2011-12-08 22:50:09 +0000787error_code detail::directory_iterator_increment(detail::DirIterState &it) {
Michael J. Spencer52714862011-01-05 16:38:57 +0000788 errno = 0;
789 dirent *cur_dir = ::readdir(reinterpret_cast<DIR *>(it.IterationHandle));
790 if (cur_dir == 0 && errno != 0) {
791 return error_code(errno, system_category());
792 } else if (cur_dir != 0) {
793 StringRef name(cur_dir->d_name, NAMLEN(cur_dir));
794 if ((name.size() == 1 && name[0] == '.') ||
795 (name.size() == 2 && name[0] == '.' && name[1] == '.'))
796 return directory_iterator_increment(it);
797 it.CurrentEntry.replace_filename(name);
798 } else
799 return directory_iterator_destruct(it);
800
David Blaikie18544b92012-02-09 19:24:12 +0000801 return error_code::success();
Michael J. Spencer52714862011-01-05 16:38:57 +0000802}
803
Michael J. Spenceree1699c2011-01-15 18:52:33 +0000804error_code get_magic(const Twine &path, uint32_t len,
805 SmallVectorImpl<char> &result) {
806 SmallString<128> PathStorage;
807 StringRef Path = path.toNullTerminatedStringRef(PathStorage);
808 result.set_size(0);
809
810 // Open path.
811 std::FILE *file = std::fopen(Path.data(), "rb");
812 if (file == 0)
813 return error_code(errno, system_category());
814
815 // Reserve storage.
816 result.reserve(len);
817
818 // Read magic!
819 size_t size = std::fread(result.data(), 1, len, file);
820 if (std::ferror(file) != 0) {
821 std::fclose(file);
822 return error_code(errno, system_category());
Evgeniy Stepanov6eb44842013-06-20 15:56:05 +0000823 } else if (size != len) {
Michael J. Spenceree1699c2011-01-15 18:52:33 +0000824 if (std::feof(file) != 0) {
825 std::fclose(file);
826 result.set_size(size);
827 return make_error_code(errc::value_too_large);
828 }
829 }
830 std::fclose(file);
Evgeniy Stepanov6eb44842013-06-20 15:56:05 +0000831 result.set_size(size);
David Blaikie18544b92012-02-09 19:24:12 +0000832 return error_code::success();
Michael J. Spenceree1699c2011-01-15 18:52:33 +0000833}
834
Nick Kledzik18497e92012-06-20 00:28:54 +0000835error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,
836 bool map_writable, void *&result) {
837 SmallString<128> path_storage;
838 StringRef name = path.toNullTerminatedStringRef(path_storage);
839 int oflags = map_writable ? O_RDWR : O_RDONLY;
840 int ofd = ::open(name.begin(), oflags);
841 if ( ofd == -1 )
842 return error_code(errno, system_category());
843 AutoFD fd(ofd);
844 int flags = map_writable ? MAP_SHARED : MAP_PRIVATE;
845 int prot = map_writable ? (PROT_READ|PROT_WRITE) : PROT_READ;
846#ifdef MAP_FILE
847 flags |= MAP_FILE;
848#endif
849 result = ::mmap(0, size, prot, flags, fd, file_offset);
850 if (result == MAP_FAILED) {
851 return error_code(errno, system_category());
852 }
853
854 return error_code::success();
855}
856
857error_code unmap_file_pages(void *base, size_t size) {
858 if ( ::munmap(base, size) == -1 )
859 return error_code(errno, system_category());
860
861 return error_code::success();
862}
863
864
Michael J. Spencer9fc1d9d2010-12-01 19:32:01 +0000865} // end namespace fs
Michael J. Spencerebad2f92010-11-29 22:28:51 +0000866} // end namespace sys
867} // end namespace llvm