Line data Source code
1 : //===- llvm/Support/Unix/Path.inc - 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 Path 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"
20 : #include <limits.h>
21 : #include <stdio.h>
22 : #if HAVE_SYS_STAT_H
23 : #include <sys/stat.h>
24 : #endif
25 : #if HAVE_FCNTL_H
26 : #include <fcntl.h>
27 : #endif
28 : #ifdef HAVE_UNISTD_H
29 : #include <unistd.h>
30 : #endif
31 : #ifdef HAVE_SYS_MMAN_H
32 : #include <sys/mman.h>
33 : #endif
34 :
35 : #include <dirent.h>
36 : #include <pwd.h>
37 :
38 : #ifdef __APPLE__
39 : #include <mach-o/dyld.h>
40 : #include <sys/attr.h>
41 : #endif
42 :
43 : // Both stdio.h and cstdio are included via different paths and
44 : // stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros
45 : // either.
46 : #undef ferror
47 : #undef feof
48 :
49 : // For GNU Hurd
50 : #if defined(__GNU__) && !defined(PATH_MAX)
51 : # define PATH_MAX 4096
52 : # define MAXPATHLEN 4096
53 : #endif
54 :
55 : #include <sys/types.h>
56 : #if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && \
57 : !defined(__linux__)
58 : #include <sys/statvfs.h>
59 : #define STATVFS statvfs
60 : #define FSTATVFS fstatvfs
61 : #define STATVFS_F_FRSIZE(vfs) vfs.f_frsize
62 : #else
63 : #if defined(__OpenBSD__) || defined(__FreeBSD__)
64 : #include <sys/mount.h>
65 : #include <sys/param.h>
66 : #elif defined(__linux__)
67 : #if defined(HAVE_LINUX_MAGIC_H)
68 : #include <linux/magic.h>
69 : #else
70 : #if defined(HAVE_LINUX_NFS_FS_H)
71 : #include <linux/nfs_fs.h>
72 : #endif
73 : #if defined(HAVE_LINUX_SMB_H)
74 : #include <linux/smb.h>
75 : #endif
76 : #endif
77 : #include <sys/vfs.h>
78 : #else
79 : #include <sys/mount.h>
80 : #endif
81 : #define STATVFS statfs
82 : #define FSTATVFS fstatfs
83 : #define STATVFS_F_FRSIZE(vfs) static_cast<uint64_t>(vfs.f_bsize)
84 : #endif
85 :
86 : #if defined(__NetBSD__)
87 : #define STATVFS_F_FLAG(vfs) (vfs).f_flag
88 : #else
89 : #define STATVFS_F_FLAG(vfs) (vfs).f_flags
90 : #endif
91 :
92 : using namespace llvm;
93 :
94 : namespace llvm {
95 : namespace sys {
96 : namespace fs {
97 :
98 : const file_t kInvalidFile = -1;
99 :
100 : #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
101 : defined(__minix) || defined(__FreeBSD_kernel__) || defined(__linux__) || \
102 : defined(__CYGWIN__) || defined(__DragonFly__) || defined(_AIX)
103 : static int
104 0 : test_dir(char ret[PATH_MAX], const char *dir, const char *bin)
105 : {
106 : struct stat sb;
107 : char fullpath[PATH_MAX];
108 :
109 0 : snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin);
110 0 : if (!realpath(fullpath, ret))
111 : return 1;
112 0 : if (stat(fullpath, &sb) != 0)
113 0 : return 1;
114 :
115 : return 0;
116 : }
117 :
118 : static char *
119 0 : getprogpath(char ret[PATH_MAX], const char *bin)
120 : {
121 : char *pv, *s, *t;
122 :
123 : /* First approach: absolute path. */
124 0 : if (bin[0] == '/') {
125 0 : if (test_dir(ret, "/", bin) == 0)
126 : return ret;
127 0 : return nullptr;
128 : }
129 :
130 : /* Second approach: relative path. */
131 0 : if (strchr(bin, '/')) {
132 : char cwd[PATH_MAX];
133 0 : if (!getcwd(cwd, PATH_MAX))
134 : return nullptr;
135 0 : if (test_dir(ret, cwd, bin) == 0)
136 : return ret;
137 0 : return nullptr;
138 : }
139 :
140 : /* Third approach: $PATH */
141 0 : if ((pv = getenv("PATH")) == nullptr)
142 : return nullptr;
143 0 : s = pv = strdup(pv);
144 0 : if (!pv)
145 : return nullptr;
146 0 : while ((t = strsep(&s, ":")) != nullptr) {
147 0 : if (test_dir(ret, t, bin) == 0) {
148 0 : free(pv);
149 0 : return ret;
150 : }
151 : }
152 0 : free(pv);
153 0 : return nullptr;
154 : }
155 : #endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__
156 :
157 : /// GetMainExecutable - Return the path to the main executable, given the
158 : /// value of argv[0] from program startup.
159 40677 : std::string getMainExecutable(const char *argv0, void *MainAddr) {
160 : #if defined(__APPLE__)
161 : // On OS X the executable path is saved to the stack by dyld. Reading it
162 : // from there is much faster than calling dladdr, especially for large
163 : // binaries with symbols.
164 : char exe_path[MAXPATHLEN];
165 : uint32_t size = sizeof(exe_path);
166 : if (_NSGetExecutablePath(exe_path, &size) == 0) {
167 : char link_path[MAXPATHLEN];
168 : if (realpath(exe_path, link_path))
169 : return link_path;
170 : }
171 : #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
172 : defined(__minix) || defined(__DragonFly__) || \
173 : defined(__FreeBSD_kernel__) || defined(_AIX)
174 : char exe_path[PATH_MAX];
175 :
176 : if (getprogpath(exe_path, argv0) != NULL)
177 : return exe_path;
178 : #elif defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__)
179 : char exe_path[MAXPATHLEN];
180 : StringRef aPath("/proc/self/exe");
181 40677 : if (sys::fs::exists(aPath)) {
182 : // /proc is not always mounted under Linux (chroot for example).
183 81354 : ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path));
184 40677 : if (len >= 0)
185 40677 : return std::string(exe_path, len);
186 : } else {
187 : // Fall back to the classical detection.
188 0 : if (getprogpath(exe_path, argv0))
189 0 : return exe_path;
190 : }
191 : #elif defined(HAVE_DLFCN_H) && defined(HAVE_DLADDR)
192 : // Use dladdr to get executable path if available.
193 : Dl_info DLInfo;
194 : int err = dladdr(MainAddr, &DLInfo);
195 : if (err == 0)
196 : return "";
197 :
198 : // If the filename is a symlink, we need to resolve and return the location of
199 : // the actual executable.
200 : char link_path[MAXPATHLEN];
201 : if (realpath(DLInfo.dli_fname, link_path))
202 : return link_path;
203 : #else
204 : #error GetMainExecutable is not implemented on this host yet.
205 : #endif
206 0 : return "";
207 : }
208 :
209 80 : TimePoint<> basic_file_status::getLastAccessedTime() const {
210 160 : return toTimePoint(fs_st_atime);
211 : }
212 :
213 1490045 : TimePoint<> basic_file_status::getLastModificationTime() const {
214 2980090 : return toTimePoint(fs_st_mtime);
215 : }
216 :
217 1566760 : UniqueID file_status::getUniqueID() const {
218 1566760 : return UniqueID(fs_st_dev, fs_st_ino);
219 : }
220 :
221 0 : uint32_t file_status::getLinkCount() const {
222 0 : return fs_st_nlinks;
223 : }
224 :
225 25 : ErrorOr<space_info> disk_space(const Twine &Path) {
226 : struct STATVFS Vfs;
227 50 : if (::STATVFS(Path.str().c_str(), &Vfs))
228 0 : return std::error_code(errno, std::generic_category());
229 25 : auto FrSize = STATVFS_F_FRSIZE(Vfs);
230 : space_info SpaceInfo;
231 25 : SpaceInfo.capacity = static_cast<uint64_t>(Vfs.f_blocks) * FrSize;
232 25 : SpaceInfo.free = static_cast<uint64_t>(Vfs.f_bfree) * FrSize;
233 25 : SpaceInfo.available = static_cast<uint64_t>(Vfs.f_bavail) * FrSize;
234 : return SpaceInfo;
235 : }
236 :
237 40414 : std::error_code current_path(SmallVectorImpl<char> &result) {
238 : result.clear();
239 :
240 40414 : const char *pwd = ::getenv("PWD");
241 40414 : llvm::sys::fs::file_status PWDStatus, DotStatus;
242 33247 : if (pwd && llvm::sys::path::is_absolute(pwd) &&
243 33247 : !llvm::sys::fs::status(pwd, PWDStatus) &&
244 73661 : !llvm::sys::fs::status(".", DotStatus) &&
245 45925 : PWDStatus.getUniqueID() == DotStatus.getUniqueID()) {
246 27736 : result.append(pwd, pwd + strlen(pwd));
247 27736 : return std::error_code();
248 : }
249 :
250 : #ifdef MAXPATHLEN
251 : result.reserve(MAXPATHLEN);
252 : #else
253 : // For GNU Hurd
254 : result.reserve(1024);
255 : #endif
256 :
257 : while (true) {
258 25356 : if (::getcwd(result.data(), result.capacity()) == nullptr) {
259 : // See if there was a real error.
260 0 : if (errno != ENOMEM)
261 0 : return std::error_code(errno, std::generic_category());
262 : // Otherwise there just wasn't enough space.
263 0 : result.reserve(result.capacity() * 2);
264 : } else
265 : break;
266 : }
267 :
268 12678 : result.set_size(strlen(result.data()));
269 12678 : return std::error_code();
270 : }
271 :
272 11023 : std::error_code set_current_path(const Twine &path) {
273 : SmallString<128> path_storage;
274 11023 : StringRef p = path.toNullTerminatedStringRef(path_storage);
275 :
276 11023 : if (::chdir(p.begin()) == -1)
277 115 : return std::error_code(errno, std::generic_category());
278 :
279 10908 : return std::error_code();
280 : }
281 :
282 3541 : std::error_code create_directory(const Twine &path, bool IgnoreExisting,
283 : perms Perms) {
284 : SmallString<128> path_storage;
285 3541 : StringRef p = path.toNullTerminatedStringRef(path_storage);
286 :
287 3541 : if (::mkdir(p.begin(), Perms) == -1) {
288 2205 : if (errno != EEXIST || !IgnoreExisting)
289 1128 : return std::error_code(errno, std::generic_category());
290 : }
291 :
292 2413 : return std::error_code();
293 : }
294 :
295 : // Note that we are using symbolic link because hard links are not supported by
296 : // all filesystems (SMB doesn't).
297 1768 : std::error_code create_link(const Twine &to, const Twine &from) {
298 : // Get arguments.
299 : SmallString<128> from_storage;
300 : SmallString<128> to_storage;
301 1768 : StringRef f = from.toNullTerminatedStringRef(from_storage);
302 1768 : StringRef t = to.toNullTerminatedStringRef(to_storage);
303 :
304 1768 : if (::symlink(t.begin(), f.begin()) == -1)
305 0 : return std::error_code(errno, std::generic_category());
306 :
307 1768 : return std::error_code();
308 : }
309 :
310 4 : std::error_code create_hard_link(const Twine &to, const Twine &from) {
311 : // Get arguments.
312 : SmallString<128> from_storage;
313 : SmallString<128> to_storage;
314 4 : StringRef f = from.toNullTerminatedStringRef(from_storage);
315 4 : StringRef t = to.toNullTerminatedStringRef(to_storage);
316 :
317 4 : if (::link(t.begin(), f.begin()) == -1)
318 0 : return std::error_code(errno, std::generic_category());
319 :
320 4 : return std::error_code();
321 : }
322 :
323 15510 : std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
324 : SmallString<128> path_storage;
325 15510 : StringRef p = path.toNullTerminatedStringRef(path_storage);
326 :
327 : struct stat buf;
328 15510 : if (lstat(p.begin(), &buf) != 0) {
329 2377 : if (errno != ENOENT || !IgnoreNonExisting)
330 1 : return std::error_code(errno, std::generic_category());
331 2376 : return std::error_code();
332 : }
333 :
334 : // Note: this check catches strange situations. In all cases, LLVM should
335 : // only be involved in the creation and deletion of regular files. This
336 : // check ensures that what we're trying to erase is a regular file. It
337 : // effectively prevents LLVM from erasing things like /dev/null, any block
338 : // special file, or other things that aren't "regular" files.
339 13133 : if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) && !S_ISLNK(buf.st_mode))
340 : return make_error_code(errc::operation_not_permitted);
341 :
342 12807 : if (::remove(p.begin()) == -1) {
343 2 : if (errno != ENOENT || !IgnoreNonExisting)
344 2 : return std::error_code(errno, std::generic_category());
345 : }
346 :
347 12805 : return std::error_code();
348 : }
349 :
350 0 : static bool is_local_impl(struct STATVFS &Vfs) {
351 : #if defined(__linux__)
352 : #ifndef NFS_SUPER_MAGIC
353 : #define NFS_SUPER_MAGIC 0x6969
354 : #endif
355 : #ifndef SMB_SUPER_MAGIC
356 : #define SMB_SUPER_MAGIC 0x517B
357 : #endif
358 : #ifndef CIFS_MAGIC_NUMBER
359 : #define CIFS_MAGIC_NUMBER 0xFF534D42
360 : #endif
361 0 : switch ((uint32_t)Vfs.f_type) {
362 : case NFS_SUPER_MAGIC:
363 : case SMB_SUPER_MAGIC:
364 : case CIFS_MAGIC_NUMBER:
365 : return false;
366 0 : default:
367 0 : return true;
368 : }
369 : #elif defined(__CYGWIN__)
370 : // Cygwin doesn't expose this information; would need to use Win32 API.
371 : return false;
372 : #elif defined(__Fuchsia__)
373 : // Fuchsia doesn't yet support remote filesystem mounts.
374 : return true;
375 : #elif defined(__HAIKU__)
376 : // Haiku doesn't expose this information.
377 : return false;
378 : #elif defined(__sun)
379 : // statvfs::f_basetype contains a null-terminated FSType name of the mounted target
380 : StringRef fstype(Vfs.f_basetype);
381 : // NFS is the only non-local fstype??
382 : return !fstype.equals("nfs");
383 : #else
384 : return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL);
385 : #endif
386 : }
387 :
388 0 : std::error_code is_local(const Twine &Path, bool &Result) {
389 : struct STATVFS Vfs;
390 0 : if (::STATVFS(Path.str().c_str(), &Vfs))
391 0 : return std::error_code(errno, std::generic_category());
392 :
393 0 : Result = is_local_impl(Vfs);
394 0 : return std::error_code();
395 : }
396 :
397 0 : std::error_code is_local(int FD, bool &Result) {
398 : struct STATVFS Vfs;
399 0 : if (::FSTATVFS(FD, &Vfs))
400 0 : return std::error_code(errno, std::generic_category());
401 :
402 0 : Result = is_local_impl(Vfs);
403 0 : return std::error_code();
404 : }
405 :
406 14891 : std::error_code rename(const Twine &from, const Twine &to) {
407 : // Get arguments.
408 : SmallString<128> from_storage;
409 : SmallString<128> to_storage;
410 14891 : StringRef f = from.toNullTerminatedStringRef(from_storage);
411 14891 : StringRef t = to.toNullTerminatedStringRef(to_storage);
412 :
413 14891 : if (::rename(f.begin(), t.begin()) == -1)
414 0 : return std::error_code(errno, std::generic_category());
415 :
416 14891 : return std::error_code();
417 : }
418 :
419 5328 : std::error_code resize_file(int FD, uint64_t Size) {
420 : #if defined(HAVE_POSIX_FALLOCATE)
421 : // If we have posix_fallocate use it. Unlike ftruncate it always allocates
422 : // space, so we get an error if the disk is full.
423 5328 : if (int Err = ::posix_fallocate(FD, 0, Size)) {
424 0 : if (Err != EINVAL && Err != EOPNOTSUPP)
425 0 : return std::error_code(Err, std::generic_category());
426 : }
427 : #endif
428 : // Use ftruncate as a fallback. It may or may not allocate space. At least on
429 : // OS X with HFS+ it does.
430 5328 : if (::ftruncate(FD, Size) == -1)
431 0 : return std::error_code(errno, std::generic_category());
432 :
433 5328 : return std::error_code();
434 : }
435 :
436 : static int convertAccessMode(AccessMode Mode) {
437 : switch (Mode) {
438 : case AccessMode::Exist:
439 : return F_OK;
440 : case AccessMode::Write:
441 : return W_OK;
442 : case AccessMode::Execute:
443 : return R_OK | X_OK; // scripts also need R_OK.
444 : }
445 0 : llvm_unreachable("invalid enum");
446 : }
447 :
448 541969 : std::error_code access(const Twine &Path, AccessMode Mode) {
449 : SmallString<128> PathStorage;
450 541969 : StringRef P = Path.toNullTerminatedStringRef(PathStorage);
451 :
452 541969 : if (::access(P.begin(), convertAccessMode(Mode)) == -1)
453 388130 : return std::error_code(errno, std::generic_category());
454 :
455 153839 : if (Mode == AccessMode::Execute) {
456 : // Don't say that directories are executable.
457 : struct stat buf;
458 9554 : if (0 != stat(P.begin(), &buf))
459 0 : return errc::permission_denied;
460 9554 : if (!S_ISREG(buf.st_mode))
461 1 : return errc::permission_denied;
462 : }
463 :
464 153838 : return std::error_code();
465 : }
466 :
467 264694 : bool can_execute(const Twine &Path) {
468 264694 : return !access(Path, AccessMode::Execute);
469 : }
470 :
471 243 : bool equivalent(file_status A, file_status B) {
472 : assert(status_known(A) && status_known(B));
473 243 : return A.fs_st_dev == B.fs_st_dev &&
474 243 : A.fs_st_ino == B.fs_st_ino;
475 : }
476 :
477 250 : std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
478 250 : file_status fsA, fsB;
479 250 : if (std::error_code ec = status(A, fsA))
480 4 : return ec;
481 246 : if (std::error_code ec = status(B, fsB))
482 5 : return ec;
483 241 : result = equivalent(fsA, fsB);
484 241 : return std::error_code();
485 : }
486 :
487 0 : static void expandTildeExpr(SmallVectorImpl<char> &Path) {
488 0 : StringRef PathStr(Path.begin(), Path.size());
489 0 : if (PathStr.empty() || !PathStr.startswith("~"))
490 0 : return;
491 :
492 0 : PathStr = PathStr.drop_front();
493 : StringRef Expr =
494 0 : PathStr.take_until([](char c) { return path::is_separator(c); });
495 0 : StringRef Remainder = PathStr.substr(Expr.size() + 1);
496 : SmallString<128> Storage;
497 0 : if (Expr.empty()) {
498 : // This is just ~/..., resolve it to the current user's home dir.
499 0 : if (!path::home_directory(Storage)) {
500 : // For some reason we couldn't get the home directory. Just exit.
501 : return;
502 : }
503 :
504 : // Overwrite the first character and insert the rest.
505 0 : Path[0] = Storage[0];
506 0 : Path.insert(Path.begin() + 1, Storage.begin() + 1, Storage.end());
507 0 : return;
508 : }
509 :
510 : // This is a string of the form ~username/, look up this user's entry in the
511 : // password database.
512 : struct passwd *Entry = nullptr;
513 : std::string User = Expr.str();
514 0 : Entry = ::getpwnam(User.c_str());
515 :
516 0 : if (!Entry) {
517 : // Unable to look up the entry, just return back the original path.
518 : return;
519 : }
520 :
521 : Storage = Remainder;
522 : Path.clear();
523 0 : Path.append(Entry->pw_dir, Entry->pw_dir + strlen(Entry->pw_dir));
524 0 : llvm::sys::path::append(Path, Storage);
525 : }
526 :
527 : static file_type typeForMode(mode_t Mode) {
528 1791875 : if (S_ISDIR(Mode))
529 : return file_type::directory_file;
530 1061047 : else if (S_ISREG(Mode))
531 : return file_type::regular_file;
532 1618 : else if (S_ISBLK(Mode))
533 : return file_type::block_file;
534 1618 : else if (S_ISCHR(Mode))
535 : return file_type::character_file;
536 677 : else if (S_ISFIFO(Mode))
537 : return file_type::fifo_file;
538 674 : else if (S_ISSOCK(Mode))
539 : return file_type::socket_file;
540 674 : else if (S_ISLNK(Mode))
541 : return file_type::symlink_file;
542 : return file_type::type_unknown;
543 : }
544 :
545 2516362 : static std::error_code fillStatus(int StatRet, const struct stat &Status,
546 : file_status &Result) {
547 2516362 : if (StatRet != 0) {
548 774151 : std::error_code EC(errno, std::generic_category());
549 : if (EC == errc::no_such_file_or_directory)
550 774069 : Result = file_status(file_type::file_not_found);
551 : else
552 82 : Result = file_status(file_type::status_error);
553 774151 : return EC;
554 : }
555 :
556 1742211 : perms Perms = static_cast<perms>(Status.st_mode) & all_perms;
557 1742211 : Result = file_status(typeForMode(Status.st_mode), Perms, Status.st_dev,
558 1742211 : Status.st_nlink, Status.st_ino, Status.st_atime,
559 1742211 : Status.st_mtime, Status.st_uid, Status.st_gid,
560 1742211 : Status.st_size);
561 :
562 1742211 : return std::error_code();
563 : }
564 :
565 1616172 : std::error_code status(const Twine &Path, file_status &Result, bool Follow) {
566 : SmallString<128> PathStorage;
567 1616172 : StringRef P = Path.toNullTerminatedStringRef(PathStorage);
568 :
569 : struct stat Status;
570 1616201 : int StatRet = (Follow ? ::stat : ::lstat)(P.begin(), &Status);
571 1616172 : return fillStatus(StatRet, Status, Result);
572 : }
573 :
574 900194 : std::error_code status(int FD, file_status &Result) {
575 : struct stat Status;
576 : int StatRet = ::fstat(FD, &Status);
577 900194 : return fillStatus(StatRet, Status, Result);
578 : }
579 :
580 27 : std::error_code setPermissions(const Twine &Path, perms Permissions) {
581 : SmallString<128> PathStorage;
582 27 : StringRef P = Path.toNullTerminatedStringRef(PathStorage);
583 :
584 27 : if (::chmod(P.begin(), Permissions))
585 0 : return std::error_code(errno, std::generic_category());
586 27 : return std::error_code();
587 : }
588 :
589 7 : std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
590 : TimePoint<> ModificationTime) {
591 : #if defined(HAVE_FUTIMENS)
592 : timespec Times[2];
593 7 : Times[0] = sys::toTimeSpec(AccessTime);
594 7 : Times[1] = sys::toTimeSpec(ModificationTime);
595 7 : if (::futimens(FD, Times))
596 0 : return std::error_code(errno, std::generic_category());
597 7 : return std::error_code();
598 : #elif defined(HAVE_FUTIMES)
599 : timeval Times[2];
600 : Times[0] = sys::toTimeVal(
601 : std::chrono::time_point_cast<std::chrono::microseconds>(AccessTime));
602 : Times[1] =
603 : sys::toTimeVal(std::chrono::time_point_cast<std::chrono::microseconds>(
604 : ModificationTime));
605 : if (::futimes(FD, Times))
606 : return std::error_code(errno, std::generic_category());
607 : return std::error_code();
608 : #else
609 : #warning Missing futimes() and futimens()
610 : return make_error_code(errc::function_not_supported);
611 : #endif
612 : }
613 :
614 169645 : std::error_code mapped_file_region::init(int FD, uint64_t Offset,
615 : mapmode Mode) {
616 : assert(Size != 0);
617 :
618 169645 : int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE;
619 169645 : int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE);
620 : #if defined(__APPLE__)
621 : //----------------------------------------------------------------------
622 : // Newer versions of MacOSX have a flag that will allow us to read from
623 : // binaries whose code signature is invalid without crashing by using
624 : // the MAP_RESILIENT_CODESIGN flag. Also if a file from removable media
625 : // is mapped we can avoid crashing and return zeroes to any pages we try
626 : // to read if the media becomes unavailable by using the
627 : // MAP_RESILIENT_MEDIA flag. These flags are only usable when mapping
628 : // with PROT_READ, so take care not to specify them otherwise.
629 : //----------------------------------------------------------------------
630 : if (Mode == readonly) {
631 : #if defined(MAP_RESILIENT_CODESIGN)
632 : flags |= MAP_RESILIENT_CODESIGN;
633 : #endif
634 : #if defined(MAP_RESILIENT_MEDIA)
635 : flags |= MAP_RESILIENT_MEDIA;
636 : #endif
637 : }
638 : #endif // #if defined (__APPLE__)
639 :
640 169645 : Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset);
641 169645 : if (Mapping == MAP_FAILED)
642 0 : return std::error_code(errno, std::generic_category());
643 169645 : return std::error_code();
644 : }
645 :
646 169645 : mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length,
647 169645 : uint64_t offset, std::error_code &ec)
648 169645 : : Size(length), Mapping(), Mode(mode) {
649 : (void)Mode;
650 169645 : ec = init(fd, offset, mode);
651 169645 : if (ec)
652 0 : Mapping = nullptr;
653 169645 : }
654 :
655 70528 : mapped_file_region::~mapped_file_region() {
656 35264 : if (Mapping)
657 35264 : ::munmap(Mapping, Size);
658 35264 : }
659 :
660 784 : size_t mapped_file_region::size() const {
661 : assert(Mapping && "Mapping failed but used anyway!");
662 784 : return Size;
663 : }
664 :
665 337695 : char *mapped_file_region::data() const {
666 : assert(Mapping && "Mapping failed but used anyway!");
667 337695 : return reinterpret_cast<char*>(Mapping);
668 : }
669 :
670 164210 : const char *mapped_file_region::const_data() const {
671 : assert(Mapping && "Mapping failed but used anyway!");
672 164210 : return reinterpret_cast<const char*>(Mapping);
673 : }
674 :
675 492627 : int mapped_file_region::alignment() {
676 492627 : return Process::getPageSize();
677 : }
678 :
679 4321384 : std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
680 : StringRef path,
681 : bool follow_symlinks) {
682 : SmallString<128> path_null(path);
683 4321408 : DIR *directory = ::opendir(path_null.c_str());
684 4321459 : if (!directory)
685 4280397 : return std::error_code(errno, std::generic_category());
686 :
687 41062 : it.IterationHandle = reinterpret_cast<intptr_t>(directory);
688 : // Add something for replace_filename to replace.
689 41062 : path::append(path_null, ".");
690 41062 : it.CurrentEntry = directory_entry(path_null.str(), follow_symlinks);
691 41062 : return directory_iterator_increment(it);
692 : }
693 :
694 4362499 : std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
695 4362499 : if (it.IterationHandle)
696 41062 : ::closedir(reinterpret_cast<DIR *>(it.IterationHandle));
697 4362499 : it.IterationHandle = 0;
698 4362499 : it.CurrentEntry = directory_entry();
699 4362513 : return std::error_code();
700 : }
701 :
702 0 : static file_type direntType(dirent* Entry) {
703 : // Most platforms provide the file type in the dirent: Linux/BSD/Mac.
704 : // The DTTOIF macro lets us reuse our status -> type conversion.
705 : #if defined(_DIRENT_HAVE_D_TYPE) && defined(DTTOIF)
706 0 : return typeForMode(DTTOIF(Entry->d_type));
707 : #else
708 : // Other platforms such as Solaris require a stat() to get the type.
709 : return file_type::type_unknown;
710 : #endif
711 : }
712 :
713 172802 : std::error_code detail::directory_iterator_increment(detail::DirIterState &It) {
714 172802 : errno = 0;
715 172802 : dirent *CurDir = ::readdir(reinterpret_cast<DIR *>(It.IterationHandle));
716 172802 : if (CurDir == nullptr && errno != 0) {
717 0 : return std::error_code(errno, std::generic_category());
718 172802 : } else if (CurDir != nullptr) {
719 131756 : StringRef Name(CurDir->d_name);
720 131756 : if ((Name.size() == 1 && Name[0] == '.') ||
721 41087 : (Name.size() == 2 && Name[0] == '.' && Name[1] == '.'))
722 82092 : return directory_iterator_increment(It);
723 108440 : It.CurrentEntry.replace_filename(Name, direntType(CurDir));
724 : } else
725 41046 : return directory_iterator_destruct(It);
726 :
727 49664 : return std::error_code();
728 : }
729 :
730 238 : ErrorOr<basic_file_status> directory_entry::status() const {
731 238 : file_status s;
732 476 : if (auto EC = fs::status(Path, s, FollowSymlinks))
733 13 : return EC;
734 : return s;
735 : }
736 :
737 : #if !defined(F_GETPATH)
738 804581 : static bool hasProcSelfFD() {
739 : // If we have a /proc filesystem mounted, we can quickly establish the
740 : // real name of the file with readlink
741 804581 : static const bool Result = (::access("/proc/self/fd", R_OK) == 0);
742 804581 : return Result;
743 : }
744 : #endif
745 :
746 2233690 : static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags,
747 : FileAccess Access) {
748 : int Result = 0;
749 2233690 : if (Access == FA_Read)
750 : Result |= O_RDONLY;
751 36505 : else if (Access == FA_Write)
752 : Result |= O_WRONLY;
753 25878 : else if (Access == (FA_Read | FA_Write))
754 : Result |= O_RDWR;
755 :
756 : // This is for compatibility with old code that assumed F_Append implied
757 : // would open an existing file. See Windows/Path.inc for a longer comment.
758 2233690 : if (Flags & F_Append)
759 : Disp = CD_OpenAlways;
760 :
761 2233685 : if (Disp == CD_CreateNew) {
762 : Result |= O_CREAT; // Create if it doesn't exist.
763 25740 : Result |= O_EXCL; // Fail if it does.
764 2207950 : } else if (Disp == CD_CreateAlways) {
765 : Result |= O_CREAT; // Create if it doesn't exist.
766 10744 : Result |= O_TRUNC; // Truncate if it does.
767 2197206 : } else if (Disp == CD_OpenAlways) {
768 9 : Result |= O_CREAT; // Create if it doesn't exist.
769 : } else if (Disp == CD_OpenExisting) {
770 : // Nothing special, just don't add O_CREAT and we get these semantics.
771 : }
772 :
773 2233690 : if (Flags & F_Append)
774 7 : Result |= O_APPEND;
775 :
776 : #ifdef O_CLOEXEC
777 2233690 : if (!(Flags & OF_ChildInherit))
778 2233690 : Result |= O_CLOEXEC;
779 : #endif
780 :
781 2233690 : return Result;
782 : }
783 :
784 2233692 : std::error_code openFile(const Twine &Name, int &ResultFD,
785 : CreationDisposition Disp, FileAccess Access,
786 : OpenFlags Flags, unsigned Mode) {
787 2233692 : int OpenFlags = nativeOpenFlags(Disp, Flags, Access);
788 :
789 : SmallString<128> Storage;
790 2233692 : StringRef P = Name.toNullTerminatedStringRef(Storage);
791 : // Call ::open in a lambda to avoid overload resolution in RetryAfterSignal
792 : // when open is overloaded, such as in Bionic.
793 2233691 : auto Open = [&]() { return ::open(P.begin(), OpenFlags, Mode); };
794 2233691 : if ((ResultFD = sys::RetryAfterSignal(-1, Open)) < 0)
795 1177606 : return std::error_code(errno, std::generic_category());
796 : #ifndef O_CLOEXEC
797 : if (!(Flags & OF_ChildInherit)) {
798 : int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
799 : (void)r;
800 : assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed");
801 : }
802 : #endif
803 1056089 : return std::error_code();
804 : }
805 :
806 0 : Expected<int> openNativeFile(const Twine &Name, CreationDisposition Disp,
807 : FileAccess Access, OpenFlags Flags,
808 : unsigned Mode) {
809 :
810 : int FD;
811 0 : std::error_code EC = openFile(Name, FD, Disp, Access, Flags, Mode);
812 0 : if (EC)
813 0 : return errorCodeToError(EC);
814 : return FD;
815 : }
816 :
817 2197187 : std::error_code openFileForRead(const Twine &Name, int &ResultFD,
818 : OpenFlags Flags,
819 : SmallVectorImpl<char> *RealPath) {
820 : std::error_code EC =
821 2197187 : openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666);
822 2197190 : if (EC)
823 1177014 : return EC;
824 :
825 : // Attempt to get the real name of the file, if the user asked
826 1020176 : if(!RealPath)
827 215595 : return std::error_code();
828 : RealPath->clear();
829 : #if defined(F_GETPATH)
830 : // When F_GETPATH is availble, it is the quickest way to get
831 : // the real path name.
832 : char Buffer[MAXPATHLEN];
833 : if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1)
834 : RealPath->append(Buffer, Buffer + strlen(Buffer));
835 : #else
836 : char Buffer[PATH_MAX];
837 804581 : if (hasProcSelfFD()) {
838 : char ProcPath[64];
839 804581 : snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD);
840 804581 : ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer));
841 804581 : if (CharCount > 0)
842 804581 : RealPath->append(Buffer, Buffer + CharCount);
843 : } else {
844 : SmallString<128> Storage;
845 0 : StringRef P = Name.toNullTerminatedStringRef(Storage);
846 :
847 : // Use ::realpath to get the real path name
848 0 : if (::realpath(P.begin(), Buffer) != nullptr)
849 0 : RealPath->append(Buffer, Buffer + strlen(Buffer));
850 : }
851 : #endif
852 804581 : return std::error_code();
853 : }
854 :
855 0 : Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags,
856 : SmallVectorImpl<char> *RealPath) {
857 : file_t ResultFD;
858 0 : std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath);
859 0 : if (EC)
860 0 : return errorCodeToError(EC);
861 : return ResultFD;
862 : }
863 :
864 0 : void closeFile(file_t &F) {
865 0 : ::close(F);
866 0 : F = kInvalidFile;
867 0 : }
868 :
869 : template <typename T>
870 16 : static std::error_code remove_directories_impl(const T &Entry,
871 : bool IgnoreErrors) {
872 : std::error_code EC;
873 16 : directory_iterator Begin(Entry, EC, false);
874 16 : directory_iterator End;
875 37 : while (Begin != End) {
876 : auto &Item = *Begin;
877 21 : ErrorOr<basic_file_status> st = Item.status();
878 21 : if (!st && !IgnoreErrors)
879 : return st.getError();
880 :
881 21 : if (is_directory(*st)) {
882 11 : EC = remove_directories_impl(Item, IgnoreErrors);
883 11 : if (EC && !IgnoreErrors)
884 0 : return EC;
885 : }
886 :
887 21 : EC = fs::remove(Item.path(), true);
888 21 : if (EC && !IgnoreErrors)
889 0 : return EC;
890 :
891 : Begin.increment(EC);
892 21 : if (EC && !IgnoreErrors)
893 0 : return EC;
894 : }
895 16 : return std::error_code();
896 : }
897 11 :
898 : std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
899 : auto EC = remove_directories_impl(path, IgnoreErrors);
900 11 : if (EC && !IgnoreErrors)
901 11 : return EC;
902 25 : EC = fs::remove(path, true);
903 : if (EC && !IgnoreErrors)
904 14 : return EC;
905 14 : return std::error_code();
906 : }
907 :
908 14 : std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
909 7 : bool expand_tilde) {
910 7 : dest.clear();
911 0 : if (path.isTriviallyEmpty())
912 : return std::error_code();
913 :
914 14 : if (expand_tilde) {
915 14 : SmallString<128> Storage;
916 0 : path.toVector(Storage);
917 : expandTildeExpr(Storage);
918 : return real_path(Storage, dest, false);
919 14 : }
920 0 :
921 : SmallString<128> Storage;
922 11 : StringRef P = path.toNullTerminatedStringRef(Storage);
923 : char Buffer[PATH_MAX];
924 5 : if (::realpath(P.begin(), Buffer) == nullptr)
925 : return std::error_code(errno, std::generic_category());
926 : dest.append(Buffer, Buffer + strlen(Buffer));
927 5 : return std::error_code();
928 5 : }
929 12 :
930 : } // end namespace fs
931 7 :
932 7 : namespace path {
933 :
934 : bool home_directory(SmallVectorImpl<char> &result) {
935 7 : char *RequestedDir = getenv("HOME");
936 4 : if (!RequestedDir) {
937 4 : struct passwd *pw = getpwuid(getuid());
938 0 : if (pw && pw->pw_dir)
939 : RequestedDir = pw->pw_dir;
940 : }
941 7 : if (!RequestedDir)
942 7 : return false;
943 0 :
944 : result.clear();
945 : result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
946 7 : return true;
947 0 : }
948 :
949 5 : static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) {
950 : #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR)
951 : // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR.
952 5 : // macros defined in <unistd.h> on darwin >= 9
953 5 : int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR
954 5 : : _CS_DARWIN_USER_CACHE_DIR;
955 0 : size_t ConfLen = confstr(ConfName, nullptr, 0);
956 5 : if (ConfLen > 0) {
957 5 : do {
958 0 : Result.resize(ConfLen);
959 5 : ConfLen = confstr(ConfName, Result.data(), Result.size());
960 : } while (ConfLen > 0 && ConfLen != Result.size());
961 :
962 1409 : if (ConfLen > 0) {
963 : assert(Result.back() == 0);
964 : Result.pop_back();
965 : return true;
966 0 : }
967 :
968 1409 : Result.clear();
969 : }
970 0 : #endif
971 0 : return false;
972 0 : }
973 :
974 : static const char *getEnvTempDir() {
975 : // Check whether the temporary directory is specified by an environment
976 1409 : // variable.
977 : const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
978 1409 : for (const char *Env : EnvironmentVariables) {
979 65 : if (const char *Dir = std::getenv(Env))
980 1344 : return Dir;
981 1344 : }
982 :
983 : return nullptr;
984 : }
985 :
986 : static const char *getDefaultTempDir(bool ErasedOnReboot) {
987 : #ifdef P_tmpdir
988 157 : if ((bool)P_tmpdir)
989 157 : return P_tmpdir;
990 157 : #endif
991 2 :
992 2 : if (ErasedOnReboot)
993 : return "/tmp";
994 : return "/var/tmp";
995 157 : }
996 :
997 : void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
998 : Result.clear();
999 157 :
1000 157 : if (ErasedOnReboot) {
1001 : // There is no env variable for the cache directory.
1002 : if (const char *RequestedDir = getEnvTempDir()) {
1003 : Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1004 : return;
1005 : }
1006 : }
1007 :
1008 : if (getDarwinConfDir(ErasedOnReboot, Result))
1009 : return;
1010 :
1011 : const char *RequestedDir = getDefaultTempDir(ErasedOnReboot);
1012 : Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1013 : }
1014 :
1015 : } // end namespace path
1016 :
1017 : } // end namespace sys
1018 : } // end namespace llvm
|