1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <__assert> 10 #include <__config> 11 #include <__utility/unreachable.h> 12 #include <array> 13 #include <climits> 14 #include <cstdlib> 15 #include <filesystem> 16 #include <iterator> 17 #include <string_view> 18 #include <system_error> 19 #include <type_traits> 20 #include <vector> 21 22 #include "error.h" 23 #include "file_descriptor.h" 24 #include "path_parser.h" 25 #include "posix_compat.h" 26 #include "time_utils.h" 27 28 #if defined(_LIBCPP_WIN32API) 29 # define WIN32_LEAN_AND_MEAN 30 # define NOMINMAX 31 # include <windows.h> 32 #else 33 # include <dirent.h> 34 # include <sys/stat.h> 35 # include <sys/statvfs.h> 36 # include <sys/types.h> 37 # include <unistd.h> 38 #endif 39 #include <fcntl.h> /* values for fchmodat */ 40 #include <time.h> 41 42 // since Linux 4.5 and FreeBSD 13, but the Linux libc wrapper is only provided by glibc >= 2.27 and musl 43 #if defined(__linux__) 44 # if defined(_LIBCPP_GLIBC_PREREQ) 45 # if _LIBCPP_GLIBC_PREREQ(2, 27) 46 # define _LIBCPP_FILESYSTEM_USE_COPY_FILE_RANGE 47 # endif 48 # elif _LIBCPP_HAS_MUSL_LIBC 49 # define _LIBCPP_FILESYSTEM_USE_COPY_FILE_RANGE 50 # endif 51 #elif defined(__FreeBSD__) 52 # define _LIBCPP_FILESYSTEM_USE_COPY_FILE_RANGE 53 #endif 54 #if __has_include(<sys/sendfile.h>) 55 # include <sys/sendfile.h> 56 # define _LIBCPP_FILESYSTEM_USE_SENDFILE 57 #elif defined(__APPLE__) || __has_include(<copyfile.h>) 58 # include <copyfile.h> 59 # define _LIBCPP_FILESYSTEM_USE_COPYFILE 60 #else 61 # define _LIBCPP_FILESYSTEM_USE_FSTREAM 62 #endif 63 64 // sendfile and copy_file_range need to fall back 65 // to the fstream implementation for special files 66 #if (defined(_LIBCPP_FILESYSTEM_USE_SENDFILE) || defined(_LIBCPP_FILESYSTEM_USE_COPY_FILE_RANGE) || \ 67 defined(_LIBCPP_FILESYSTEM_USE_FSTREAM)) && \ 68 _LIBCPP_HAS_LOCALIZATION 69 # include <fstream> 70 # define _LIBCPP_FILESYSTEM_NEED_FSTREAM 71 #endif 72 73 #if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) 74 # pragma comment(lib, "rt") 75 #endif 76 77 _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM 78 79 using detail::capture_errno; 80 using detail::ErrorHandler; 81 using detail::StatT; 82 using detail::TimeSpec; 83 using parser::createView; 84 using parser::PathParser; 85 using parser::string_view_t; 86 87 static path __do_absolute(const path& p, path* cwd, error_code* ec) { 88 if (ec) 89 ec->clear(); 90 if (p.is_absolute()) 91 return p; 92 *cwd = __current_path(ec); 93 if (ec && *ec) 94 return {}; 95 return (*cwd) / p; 96 } 97 98 path __absolute(const path& p, error_code* ec) { 99 path cwd; 100 return __do_absolute(p, &cwd, ec); 101 } 102 103 path __canonical(path const& orig_p, error_code* ec) { 104 path cwd; 105 ErrorHandler<path> err("canonical", ec, &orig_p, &cwd); 106 107 path p = __do_absolute(orig_p, &cwd, ec); 108 #if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || defined(_LIBCPP_WIN32API) 109 std::unique_ptr<path::value_type, decltype(&::free)> hold(detail::realpath(p.c_str(), nullptr), &::free); 110 if (hold.get() == nullptr) 111 return err.report(detail::get_last_error()); 112 return {hold.get()}; 113 #else 114 # if defined(__MVS__) && !defined(PATH_MAX) 115 path::value_type buff[_XOPEN_PATH_MAX + 1]; 116 # else 117 path::value_type buff[PATH_MAX + 1]; 118 # endif 119 path::value_type* ret; 120 if ((ret = detail::realpath(p.c_str(), buff)) == nullptr) 121 return err.report(detail::get_last_error()); 122 return {ret}; 123 #endif 124 } 125 126 void __copy(const path& from, const path& to, copy_options options, error_code* ec) { 127 ErrorHandler<void> err("copy", ec, &from, &to); 128 129 const bool sym_status = bool(options & (copy_options::create_symlinks | copy_options::skip_symlinks)); 130 131 const bool sym_status2 = bool(options & copy_options::copy_symlinks); 132 133 error_code m_ec1; 134 StatT f_st; 135 const file_status f = 136 sym_status || sym_status2 ? detail::posix_lstat(from, f_st, &m_ec1) : detail::posix_stat(from, f_st, &m_ec1); 137 if (m_ec1) 138 return err.report(m_ec1); 139 140 StatT t_st; 141 const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1) : detail::posix_stat(to, t_st, &m_ec1); 142 143 if (not status_known(t)) 144 return err.report(m_ec1); 145 146 if (!exists(f) || is_other(f) || is_other(t) || (is_directory(f) && is_regular_file(t)) || 147 (exists(t) && detail::stat_equivalent(f_st, t_st))) { 148 return err.report(errc::function_not_supported); 149 } 150 151 if (is_symlink(f)) { 152 if (bool(copy_options::skip_symlinks & options)) { 153 // do nothing 154 } else if (not exists(t)) { 155 __copy_symlink(from, to, ec); 156 } else { 157 return err.report(errc::file_exists); 158 } 159 return; 160 } else if (is_regular_file(f)) { 161 if (bool(copy_options::directories_only & options)) { 162 // do nothing 163 } else if (bool(copy_options::create_symlinks & options)) { 164 __create_symlink(from, to, ec); 165 } else if (bool(copy_options::create_hard_links & options)) { 166 __create_hard_link(from, to, ec); 167 } else if (is_directory(t)) { 168 __copy_file(from, to / from.filename(), options, ec); 169 } else { 170 __copy_file(from, to, options, ec); 171 } 172 return; 173 } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) { 174 return err.report(errc::is_a_directory); 175 } else if (is_directory(f) && (bool(copy_options::recursive & options) || copy_options::none == options)) { 176 if (!exists(t)) { 177 // create directory to with attributes from 'from'. 178 __create_directory(to, from, ec); 179 if (ec && *ec) { 180 return; 181 } 182 } 183 directory_iterator it = ec ? directory_iterator(from, *ec) : directory_iterator(from); 184 if (ec && *ec) { 185 return; 186 } 187 error_code m_ec2; 188 for (; !m_ec2 && it != directory_iterator(); it.increment(m_ec2)) { 189 __copy(it->path(), to / it->path().filename(), options | copy_options::__in_recursive_copy, ec); 190 if (ec && *ec) { 191 return; 192 } 193 } 194 if (m_ec2) { 195 return err.report(m_ec2); 196 } 197 } 198 } 199 200 namespace detail { 201 namespace { 202 203 #if defined(_LIBCPP_FILESYSTEM_NEED_FSTREAM) 204 bool copy_file_impl_fstream(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { 205 ifstream in; 206 in.__open(read_fd.fd, ios::binary); 207 if (!in.is_open()) { 208 // This assumes that __open didn't reset the error code. 209 ec = capture_errno(); 210 return false; 211 } 212 read_fd.fd = -1; 213 ofstream out; 214 out.__open(write_fd.fd, ios::binary); 215 if (!out.is_open()) { 216 ec = capture_errno(); 217 return false; 218 } 219 write_fd.fd = -1; 220 221 if (in.good() && out.good()) { 222 using InIt = istreambuf_iterator<char>; 223 using OutIt = ostreambuf_iterator<char>; 224 InIt bin(in); 225 InIt ein; 226 OutIt bout(out); 227 copy(bin, ein, bout); 228 } 229 if (out.fail() || in.fail()) { 230 ec = make_error_code(errc::io_error); 231 return false; 232 } 233 234 ec.clear(); 235 return true; 236 } 237 #endif 238 239 #if defined(_LIBCPP_FILESYSTEM_USE_COPY_FILE_RANGE) 240 bool copy_file_impl_copy_file_range(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { 241 size_t count = read_fd.get_stat().st_size; 242 // a zero-length file is either empty, or not copyable by this syscall 243 // return early to avoid the syscall cost 244 if (count == 0) { 245 ec = {EINVAL, generic_category()}; 246 return false; 247 } 248 // do not modify the fd positions as copy_file_impl_sendfile may be called after a partial copy 249 # if defined(__linux__) 250 loff_t off_in = 0; 251 loff_t off_out = 0; 252 # else 253 off_t off_in = 0; 254 off_t off_out = 0; 255 # endif 256 257 do { 258 ssize_t res; 259 260 if ((res = ::copy_file_range(read_fd.fd, &off_in, write_fd.fd, &off_out, count, 0)) == -1) { 261 ec = capture_errno(); 262 return false; 263 } 264 count -= res; 265 } while (count > 0); 266 267 ec.clear(); 268 269 return true; 270 } 271 #endif 272 273 #if defined(_LIBCPP_FILESYSTEM_USE_SENDFILE) 274 bool copy_file_impl_sendfile(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { 275 size_t count = read_fd.get_stat().st_size; 276 // a zero-length file is either empty, or not copyable by this syscall 277 // return early to avoid the syscall cost 278 // however, we can't afford this luxury in the no-locale build, 279 // as we can't utilize the fstream impl to copy empty files 280 # if _LIBCPP_HAS_LOCALIZATION 281 if (count == 0) { 282 ec = {EINVAL, generic_category()}; 283 return false; 284 } 285 # endif 286 do { 287 ssize_t res; 288 if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) { 289 ec = capture_errno(); 290 return false; 291 } 292 count -= res; 293 } while (count > 0); 294 295 ec.clear(); 296 297 return true; 298 } 299 #endif 300 301 #if defined(_LIBCPP_FILESYSTEM_USE_COPY_FILE_RANGE) || defined(_LIBCPP_FILESYSTEM_USE_SENDFILE) 302 // If we have copy_file_range or sendfile, try both in succession (if available). 303 // If both fail, fall back to using fstream. 304 bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { 305 # if defined(_LIBCPP_FILESYSTEM_USE_COPY_FILE_RANGE) 306 if (copy_file_impl_copy_file_range(read_fd, write_fd, ec)) { 307 return true; 308 } 309 // EINVAL: src and dst are the same file (this is not cheaply 310 // detectable from userspace) 311 // EINVAL: copy_file_range is unsupported for this file type by the 312 // underlying filesystem 313 // ENOTSUP: undocumented, can arise with old kernels and NFS 314 // EOPNOTSUPP: filesystem does not implement copy_file_range 315 // ETXTBSY: src or dst is an active swapfile (nonsensical, but allowed 316 // with normal copying) 317 // EXDEV: src and dst are on different filesystems that do not support 318 // cross-fs copy_file_range 319 // ENOENT: undocumented, can arise with CIFS 320 // ENOSYS: unsupported by kernel or blocked by seccomp 321 if (ec.value() != EINVAL && ec.value() != ENOTSUP && ec.value() != EOPNOTSUPP && ec.value() != ETXTBSY && 322 ec.value() != EXDEV && ec.value() != ENOENT && ec.value() != ENOSYS) { 323 return false; 324 } 325 ec.clear(); 326 # endif 327 328 # if defined(_LIBCPP_FILESYSTEM_USE_SENDFILE) 329 if (copy_file_impl_sendfile(read_fd, write_fd, ec)) { 330 return true; 331 } 332 // EINVAL: unsupported file type 333 if (ec.value() != EINVAL) { 334 return false; 335 } 336 ec.clear(); 337 # endif 338 339 # if defined(_LIBCPP_FILESYSTEM_NEED_FSTREAM) 340 return copy_file_impl_fstream(read_fd, write_fd, ec); 341 # else 342 // since iostreams are unavailable in the no-locale build, just fail after a failed sendfile 343 ec.assign(EINVAL, std::system_category()); 344 return false; 345 # endif 346 } 347 #elif defined(_LIBCPP_FILESYSTEM_USE_COPYFILE) 348 bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { 349 struct CopyFileState { 350 copyfile_state_t state; 351 CopyFileState() { state = copyfile_state_alloc(); } 352 ~CopyFileState() { copyfile_state_free(state); } 353 354 private: 355 CopyFileState(CopyFileState const&) = delete; 356 CopyFileState& operator=(CopyFileState const&) = delete; 357 }; 358 359 CopyFileState cfs; 360 if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) { 361 ec = capture_errno(); 362 return false; 363 } 364 365 ec.clear(); 366 return true; 367 } 368 #elif defined(_LIBCPP_FILESYSTEM_USE_FSTREAM) 369 bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { 370 return copy_file_impl_fstream(read_fd, write_fd, ec); 371 } 372 #else 373 # error "Unknown implementation for copy_file_impl" 374 #endif // copy_file_impl implementation 375 376 } // end anonymous namespace 377 } // namespace detail 378 379 bool __copy_file(const path& from, const path& to, copy_options options, error_code* ec) { 380 using detail::FileDescriptor; 381 ErrorHandler<bool> err("copy_file", ec, &to, &from); 382 383 error_code m_ec; 384 FileDescriptor from_fd = FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK | O_BINARY); 385 if (m_ec) 386 return err.report(m_ec); 387 388 auto from_st = from_fd.get_status(); 389 StatT const& from_stat = from_fd.get_stat(); 390 if (!is_regular_file(from_st)) { 391 if (not m_ec) 392 m_ec = make_error_code(errc::not_supported); 393 return err.report(m_ec); 394 } 395 396 const bool skip_existing = bool(copy_options::skip_existing & options); 397 const bool update_existing = bool(copy_options::update_existing & options); 398 const bool overwrite_existing = bool(copy_options::overwrite_existing & options); 399 400 StatT to_stat_path; 401 file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec); 402 if (!status_known(to_st)) 403 return err.report(m_ec); 404 405 const bool to_exists = exists(to_st); 406 if (to_exists && !is_regular_file(to_st)) 407 return err.report(errc::not_supported); 408 409 if (to_exists && detail::stat_equivalent(from_stat, to_stat_path)) 410 return err.report(errc::file_exists); 411 412 if (to_exists && skip_existing) 413 return false; 414 415 bool ShouldCopy = [&]() { 416 if (to_exists && update_existing) { 417 auto from_time = detail::extract_mtime(from_stat); 418 auto to_time = detail::extract_mtime(to_stat_path); 419 if (from_time.tv_sec < to_time.tv_sec) 420 return false; 421 if (from_time.tv_sec == to_time.tv_sec && from_time.tv_nsec <= to_time.tv_nsec) 422 return false; 423 return true; 424 } 425 if (!to_exists || overwrite_existing) 426 return true; 427 return err.report(errc::file_exists); 428 }(); 429 if (!ShouldCopy) 430 return false; 431 432 // Don't truncate right away. We may not be opening the file we originally 433 // looked at; we'll check this later. 434 int to_open_flags = O_WRONLY | O_BINARY; 435 if (!to_exists) 436 to_open_flags |= O_CREAT; 437 FileDescriptor to_fd = FileDescriptor::create_with_status(&to, m_ec, to_open_flags, from_stat.st_mode); 438 if (m_ec) 439 return err.report(m_ec); 440 441 if (to_exists) { 442 // Check that the file we initially stat'ed is equivalent to the one 443 // we opened. 444 // FIXME: report this better. 445 if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat())) 446 return err.report(errc::bad_file_descriptor); 447 448 // Set the permissions and truncate the file we opened. 449 if (detail::posix_fchmod(to_fd, from_stat, m_ec)) 450 return err.report(m_ec); 451 if (detail::posix_ftruncate(to_fd, 0, m_ec)) 452 return err.report(m_ec); 453 } 454 455 if (!detail::copy_file_impl(from_fd, to_fd, m_ec)) { 456 // FIXME: Remove the dest file if we failed, and it didn't exist previously. 457 return err.report(m_ec); 458 } 459 460 return true; 461 } 462 463 void __copy_symlink(const path& existing_symlink, const path& new_symlink, error_code* ec) { 464 const path real_path(__read_symlink(existing_symlink, ec)); 465 if (ec && *ec) { 466 return; 467 } 468 #if defined(_LIBCPP_WIN32API) 469 error_code local_ec; 470 if (is_directory(real_path, local_ec)) 471 __create_directory_symlink(real_path, new_symlink, ec); 472 else 473 #endif 474 __create_symlink(real_path, new_symlink, ec); 475 } 476 477 bool __create_directories(const path& p, error_code* ec) { 478 ErrorHandler<bool> err("create_directories", ec, &p); 479 480 error_code m_ec; 481 auto const st = detail::posix_stat(p, &m_ec); 482 if (!status_known(st)) 483 return err.report(m_ec); 484 else if (is_directory(st)) 485 return false; 486 else if (exists(st)) 487 return err.report(errc::file_exists); 488 489 const path parent = p.parent_path(); 490 if (!parent.empty()) { 491 const file_status parent_st = status(parent, m_ec); 492 if (not status_known(parent_st)) 493 return err.report(m_ec); 494 if (not exists(parent_st)) { 495 if (parent == p) 496 return err.report(errc::invalid_argument); 497 __create_directories(parent, ec); 498 if (ec && *ec) { 499 return false; 500 } 501 } else if (not is_directory(parent_st)) 502 return err.report(errc::not_a_directory); 503 } 504 bool ret = __create_directory(p, &m_ec); 505 if (m_ec) 506 return err.report(m_ec); 507 return ret; 508 } 509 510 bool __create_directory(const path& p, error_code* ec) { 511 ErrorHandler<bool> err("create_directory", ec, &p); 512 513 if (detail::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0) 514 return true; 515 516 error_code mec = detail::get_last_error(); 517 if (mec != errc::file_exists) 518 return err.report(mec); 519 error_code ignored_ec; 520 const file_status st = status(p, ignored_ec); 521 if (!is_directory(st)) 522 return err.report(mec); 523 return false; 524 } 525 526 bool __create_directory(path const& p, path const& attributes, error_code* ec) { 527 ErrorHandler<bool> err("create_directory", ec, &p, &attributes); 528 529 StatT attr_stat; 530 error_code mec; 531 file_status st = detail::posix_stat(attributes, attr_stat, &mec); 532 if (!status_known(st)) 533 return err.report(mec); 534 if (!is_directory(st)) 535 return err.report(errc::not_a_directory, "the specified attribute path is invalid"); 536 537 if (detail::mkdir(p.c_str(), attr_stat.st_mode) == 0) 538 return true; 539 540 mec = detail::get_last_error(); 541 if (mec != errc::file_exists) 542 return err.report(mec); 543 544 error_code ignored_ec; 545 st = status(p, ignored_ec); 546 if (!is_directory(st)) 547 return err.report(mec); 548 return false; 549 } 550 551 void __create_directory_symlink(path const& from, path const& to, error_code* ec) { 552 ErrorHandler<void> err("create_directory_symlink", ec, &from, &to); 553 if (detail::symlink_dir(from.c_str(), to.c_str()) == -1) 554 return err.report(detail::get_last_error()); 555 } 556 557 void __create_hard_link(const path& from, const path& to, error_code* ec) { 558 ErrorHandler<void> err("create_hard_link", ec, &from, &to); 559 if (detail::link(from.c_str(), to.c_str()) == -1) 560 return err.report(detail::get_last_error()); 561 } 562 563 void __create_symlink(path const& from, path const& to, error_code* ec) { 564 ErrorHandler<void> err("create_symlink", ec, &from, &to); 565 if (detail::symlink_file(from.c_str(), to.c_str()) == -1) 566 return err.report(detail::get_last_error()); 567 } 568 569 path __current_path(error_code* ec) { 570 ErrorHandler<path> err("current_path", ec); 571 572 #if defined(_LIBCPP_WIN32API) || defined(__GLIBC__) || defined(__APPLE__) 573 // Common extension outside of POSIX getcwd() spec, without needing to 574 // preallocate a buffer. Also supported by a number of other POSIX libcs. 575 int size = 0; 576 path::value_type* ptr = nullptr; 577 typedef decltype(&::free) Deleter; 578 Deleter deleter = &::free; 579 #else 580 errno = 0; // Note: POSIX mandates that modifying `errno` is thread-safe. 581 auto size = ::pathconf(".", _PC_PATH_MAX); 582 if (size == -1) { 583 if (errno != 0) { 584 return err.report(capture_errno(), "call to pathconf failed"); 585 586 // `pathconf` returns `-1` without an error to indicate no limit. 587 } else { 588 # if defined(__MVS__) && !defined(PATH_MAX) 589 size = _XOPEN_PATH_MAX + 1; 590 # else 591 size = PATH_MAX + 1; 592 # endif 593 } 594 } 595 596 auto buff = unique_ptr<path::value_type[]>(new path::value_type[size + 1]); 597 path::value_type* ptr = buff.get(); 598 599 // Preallocated buffer, don't free the buffer in the second unique_ptr 600 // below. 601 struct Deleter { 602 void operator()(void*) const {} 603 }; 604 Deleter deleter; 605 #endif 606 607 unique_ptr<path::value_type, Deleter> hold(detail::getcwd(ptr, size), deleter); 608 if (hold.get() == nullptr) 609 return err.report(detail::get_last_error(), "call to getcwd failed"); 610 611 return {hold.get()}; 612 } 613 614 void __current_path(const path& p, error_code* ec) { 615 ErrorHandler<void> err("current_path", ec, &p); 616 if (detail::chdir(p.c_str()) == -1) 617 err.report(detail::get_last_error()); 618 } 619 620 bool __equivalent(const path& p1, const path& p2, error_code* ec) { 621 ErrorHandler<bool> err("equivalent", ec, &p1, &p2); 622 623 error_code ec1, ec2; 624 StatT st1 = {}, st2 = {}; 625 auto s1 = detail::posix_stat(p1.native(), st1, &ec1); 626 if (!exists(s1)) 627 return err.report(errc::not_supported); 628 auto s2 = detail::posix_stat(p2.native(), st2, &ec2); 629 if (!exists(s2)) 630 return err.report(errc::not_supported); 631 632 return detail::stat_equivalent(st1, st2); 633 } 634 635 uintmax_t __file_size(const path& p, error_code* ec) { 636 ErrorHandler<uintmax_t> err("file_size", ec, &p); 637 638 error_code m_ec; 639 StatT st; 640 file_status fst = detail::posix_stat(p, st, &m_ec); 641 if (!exists(fst) || !is_regular_file(fst)) { 642 errc error_kind = is_directory(fst) ? errc::is_a_directory : errc::not_supported; 643 if (!m_ec) 644 m_ec = make_error_code(error_kind); 645 return err.report(m_ec); 646 } 647 // is_regular_file(p) == true 648 return static_cast<uintmax_t>(st.st_size); 649 } 650 651 uintmax_t __hard_link_count(const path& p, error_code* ec) { 652 ErrorHandler<uintmax_t> err("hard_link_count", ec, &p); 653 654 error_code m_ec; 655 StatT st; 656 detail::posix_stat(p, st, &m_ec); 657 if (m_ec) 658 return err.report(m_ec); 659 return static_cast<uintmax_t>(st.st_nlink); 660 } 661 662 bool __fs_is_empty(const path& p, error_code* ec) { 663 ErrorHandler<bool> err("is_empty", ec, &p); 664 665 error_code m_ec; 666 StatT pst; 667 auto st = detail::posix_stat(p, pst, &m_ec); 668 if (m_ec) 669 return err.report(m_ec); 670 else if (!is_directory(st) && !is_regular_file(st)) 671 return err.report(errc::not_supported); 672 else if (is_directory(st)) { 673 auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p); 674 if (ec && *ec) 675 return false; 676 return it == directory_iterator{}; 677 } else if (is_regular_file(st)) 678 return static_cast<uintmax_t>(pst.st_size) == 0; 679 680 __libcpp_unreachable(); 681 } 682 683 file_time_type __last_write_time(const path& p, error_code* ec) { 684 using namespace chrono; 685 ErrorHandler<file_time_type> err("last_write_time", ec, &p); 686 687 error_code m_ec; 688 StatT st; 689 detail::posix_stat(p, st, &m_ec); 690 if (m_ec) 691 return err.report(m_ec); 692 return detail::__extract_last_write_time(p, st, ec); 693 } 694 695 void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { 696 using detail::fs_time; 697 ErrorHandler<void> err("last_write_time", ec, &p); 698 699 #if defined(_LIBCPP_WIN32API) 700 TimeSpec ts; 701 if (!fs_time::convert_to_timespec(ts, new_time)) 702 return err.report(errc::value_too_large); 703 detail::WinHandle h(p.c_str(), FILE_WRITE_ATTRIBUTES, 0); 704 if (!h) 705 return err.report(detail::get_last_error()); 706 FILETIME last_write = timespec_to_filetime(ts); 707 if (!SetFileTime(h, nullptr, nullptr, &last_write)) 708 return err.report(detail::get_last_error()); 709 #else 710 error_code m_ec; 711 array<TimeSpec, 2> tbuf; 712 # if !defined(_LIBCPP_USE_UTIMENSAT) 713 // This implementation has a race condition between determining the 714 // last access time and attempting to set it to the same value using 715 // ::utimes 716 StatT st; 717 file_status fst = detail::posix_stat(p, st, &m_ec); 718 if (m_ec) 719 return err.report(m_ec); 720 tbuf[0] = detail::extract_atime(st); 721 # else 722 tbuf[0].tv_sec = 0; 723 tbuf[0].tv_nsec = UTIME_OMIT; 724 # endif 725 if (!fs_time::convert_to_timespec(tbuf[1], new_time)) 726 return err.report(errc::value_too_large); 727 728 detail::set_file_times(p, tbuf, m_ec); 729 if (m_ec) 730 return err.report(m_ec); 731 #endif 732 } 733 734 void __permissions(const path& p, perms prms, perm_options opts, error_code* ec) { 735 ErrorHandler<void> err("permissions", ec, &p); 736 737 auto has_opt = [&](perm_options o) { return bool(o & opts); }; 738 const bool resolve_symlinks = !has_opt(perm_options::nofollow); 739 const bool add_perms = has_opt(perm_options::add); 740 const bool remove_perms = has_opt(perm_options::remove); 741 _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( 742 (add_perms + remove_perms + has_opt(perm_options::replace)) == 1, 743 "One and only one of the perm_options constants 'replace', 'add', or 'remove' must be present in opts"); 744 745 bool set_sym_perms = false; 746 prms &= perms::mask; 747 if (!resolve_symlinks || (add_perms || remove_perms)) { 748 error_code m_ec; 749 file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec) : detail::posix_lstat(p, &m_ec); 750 set_sym_perms = is_symlink(st); 751 if (m_ec) 752 return err.report(m_ec); 753 // TODO(hardening): double-check this assertion -- it might be a valid (if rare) case when the permissions are 754 // unknown. 755 _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(st.permissions() != perms::unknown, "Permissions unexpectedly unknown"); 756 if (add_perms) 757 prms |= st.permissions(); 758 else if (remove_perms) 759 prms = st.permissions() & ~prms; 760 } 761 const auto real_perms = static_cast<detail::ModeT>(prms & perms::mask); 762 763 #if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) 764 const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; 765 if (detail::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { 766 return err.report(detail::get_last_error()); 767 } 768 #else 769 if (set_sym_perms) 770 return err.report(errc::operation_not_supported); 771 if (::chmod(p.c_str(), real_perms) == -1) { 772 return err.report(capture_errno()); 773 } 774 #endif 775 } 776 777 path __read_symlink(const path& p, error_code* ec) { 778 ErrorHandler<path> err("read_symlink", ec, &p); 779 780 #if defined(PATH_MAX) || defined(MAX_SYMLINK_SIZE) 781 struct NullDeleter { 782 void operator()(void*) const {} 783 }; 784 # ifdef MAX_SYMLINK_SIZE 785 const size_t size = MAX_SYMLINK_SIZE + 1; 786 # else 787 const size_t size = PATH_MAX + 1; 788 # endif 789 path::value_type stack_buff[size]; 790 auto buff = std::unique_ptr<path::value_type[], NullDeleter>(stack_buff); 791 #else 792 StatT sb; 793 if (detail::lstat(p.c_str(), &sb) == -1) { 794 return err.report(detail::get_last_error()); 795 } 796 const size_t size = sb.st_size + 1; 797 auto buff = unique_ptr<path::value_type[]>(new path::value_type[size]); 798 #endif 799 detail::SSizeT ret; 800 if ((ret = detail::readlink(p.c_str(), buff.get(), size)) == -1) 801 return err.report(detail::get_last_error()); 802 // Note that `ret` returning `0` would work, resulting in a valid empty string being returned. 803 if (static_cast<size_t>(ret) >= size) 804 return err.report(errc::value_too_large); 805 buff[ret] = 0; 806 return {buff.get()}; 807 } 808 809 bool __remove(const path& p, error_code* ec) { 810 ErrorHandler<bool> err("remove", ec, &p); 811 if (detail::remove(p.c_str()) == -1) { 812 error_code mec = detail::get_last_error(); 813 if (mec != errc::no_such_file_or_directory) 814 err.report(mec); 815 return false; 816 } 817 return true; 818 } 819 820 // We currently have two implementations of `__remove_all`. The first one is general and 821 // used on platforms where we don't have access to the `openat()` family of POSIX functions. 822 // That implementation uses `directory_iterator`, however it is vulnerable to some race 823 // conditions, see https://reviews.llvm.org/D118134 for details. 824 // 825 // The second implementation is used on platforms where `openat()` & friends are available, 826 // and it threads file descriptors through recursive calls to avoid such race conditions. 827 #if defined(_LIBCPP_WIN32API) || defined(__MVS__) 828 # define REMOVE_ALL_USE_DIRECTORY_ITERATOR 829 #endif 830 831 #if defined(REMOVE_ALL_USE_DIRECTORY_ITERATOR) 832 833 namespace { 834 835 uintmax_t remove_all_impl(path const& p, error_code& ec) { 836 const auto npos = static_cast<uintmax_t>(-1); 837 const file_status st = __symlink_status(p, &ec); 838 if (ec) 839 return npos; 840 uintmax_t count = 1; 841 if (is_directory(st)) { 842 for (directory_iterator it(p, ec); !ec && it != directory_iterator(); it.increment(ec)) { 843 auto other_count = remove_all_impl(it->path(), ec); 844 if (ec) 845 return npos; 846 count += other_count; 847 } 848 if (ec) 849 return npos; 850 } 851 if (!__remove(p, &ec)) 852 return npos; 853 return count; 854 } 855 856 } // namespace 857 858 uintmax_t __remove_all(const path& p, error_code* ec) { 859 ErrorHandler<uintmax_t> err("remove_all", ec, &p); 860 861 error_code mec; 862 auto count = remove_all_impl(p, mec); 863 if (mec) { 864 if (mec == errc::no_such_file_or_directory) 865 return 0; 866 return err.report(mec); 867 } 868 return count; 869 } 870 871 #else // !REMOVE_ALL_USE_DIRECTORY_ITERATOR 872 873 namespace { 874 875 template <class Cleanup> 876 struct scope_exit { 877 explicit scope_exit(Cleanup const& cleanup) : cleanup_(cleanup) {} 878 879 ~scope_exit() { cleanup_(); } 880 881 private: 882 Cleanup cleanup_; 883 }; 884 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scope_exit); 885 886 uintmax_t remove_all_impl(int parent_directory, const path& p, error_code& ec) { 887 // First, try to open the path as a directory. 888 const int options = O_CLOEXEC | O_RDONLY | O_DIRECTORY | O_NOFOLLOW; 889 int fd = ::openat(parent_directory, p.c_str(), options); 890 if (fd != -1) { 891 // If that worked, iterate over the contents of the directory and 892 // remove everything in it, recursively. 893 DIR* stream = ::fdopendir(fd); 894 if (stream == nullptr) { 895 ::close(fd); 896 ec = detail::capture_errno(); 897 return 0; 898 } 899 // Note: `::closedir` will also close the associated file descriptor, so 900 // there should be no call to `close(fd)`. 901 scope_exit close_stream([=] { ::closedir(stream); }); 902 903 uintmax_t count = 0; 904 while (true) { 905 auto [str, type] = detail::posix_readdir(stream, ec); 906 static_assert(std::is_same_v<decltype(str), std::string_view>); 907 if (str == "." || str == "..") { 908 continue; 909 } else if (ec || str.empty()) { 910 break; // we're done iterating through the directory 911 } else { 912 count += remove_all_impl(fd, str, ec); 913 } 914 } 915 916 // Then, remove the now-empty directory itself. 917 if (::unlinkat(parent_directory, p.c_str(), AT_REMOVEDIR) == -1) { 918 ec = detail::capture_errno(); 919 return count; 920 } 921 922 return count + 1; // the contents of the directory + the directory itself 923 } 924 925 ec = detail::capture_errno(); 926 927 // If we failed to open `p` because it didn't exist, it's not an 928 // error -- it might have moved or have been deleted already. 929 if (ec == errc::no_such_file_or_directory) { 930 ec.clear(); 931 return 0; 932 } 933 934 // If opening `p` failed because it wasn't a directory, remove it as 935 // a normal file instead. Note that `openat()` can return either ENOTDIR 936 // or ELOOP depending on the exact reason of the failure. On FreeBSD it 937 // may return EMLINK instead of ELOOP, contradicting POSIX. 938 if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels || ec == errc::too_many_links) { 939 ec.clear(); 940 if (::unlinkat(parent_directory, p.c_str(), /* flags = */ 0) == -1) { 941 ec = detail::capture_errno(); 942 return 0; 943 } 944 return 1; 945 } 946 947 // Otherwise, it's a real error -- we don't remove anything. 948 return 0; 949 } 950 951 } // namespace 952 953 uintmax_t __remove_all(const path& p, error_code* ec) { 954 ErrorHandler<uintmax_t> err("remove_all", ec, &p); 955 error_code mec; 956 uintmax_t count = remove_all_impl(AT_FDCWD, p, mec); 957 if (mec) 958 return err.report(mec); 959 return count; 960 } 961 962 #endif // REMOVE_ALL_USE_DIRECTORY_ITERATOR 963 964 void __rename(const path& from, const path& to, error_code* ec) { 965 ErrorHandler<void> err("rename", ec, &from, &to); 966 if (detail::rename(from.c_str(), to.c_str()) == -1) 967 err.report(detail::get_last_error()); 968 } 969 970 void __resize_file(const path& p, uintmax_t size, error_code* ec) { 971 ErrorHandler<void> err("resize_file", ec, &p); 972 if (detail::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) 973 return err.report(detail::get_last_error()); 974 } 975 976 space_info __space(const path& p, error_code* ec) { 977 ErrorHandler<void> err("space", ec, &p); 978 space_info si; 979 detail::StatVFS m_svfs = {}; 980 if (detail::statvfs(p.c_str(), &m_svfs) == -1) { 981 err.report(detail::get_last_error()); 982 si.capacity = si.free = si.available = static_cast<uintmax_t>(-1); 983 return si; 984 } 985 // Multiply with overflow checking. 986 auto do_mult = [&](uintmax_t& out, uintmax_t other) { 987 out = other * m_svfs.f_frsize; 988 if (other == 0 || out / other != m_svfs.f_frsize) 989 out = static_cast<uintmax_t>(-1); 990 }; 991 do_mult(si.capacity, m_svfs.f_blocks); 992 do_mult(si.free, m_svfs.f_bfree); 993 do_mult(si.available, m_svfs.f_bavail); 994 return si; 995 } 996 997 file_status __status(const path& p, error_code* ec) { return detail::posix_stat(p, ec); } 998 999 file_status __symlink_status(const path& p, error_code* ec) { return detail::posix_lstat(p, ec); } 1000 1001 path __temp_directory_path(error_code* ec) { 1002 ErrorHandler<path> err("temp_directory_path", ec); 1003 1004 #if defined(_LIBCPP_WIN32API) 1005 wchar_t buf[MAX_PATH]; 1006 DWORD retval = GetTempPathW(MAX_PATH, buf); 1007 if (!retval) 1008 return err.report(detail::get_last_error()); 1009 if (retval > MAX_PATH) 1010 return err.report(errc::filename_too_long); 1011 // GetTempPathW returns a path with a trailing slash, which we 1012 // shouldn't include for consistency. 1013 if (buf[retval - 1] == L'\\') 1014 buf[retval - 1] = L'\0'; 1015 path p(buf); 1016 #else 1017 const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; 1018 const char* ret = nullptr; 1019 1020 for (auto& ep : env_paths) 1021 if ((ret = getenv(ep))) 1022 break; 1023 if (ret == nullptr) { 1024 # if defined(__ANDROID__) 1025 ret = "/data/local/tmp"; 1026 # else 1027 ret = "/tmp"; 1028 # endif 1029 } 1030 1031 path p(ret); 1032 #endif 1033 error_code m_ec; 1034 file_status st = detail::posix_stat(p, &m_ec); 1035 if (!status_known(st)) 1036 return err.report(m_ec, "cannot access path " PATH_CSTR_FMT, p.c_str()); 1037 1038 if (!exists(st) || !is_directory(st)) 1039 return err.report(errc::not_a_directory, "path " PATH_CSTR_FMT " is not a directory", p.c_str()); 1040 1041 return p; 1042 } 1043 1044 path __weakly_canonical(const path& p, error_code* ec) { 1045 ErrorHandler<path> err("weakly_canonical", ec, &p); 1046 1047 if (p.empty()) 1048 return __canonical("", ec); 1049 1050 path result; 1051 path tmp; 1052 tmp.__reserve(p.native().size()); 1053 auto PP = PathParser::CreateEnd(p.native()); 1054 --PP; 1055 vector<string_view_t> DNEParts; 1056 1057 error_code m_ec; 1058 while (PP.State_ != PathParser::PS_BeforeBegin) { 1059 tmp.assign(createView(p.native().data(), &PP.RawEntry.back())); 1060 file_status st = __status(tmp, &m_ec); 1061 if (!status_known(st)) { 1062 return err.report(m_ec); 1063 } else if (exists(st)) { 1064 result = __canonical(tmp, &m_ec); 1065 if (m_ec) { 1066 return err.report(m_ec); 1067 } 1068 break; 1069 } 1070 DNEParts.push_back(*PP); 1071 --PP; 1072 } 1073 if (PP.State_ == PathParser::PS_BeforeBegin) { 1074 result = __canonical("", &m_ec); 1075 if (m_ec) { 1076 return err.report(m_ec); 1077 } 1078 } 1079 if (DNEParts.empty()) 1080 return result; 1081 for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It) 1082 result /= *It; 1083 return result.lexically_normal(); 1084 } 1085 1086 _LIBCPP_END_NAMESPACE_FILESYSTEM 1087