test-fs-copyfile.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* Copyright libuv project contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include "uv.h"
  22. #include "task.h"
  23. #if defined(__unix__) || defined(__POSIX__) || \
  24. defined(__APPLE__) || defined(__sun) || \
  25. defined(_AIX) || defined(__MVS__) || \
  26. defined(__HAIKU__)
  27. #include <unistd.h> /* unlink, etc. */
  28. #else
  29. # include <direct.h>
  30. # include <io.h>
  31. # define unlink _unlink
  32. #endif
  33. static const char fixture[] = "test/fixtures/load_error.node";
  34. static const char dst[] = "test_file_dst";
  35. static int result_check_count;
  36. static void fail_cb(uv_fs_t* req) {
  37. FATAL("fail_cb should not have been called");
  38. }
  39. static void handle_result(uv_fs_t* req) {
  40. uv_fs_t stat_req;
  41. uint64_t size;
  42. uint64_t mode;
  43. int r;
  44. ASSERT(req->fs_type == UV_FS_COPYFILE);
  45. ASSERT(req->result == 0);
  46. /* Verify that the file size and mode are the same. */
  47. r = uv_fs_stat(NULL, &stat_req, req->path, NULL);
  48. ASSERT(r == 0);
  49. size = stat_req.statbuf.st_size;
  50. mode = stat_req.statbuf.st_mode;
  51. uv_fs_req_cleanup(&stat_req);
  52. r = uv_fs_stat(NULL, &stat_req, dst, NULL);
  53. ASSERT(r == 0);
  54. ASSERT(stat_req.statbuf.st_size == size);
  55. ASSERT(stat_req.statbuf.st_mode == mode);
  56. uv_fs_req_cleanup(&stat_req);
  57. uv_fs_req_cleanup(req);
  58. result_check_count++;
  59. }
  60. static void touch_file(const char* name, unsigned int size) {
  61. uv_file file;
  62. uv_fs_t req;
  63. uv_buf_t buf;
  64. int r;
  65. unsigned int i;
  66. r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT | O_TRUNC,
  67. S_IWUSR | S_IRUSR, NULL);
  68. uv_fs_req_cleanup(&req);
  69. ASSERT(r >= 0);
  70. file = r;
  71. buf = uv_buf_init("a", 1);
  72. /* Inefficient but simple. */
  73. for (i = 0; i < size; i++) {
  74. r = uv_fs_write(NULL, &req, file, &buf, 1, i, NULL);
  75. uv_fs_req_cleanup(&req);
  76. ASSERT(r >= 0);
  77. }
  78. r = uv_fs_close(NULL, &req, file, NULL);
  79. uv_fs_req_cleanup(&req);
  80. ASSERT(r == 0);
  81. }
  82. TEST_IMPL(fs_copyfile) {
  83. const char src[] = "test_file_src";
  84. uv_loop_t* loop;
  85. uv_fs_t req;
  86. int r;
  87. loop = uv_default_loop();
  88. /* Fails with EINVAL if bad flags are passed. */
  89. r = uv_fs_copyfile(NULL, &req, src, dst, -1, NULL);
  90. ASSERT(r == UV_EINVAL);
  91. uv_fs_req_cleanup(&req);
  92. /* Fails with ENOENT if source does not exist. */
  93. unlink(src);
  94. unlink(dst);
  95. r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL);
  96. ASSERT(req.result == UV_ENOENT);
  97. ASSERT(r == UV_ENOENT);
  98. uv_fs_req_cleanup(&req);
  99. /* The destination should not exist. */
  100. r = uv_fs_stat(NULL, &req, dst, NULL);
  101. ASSERT(r != 0);
  102. uv_fs_req_cleanup(&req);
  103. /* Succeeds if src and dst files are identical. */
  104. touch_file(src, 12);
  105. r = uv_fs_copyfile(NULL, &req, src, src, 0, NULL);
  106. ASSERT(r == 0);
  107. uv_fs_req_cleanup(&req);
  108. unlink(src);
  109. /* Copies file synchronously. Creates new file. */
  110. unlink(dst);
  111. r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL);
  112. ASSERT(r == 0);
  113. handle_result(&req);
  114. /* Copies a file of size zero. */
  115. unlink(dst);
  116. touch_file(src, 0);
  117. r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL);
  118. ASSERT(r == 0);
  119. handle_result(&req);
  120. /* Copies file synchronously. Overwrites existing file. */
  121. r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL);
  122. ASSERT(r == 0);
  123. handle_result(&req);
  124. /* Fails to overwrites existing file. */
  125. r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_EXCL, NULL);
  126. ASSERT(r == UV_EEXIST);
  127. uv_fs_req_cleanup(&req);
  128. /* Truncates when an existing destination is larger than the source file. */
  129. touch_file(src, 1);
  130. r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL);
  131. ASSERT(r == 0);
  132. handle_result(&req);
  133. /* Copies a larger file. */
  134. unlink(dst);
  135. touch_file(src, 4096 * 2);
  136. r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL);
  137. ASSERT(r == 0);
  138. handle_result(&req);
  139. unlink(src);
  140. /* Copies file asynchronously */
  141. unlink(dst);
  142. r = uv_fs_copyfile(loop, &req, fixture, dst, 0, handle_result);
  143. ASSERT(r == 0);
  144. ASSERT(result_check_count == 5);
  145. uv_run(loop, UV_RUN_DEFAULT);
  146. ASSERT(result_check_count == 6);
  147. /* If the flags are invalid, the loop should not be kept open */
  148. unlink(dst);
  149. r = uv_fs_copyfile(loop, &req, fixture, dst, -1, fail_cb);
  150. ASSERT(r == UV_EINVAL);
  151. uv_run(loop, UV_RUN_DEFAULT);
  152. /* Copies file using UV_FS_COPYFILE_FICLONE. */
  153. unlink(dst);
  154. r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE, NULL);
  155. ASSERT(r == 0);
  156. handle_result(&req);
  157. /* Copies file using UV_FS_COPYFILE_FICLONE_FORCE. */
  158. unlink(dst);
  159. r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE_FORCE,
  160. NULL);
  161. ASSERT(r <= 0);
  162. if (r == 0)
  163. handle_result(&req);
  164. #ifndef _WIN32
  165. /* Copying respects permissions/mode. */
  166. unlink(dst);
  167. touch_file(dst, 0);
  168. chmod(dst, S_IRUSR|S_IRGRP|S_IROTH); /* Sets file mode to 444 (read-only). */
  169. r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL);
  170. /* On IBMi PASE, qsecofr users can overwrite read-only files */
  171. # ifndef __PASE__
  172. ASSERT(req.result == UV_EACCES);
  173. ASSERT(r == UV_EACCES);
  174. # endif
  175. uv_fs_req_cleanup(&req);
  176. #endif
  177. unlink(dst); /* Cleanup */
  178. return 0;
  179. }