cp.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/LexicalPath.h>
  7. #include <LibCore/ArgsParser.h>
  8. #include <LibCore/File.h>
  9. #include <stdio.h>
  10. #include <unistd.h>
  11. int main(int argc, char** argv)
  12. {
  13. if (pledge("stdio rpath wpath cpath fattr chown", nullptr) < 0) {
  14. perror("pledge");
  15. return 1;
  16. }
  17. bool link = false;
  18. bool preserve = false;
  19. bool recursion_allowed = false;
  20. bool verbose = false;
  21. Vector<String> sources;
  22. String destination;
  23. Core::ArgsParser args_parser;
  24. args_parser.add_option(link, "Link files instead of copying", "link", 'l');
  25. args_parser.add_option(preserve, "Preserve time, UID/GID and file permissions", nullptr, 'p');
  26. args_parser.add_option(recursion_allowed, "Copy directories recursively", "recursive", 'R');
  27. args_parser.add_option(recursion_allowed, "Same as -R", nullptr, 'r');
  28. args_parser.add_option(verbose, "Verbose", "verbose", 'v');
  29. args_parser.add_positional_argument(sources, "Source file paths", "source");
  30. args_parser.add_positional_argument(destination, "Destination file path", "destination");
  31. args_parser.parse(argc, argv);
  32. if (preserve) {
  33. umask(0);
  34. } else {
  35. if (pledge("stdio rpath wpath cpath fattr", nullptr) < 0) {
  36. perror("pledge");
  37. return 1;
  38. }
  39. }
  40. bool destination_is_existing_dir = Core::File::is_directory(destination);
  41. for (auto& source : sources) {
  42. auto destination_path = destination_is_existing_dir
  43. ? String::formatted("{}/{}", destination, LexicalPath::basename(source))
  44. : destination;
  45. auto result = Core::File::copy_file_or_directory(
  46. destination_path, source,
  47. recursion_allowed ? Core::File::RecursionMode::Allowed : Core::File::RecursionMode::Disallowed,
  48. link ? Core::File::LinkMode::Allowed : Core::File::LinkMode::Disallowed,
  49. Core::File::AddDuplicateFileMarker::No,
  50. preserve ? Core::File::PreserveMode::PermissionsOwnershipTimestamps : Core::File::PreserveMode::Nothing);
  51. if (result.is_error()) {
  52. if (result.error().tried_recursing)
  53. warnln("cp: -R not specified; omitting directory '{}'", source);
  54. else
  55. warnln("cp: unable to copy '{}' to '{}': {}", source, destination_path, static_cast<Error const&>(result.error()));
  56. return 1;
  57. }
  58. if (verbose)
  59. outln("'{}' -> '{}'", source, destination_path);
  60. }
  61. return 0;
  62. }