Mercurial
comparison third_party/libuv/test/test-fs-copyfile.c @ 160:948de3f54cea
[ThirdParty] Added libuv
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Wed, 14 Jan 2026 19:39:52 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 159:05cf9467a1c3 | 160:948de3f54cea |
|---|---|
| 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 | |
| 22 #include "uv.h" | |
| 23 #include "task.h" | |
| 24 | |
| 25 #if defined(__unix__) || defined(__POSIX__) || \ | |
| 26 defined(__APPLE__) || defined(__sun) || \ | |
| 27 defined(_AIX) || defined(__MVS__) || \ | |
| 28 defined(__HAIKU__) || defined(__QNX__) | |
| 29 #include <unistd.h> /* unlink, etc. */ | |
| 30 #else | |
| 31 # include <direct.h> | |
| 32 # include <io.h> | |
| 33 # define unlink _unlink | |
| 34 #endif | |
| 35 | |
| 36 static const char fixture[] = "test/fixtures/load_error.node"; | |
| 37 static const char dst[] = "test_file_dst"; | |
| 38 static int result_check_count; | |
| 39 | |
| 40 | |
| 41 static void fail_cb(uv_fs_t* req) { | |
| 42 FATAL("fail_cb should not have been called"); | |
| 43 } | |
| 44 | |
| 45 static void handle_result(uv_fs_t* req) { | |
| 46 uv_fs_t stat_req; | |
| 47 uint64_t size; | |
| 48 uint64_t mode; | |
| 49 uint64_t uid; | |
| 50 uint64_t gid; | |
| 51 int r; | |
| 52 | |
| 53 ASSERT_EQ(req->fs_type, UV_FS_COPYFILE); | |
| 54 ASSERT_OK(req->result); | |
| 55 | |
| 56 /* Verify that the file size and mode are the same. */ | |
| 57 r = uv_fs_stat(NULL, &stat_req, req->path, NULL); | |
| 58 ASSERT_OK(r); | |
| 59 size = stat_req.statbuf.st_size; | |
| 60 mode = stat_req.statbuf.st_mode; | |
| 61 uid = stat_req.statbuf.st_uid; | |
| 62 gid = stat_req.statbuf.st_gid; | |
| 63 uv_fs_req_cleanup(&stat_req); | |
| 64 r = uv_fs_stat(NULL, &stat_req, dst, NULL); | |
| 65 ASSERT_OK(r); | |
| 66 ASSERT_EQ(stat_req.statbuf.st_size, size); | |
| 67 ASSERT_EQ(stat_req.statbuf.st_mode, mode); | |
| 68 ASSERT_EQ(stat_req.statbuf.st_uid, uid); | |
| 69 ASSERT_EQ(stat_req.statbuf.st_gid, gid); | |
| 70 uv_fs_req_cleanup(&stat_req); | |
| 71 uv_fs_req_cleanup(req); | |
| 72 result_check_count++; | |
| 73 } | |
| 74 | |
| 75 | |
| 76 static void touch_file(const char* name, unsigned int size) { | |
| 77 uv_file file; | |
| 78 uv_fs_t req; | |
| 79 uv_buf_t buf; | |
| 80 int r; | |
| 81 unsigned int i; | |
| 82 | |
| 83 r = uv_fs_open(NULL, &req, name, | |
| 84 UV_FS_O_WRONLY | UV_FS_O_CREAT | UV_FS_O_TRUNC, | |
| 85 S_IWUSR | S_IRUSR, NULL); | |
| 86 uv_fs_req_cleanup(&req); | |
| 87 ASSERT_GE(r, 0); | |
| 88 file = r; | |
| 89 | |
| 90 buf = uv_buf_init("a", 1); | |
| 91 | |
| 92 /* Inefficient but simple. */ | |
| 93 for (i = 0; i < size; i++) { | |
| 94 r = uv_fs_write(NULL, &req, file, &buf, 1, i, NULL); | |
| 95 uv_fs_req_cleanup(&req); | |
| 96 ASSERT_GE(r, 0); | |
| 97 } | |
| 98 | |
| 99 r = uv_fs_close(NULL, &req, file, NULL); | |
| 100 uv_fs_req_cleanup(&req); | |
| 101 ASSERT_OK(r); | |
| 102 } | |
| 103 | |
| 104 | |
| 105 TEST_IMPL(fs_copyfile) { | |
| 106 const char src[] = "test_file_src"; | |
| 107 uv_loop_t* loop; | |
| 108 uv_fs_t req; | |
| 109 int r; | |
| 110 | |
| 111 loop = uv_default_loop(); | |
| 112 | |
| 113 /* Fails with EINVAL if bad flags are passed. */ | |
| 114 r = uv_fs_copyfile(NULL, &req, src, dst, -1, NULL); | |
| 115 ASSERT_EQ(r, UV_EINVAL); | |
| 116 uv_fs_req_cleanup(&req); | |
| 117 | |
| 118 /* Fails with ENOENT if source does not exist. */ | |
| 119 unlink(src); | |
| 120 unlink(dst); | |
| 121 r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL); | |
| 122 ASSERT_EQ(req.result, UV_ENOENT); | |
| 123 ASSERT_EQ(r, UV_ENOENT); | |
| 124 uv_fs_req_cleanup(&req); | |
| 125 /* The destination should not exist. */ | |
| 126 r = uv_fs_stat(NULL, &req, dst, NULL); | |
| 127 ASSERT(r); | |
| 128 uv_fs_req_cleanup(&req); | |
| 129 | |
| 130 /* Succeeds if src and dst files are identical. */ | |
| 131 touch_file(src, 12); | |
| 132 r = uv_fs_copyfile(NULL, &req, src, src, 0, NULL); | |
| 133 ASSERT_OK(r); | |
| 134 uv_fs_req_cleanup(&req); | |
| 135 /* Verify that the src file did not get truncated. */ | |
| 136 r = uv_fs_stat(NULL, &req, src, NULL); | |
| 137 ASSERT_OK(r); | |
| 138 ASSERT_EQ(12, req.statbuf.st_size); | |
| 139 uv_fs_req_cleanup(&req); | |
| 140 unlink(src); | |
| 141 | |
| 142 /* Copies file synchronously. Creates new file. */ | |
| 143 unlink(dst); | |
| 144 r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL); | |
| 145 ASSERT_OK(r); | |
| 146 handle_result(&req); | |
| 147 | |
| 148 /* Copies a file of size zero. */ | |
| 149 unlink(dst); | |
| 150 touch_file(src, 0); | |
| 151 r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL); | |
| 152 ASSERT_OK(r); | |
| 153 handle_result(&req); | |
| 154 | |
| 155 /* Copies file synchronously. Overwrites existing file. */ | |
| 156 r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL); | |
| 157 ASSERT_OK(r); | |
| 158 handle_result(&req); | |
| 159 | |
| 160 /* Fails to overwrites existing file. */ | |
| 161 ASSERT_OK(uv_fs_chmod(NULL, &req, dst, 0644, NULL)); | |
| 162 uv_fs_req_cleanup(&req); | |
| 163 r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_EXCL, NULL); | |
| 164 ASSERT_EQ(r, UV_EEXIST); | |
| 165 uv_fs_req_cleanup(&req); | |
| 166 | |
| 167 /* Truncates when an existing destination is larger than the source file. */ | |
| 168 ASSERT_OK(uv_fs_chmod(NULL, &req, dst, 0644, NULL)); | |
| 169 uv_fs_req_cleanup(&req); | |
| 170 touch_file(src, 1); | |
| 171 r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL); | |
| 172 ASSERT_OK(r); | |
| 173 handle_result(&req); | |
| 174 | |
| 175 /* Copies a larger file. */ | |
| 176 unlink(dst); | |
| 177 touch_file(src, 4096 * 2); | |
| 178 r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL); | |
| 179 ASSERT_OK(r); | |
| 180 handle_result(&req); | |
| 181 unlink(src); | |
| 182 | |
| 183 /* Copies file asynchronously */ | |
| 184 unlink(dst); | |
| 185 r = uv_fs_copyfile(loop, &req, fixture, dst, 0, handle_result); | |
| 186 ASSERT_OK(r); | |
| 187 ASSERT_EQ(5, result_check_count); | |
| 188 uv_run(loop, UV_RUN_DEFAULT); | |
| 189 ASSERT_EQ(6, result_check_count); | |
| 190 /* Ensure file is user-writable (not copied from src). */ | |
| 191 ASSERT_OK(uv_fs_chmod(NULL, &req, dst, 0644, NULL)); | |
| 192 uv_fs_req_cleanup(&req); | |
| 193 | |
| 194 /* If the flags are invalid, the loop should not be kept open */ | |
| 195 unlink(dst); | |
| 196 r = uv_fs_copyfile(loop, &req, fixture, dst, -1, fail_cb); | |
| 197 ASSERT_EQ(r, UV_EINVAL); | |
| 198 uv_run(loop, UV_RUN_DEFAULT); | |
| 199 | |
| 200 /* Copies file using UV_FS_COPYFILE_FICLONE. */ | |
| 201 unlink(dst); | |
| 202 r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE, NULL); | |
| 203 ASSERT_OK(r); | |
| 204 handle_result(&req); | |
| 205 | |
| 206 /* Copies file using UV_FS_COPYFILE_FICLONE_FORCE. */ | |
| 207 unlink(dst); | |
| 208 r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE_FORCE, | |
| 209 NULL); | |
| 210 ASSERT_LE(r, 0); | |
| 211 | |
| 212 if (r == 0) | |
| 213 handle_result(&req); | |
| 214 | |
| 215 #ifndef _WIN32 | |
| 216 /* Copying respects permissions/mode. */ | |
| 217 unlink(dst); | |
| 218 touch_file(dst, 0); | |
| 219 chmod(dst, S_IRUSR|S_IRGRP|S_IROTH); /* Sets file mode to 444 (read-only). */ | |
| 220 r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL); | |
| 221 /* On IBMi PASE, qsecofr users can overwrite read-only files */ | |
| 222 # ifndef __PASE__ | |
| 223 ASSERT_EQ(req.result, UV_EACCES); | |
| 224 ASSERT_EQ(r, UV_EACCES); | |
| 225 # endif | |
| 226 uv_fs_req_cleanup(&req); | |
| 227 #endif | |
| 228 | |
| 229 unlink(dst); /* Cleanup */ | |
| 230 MAKE_VALGRIND_HAPPY(loop); | |
| 231 return 0; | |
| 232 } |