3
0

cp.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini cp implementation for busybox
  4. *
  5. * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
  6. *
  7. * Licensed under GPL v2 or later, see file LICENSE in this tarball for details.
  8. */
  9. /* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */
  10. /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
  11. *
  12. * Size reduction.
  13. */
  14. #include "busybox.h"
  15. #include "libcoreutils/coreutils.h"
  16. int cp_main(int argc, char **argv)
  17. {
  18. struct stat source_stat;
  19. struct stat dest_stat;
  20. const char *last;
  21. const char *dest;
  22. int s_flags;
  23. int d_flags;
  24. int flags;
  25. int status = 0;
  26. enum {
  27. OPT_a = 1 << (sizeof(FILEUTILS_CP_OPTSTR)-1),
  28. OPT_r = 1 << (sizeof(FILEUTILS_CP_OPTSTR)),
  29. OPT_P = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+1),
  30. OPT_H = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+2),
  31. OPT_L = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3),
  32. };
  33. // Soft- and hardlinking don't mix
  34. // -P and -d are the same (-P is POSIX, -d is GNU)
  35. // -r and -R are the same
  36. // -a = -pdR
  37. opt_complementary = "?:l--s:s--l:Pd:rR:apdR";
  38. flags = getopt32(argc, argv, FILEUTILS_CP_OPTSTR "arPHL");
  39. /* Default behavior of cp is to dereference, so we don't have to do
  40. * anything special when we are given -L.
  41. * The behavior of -H is *almost* like -L, but not quite, so let's
  42. * just ignore it too for fun.
  43. if (flags & OPT_L) ...
  44. if (flags & OPT_H) ... // deref command-line params only
  45. */
  46. flags ^= FILEUTILS_DEREFERENCE; /* The sense of this flag was reversed. */
  47. if (optind + 2 > argc) {
  48. bb_show_usage();
  49. }
  50. last = argv[argc - 1];
  51. argv += optind;
  52. /* If there are only two arguments and... */
  53. if (optind + 2 == argc) {
  54. s_flags = cp_mv_stat2(*argv, &source_stat,
  55. (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
  56. if (s_flags < 0)
  57. return EXIT_FAILURE;
  58. d_flags = cp_mv_stat(last, &dest_stat);
  59. if (d_flags < 0)
  60. return EXIT_FAILURE;
  61. /* ...if neither is a directory or... */
  62. if ( !((s_flags | d_flags) & 2) ||
  63. /* ...recursing, the 1st is a directory, and the 2nd doesn't exist... */
  64. ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags)
  65. ) {
  66. /* ...do a simple copy. */
  67. dest = xstrdup(last);
  68. goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */
  69. }
  70. }
  71. do {
  72. dest = concat_path_file(last, bb_get_last_path_component(*argv));
  73. DO_COPY:
  74. if (copy_file(*argv, dest, flags) < 0) {
  75. status = 1;
  76. }
  77. free((void*)dest);
  78. } while (*++argv != last);
  79. return status;
  80. }