1 /* Copyright Joyent, Inc. and other Node 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 #include <errno.h> 26 #include <string.h> /* memset */ 27 #include <fcntl.h> 28 #include <sys/stat.h> 29 #include <limits.h> /* INT_MAX, PATH_MAX, IOV_MAX */ 30 31 /* FIXME we shouldn't need to branch in this file */ 32 #if defined(__unix__) || defined(__POSIX__) || \ 33 defined(__APPLE__) || defined(__sun) || \ 34 defined(_AIX) || defined(__MVS__) || \ 35 defined(__HAIKU__) 36 #include <unistd.h> /* unlink, rmdir, etc. */ 37 #else 38 # include <winioctl.h> 39 # include <direct.h> 40 # include <io.h> 41 # ifndef ERROR_SYMLINK_NOT_SUPPORTED 42 # define ERROR_SYMLINK_NOT_SUPPORTED 1464 43 # endif 44 # define unlink _unlink 45 # define rmdir _rmdir 46 # define open _open 47 # define write _write 48 # define close _close 49 # ifndef stat 50 # define stat _stati64 51 # endif 52 # ifndef lseek 53 # define lseek _lseek 54 # endif 55 #endif 56 57 #define TOO_LONG_NAME_LENGTH 65536 58 #define PATHMAX 4096 59 60 typedef struct { 61 const char* path; 62 double atime; 63 double mtime; 64 } utime_check_t; 65 66 67 static int dummy_cb_count; 68 static int close_cb_count; 69 static int create_cb_count; 70 static int open_cb_count; 71 static int read_cb_count; 72 static int write_cb_count; 73 static int unlink_cb_count; 74 static int mkdir_cb_count; 75 static int mkdtemp_cb_count; 76 static int mkstemp_cb_count; 77 static int rmdir_cb_count; 78 static int scandir_cb_count; 79 static int stat_cb_count; 80 static int rename_cb_count; 81 static int fsync_cb_count; 82 static int fdatasync_cb_count; 83 static int ftruncate_cb_count; 84 static int sendfile_cb_count; 85 static int fstat_cb_count; 86 static int access_cb_count; 87 static int chmod_cb_count; 88 static int fchmod_cb_count; 89 static int chown_cb_count; 90 static int fchown_cb_count; 91 static int lchown_cb_count; 92 static int link_cb_count; 93 static int symlink_cb_count; 94 static int readlink_cb_count; 95 static int realpath_cb_count; 96 static int utime_cb_count; 97 static int futime_cb_count; 98 static int lutime_cb_count; 99 static int statfs_cb_count; 100 101 static uv_loop_t* loop; 102 103 static uv_fs_t open_req1; 104 static uv_fs_t open_req2; 105 static uv_fs_t read_req; 106 static uv_fs_t write_req; 107 static uv_fs_t unlink_req; 108 static uv_fs_t close_req; 109 static uv_fs_t mkdir_req; 110 static uv_fs_t mkdtemp_req1; 111 static uv_fs_t mkdtemp_req2; 112 static uv_fs_t mkstemp_req1; 113 static uv_fs_t mkstemp_req2; 114 static uv_fs_t mkstemp_req3; 115 static uv_fs_t rmdir_req; 116 static uv_fs_t scandir_req; 117 static uv_fs_t stat_req; 118 static uv_fs_t rename_req; 119 static uv_fs_t fsync_req; 120 static uv_fs_t fdatasync_req; 121 static uv_fs_t ftruncate_req; 122 static uv_fs_t sendfile_req; 123 static uv_fs_t utime_req; 124 static uv_fs_t futime_req; 125 126 static char buf[32]; 127 static char buf2[32]; 128 static char test_buf[] = "test-buffer\n"; 129 static char test_buf2[] = "second-buffer\n"; 130 static uv_buf_t iov; 131 132 #ifdef _WIN32 133 int uv_test_getiovmax(void) { 134 return INT32_MAX; /* Emulated by libuv, so no real limit. */ 135 } 136 #else 137 int uv_test_getiovmax(void) { 138 #if defined(IOV_MAX) 139 return IOV_MAX; 140 #elif defined(_SC_IOV_MAX) 141 static int iovmax = -1; 142 if (iovmax == -1) { 143 iovmax = sysconf(_SC_IOV_MAX); 144 /* On some embedded devices (arm-linux-uclibc based ip camera), 145 * sysconf(_SC_IOV_MAX) can not get the correct value. The return 146 * value is -1 and the errno is EINPROGRESS. Degrade the value to 1. 147 */ 148 if (iovmax == -1) iovmax = 1; 149 } 150 return iovmax; 151 #else 152 return 1024; 153 #endif 154 } 155 #endif 156 157 #ifdef _WIN32 158 /* 159 * This tag and guid have no special meaning, and don't conflict with 160 * reserved ids. 161 */ 162 static unsigned REPARSE_TAG = 0x9913; 163 static GUID REPARSE_GUID = { 164 0x1bf6205f, 0x46ae, 0x4527, 165 { 0xb1, 0x0c, 0xc5, 0x09, 0xb7, 0x55, 0x22, 0x80 }}; 166 #endif 167 168 static void check_permission(const char* filename, unsigned int mode) { 169 int r; 170 uv_fs_t req; 171 uv_stat_t* s; 172 173 r = uv_fs_stat(NULL, &req, filename, NULL); 174 ASSERT(r == 0); 175 ASSERT(req.result == 0); 176 177 s = &req.statbuf; 178 #if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__) 179 /* 180 * On Windows, chmod can only modify S_IWUSR (_S_IWRITE) bit, 181 * so only testing for the specified flags. 182 */ 183 ASSERT((s->st_mode & 0777) & mode); 184 #else 185 ASSERT((s->st_mode & 0777) == mode); 186 #endif 187 188 uv_fs_req_cleanup(&req); 189 } 190 191 192 static void dummy_cb(uv_fs_t* req) { 193 (void) req; 194 dummy_cb_count++; 195 } 196 197 198 static void link_cb(uv_fs_t* req) { 199 ASSERT(req->fs_type == UV_FS_LINK); 200 ASSERT(req->result == 0); 201 link_cb_count++; 202 uv_fs_req_cleanup(req); 203 } 204 205 206 static void symlink_cb(uv_fs_t* req) { 207 ASSERT(req->fs_type == UV_FS_SYMLINK); 208 ASSERT(req->result == 0); 209 symlink_cb_count++; 210 uv_fs_req_cleanup(req); 211 } 212 213 static void readlink_cb(uv_fs_t* req) { 214 ASSERT(req->fs_type == UV_FS_READLINK); 215 ASSERT(req->result == 0); 216 ASSERT(strcmp(req->ptr, "test_file_symlink2") == 0); 217 readlink_cb_count++; 218 uv_fs_req_cleanup(req); 219 } 220 221 222 static void realpath_cb(uv_fs_t* req) { 223 char test_file_abs_buf[PATHMAX]; 224 size_t test_file_abs_size = sizeof(test_file_abs_buf); 225 ASSERT(req->fs_type == UV_FS_REALPATH); 226 #ifdef _WIN32 227 /* 228 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() 229 */ 230 if (req->result == UV_ENOSYS) { 231 realpath_cb_count++; 232 uv_fs_req_cleanup(req); 233 return; 234 } 235 #endif 236 ASSERT(req->result == 0); 237 238 uv_cwd(test_file_abs_buf, &test_file_abs_size); 239 #ifdef _WIN32 240 strcat(test_file_abs_buf, "\\test_file"); 241 ASSERT(stricmp(req->ptr, test_file_abs_buf) == 0); 242 #else 243 strcat(test_file_abs_buf, "/test_file"); 244 ASSERT(strcmp(req->ptr, test_file_abs_buf) == 0); 245 #endif 246 realpath_cb_count++; 247 uv_fs_req_cleanup(req); 248 } 249 250 251 static void access_cb(uv_fs_t* req) { 252 ASSERT(req->fs_type == UV_FS_ACCESS); 253 access_cb_count++; 254 uv_fs_req_cleanup(req); 255 } 256 257 258 static void fchmod_cb(uv_fs_t* req) { 259 ASSERT(req->fs_type == UV_FS_FCHMOD); 260 ASSERT(req->result == 0); 261 fchmod_cb_count++; 262 uv_fs_req_cleanup(req); 263 check_permission("test_file", *(int*)req->data); 264 } 265 266 267 static void chmod_cb(uv_fs_t* req) { 268 ASSERT(req->fs_type == UV_FS_CHMOD); 269 ASSERT(req->result == 0); 270 chmod_cb_count++; 271 uv_fs_req_cleanup(req); 272 check_permission("test_file", *(int*)req->data); 273 } 274 275 276 static void fchown_cb(uv_fs_t* req) { 277 ASSERT(req->fs_type == UV_FS_FCHOWN); 278 ASSERT(req->result == 0); 279 fchown_cb_count++; 280 uv_fs_req_cleanup(req); 281 } 282 283 284 static void chown_cb(uv_fs_t* req) { 285 ASSERT(req->fs_type == UV_FS_CHOWN); 286 ASSERT(req->result == 0); 287 chown_cb_count++; 288 uv_fs_req_cleanup(req); 289 } 290 291 static void lchown_cb(uv_fs_t* req) { 292 ASSERT(req->fs_type == UV_FS_LCHOWN); 293 ASSERT(req->result == 0); 294 lchown_cb_count++; 295 uv_fs_req_cleanup(req); 296 } 297 298 static void chown_root_cb(uv_fs_t* req) { 299 ASSERT(req->fs_type == UV_FS_CHOWN); 300 #if defined(_WIN32) || defined(__MSYS__) 301 /* On windows, chown is a no-op and always succeeds. */ 302 ASSERT(req->result == 0); 303 #else 304 /* On unix, chown'ing the root directory is not allowed - 305 * unless you're root, of course. 306 */ 307 if (geteuid() == 0) 308 ASSERT(req->result == 0); 309 else 310 # if defined(__CYGWIN__) 311 /* On Cygwin, uid 0 is invalid (no root). */ 312 ASSERT(req->result == UV_EINVAL); 313 # elif defined(__PASE__) 314 /* On IBMi PASE, there is no root user. uid 0 is user qsecofr. 315 * User may grant qsecofr's privileges, including changing 316 * the file's ownership to uid 0. 317 */ 318 ASSERT(req->result == 0 || req->result == UV_EPERM); 319 # else 320 ASSERT(req->result == UV_EPERM); 321 # endif 322 #endif 323 chown_cb_count++; 324 uv_fs_req_cleanup(req); 325 } 326 327 static void unlink_cb(uv_fs_t* req) { 328 ASSERT(req == &unlink_req); 329 ASSERT(req->fs_type == UV_FS_UNLINK); 330 ASSERT(req->result == 0); 331 unlink_cb_count++; 332 uv_fs_req_cleanup(req); 333 } 334 335 static void fstat_cb(uv_fs_t* req) { 336 uv_stat_t* s = req->ptr; 337 ASSERT(req->fs_type == UV_FS_FSTAT); 338 ASSERT(req->result == 0); 339 ASSERT(s->st_size == sizeof(test_buf)); 340 uv_fs_req_cleanup(req); 341 fstat_cb_count++; 342 } 343 344 345 static void statfs_cb(uv_fs_t* req) { 346 uv_statfs_t* stats; 347 348 ASSERT(req->fs_type == UV_FS_STATFS); 349 ASSERT(req->result == 0); 350 ASSERT(req->ptr != NULL); 351 stats = req->ptr; 352 353 #if defined(_WIN32) || defined(__sun) || defined(_AIX) || defined(__MVS__) || \ 354 defined(__OpenBSD__) || defined(__NetBSD__) 355 ASSERT(stats->f_type == 0); 356 #else 357 ASSERT(stats->f_type > 0); 358 #endif 359 360 ASSERT(stats->f_bsize > 0); 361 ASSERT(stats->f_blocks > 0); 362 ASSERT(stats->f_bfree <= stats->f_blocks); 363 ASSERT(stats->f_bavail <= stats->f_bfree); 364 365 #ifdef _WIN32 366 ASSERT(stats->f_files == 0); 367 ASSERT(stats->f_ffree == 0); 368 #else 369 /* There is no assertion for stats->f_files that makes sense, so ignore it. */ 370 ASSERT(stats->f_ffree <= stats->f_files); 371 #endif 372 uv_fs_req_cleanup(req); 373 ASSERT(req->ptr == NULL); 374 statfs_cb_count++; 375 } 376 377 378 static void close_cb(uv_fs_t* req) { 379 int r; 380 ASSERT(req == &close_req); 381 ASSERT(req->fs_type == UV_FS_CLOSE); 382 ASSERT(req->result == 0); 383 close_cb_count++; 384 uv_fs_req_cleanup(req); 385 if (close_cb_count == 3) { 386 r = uv_fs_unlink(loop, &unlink_req, "test_file2", unlink_cb); 387 ASSERT(r == 0); 388 } 389 } 390 391 392 static void ftruncate_cb(uv_fs_t* req) { 393 int r; 394 ASSERT(req == &ftruncate_req); 395 ASSERT(req->fs_type == UV_FS_FTRUNCATE); 396 ASSERT(req->result == 0); 397 ftruncate_cb_count++; 398 uv_fs_req_cleanup(req); 399 r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); 400 ASSERT(r == 0); 401 } 402 403 static void fail_cb(uv_fs_t* req) { 404 FATAL("fail_cb should not have been called"); 405 } 406 407 static void read_cb(uv_fs_t* req) { 408 int r; 409 ASSERT(req == &read_req); 410 ASSERT(req->fs_type == UV_FS_READ); 411 ASSERT(req->result >= 0); /* FIXME(bnoordhuis) Check if requested size? */ 412 read_cb_count++; 413 uv_fs_req_cleanup(req); 414 if (read_cb_count == 1) { 415 ASSERT(strcmp(buf, test_buf) == 0); 416 r = uv_fs_ftruncate(loop, &ftruncate_req, open_req1.result, 7, 417 ftruncate_cb); 418 } else { 419 ASSERT(strcmp(buf, "test-bu") == 0); 420 r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); 421 } 422 ASSERT(r == 0); 423 } 424 425 426 static void open_cb(uv_fs_t* req) { 427 int r; 428 ASSERT(req == &open_req1); 429 ASSERT(req->fs_type == UV_FS_OPEN); 430 if (req->result < 0) { 431 fprintf(stderr, "async open error: %d\n", (int) req->result); 432 ASSERT(0); 433 } 434 open_cb_count++; 435 ASSERT(req->path); 436 ASSERT(memcmp(req->path, "test_file2\0", 11) == 0); 437 uv_fs_req_cleanup(req); 438 memset(buf, 0, sizeof(buf)); 439 iov = uv_buf_init(buf, sizeof(buf)); 440 r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, 441 read_cb); 442 ASSERT(r == 0); 443 } 444 445 446 static void open_cb_simple(uv_fs_t* req) { 447 ASSERT(req->fs_type == UV_FS_OPEN); 448 if (req->result < 0) { 449 fprintf(stderr, "async open error: %d\n", (int) req->result); 450 ASSERT(0); 451 } 452 open_cb_count++; 453 ASSERT(req->path); 454 uv_fs_req_cleanup(req); 455 } 456 457 458 static void fsync_cb(uv_fs_t* req) { 459 int r; 460 ASSERT(req == &fsync_req); 461 ASSERT(req->fs_type == UV_FS_FSYNC); 462 ASSERT(req->result == 0); 463 fsync_cb_count++; 464 uv_fs_req_cleanup(req); 465 r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); 466 ASSERT(r == 0); 467 } 468 469 470 static void fdatasync_cb(uv_fs_t* req) { 471 int r; 472 ASSERT(req == &fdatasync_req); 473 ASSERT(req->fs_type == UV_FS_FDATASYNC); 474 ASSERT(req->result == 0); 475 fdatasync_cb_count++; 476 uv_fs_req_cleanup(req); 477 r = uv_fs_fsync(loop, &fsync_req, open_req1.result, fsync_cb); 478 ASSERT(r == 0); 479 } 480 481 482 static void write_cb(uv_fs_t* req) { 483 int r; 484 ASSERT(req == &write_req); 485 ASSERT(req->fs_type == UV_FS_WRITE); 486 ASSERT(req->result >= 0); /* FIXME(bnoordhuis) Check if requested size? */ 487 write_cb_count++; 488 uv_fs_req_cleanup(req); 489 r = uv_fs_fdatasync(loop, &fdatasync_req, open_req1.result, fdatasync_cb); 490 ASSERT(r == 0); 491 } 492 493 494 static void create_cb(uv_fs_t* req) { 495 int r; 496 ASSERT(req == &open_req1); 497 ASSERT(req->fs_type == UV_FS_OPEN); 498 ASSERT(req->result >= 0); 499 create_cb_count++; 500 uv_fs_req_cleanup(req); 501 iov = uv_buf_init(test_buf, sizeof(test_buf)); 502 r = uv_fs_write(loop, &write_req, req->result, &iov, 1, -1, write_cb); 503 ASSERT(r == 0); 504 } 505 506 507 static void rename_cb(uv_fs_t* req) { 508 ASSERT(req == &rename_req); 509 ASSERT(req->fs_type == UV_FS_RENAME); 510 ASSERT(req->result == 0); 511 rename_cb_count++; 512 uv_fs_req_cleanup(req); 513 } 514 515 516 static void mkdir_cb(uv_fs_t* req) { 517 ASSERT(req == &mkdir_req); 518 ASSERT(req->fs_type == UV_FS_MKDIR); 519 ASSERT(req->result == 0); 520 mkdir_cb_count++; 521 ASSERT(req->path); 522 ASSERT(memcmp(req->path, "test_dir\0", 9) == 0); 523 uv_fs_req_cleanup(req); 524 } 525 526 527 static void check_mkdtemp_result(uv_fs_t* req) { 528 int r; 529 530 ASSERT(req->fs_type == UV_FS_MKDTEMP); 531 ASSERT(req->result == 0); 532 ASSERT(req->path); 533 ASSERT(strlen(req->path) == 15); 534 ASSERT(memcmp(req->path, "test_dir_", 9) == 0); 535 ASSERT(memcmp(req->path + 9, "XXXXXX", 6) != 0); 536 check_permission(req->path, 0700); 537 538 /* Check if req->path is actually a directory */ 539 r = uv_fs_stat(NULL, &stat_req, req->path, NULL); 540 ASSERT(r == 0); 541 ASSERT(((uv_stat_t*)stat_req.ptr)->st_mode & S_IFDIR); 542 uv_fs_req_cleanup(&stat_req); 543 } 544 545 546 static void mkdtemp_cb(uv_fs_t* req) { 547 ASSERT(req == &mkdtemp_req1); 548 check_mkdtemp_result(req); 549 mkdtemp_cb_count++; 550 } 551 552 553 static void check_mkstemp_result(uv_fs_t* req) { 554 int r; 555 556 ASSERT(req->fs_type == UV_FS_MKSTEMP); 557 ASSERT(req->result >= 0); 558 ASSERT(req->path); 559 ASSERT(strlen(req->path) == 16); 560 ASSERT(memcmp(req->path, "test_file_", 10) == 0); 561 ASSERT(memcmp(req->path + 10, "XXXXXX", 6) != 0); 562 check_permission(req->path, 0600); 563 564 /* Check if req->path is actually a file */ 565 r = uv_fs_stat(NULL, &stat_req, req->path, NULL); 566 ASSERT(r == 0); 567 ASSERT(stat_req.statbuf.st_mode & S_IFREG); 568 uv_fs_req_cleanup(&stat_req); 569 } 570 571 572 static void mkstemp_cb(uv_fs_t* req) { 573 ASSERT(req == &mkstemp_req1); 574 check_mkstemp_result(req); 575 mkstemp_cb_count++; 576 } 577 578 579 static void rmdir_cb(uv_fs_t* req) { 580 ASSERT(req == &rmdir_req); 581 ASSERT(req->fs_type == UV_FS_RMDIR); 582 ASSERT(req->result == 0); 583 rmdir_cb_count++; 584 ASSERT(req->path); 585 ASSERT(memcmp(req->path, "test_dir\0", 9) == 0); 586 uv_fs_req_cleanup(req); 587 } 588 589 590 static void assert_is_file_type(uv_dirent_t dent) { 591 #ifdef HAVE_DIRENT_TYPES 592 /* 593 * For Apple and Windows, we know getdents is expected to work but for other 594 * environments, the filesystem dictates whether or not getdents supports 595 * returning the file type. 596 * 597 * See: 598 * http://man7.org/linux/man-pages/man2/getdents.2.html 599 * https://github.com/libuv/libuv/issues/501 600 */ 601 #if defined(__APPLE__) || defined(_WIN32) 602 ASSERT(dent.type == UV_DIRENT_FILE); 603 #else 604 ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); 605 #endif 606 #else 607 ASSERT(dent.type == UV_DIRENT_UNKNOWN); 608 #endif 609 } 610 611 612 static void scandir_cb(uv_fs_t* req) { 613 uv_dirent_t dent; 614 ASSERT(req == &scandir_req); 615 ASSERT(req->fs_type == UV_FS_SCANDIR); 616 ASSERT(req->result == 2); 617 ASSERT(req->ptr); 618 619 while (UV_EOF != uv_fs_scandir_next(req, &dent)) { 620 ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); 621 assert_is_file_type(dent); 622 } 623 scandir_cb_count++; 624 ASSERT(req->path); 625 ASSERT(memcmp(req->path, "test_dir\0", 9) == 0); 626 uv_fs_req_cleanup(req); 627 ASSERT(!req->ptr); 628 } 629 630 631 static void empty_scandir_cb(uv_fs_t* req) { 632 uv_dirent_t dent; 633 634 ASSERT(req == &scandir_req); 635 ASSERT(req->fs_type == UV_FS_SCANDIR); 636 ASSERT(req->result == 0); 637 ASSERT(req->ptr == NULL); 638 ASSERT(UV_EOF == uv_fs_scandir_next(req, &dent)); 639 uv_fs_req_cleanup(req); 640 scandir_cb_count++; 641 } 642 643 static void non_existent_scandir_cb(uv_fs_t* req) { 644 uv_dirent_t dent; 645 646 ASSERT(req == &scandir_req); 647 ASSERT(req->fs_type == UV_FS_SCANDIR); 648 ASSERT(req->result == UV_ENOENT); 649 ASSERT(req->ptr == NULL); 650 ASSERT(UV_ENOENT == uv_fs_scandir_next(req, &dent)); 651 uv_fs_req_cleanup(req); 652 scandir_cb_count++; 653 } 654 655 656 static void file_scandir_cb(uv_fs_t* req) { 657 ASSERT(req == &scandir_req); 658 ASSERT(req->fs_type == UV_FS_SCANDIR); 659 ASSERT(req->result == UV_ENOTDIR); 660 ASSERT(req->ptr == NULL); 661 uv_fs_req_cleanup(req); 662 scandir_cb_count++; 663 } 664 665 666 static void stat_cb(uv_fs_t* req) { 667 ASSERT(req == &stat_req); 668 ASSERT(req->fs_type == UV_FS_STAT || req->fs_type == UV_FS_LSTAT); 669 ASSERT(req->result == 0); 670 ASSERT(req->ptr); 671 stat_cb_count++; 672 uv_fs_req_cleanup(req); 673 ASSERT(!req->ptr); 674 } 675 676 677 static void sendfile_cb(uv_fs_t* req) { 678 ASSERT(req == &sendfile_req); 679 ASSERT(req->fs_type == UV_FS_SENDFILE); 680 ASSERT(req->result == 65546); 681 sendfile_cb_count++; 682 uv_fs_req_cleanup(req); 683 } 684 685 686 static void sendfile_nodata_cb(uv_fs_t* req) { 687 ASSERT(req == &sendfile_req); 688 ASSERT(req->fs_type == UV_FS_SENDFILE); 689 ASSERT(req->result == 0); 690 sendfile_cb_count++; 691 uv_fs_req_cleanup(req); 692 } 693 694 695 static void open_noent_cb(uv_fs_t* req) { 696 ASSERT(req->fs_type == UV_FS_OPEN); 697 ASSERT(req->result == UV_ENOENT); 698 open_cb_count++; 699 uv_fs_req_cleanup(req); 700 } 701 702 static void open_nametoolong_cb(uv_fs_t* req) { 703 ASSERT(req->fs_type == UV_FS_OPEN); 704 ASSERT(req->result == UV_ENAMETOOLONG); 705 open_cb_count++; 706 uv_fs_req_cleanup(req); 707 } 708 709 static void open_loop_cb(uv_fs_t* req) { 710 ASSERT(req->fs_type == UV_FS_OPEN); 711 ASSERT(req->result == UV_ELOOP); 712 open_cb_count++; 713 uv_fs_req_cleanup(req); 714 } 715 716 717 TEST_IMPL(fs_file_noent) { 718 uv_fs_t req; 719 int r; 720 721 loop = uv_default_loop(); 722 723 r = uv_fs_open(NULL, &req, "does_not_exist", O_RDONLY, 0, NULL); 724 ASSERT(r == UV_ENOENT); 725 ASSERT(req.result == UV_ENOENT); 726 uv_fs_req_cleanup(&req); 727 728 r = uv_fs_open(loop, &req, "does_not_exist", O_RDONLY, 0, open_noent_cb); 729 ASSERT(r == 0); 730 731 ASSERT(open_cb_count == 0); 732 uv_run(loop, UV_RUN_DEFAULT); 733 ASSERT(open_cb_count == 1); 734 735 /* TODO add EACCES test */ 736 737 MAKE_VALGRIND_HAPPY(); 738 return 0; 739 } 740 741 TEST_IMPL(fs_file_nametoolong) { 742 uv_fs_t req; 743 int r; 744 char name[TOO_LONG_NAME_LENGTH + 1]; 745 746 loop = uv_default_loop(); 747 748 memset(name, 'a', TOO_LONG_NAME_LENGTH); 749 name[TOO_LONG_NAME_LENGTH] = 0; 750 751 r = uv_fs_open(NULL, &req, name, O_RDONLY, 0, NULL); 752 ASSERT(r == UV_ENAMETOOLONG); 753 ASSERT(req.result == UV_ENAMETOOLONG); 754 uv_fs_req_cleanup(&req); 755 756 r = uv_fs_open(loop, &req, name, O_RDONLY, 0, open_nametoolong_cb); 757 ASSERT(r == 0); 758 759 ASSERT(open_cb_count == 0); 760 uv_run(loop, UV_RUN_DEFAULT); 761 ASSERT(open_cb_count == 1); 762 763 MAKE_VALGRIND_HAPPY(); 764 return 0; 765 } 766 767 TEST_IMPL(fs_file_loop) { 768 uv_fs_t req; 769 int r; 770 771 loop = uv_default_loop(); 772 773 unlink("test_symlink"); 774 r = uv_fs_symlink(NULL, &req, "test_symlink", "test_symlink", 0, NULL); 775 #ifdef _WIN32 776 /* 777 * Windows XP and Server 2003 don't support symlinks; we'll get UV_ENOTSUP. 778 * Starting with vista they are supported, but only when elevated, otherwise 779 * we'll see UV_EPERM. 780 */ 781 if (r == UV_ENOTSUP || r == UV_EPERM) 782 return 0; 783 #elif defined(__MSYS__) 784 /* MSYS2's approximation of symlinks with copies does not work for broken 785 links. */ 786 if (r == UV_ENOENT) 787 return 0; 788 #endif 789 ASSERT(r == 0); 790 uv_fs_req_cleanup(&req); 791 792 r = uv_fs_open(NULL, &req, "test_symlink", O_RDONLY, 0, NULL); 793 ASSERT(r == UV_ELOOP); 794 ASSERT(req.result == UV_ELOOP); 795 uv_fs_req_cleanup(&req); 796 797 r = uv_fs_open(loop, &req, "test_symlink", O_RDONLY, 0, open_loop_cb); 798 ASSERT(r == 0); 799 800 ASSERT(open_cb_count == 0); 801 uv_run(loop, UV_RUN_DEFAULT); 802 ASSERT(open_cb_count == 1); 803 804 unlink("test_symlink"); 805 806 MAKE_VALGRIND_HAPPY(); 807 return 0; 808 } 809 810 static void check_utime(const char* path, 811 double atime, 812 double mtime, 813 int test_lutime) { 814 uv_stat_t* s; 815 uv_fs_t req; 816 int r; 817 818 if (test_lutime) 819 r = uv_fs_lstat(loop, &req, path, NULL); 820 else 821 r = uv_fs_stat(loop, &req, path, NULL); 822 823 ASSERT(r == 0); 824 825 ASSERT(req.result == 0); 826 s = &req.statbuf; 827 828 ASSERT(s->st_atim.tv_sec + (s->st_atim.tv_nsec / 1000000000.0) == atime); 829 ASSERT(s->st_mtim.tv_sec + (s->st_mtim.tv_nsec / 1000000000.0) == mtime); 830 831 uv_fs_req_cleanup(&req); 832 } 833 834 835 static void utime_cb(uv_fs_t* req) { 836 utime_check_t* c; 837 838 ASSERT(req == &utime_req); 839 ASSERT(req->result == 0); 840 ASSERT(req->fs_type == UV_FS_UTIME); 841 842 c = req->data; 843 check_utime(c->path, c->atime, c->mtime, /* test_lutime */ 0); 844 845 uv_fs_req_cleanup(req); 846 utime_cb_count++; 847 } 848 849 850 static void futime_cb(uv_fs_t* req) { 851 utime_check_t* c; 852 853 ASSERT(req == &futime_req); 854 ASSERT(req->result == 0); 855 ASSERT(req->fs_type == UV_FS_FUTIME); 856 857 c = req->data; 858 check_utime(c->path, c->atime, c->mtime, /* test_lutime */ 0); 859 860 uv_fs_req_cleanup(req); 861 futime_cb_count++; 862 } 863 864 865 static void lutime_cb(uv_fs_t* req) { 866 utime_check_t* c; 867 868 ASSERT(req->result == 0); 869 ASSERT(req->fs_type == UV_FS_LUTIME); 870 871 c = req->data; 872 check_utime(c->path, c->atime, c->mtime, /* test_lutime */ 1); 873 874 uv_fs_req_cleanup(req); 875 lutime_cb_count++; 876 } 877 878 879 TEST_IMPL(fs_file_async) { 880 int r; 881 882 /* Setup. */ 883 unlink("test_file"); 884 unlink("test_file2"); 885 886 loop = uv_default_loop(); 887 888 r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, 889 S_IRUSR | S_IWUSR, create_cb); 890 ASSERT(r == 0); 891 uv_run(loop, UV_RUN_DEFAULT); 892 893 ASSERT(create_cb_count == 1); 894 ASSERT(write_cb_count == 1); 895 ASSERT(fsync_cb_count == 1); 896 ASSERT(fdatasync_cb_count == 1); 897 ASSERT(close_cb_count == 1); 898 899 r = uv_fs_rename(loop, &rename_req, "test_file", "test_file2", rename_cb); 900 ASSERT(r == 0); 901 902 uv_run(loop, UV_RUN_DEFAULT); 903 ASSERT(create_cb_count == 1); 904 ASSERT(write_cb_count == 1); 905 ASSERT(close_cb_count == 1); 906 ASSERT(rename_cb_count == 1); 907 908 r = uv_fs_open(loop, &open_req1, "test_file2", O_RDWR, 0, open_cb); 909 ASSERT(r == 0); 910 911 uv_run(loop, UV_RUN_DEFAULT); 912 ASSERT(open_cb_count == 1); 913 ASSERT(read_cb_count == 1); 914 ASSERT(close_cb_count == 2); 915 ASSERT(rename_cb_count == 1); 916 ASSERT(create_cb_count == 1); 917 ASSERT(write_cb_count == 1); 918 ASSERT(ftruncate_cb_count == 1); 919 920 r = uv_fs_open(loop, &open_req1, "test_file2", O_RDONLY, 0, open_cb); 921 ASSERT(r == 0); 922 923 uv_run(loop, UV_RUN_DEFAULT); 924 ASSERT(open_cb_count == 2); 925 ASSERT(read_cb_count == 2); 926 ASSERT(close_cb_count == 3); 927 ASSERT(rename_cb_count == 1); 928 ASSERT(unlink_cb_count == 1); 929 ASSERT(create_cb_count == 1); 930 ASSERT(write_cb_count == 1); 931 ASSERT(ftruncate_cb_count == 1); 932 933 /* Cleanup. */ 934 unlink("test_file"); 935 unlink("test_file2"); 936 937 MAKE_VALGRIND_HAPPY(); 938 return 0; 939 } 940 941 942 static void fs_file_sync(int add_flags) { 943 int r; 944 945 /* Setup. */ 946 unlink("test_file"); 947 unlink("test_file2"); 948 949 loop = uv_default_loop(); 950 951 r = uv_fs_open(loop, &open_req1, "test_file", 952 O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); 953 ASSERT(r >= 0); 954 ASSERT(open_req1.result >= 0); 955 uv_fs_req_cleanup(&open_req1); 956 957 iov = uv_buf_init(test_buf, sizeof(test_buf)); 958 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); 959 ASSERT(r >= 0); 960 ASSERT(write_req.result >= 0); 961 uv_fs_req_cleanup(&write_req); 962 963 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 964 ASSERT(r == 0); 965 ASSERT(close_req.result == 0); 966 uv_fs_req_cleanup(&close_req); 967 968 r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR | add_flags, 0, NULL); 969 ASSERT(r >= 0); 970 ASSERT(open_req1.result >= 0); 971 uv_fs_req_cleanup(&open_req1); 972 973 iov = uv_buf_init(buf, sizeof(buf)); 974 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 975 ASSERT(r >= 0); 976 ASSERT(read_req.result >= 0); 977 ASSERT(strcmp(buf, test_buf) == 0); 978 uv_fs_req_cleanup(&read_req); 979 980 r = uv_fs_ftruncate(NULL, &ftruncate_req, open_req1.result, 7, NULL); 981 ASSERT(r == 0); 982 ASSERT(ftruncate_req.result == 0); 983 uv_fs_req_cleanup(&ftruncate_req); 984 985 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 986 ASSERT(r == 0); 987 ASSERT(close_req.result == 0); 988 uv_fs_req_cleanup(&close_req); 989 990 r = uv_fs_rename(NULL, &rename_req, "test_file", "test_file2", NULL); 991 ASSERT(r == 0); 992 ASSERT(rename_req.result == 0); 993 uv_fs_req_cleanup(&rename_req); 994 995 r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY | add_flags, 0, 996 NULL); 997 ASSERT(r >= 0); 998 ASSERT(open_req1.result >= 0); 999 uv_fs_req_cleanup(&open_req1); 1000 1001 memset(buf, 0, sizeof(buf)); 1002 iov = uv_buf_init(buf, sizeof(buf)); 1003 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 1004 ASSERT(r >= 0); 1005 ASSERT(read_req.result >= 0); 1006 ASSERT(strcmp(buf, "test-bu") == 0); 1007 uv_fs_req_cleanup(&read_req); 1008 1009 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 1010 ASSERT(r == 0); 1011 ASSERT(close_req.result == 0); 1012 uv_fs_req_cleanup(&close_req); 1013 1014 r = uv_fs_unlink(NULL, &unlink_req, "test_file2", NULL); 1015 ASSERT(r == 0); 1016 ASSERT(unlink_req.result == 0); 1017 uv_fs_req_cleanup(&unlink_req); 1018 1019 /* Cleanup */ 1020 unlink("test_file"); 1021 unlink("test_file2"); 1022 } 1023 TEST_IMPL(fs_file_sync) { 1024 fs_file_sync(0); 1025 fs_file_sync(UV_FS_O_FILEMAP); 1026 1027 MAKE_VALGRIND_HAPPY(); 1028 return 0; 1029 } 1030 1031 1032 static void fs_file_write_null_buffer(int add_flags) { 1033 int r; 1034 1035 /* Setup. */ 1036 unlink("test_file"); 1037 1038 loop = uv_default_loop(); 1039 1040 r = uv_fs_open(NULL, &open_req1, "test_file", 1041 O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); 1042 ASSERT(r >= 0); 1043 ASSERT(open_req1.result >= 0); 1044 uv_fs_req_cleanup(&open_req1); 1045 1046 iov = uv_buf_init(NULL, 0); 1047 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); 1048 ASSERT(r == 0); 1049 ASSERT(write_req.result == 0); 1050 uv_fs_req_cleanup(&write_req); 1051 1052 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 1053 ASSERT(r == 0); 1054 ASSERT(close_req.result == 0); 1055 uv_fs_req_cleanup(&close_req); 1056 1057 unlink("test_file"); 1058 } 1059 TEST_IMPL(fs_file_write_null_buffer) { 1060 fs_file_write_null_buffer(0); 1061 fs_file_write_null_buffer(UV_FS_O_FILEMAP); 1062 1063 MAKE_VALGRIND_HAPPY(); 1064 return 0; 1065 } 1066 1067 1068 TEST_IMPL(fs_async_dir) { 1069 int r; 1070 uv_dirent_t dent; 1071 1072 /* Setup */ 1073 unlink("test_dir/file1"); 1074 unlink("test_dir/file2"); 1075 rmdir("test_dir"); 1076 1077 loop = uv_default_loop(); 1078 1079 r = uv_fs_mkdir(loop, &mkdir_req, "test_dir", 0755, mkdir_cb); 1080 ASSERT(r == 0); 1081 1082 uv_run(loop, UV_RUN_DEFAULT); 1083 ASSERT(mkdir_cb_count == 1); 1084 1085 /* Create 2 files synchronously. */ 1086 r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, 1087 S_IWUSR | S_IRUSR, NULL); 1088 ASSERT(r >= 0); 1089 uv_fs_req_cleanup(&open_req1); 1090 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 1091 ASSERT(r == 0); 1092 uv_fs_req_cleanup(&close_req); 1093 1094 r = uv_fs_open(NULL, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, 1095 S_IWUSR | S_IRUSR, NULL); 1096 ASSERT(r >= 0); 1097 uv_fs_req_cleanup(&open_req1); 1098 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 1099 ASSERT(r == 0); 1100 uv_fs_req_cleanup(&close_req); 1101 1102 r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, scandir_cb); 1103 ASSERT(r == 0); 1104 1105 uv_run(loop, UV_RUN_DEFAULT); 1106 ASSERT(scandir_cb_count == 1); 1107 1108 /* sync uv_fs_scandir */ 1109 r = uv_fs_scandir(NULL, &scandir_req, "test_dir", 0, NULL); 1110 ASSERT(r == 2); 1111 ASSERT(scandir_req.result == 2); 1112 ASSERT(scandir_req.ptr); 1113 while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { 1114 ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); 1115 assert_is_file_type(dent); 1116 } 1117 uv_fs_req_cleanup(&scandir_req); 1118 ASSERT(!scandir_req.ptr); 1119 1120 r = uv_fs_stat(loop, &stat_req, "test_dir", stat_cb); 1121 ASSERT(r == 0); 1122 uv_run(loop, UV_RUN_DEFAULT); 1123 1124 r = uv_fs_stat(loop, &stat_req, "test_dir/", stat_cb); 1125 ASSERT(r == 0); 1126 uv_run(loop, UV_RUN_DEFAULT); 1127 1128 r = uv_fs_lstat(loop, &stat_req, "test_dir", stat_cb); 1129 ASSERT(r == 0); 1130 uv_run(loop, UV_RUN_DEFAULT); 1131 1132 r = uv_fs_lstat(loop, &stat_req, "test_dir/", stat_cb); 1133 ASSERT(r == 0); 1134 uv_run(loop, UV_RUN_DEFAULT); 1135 1136 ASSERT(stat_cb_count == 4); 1137 1138 r = uv_fs_unlink(loop, &unlink_req, "test_dir/file1", unlink_cb); 1139 ASSERT(r == 0); 1140 uv_run(loop, UV_RUN_DEFAULT); 1141 ASSERT(unlink_cb_count == 1); 1142 1143 r = uv_fs_unlink(loop, &unlink_req, "test_dir/file2", unlink_cb); 1144 ASSERT(r == 0); 1145 uv_run(loop, UV_RUN_DEFAULT); 1146 ASSERT(unlink_cb_count == 2); 1147 1148 r = uv_fs_rmdir(loop, &rmdir_req, "test_dir", rmdir_cb); 1149 ASSERT(r == 0); 1150 uv_run(loop, UV_RUN_DEFAULT); 1151 ASSERT(rmdir_cb_count == 1); 1152 1153 /* Cleanup */ 1154 unlink("test_dir/file1"); 1155 unlink("test_dir/file2"); 1156 rmdir("test_dir"); 1157 1158 MAKE_VALGRIND_HAPPY(); 1159 return 0; 1160 } 1161 1162 1163 static int test_sendfile(void (*setup)(int), uv_fs_cb cb, off_t expected_size) { 1164 int f, r; 1165 struct stat s1, s2; 1166 1167 loop = uv_default_loop(); 1168 1169 /* Setup. */ 1170 unlink("test_file"); 1171 unlink("test_file2"); 1172 1173 f = open("test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR); 1174 ASSERT(f != -1); 1175 1176 if (setup != NULL) 1177 setup(f); 1178 1179 r = close(f); 1180 ASSERT(r == 0); 1181 1182 /* Test starts here. */ 1183 r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR, 0, NULL); 1184 ASSERT(r >= 0); 1185 ASSERT(open_req1.result >= 0); 1186 uv_fs_req_cleanup(&open_req1); 1187 1188 r = uv_fs_open(NULL, &open_req2, "test_file2", O_WRONLY | O_CREAT, 1189 S_IWUSR | S_IRUSR, NULL); 1190 ASSERT(r >= 0); 1191 ASSERT(open_req2.result >= 0); 1192 uv_fs_req_cleanup(&open_req2); 1193 1194 r = uv_fs_sendfile(loop, &sendfile_req, open_req2.result, open_req1.result, 1195 0, 131072, cb); 1196 ASSERT(r == 0); 1197 uv_run(loop, UV_RUN_DEFAULT); 1198 1199 ASSERT(sendfile_cb_count == 1); 1200 1201 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 1202 ASSERT(r == 0); 1203 uv_fs_req_cleanup(&close_req); 1204 r = uv_fs_close(NULL, &close_req, open_req2.result, NULL); 1205 ASSERT(r == 0); 1206 uv_fs_req_cleanup(&close_req); 1207 1208 ASSERT(0 == stat("test_file", &s1)); 1209 ASSERT(0 == stat("test_file2", &s2)); 1210 ASSERT(s1.st_size == s2.st_size); 1211 ASSERT(s2.st_size == expected_size); 1212 1213 /* Cleanup. */ 1214 unlink("test_file"); 1215 unlink("test_file2"); 1216 1217 MAKE_VALGRIND_HAPPY(); 1218 return 0; 1219 } 1220 1221 1222 static void sendfile_setup(int f) { 1223 ASSERT(6 == write(f, "begin\n", 6)); 1224 ASSERT(65542 == lseek(f, 65536, SEEK_CUR)); 1225 ASSERT(4 == write(f, "end\n", 4)); 1226 } 1227 1228 1229 TEST_IMPL(fs_async_sendfile) { 1230 return test_sendfile(sendfile_setup, sendfile_cb, 65546); 1231 } 1232 1233 1234 TEST_IMPL(fs_async_sendfile_nodata) { 1235 return test_sendfile(NULL, sendfile_nodata_cb, 0); 1236 } 1237 1238 1239 TEST_IMPL(fs_mkdtemp) { 1240 int r; 1241 const char* path_template = "test_dir_XXXXXX"; 1242 1243 loop = uv_default_loop(); 1244 1245 r = uv_fs_mkdtemp(loop, &mkdtemp_req1, path_template, mkdtemp_cb); 1246 ASSERT(r == 0); 1247 1248 uv_run(loop, UV_RUN_DEFAULT); 1249 ASSERT(mkdtemp_cb_count == 1); 1250 1251 /* sync mkdtemp */ 1252 r = uv_fs_mkdtemp(NULL, &mkdtemp_req2, path_template, NULL); 1253 ASSERT(r == 0); 1254 check_mkdtemp_result(&mkdtemp_req2); 1255 1256 /* mkdtemp return different values on subsequent calls */ 1257 ASSERT(strcmp(mkdtemp_req1.path, mkdtemp_req2.path) != 0); 1258 1259 /* Cleanup */ 1260 rmdir(mkdtemp_req1.path); 1261 rmdir(mkdtemp_req2.path); 1262 uv_fs_req_cleanup(&mkdtemp_req1); 1263 uv_fs_req_cleanup(&mkdtemp_req2); 1264 1265 MAKE_VALGRIND_HAPPY(); 1266 return 0; 1267 } 1268 1269 1270 TEST_IMPL(fs_mkstemp) { 1271 int r; 1272 int fd; 1273 const char path_template[] = "test_file_XXXXXX"; 1274 uv_fs_t req; 1275 1276 loop = uv_default_loop(); 1277 1278 r = uv_fs_mkstemp(loop, &mkstemp_req1, path_template, mkstemp_cb); 1279 ASSERT(r == 0); 1280 1281 uv_run(loop, UV_RUN_DEFAULT); 1282 ASSERT(mkstemp_cb_count == 1); 1283 1284 /* sync mkstemp */ 1285 r = uv_fs_mkstemp(NULL, &mkstemp_req2, path_template, NULL); 1286 ASSERT(r >= 0); 1287 check_mkstemp_result(&mkstemp_req2); 1288 1289 /* mkstemp return different values on subsequent calls */ 1290 ASSERT(strcmp(mkstemp_req1.path, mkstemp_req2.path) != 0); 1291 1292 /* invalid template returns EINVAL */ 1293 ASSERT(uv_fs_mkstemp(NULL, &mkstemp_req3, "test_file", NULL) == UV_EINVAL); 1294 1295 /* We can write to the opened file */ 1296 iov = uv_buf_init(test_buf, sizeof(test_buf)); 1297 r = uv_fs_write(NULL, &req, mkstemp_req1.result, &iov, 1, -1, NULL); 1298 ASSERT(r == sizeof(test_buf)); 1299 ASSERT(req.result == sizeof(test_buf)); 1300 uv_fs_req_cleanup(&req); 1301 1302 /* Cleanup */ 1303 uv_fs_close(NULL, &req, mkstemp_req1.result, NULL); 1304 uv_fs_req_cleanup(&req); 1305 uv_fs_close(NULL, &req, mkstemp_req2.result, NULL); 1306 uv_fs_req_cleanup(&req); 1307 1308 fd = uv_fs_open(NULL, &req, mkstemp_req1.path , O_RDONLY, 0, NULL); 1309 ASSERT(fd >= 0); 1310 uv_fs_req_cleanup(&req); 1311 1312 memset(buf, 0, sizeof(buf)); 1313 iov = uv_buf_init(buf, sizeof(buf)); 1314 r = uv_fs_read(NULL, &req, fd, &iov, 1, -1, NULL); 1315 ASSERT(r >= 0); 1316 ASSERT(req.result >= 0); 1317 ASSERT(strcmp(buf, test_buf) == 0); 1318 uv_fs_req_cleanup(&req); 1319 1320 uv_fs_close(NULL, &req, fd, NULL); 1321 uv_fs_req_cleanup(&req); 1322 1323 unlink(mkstemp_req1.path); 1324 unlink(mkstemp_req2.path); 1325 uv_fs_req_cleanup(&mkstemp_req1); 1326 uv_fs_req_cleanup(&mkstemp_req2); 1327 1328 MAKE_VALGRIND_HAPPY(); 1329 return 0; 1330 } 1331 1332 1333 TEST_IMPL(fs_fstat) { 1334 int r; 1335 uv_fs_t req; 1336 uv_file file; 1337 uv_stat_t* s; 1338 #ifndef _WIN32 1339 struct stat t; 1340 #endif 1341 1342 /* Setup. */ 1343 unlink("test_file"); 1344 1345 loop = uv_default_loop(); 1346 1347 r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, 1348 S_IWUSR | S_IRUSR, NULL); 1349 ASSERT(r >= 0); 1350 ASSERT(req.result >= 0); 1351 file = req.result; 1352 uv_fs_req_cleanup(&req); 1353 1354 #ifndef _WIN32 1355 ASSERT(0 == fstat(file, &t)); 1356 ASSERT(0 == uv_fs_fstat(NULL, &req, file, NULL)); 1357 ASSERT(req.result == 0); 1358 s = req.ptr; 1359 # if defined(__APPLE__) 1360 ASSERT(s->st_birthtim.tv_sec == t.st_birthtimespec.tv_sec); 1361 ASSERT(s->st_birthtim.tv_nsec == t.st_birthtimespec.tv_nsec); 1362 # elif defined(__linux__) 1363 /* If statx() is supported, the birth time should be equal to the change time 1364 * because we just created the file. On older kernels, it's set to zero. 1365 */ 1366 ASSERT(s->st_birthtim.tv_sec == 0 || 1367 s->st_birthtim.tv_sec == t.st_ctim.tv_sec); 1368 ASSERT(s->st_birthtim.tv_nsec == 0 || 1369 s->st_birthtim.tv_nsec == t.st_ctim.tv_nsec); 1370 # endif 1371 #endif 1372 1373 iov = uv_buf_init(test_buf, sizeof(test_buf)); 1374 r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); 1375 ASSERT(r == sizeof(test_buf)); 1376 ASSERT(req.result == sizeof(test_buf)); 1377 uv_fs_req_cleanup(&req); 1378 1379 memset(&req.statbuf, 0xaa, sizeof(req.statbuf)); 1380 r = uv_fs_fstat(NULL, &req, file, NULL); 1381 ASSERT(r == 0); 1382 ASSERT(req.result == 0); 1383 s = req.ptr; 1384 ASSERT(s->st_size == sizeof(test_buf)); 1385 1386 #ifndef _WIN32 1387 r = fstat(file, &t); 1388 ASSERT(r == 0); 1389 1390 ASSERT(s->st_dev == (uint64_t) t.st_dev); 1391 ASSERT(s->st_mode == (uint64_t) t.st_mode); 1392 ASSERT(s->st_nlink == (uint64_t) t.st_nlink); 1393 ASSERT(s->st_uid == (uint64_t) t.st_uid); 1394 ASSERT(s->st_gid == (uint64_t) t.st_gid); 1395 ASSERT(s->st_rdev == (uint64_t) t.st_rdev); 1396 ASSERT(s->st_ino == (uint64_t) t.st_ino); 1397 ASSERT(s->st_size == (uint64_t) t.st_size); 1398 ASSERT(s->st_blksize == (uint64_t) t.st_blksize); 1399 ASSERT(s->st_blocks == (uint64_t) t.st_blocks); 1400 #if defined(__APPLE__) 1401 ASSERT(s->st_atim.tv_sec == t.st_atimespec.tv_sec); 1402 ASSERT(s->st_atim.tv_nsec == t.st_atimespec.tv_nsec); 1403 ASSERT(s->st_mtim.tv_sec == t.st_mtimespec.tv_sec); 1404 ASSERT(s->st_mtim.tv_nsec == t.st_mtimespec.tv_nsec); 1405 ASSERT(s->st_ctim.tv_sec == t.st_ctimespec.tv_sec); 1406 ASSERT(s->st_ctim.tv_nsec == t.st_ctimespec.tv_nsec); 1407 #elif defined(_AIX) 1408 ASSERT(s->st_atim.tv_sec == t.st_atime); 1409 ASSERT(s->st_atim.tv_nsec == 0); 1410 ASSERT(s->st_mtim.tv_sec == t.st_mtime); 1411 ASSERT(s->st_mtim.tv_nsec == 0); 1412 ASSERT(s->st_ctim.tv_sec == t.st_ctime); 1413 ASSERT(s->st_ctim.tv_nsec == 0); 1414 #elif defined(__ANDROID__) 1415 ASSERT(s->st_atim.tv_sec == t.st_atime); 1416 ASSERT(s->st_atim.tv_nsec == t.st_atimensec); 1417 ASSERT(s->st_mtim.tv_sec == t.st_mtime); 1418 ASSERT(s->st_mtim.tv_nsec == t.st_mtimensec); 1419 ASSERT(s->st_ctim.tv_sec == t.st_ctime); 1420 ASSERT(s->st_ctim.tv_nsec == t.st_ctimensec); 1421 #elif defined(__sun) || \ 1422 defined(__DragonFly__) || \ 1423 defined(__FreeBSD__) || \ 1424 defined(__OpenBSD__) || \ 1425 defined(__NetBSD__) || \ 1426 defined(_GNU_SOURCE) || \ 1427 defined(_BSD_SOURCE) || \ 1428 defined(_SVID_SOURCE) || \ 1429 defined(_XOPEN_SOURCE) || \ 1430 defined(_DEFAULT_SOURCE) 1431 ASSERT(s->st_atim.tv_sec == t.st_atim.tv_sec); 1432 ASSERT(s->st_atim.tv_nsec == t.st_atim.tv_nsec); 1433 ASSERT(s->st_mtim.tv_sec == t.st_mtim.tv_sec); 1434 ASSERT(s->st_mtim.tv_nsec == t.st_mtim.tv_nsec); 1435 ASSERT(s->st_ctim.tv_sec == t.st_ctim.tv_sec); 1436 ASSERT(s->st_ctim.tv_nsec == t.st_ctim.tv_nsec); 1437 # if defined(__FreeBSD__) || \ 1438 defined(__NetBSD__) 1439 ASSERT(s->st_birthtim.tv_sec == t.st_birthtim.tv_sec); 1440 ASSERT(s->st_birthtim.tv_nsec == t.st_birthtim.tv_nsec); 1441 # endif 1442 #else 1443 ASSERT(s->st_atim.tv_sec == t.st_atime); 1444 ASSERT(s->st_atim.tv_nsec == 0); 1445 ASSERT(s->st_mtim.tv_sec == t.st_mtime); 1446 ASSERT(s->st_mtim.tv_nsec == 0); 1447 ASSERT(s->st_ctim.tv_sec == t.st_ctime); 1448 ASSERT(s->st_ctim.tv_nsec == 0); 1449 #endif 1450 #endif 1451 1452 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) 1453 ASSERT(s->st_flags == t.st_flags); 1454 ASSERT(s->st_gen == t.st_gen); 1455 #else 1456 ASSERT(s->st_flags == 0); 1457 ASSERT(s->st_gen == 0); 1458 #endif 1459 1460 uv_fs_req_cleanup(&req); 1461 1462 /* Now do the uv_fs_fstat call asynchronously */ 1463 r = uv_fs_fstat(loop, &req, file, fstat_cb); 1464 ASSERT(r == 0); 1465 uv_run(loop, UV_RUN_DEFAULT); 1466 ASSERT(fstat_cb_count == 1); 1467 1468 1469 r = uv_fs_close(NULL, &req, file, NULL); 1470 ASSERT(r == 0); 1471 ASSERT(req.result == 0); 1472 uv_fs_req_cleanup(&req); 1473 1474 /* 1475 * Run the loop just to check we don't have make any extraneous uv_ref() 1476 * calls. This should drop out immediately. 1477 */ 1478 uv_run(loop, UV_RUN_DEFAULT); 1479 1480 /* Cleanup. */ 1481 unlink("test_file"); 1482 1483 MAKE_VALGRIND_HAPPY(); 1484 return 0; 1485 } 1486 1487 1488 TEST_IMPL(fs_access) { 1489 int r; 1490 uv_fs_t req; 1491 uv_file file; 1492 1493 /* Setup. */ 1494 unlink("test_file"); 1495 rmdir("test_dir"); 1496 1497 loop = uv_default_loop(); 1498 1499 /* File should not exist */ 1500 r = uv_fs_access(NULL, &req, "test_file", F_OK, NULL); 1501 ASSERT(r < 0); 1502 ASSERT(req.result < 0); 1503 uv_fs_req_cleanup(&req); 1504 1505 /* File should not exist */ 1506 r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb); 1507 ASSERT(r == 0); 1508 uv_run(loop, UV_RUN_DEFAULT); 1509 ASSERT(access_cb_count == 1); 1510 access_cb_count = 0; /* reset for the next test */ 1511 1512 /* Create file */ 1513 r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, 1514 S_IWUSR | S_IRUSR, NULL); 1515 ASSERT(r >= 0); 1516 ASSERT(req.result >= 0); 1517 file = req.result; 1518 uv_fs_req_cleanup(&req); 1519 1520 /* File should exist */ 1521 r = uv_fs_access(NULL, &req, "test_file", F_OK, NULL); 1522 ASSERT(r == 0); 1523 ASSERT(req.result == 0); 1524 uv_fs_req_cleanup(&req); 1525 1526 /* File should exist */ 1527 r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb); 1528 ASSERT(r == 0); 1529 uv_run(loop, UV_RUN_DEFAULT); 1530 ASSERT(access_cb_count == 1); 1531 access_cb_count = 0; /* reset for the next test */ 1532 1533 /* Close file */ 1534 r = uv_fs_close(NULL, &req, file, NULL); 1535 ASSERT(r == 0); 1536 ASSERT(req.result == 0); 1537 uv_fs_req_cleanup(&req); 1538 1539 /* Directory access */ 1540 r = uv_fs_mkdir(NULL, &req, "test_dir", 0777, NULL); 1541 ASSERT(r == 0); 1542 uv_fs_req_cleanup(&req); 1543 1544 r = uv_fs_access(NULL, &req, "test_dir", W_OK, NULL); 1545 ASSERT(r == 0); 1546 ASSERT(req.result == 0); 1547 uv_fs_req_cleanup(&req); 1548 1549 /* 1550 * Run the loop just to check we don't have make any extraneous uv_ref() 1551 * calls. This should drop out immediately. 1552 */ 1553 uv_run(loop, UV_RUN_DEFAULT); 1554 1555 /* Cleanup. */ 1556 unlink("test_file"); 1557 rmdir("test_dir"); 1558 1559 MAKE_VALGRIND_HAPPY(); 1560 return 0; 1561 } 1562 1563 1564 TEST_IMPL(fs_chmod) { 1565 int r; 1566 uv_fs_t req; 1567 uv_file file; 1568 1569 /* Setup. */ 1570 unlink("test_file"); 1571 1572 loop = uv_default_loop(); 1573 1574 r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, 1575 S_IWUSR | S_IRUSR, NULL); 1576 ASSERT(r >= 0); 1577 ASSERT(req.result >= 0); 1578 file = req.result; 1579 uv_fs_req_cleanup(&req); 1580 1581 iov = uv_buf_init(test_buf, sizeof(test_buf)); 1582 r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); 1583 ASSERT(r == sizeof(test_buf)); 1584 ASSERT(req.result == sizeof(test_buf)); 1585 uv_fs_req_cleanup(&req); 1586 1587 #ifndef _WIN32 1588 /* Make the file write-only */ 1589 r = uv_fs_chmod(NULL, &req, "test_file", 0200, NULL); 1590 ASSERT(r == 0); 1591 ASSERT(req.result == 0); 1592 uv_fs_req_cleanup(&req); 1593 1594 check_permission("test_file", 0200); 1595 #endif 1596 1597 /* Make the file read-only */ 1598 r = uv_fs_chmod(NULL, &req, "test_file", 0400, NULL); 1599 ASSERT(r == 0); 1600 ASSERT(req.result == 0); 1601 uv_fs_req_cleanup(&req); 1602 1603 check_permission("test_file", 0400); 1604 1605 /* Make the file read+write with sync uv_fs_fchmod */ 1606 r = uv_fs_fchmod(NULL, &req, file, 0600, NULL); 1607 ASSERT(r == 0); 1608 ASSERT(req.result == 0); 1609 uv_fs_req_cleanup(&req); 1610 1611 check_permission("test_file", 0600); 1612 1613 #ifndef _WIN32 1614 /* async chmod */ 1615 { 1616 static int mode = 0200; 1617 req.data = &mode; 1618 } 1619 r = uv_fs_chmod(loop, &req, "test_file", 0200, chmod_cb); 1620 ASSERT(r == 0); 1621 uv_run(loop, UV_RUN_DEFAULT); 1622 ASSERT(chmod_cb_count == 1); 1623 chmod_cb_count = 0; /* reset for the next test */ 1624 #endif 1625 1626 /* async chmod */ 1627 { 1628 static int mode = 0400; 1629 req.data = &mode; 1630 } 1631 r = uv_fs_chmod(loop, &req, "test_file", 0400, chmod_cb); 1632 ASSERT(r == 0); 1633 uv_run(loop, UV_RUN_DEFAULT); 1634 ASSERT(chmod_cb_count == 1); 1635 1636 /* async fchmod */ 1637 { 1638 static int mode = 0600; 1639 req.data = &mode; 1640 } 1641 r = uv_fs_fchmod(loop, &req, file, 0600, fchmod_cb); 1642 ASSERT(r == 0); 1643 uv_run(loop, UV_RUN_DEFAULT); 1644 ASSERT(fchmod_cb_count == 1); 1645 1646 uv_fs_close(loop, &req, file, NULL); 1647 1648 /* 1649 * Run the loop just to check we don't have make any extraneous uv_ref() 1650 * calls. This should drop out immediately. 1651 */ 1652 uv_run(loop, UV_RUN_DEFAULT); 1653 1654 /* Cleanup. */ 1655 unlink("test_file"); 1656 1657 MAKE_VALGRIND_HAPPY(); 1658 return 0; 1659 } 1660 1661 1662 TEST_IMPL(fs_unlink_readonly) { 1663 int r; 1664 uv_fs_t req; 1665 uv_file file; 1666 1667 /* Setup. */ 1668 unlink("test_file"); 1669 1670 loop = uv_default_loop(); 1671 1672 r = uv_fs_open(NULL, 1673 &req, 1674 "test_file", 1675 O_RDWR | O_CREAT, 1676 S_IWUSR | S_IRUSR, 1677 NULL); 1678 ASSERT(r >= 0); 1679 ASSERT(req.result >= 0); 1680 file = req.result; 1681 uv_fs_req_cleanup(&req); 1682 1683 iov = uv_buf_init(test_buf, sizeof(test_buf)); 1684 r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); 1685 ASSERT(r == sizeof(test_buf)); 1686 ASSERT(req.result == sizeof(test_buf)); 1687 uv_fs_req_cleanup(&req); 1688 1689 uv_fs_close(loop, &req, file, NULL); 1690 1691 /* Make the file read-only */ 1692 r = uv_fs_chmod(NULL, &req, "test_file", 0400, NULL); 1693 ASSERT(r == 0); 1694 ASSERT(req.result == 0); 1695 uv_fs_req_cleanup(&req); 1696 1697 check_permission("test_file", 0400); 1698 1699 /* Try to unlink the file */ 1700 r = uv_fs_unlink(NULL, &req, "test_file", NULL); 1701 ASSERT(r == 0); 1702 ASSERT(req.result == 0); 1703 uv_fs_req_cleanup(&req); 1704 1705 /* 1706 * Run the loop just to check we don't have make any extraneous uv_ref() 1707 * calls. This should drop out immediately. 1708 */ 1709 uv_run(loop, UV_RUN_DEFAULT); 1710 1711 /* Cleanup. */ 1712 uv_fs_chmod(NULL, &req, "test_file", 0600, NULL); 1713 uv_fs_req_cleanup(&req); 1714 unlink("test_file"); 1715 1716 MAKE_VALGRIND_HAPPY(); 1717 return 0; 1718 } 1719 1720 #ifdef _WIN32 1721 TEST_IMPL(fs_unlink_archive_readonly) { 1722 int r; 1723 uv_fs_t req; 1724 uv_file file; 1725 1726 /* Setup. */ 1727 unlink("test_file"); 1728 1729 loop = uv_default_loop(); 1730 1731 r = uv_fs_open(NULL, 1732 &req, 1733 "test_file", 1734 O_RDWR | O_CREAT, 1735 S_IWUSR | S_IRUSR, 1736 NULL); 1737 ASSERT(r >= 0); 1738 ASSERT(req.result >= 0); 1739 file = req.result; 1740 uv_fs_req_cleanup(&req); 1741 1742 iov = uv_buf_init(test_buf, sizeof(test_buf)); 1743 r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); 1744 ASSERT(r == sizeof(test_buf)); 1745 ASSERT(req.result == sizeof(test_buf)); 1746 uv_fs_req_cleanup(&req); 1747 1748 uv_fs_close(loop, &req, file, NULL); 1749 1750 /* Make the file read-only and clear archive flag */ 1751 r = SetFileAttributes("test_file", FILE_ATTRIBUTE_READONLY); 1752 ASSERT(r != 0); 1753 uv_fs_req_cleanup(&req); 1754 1755 check_permission("test_file", 0400); 1756 1757 /* Try to unlink the file */ 1758 r = uv_fs_unlink(NULL, &req, "test_file", NULL); 1759 ASSERT(r == 0); 1760 ASSERT(req.result == 0); 1761 uv_fs_req_cleanup(&req); 1762 1763 /* 1764 * Run the loop just to check we don't have make any extraneous uv_ref() 1765 * calls. This should drop out immediately. 1766 */ 1767 uv_run(loop, UV_RUN_DEFAULT); 1768 1769 /* Cleanup. */ 1770 uv_fs_chmod(NULL, &req, "test_file", 0600, NULL); 1771 uv_fs_req_cleanup(&req); 1772 unlink("test_file"); 1773 1774 MAKE_VALGRIND_HAPPY(); 1775 return 0; 1776 } 1777 #endif 1778 1779 TEST_IMPL(fs_chown) { 1780 int r; 1781 uv_fs_t req; 1782 uv_file file; 1783 1784 /* Setup. */ 1785 unlink("test_file"); 1786 unlink("test_file_link"); 1787 1788 loop = uv_default_loop(); 1789 1790 r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, 1791 S_IWUSR | S_IRUSR, NULL); 1792 ASSERT(r >= 0); 1793 ASSERT(req.result >= 0); 1794 file = req.result; 1795 uv_fs_req_cleanup(&req); 1796 1797 /* sync chown */ 1798 r = uv_fs_chown(NULL, &req, "test_file", -1, -1, NULL); 1799 ASSERT(r == 0); 1800 ASSERT(req.result == 0); 1801 uv_fs_req_cleanup(&req); 1802 1803 /* sync fchown */ 1804 r = uv_fs_fchown(NULL, &req, file, -1, -1, NULL); 1805 ASSERT(r == 0); 1806 ASSERT(req.result == 0); 1807 uv_fs_req_cleanup(&req); 1808 1809 /* async chown */ 1810 r = uv_fs_chown(loop, &req, "test_file", -1, -1, chown_cb); 1811 ASSERT(r == 0); 1812 uv_run(loop, UV_RUN_DEFAULT); 1813 ASSERT(chown_cb_count == 1); 1814 1815 #ifndef __MVS__ 1816 /* chown to root (fail) */ 1817 chown_cb_count = 0; 1818 r = uv_fs_chown(loop, &req, "test_file", 0, 0, chown_root_cb); 1819 ASSERT(r == 0); 1820 uv_run(loop, UV_RUN_DEFAULT); 1821 ASSERT(chown_cb_count == 1); 1822 #endif 1823 1824 /* async fchown */ 1825 r = uv_fs_fchown(loop, &req, file, -1, -1, fchown_cb); 1826 ASSERT(r == 0); 1827 uv_run(loop, UV_RUN_DEFAULT); 1828 ASSERT(fchown_cb_count == 1); 1829 1830 #ifndef __HAIKU__ 1831 /* Haiku doesn't support hardlink */ 1832 /* sync link */ 1833 r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL); 1834 ASSERT(r == 0); 1835 ASSERT(req.result == 0); 1836 uv_fs_req_cleanup(&req); 1837 1838 /* sync lchown */ 1839 r = uv_fs_lchown(NULL, &req, "test_file_link", -1, -1, NULL); 1840 ASSERT(r == 0); 1841 ASSERT(req.result == 0); 1842 uv_fs_req_cleanup(&req); 1843 1844 /* async lchown */ 1845 r = uv_fs_lchown(loop, &req, "test_file_link", -1, -1, lchown_cb); 1846 ASSERT(r == 0); 1847 uv_run(loop, UV_RUN_DEFAULT); 1848 ASSERT(lchown_cb_count == 1); 1849 #endif 1850 1851 /* Close file */ 1852 r = uv_fs_close(NULL, &req, file, NULL); 1853 ASSERT(r == 0); 1854 ASSERT(req.result == 0); 1855 uv_fs_req_cleanup(&req); 1856 1857 /* 1858 * Run the loop just to check we don't have make any extraneous uv_ref() 1859 * calls. This should drop out immediately. 1860 */ 1861 uv_run(loop, UV_RUN_DEFAULT); 1862 1863 /* Cleanup. */ 1864 unlink("test_file"); 1865 unlink("test_file_link"); 1866 1867 MAKE_VALGRIND_HAPPY(); 1868 return 0; 1869 } 1870 1871 1872 TEST_IMPL(fs_link) { 1873 int r; 1874 uv_fs_t req; 1875 uv_file file; 1876 uv_file link; 1877 1878 /* Setup. */ 1879 unlink("test_file"); 1880 unlink("test_file_link"); 1881 unlink("test_file_link2"); 1882 1883 loop = uv_default_loop(); 1884 1885 r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, 1886 S_IWUSR | S_IRUSR, NULL); 1887 ASSERT(r >= 0); 1888 ASSERT(req.result >= 0); 1889 file = req.result; 1890 uv_fs_req_cleanup(&req); 1891 1892 iov = uv_buf_init(test_buf, sizeof(test_buf)); 1893 r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); 1894 ASSERT(r == sizeof(test_buf)); 1895 ASSERT(req.result == sizeof(test_buf)); 1896 uv_fs_req_cleanup(&req); 1897 1898 uv_fs_close(loop, &req, file, NULL); 1899 1900 /* sync link */ 1901 r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL); 1902 ASSERT(r == 0); 1903 ASSERT(req.result == 0); 1904 uv_fs_req_cleanup(&req); 1905 1906 r = uv_fs_open(NULL, &req, "test_file_link", O_RDWR, 0, NULL); 1907 ASSERT(r >= 0); 1908 ASSERT(req.result >= 0); 1909 link = req.result; 1910 uv_fs_req_cleanup(&req); 1911 1912 memset(buf, 0, sizeof(buf)); 1913 iov = uv_buf_init(buf, sizeof(buf)); 1914 r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL); 1915 ASSERT(r >= 0); 1916 ASSERT(req.result >= 0); 1917 ASSERT(strcmp(buf, test_buf) == 0); 1918 1919 close(link); 1920 1921 /* async link */ 1922 r = uv_fs_link(loop, &req, "test_file", "test_file_link2", link_cb); 1923 ASSERT(r == 0); 1924 uv_run(loop, UV_RUN_DEFAULT); 1925 ASSERT(link_cb_count == 1); 1926 1927 r = uv_fs_open(NULL, &req, "test_file_link2", O_RDWR, 0, NULL); 1928 ASSERT(r >= 0); 1929 ASSERT(req.result >= 0); 1930 link = req.result; 1931 uv_fs_req_cleanup(&req); 1932 1933 memset(buf, 0, sizeof(buf)); 1934 iov = uv_buf_init(buf, sizeof(buf)); 1935 r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL); 1936 ASSERT(r >= 0); 1937 ASSERT(req.result >= 0); 1938 ASSERT(strcmp(buf, test_buf) == 0); 1939 1940 uv_fs_close(loop, &req, link, NULL); 1941 1942 /* 1943 * Run the loop just to check we don't have make any extraneous uv_ref() 1944 * calls. This should drop out immediately. 1945 */ 1946 uv_run(loop, UV_RUN_DEFAULT); 1947 1948 /* Cleanup. */ 1949 unlink("test_file"); 1950 unlink("test_file_link"); 1951 unlink("test_file_link2"); 1952 1953 MAKE_VALGRIND_HAPPY(); 1954 return 0; 1955 } 1956 1957 1958 TEST_IMPL(fs_readlink) { 1959 uv_fs_t req; 1960 1961 loop = uv_default_loop(); 1962 ASSERT(0 == uv_fs_readlink(loop, &req, "no_such_file", dummy_cb)); 1963 ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); 1964 ASSERT(dummy_cb_count == 1); 1965 ASSERT(req.ptr == NULL); 1966 ASSERT(req.result == UV_ENOENT); 1967 uv_fs_req_cleanup(&req); 1968 1969 ASSERT(UV_ENOENT == uv_fs_readlink(NULL, &req, "no_such_file", NULL)); 1970 ASSERT(req.ptr == NULL); 1971 ASSERT(req.result == UV_ENOENT); 1972 uv_fs_req_cleanup(&req); 1973 1974 MAKE_VALGRIND_HAPPY(); 1975 return 0; 1976 } 1977 1978 1979 TEST_IMPL(fs_realpath) { 1980 uv_fs_t req; 1981 1982 loop = uv_default_loop(); 1983 ASSERT(0 == uv_fs_realpath(loop, &req, "no_such_file", dummy_cb)); 1984 ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); 1985 ASSERT(dummy_cb_count == 1); 1986 ASSERT(req.ptr == NULL); 1987 #ifdef _WIN32 1988 /* 1989 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() 1990 */ 1991 if (req.result == UV_ENOSYS) { 1992 uv_fs_req_cleanup(&req); 1993 RETURN_SKIP("realpath is not supported on Windows XP"); 1994 } 1995 #endif 1996 ASSERT(req.result == UV_ENOENT); 1997 uv_fs_req_cleanup(&req); 1998 1999 ASSERT(UV_ENOENT == uv_fs_realpath(NULL, &req, "no_such_file", NULL)); 2000 ASSERT(req.ptr == NULL); 2001 ASSERT(req.result == UV_ENOENT); 2002 uv_fs_req_cleanup(&req); 2003 2004 MAKE_VALGRIND_HAPPY(); 2005 return 0; 2006 } 2007 2008 2009 TEST_IMPL(fs_symlink) { 2010 int r; 2011 uv_fs_t req; 2012 uv_file file; 2013 uv_file link; 2014 char test_file_abs_buf[PATHMAX]; 2015 size_t test_file_abs_size; 2016 2017 /* Setup. */ 2018 unlink("test_file"); 2019 unlink("test_file_symlink"); 2020 unlink("test_file_symlink2"); 2021 unlink("test_file_symlink_symlink"); 2022 unlink("test_file_symlink2_symlink"); 2023 test_file_abs_size = sizeof(test_file_abs_buf); 2024 #ifdef _WIN32 2025 uv_cwd(test_file_abs_buf, &test_file_abs_size); 2026 strcat(test_file_abs_buf, "\\test_file"); 2027 #else 2028 uv_cwd(test_file_abs_buf, &test_file_abs_size); 2029 strcat(test_file_abs_buf, "/test_file"); 2030 #endif 2031 2032 loop = uv_default_loop(); 2033 2034 r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, 2035 S_IWUSR | S_IRUSR, NULL); 2036 ASSERT(r >= 0); 2037 ASSERT(req.result >= 0); 2038 file = req.result; 2039 uv_fs_req_cleanup(&req); 2040 2041 iov = uv_buf_init(test_buf, sizeof(test_buf)); 2042 r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); 2043 ASSERT(r == sizeof(test_buf)); 2044 ASSERT(req.result == sizeof(test_buf)); 2045 uv_fs_req_cleanup(&req); 2046 2047 uv_fs_close(loop, &req, file, NULL); 2048 2049 /* sync symlink */ 2050 r = uv_fs_symlink(NULL, &req, "test_file", "test_file_symlink", 0, NULL); 2051 #ifdef _WIN32 2052 if (r < 0) { 2053 if (r == UV_ENOTSUP) { 2054 /* 2055 * Windows doesn't support symlinks on older versions. 2056 * We just pass the test and bail out early if we get ENOTSUP. 2057 */ 2058 return 0; 2059 } else if (r == UV_EPERM) { 2060 /* 2061 * Creating a symlink is only allowed when running elevated. 2062 * We pass the test and bail out early if we get UV_EPERM. 2063 */ 2064 return 0; 2065 } 2066 } 2067 #endif 2068 ASSERT(r == 0); 2069 ASSERT(req.result == 0); 2070 uv_fs_req_cleanup(&req); 2071 2072 r = uv_fs_open(NULL, &req, "test_file_symlink", O_RDWR, 0, NULL); 2073 ASSERT(r >= 0); 2074 ASSERT(req.result >= 0); 2075 link = req.result; 2076 uv_fs_req_cleanup(&req); 2077 2078 memset(buf, 0, sizeof(buf)); 2079 iov = uv_buf_init(buf, sizeof(buf)); 2080 r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL); 2081 ASSERT(r >= 0); 2082 ASSERT(req.result >= 0); 2083 ASSERT(strcmp(buf, test_buf) == 0); 2084 2085 uv_fs_close(loop, &req, link, NULL); 2086 2087 r = uv_fs_symlink(NULL, 2088 &req, 2089 "test_file_symlink", 2090 "test_file_symlink_symlink", 2091 0, 2092 NULL); 2093 ASSERT(r == 0); 2094 uv_fs_req_cleanup(&req); 2095 2096 #if defined(__MSYS__) 2097 RETURN_SKIP("symlink reading is not supported on MSYS2"); 2098 #endif 2099 2100 r = uv_fs_readlink(NULL, &req, "test_file_symlink_symlink", NULL); 2101 ASSERT(r == 0); 2102 ASSERT(strcmp(req.ptr, "test_file_symlink") == 0); 2103 uv_fs_req_cleanup(&req); 2104 2105 r = uv_fs_realpath(NULL, &req, "test_file_symlink_symlink", NULL); 2106 #ifdef _WIN32 2107 /* 2108 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() 2109 */ 2110 if (r == UV_ENOSYS) { 2111 uv_fs_req_cleanup(&req); 2112 RETURN_SKIP("realpath is not supported on Windows XP"); 2113 } 2114 #endif 2115 ASSERT(r == 0); 2116 #ifdef _WIN32 2117 ASSERT(stricmp(req.ptr, test_file_abs_buf) == 0); 2118 #else 2119 ASSERT(strcmp(req.ptr, test_file_abs_buf) == 0); 2120 #endif 2121 uv_fs_req_cleanup(&req); 2122 2123 /* async link */ 2124 r = uv_fs_symlink(loop, 2125 &req, 2126 "test_file", 2127 "test_file_symlink2", 2128 0, 2129 symlink_cb); 2130 ASSERT(r == 0); 2131 uv_run(loop, UV_RUN_DEFAULT); 2132 ASSERT(symlink_cb_count == 1); 2133 2134 r = uv_fs_open(NULL, &req, "test_file_symlink2", O_RDWR, 0, NULL); 2135 ASSERT(r >= 0); 2136 ASSERT(req.result >= 0); 2137 link = req.result; 2138 uv_fs_req_cleanup(&req); 2139 2140 memset(buf, 0, sizeof(buf)); 2141 iov = uv_buf_init(buf, sizeof(buf)); 2142 r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL); 2143 ASSERT(r >= 0); 2144 ASSERT(req.result >= 0); 2145 ASSERT(strcmp(buf, test_buf) == 0); 2146 2147 uv_fs_close(loop, &req, link, NULL); 2148 2149 r = uv_fs_symlink(NULL, 2150 &req, 2151 "test_file_symlink2", 2152 "test_file_symlink2_symlink", 2153 0, 2154 NULL); 2155 ASSERT(r == 0); 2156 uv_fs_req_cleanup(&req); 2157 2158 r = uv_fs_readlink(loop, &req, "test_file_symlink2_symlink", readlink_cb); 2159 ASSERT(r == 0); 2160 uv_run(loop, UV_RUN_DEFAULT); 2161 ASSERT(readlink_cb_count == 1); 2162 2163 r = uv_fs_realpath(loop, &req, "test_file", realpath_cb); 2164 #ifdef _WIN32 2165 /* 2166 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() 2167 */ 2168 if (r == UV_ENOSYS) { 2169 uv_fs_req_cleanup(&req); 2170 RETURN_SKIP("realpath is not supported on Windows XP"); 2171 } 2172 #endif 2173 ASSERT(r == 0); 2174 uv_run(loop, UV_RUN_DEFAULT); 2175 ASSERT(realpath_cb_count == 1); 2176 2177 /* 2178 * Run the loop just to check we don't have make any extraneous uv_ref() 2179 * calls. This should drop out immediately. 2180 */ 2181 uv_run(loop, UV_RUN_DEFAULT); 2182 2183 /* Cleanup. */ 2184 unlink("test_file"); 2185 unlink("test_file_symlink"); 2186 unlink("test_file_symlink_symlink"); 2187 unlink("test_file_symlink2"); 2188 unlink("test_file_symlink2_symlink"); 2189 2190 MAKE_VALGRIND_HAPPY(); 2191 return 0; 2192 } 2193 2194 2195 int test_symlink_dir_impl(int type) { 2196 uv_fs_t req; 2197 int r; 2198 char* test_dir; 2199 uv_dirent_t dent; 2200 static char test_dir_abs_buf[PATHMAX]; 2201 size_t test_dir_abs_size; 2202 2203 /* set-up */ 2204 unlink("test_dir/file1"); 2205 unlink("test_dir/file2"); 2206 rmdir("test_dir"); 2207 rmdir("test_dir_symlink"); 2208 test_dir_abs_size = sizeof(test_dir_abs_buf); 2209 2210 loop = uv_default_loop(); 2211 2212 uv_fs_mkdir(NULL, &req, "test_dir", 0777, NULL); 2213 uv_fs_req_cleanup(&req); 2214 2215 #ifdef _WIN32 2216 strcpy(test_dir_abs_buf, "\\\\?\\"); 2217 uv_cwd(test_dir_abs_buf + 4, &test_dir_abs_size); 2218 test_dir_abs_size += 4; 2219 strcat(test_dir_abs_buf, "\\test_dir\\"); 2220 test_dir_abs_size += strlen("\\test_dir\\"); 2221 test_dir = test_dir_abs_buf; 2222 #else 2223 uv_cwd(test_dir_abs_buf, &test_dir_abs_size); 2224 strcat(test_dir_abs_buf, "/test_dir"); 2225 test_dir_abs_size += strlen("/test_dir"); 2226 test_dir = "test_dir"; 2227 #endif 2228 2229 r = uv_fs_symlink(NULL, &req, test_dir, "test_dir_symlink", type, NULL); 2230 if (type == UV_FS_SYMLINK_DIR && (r == UV_ENOTSUP || r == UV_EPERM)) { 2231 uv_fs_req_cleanup(&req); 2232 RETURN_SKIP("this version of Windows doesn't support unprivileged " 2233 "creation of directory symlinks"); 2234 } 2235 fprintf(stderr, "r == %i\n", r); 2236 ASSERT(r == 0); 2237 ASSERT(req.result == 0); 2238 uv_fs_req_cleanup(&req); 2239 2240 r = uv_fs_stat(NULL, &req, "test_dir_symlink", NULL); 2241 ASSERT(r == 0); 2242 ASSERT(((uv_stat_t*)req.ptr)->st_mode & S_IFDIR); 2243 uv_fs_req_cleanup(&req); 2244 2245 r = uv_fs_lstat(NULL, &req, "test_dir_symlink", NULL); 2246 ASSERT(r == 0); 2247 #if defined(__MSYS__) 2248 RETURN_SKIP("symlink reading is not supported on MSYS2"); 2249 #endif 2250 ASSERT(((uv_stat_t*)req.ptr)->st_mode & S_IFLNK); 2251 #ifdef _WIN32 2252 ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir + 4)); 2253 #else 2254 # ifdef __PASE__ 2255 /* On IBMi PASE, st_size returns the length of the symlink itself. */ 2256 ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen("test_dir_symlink")); 2257 # else 2258 ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir)); 2259 # endif 2260 #endif 2261 uv_fs_req_cleanup(&req); 2262 2263 r = uv_fs_readlink(NULL, &req, "test_dir_symlink", NULL); 2264 ASSERT(r == 0); 2265 #ifdef _WIN32 2266 ASSERT(strcmp(req.ptr, test_dir + 4) == 0); 2267 #else 2268 ASSERT(strcmp(req.ptr, test_dir) == 0); 2269 #endif 2270 uv_fs_req_cleanup(&req); 2271 2272 r = uv_fs_realpath(NULL, &req, "test_dir_symlink", NULL); 2273 #ifdef _WIN32 2274 /* 2275 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() 2276 */ 2277 if (r == UV_ENOSYS) { 2278 uv_fs_req_cleanup(&req); 2279 RETURN_SKIP("realpath is not supported on Windows XP"); 2280 } 2281 #endif 2282 ASSERT(r == 0); 2283 #ifdef _WIN32 2284 ASSERT(strlen(req.ptr) == test_dir_abs_size - 5); 2285 ASSERT(strnicmp(req.ptr, test_dir + 4, test_dir_abs_size - 5) == 0); 2286 #else 2287 ASSERT(strcmp(req.ptr, test_dir_abs_buf) == 0); 2288 #endif 2289 uv_fs_req_cleanup(&req); 2290 2291 r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, 2292 S_IWUSR | S_IRUSR, NULL); 2293 ASSERT(r >= 0); 2294 uv_fs_req_cleanup(&open_req1); 2295 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 2296 ASSERT(r == 0); 2297 uv_fs_req_cleanup(&close_req); 2298 2299 r = uv_fs_open(NULL, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, 2300 S_IWUSR | S_IRUSR, NULL); 2301 ASSERT(r >= 0); 2302 uv_fs_req_cleanup(&open_req1); 2303 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 2304 ASSERT(r == 0); 2305 uv_fs_req_cleanup(&close_req); 2306 2307 r = uv_fs_scandir(NULL, &scandir_req, "test_dir_symlink", 0, NULL); 2308 ASSERT(r == 2); 2309 ASSERT(scandir_req.result == 2); 2310 ASSERT(scandir_req.ptr); 2311 while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { 2312 ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); 2313 assert_is_file_type(dent); 2314 } 2315 uv_fs_req_cleanup(&scandir_req); 2316 ASSERT(!scandir_req.ptr); 2317 2318 /* unlink will remove the directory symlink */ 2319 r = uv_fs_unlink(NULL, &req, "test_dir_symlink", NULL); 2320 ASSERT(r == 0); 2321 uv_fs_req_cleanup(&req); 2322 2323 r = uv_fs_scandir(NULL, &scandir_req, "test_dir_symlink", 0, NULL); 2324 ASSERT(r == UV_ENOENT); 2325 uv_fs_req_cleanup(&scandir_req); 2326 2327 r = uv_fs_scandir(NULL, &scandir_req, "test_dir", 0, NULL); 2328 ASSERT(r == 2); 2329 ASSERT(scandir_req.result == 2); 2330 ASSERT(scandir_req.ptr); 2331 while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { 2332 ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); 2333 assert_is_file_type(dent); 2334 } 2335 uv_fs_req_cleanup(&scandir_req); 2336 ASSERT(!scandir_req.ptr); 2337 2338 /* clean-up */ 2339 unlink("test_dir/file1"); 2340 unlink("test_dir/file2"); 2341 rmdir("test_dir"); 2342 rmdir("test_dir_symlink"); 2343 2344 MAKE_VALGRIND_HAPPY(); 2345 return 0; 2346 } 2347 2348 TEST_IMPL(fs_symlink_dir) { 2349 return test_symlink_dir_impl(UV_FS_SYMLINK_DIR); 2350 } 2351 2352 TEST_IMPL(fs_symlink_junction) { 2353 return test_symlink_dir_impl(UV_FS_SYMLINK_JUNCTION); 2354 } 2355 2356 #ifdef _WIN32 2357 TEST_IMPL(fs_non_symlink_reparse_point) { 2358 uv_fs_t req; 2359 int r; 2360 HANDLE file_handle; 2361 REPARSE_GUID_DATA_BUFFER reparse_buffer; 2362 DWORD bytes_returned; 2363 uv_dirent_t dent; 2364 2365 /* set-up */ 2366 unlink("test_dir/test_file"); 2367 rmdir("test_dir"); 2368 2369 loop = uv_default_loop(); 2370 2371 uv_fs_mkdir(NULL, &req, "test_dir", 0777, NULL); 2372 uv_fs_req_cleanup(&req); 2373 2374 file_handle = CreateFile("test_dir/test_file", 2375 GENERIC_WRITE | FILE_WRITE_ATTRIBUTES, 2376 0, 2377 NULL, 2378 CREATE_ALWAYS, 2379 FILE_FLAG_OPEN_REPARSE_POINT | 2380 FILE_FLAG_BACKUP_SEMANTICS, 2381 NULL); 2382 ASSERT(file_handle != INVALID_HANDLE_VALUE); 2383 2384 memset(&reparse_buffer, 0, REPARSE_GUID_DATA_BUFFER_HEADER_SIZE); 2385 reparse_buffer.ReparseTag = REPARSE_TAG; 2386 reparse_buffer.ReparseDataLength = 0; 2387 reparse_buffer.ReparseGuid = REPARSE_GUID; 2388 2389 r = DeviceIoControl(file_handle, 2390 FSCTL_SET_REPARSE_POINT, 2391 &reparse_buffer, 2392 REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, 2393 NULL, 2394 0, 2395 &bytes_returned, 2396 NULL); 2397 ASSERT(r != 0); 2398 2399 CloseHandle(file_handle); 2400 2401 r = uv_fs_readlink(NULL, &req, "test_dir/test_file", NULL); 2402 ASSERT(r == UV_EINVAL && GetLastError() == ERROR_SYMLINK_NOT_SUPPORTED); 2403 uv_fs_req_cleanup(&req); 2404 2405 /* 2406 Placeholder tests for exercising the behavior fixed in issue #995. 2407 To run, update the path with the IP address of a Mac with the hard drive 2408 shared via SMB as "Macintosh HD". 2409 2410 r = uv_fs_stat(NULL, &req, "\\\\<mac_ip>\\Macintosh HD\\.DS_Store", NULL); 2411 ASSERT(r == 0); 2412 uv_fs_req_cleanup(&req); 2413 2414 r = uv_fs_lstat(NULL, &req, "\\\\<mac_ip>\\Macintosh HD\\.DS_Store", NULL); 2415 ASSERT(r == 0); 2416 uv_fs_req_cleanup(&req); 2417 */ 2418 2419 /* 2420 uv_fs_stat and uv_fs_lstat can only work on non-symlink reparse 2421 points when a minifilter driver is registered which intercepts 2422 associated filesystem requests. Installing a driver is beyond 2423 the scope of this test. 2424 2425 r = uv_fs_stat(NULL, &req, "test_dir/test_file", NULL); 2426 ASSERT(r == 0); 2427 uv_fs_req_cleanup(&req); 2428 2429 r = uv_fs_lstat(NULL, &req, "test_dir/test_file", NULL); 2430 ASSERT(r == 0); 2431 uv_fs_req_cleanup(&req); 2432 */ 2433 2434 r = uv_fs_scandir(NULL, &scandir_req, "test_dir", 0, NULL); 2435 ASSERT(r == 1); 2436 ASSERT(scandir_req.result == 1); 2437 ASSERT(scandir_req.ptr); 2438 while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { 2439 ASSERT(strcmp(dent.name, "test_file") == 0); 2440 /* uv_fs_scandir incorrectly identifies non-symlink reparse points 2441 as links because it doesn't open the file and verify the reparse 2442 point tag. The PowerShell Get-ChildItem command shares this 2443 behavior, so it's reasonable to leave it as is. */ 2444 ASSERT(dent.type == UV_DIRENT_LINK); 2445 } 2446 uv_fs_req_cleanup(&scandir_req); 2447 ASSERT(!scandir_req.ptr); 2448 2449 /* clean-up */ 2450 unlink("test_dir/test_file"); 2451 rmdir("test_dir"); 2452 2453 MAKE_VALGRIND_HAPPY(); 2454 return 0; 2455 } 2456 2457 TEST_IMPL(fs_lstat_windows_store_apps) { 2458 uv_loop_t* loop; 2459 char localappdata[MAX_PATH]; 2460 char windowsapps_path[MAX_PATH]; 2461 char file_path[MAX_PATH]; 2462 size_t len; 2463 int r; 2464 uv_fs_t req; 2465 uv_fs_t stat_req; 2466 uv_dirent_t dirent; 2467 2468 loop = uv_default_loop(); 2469 ASSERT_NOT_NULL(loop); 2470 len = sizeof(localappdata); 2471 r = uv_os_getenv("LOCALAPPDATA", localappdata, &len); 2472 if (r == UV_ENOENT) { 2473 MAKE_VALGRIND_HAPPY(); 2474 return TEST_SKIP; 2475 } 2476 ASSERT_EQ(r, 0); 2477 r = snprintf(windowsapps_path, 2478 sizeof(localappdata), 2479 "%s\\Microsoft\\WindowsApps", 2480 localappdata); 2481 ASSERT_GT(r, 0); 2482 if (uv_fs_opendir(loop, &req, windowsapps_path, NULL) != 0) { 2483 /* If we cannot read the directory, skip the test. */ 2484 MAKE_VALGRIND_HAPPY(); 2485 return TEST_SKIP; 2486 } 2487 if (uv_fs_scandir(loop, &req, windowsapps_path, 0, NULL) <= 0) { 2488 MAKE_VALGRIND_HAPPY(); 2489 return TEST_SKIP; 2490 } 2491 while (uv_fs_scandir_next(&req, &dirent) != UV_EOF) { 2492 if (dirent.type != UV_DIRENT_LINK) { 2493 continue; 2494 } 2495 if (snprintf(file_path, 2496 sizeof(file_path), 2497 "%s\\%s", 2498 windowsapps_path, 2499 dirent.name) < 0) { 2500 continue; 2501 } 2502 ASSERT_EQ(uv_fs_lstat(loop, &stat_req, file_path, NULL), 0); 2503 } 2504 MAKE_VALGRIND_HAPPY(); 2505 return 0; 2506 } 2507 #endif 2508 2509 2510 TEST_IMPL(fs_utime) { 2511 utime_check_t checkme; 2512 const char* path = "test_file"; 2513 double atime; 2514 double mtime; 2515 uv_fs_t req; 2516 int r; 2517 2518 /* Setup. */ 2519 loop = uv_default_loop(); 2520 unlink(path); 2521 r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); 2522 ASSERT(r >= 0); 2523 ASSERT(req.result >= 0); 2524 uv_fs_req_cleanup(&req); 2525 uv_fs_close(loop, &req, r, NULL); 2526 2527 atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ 2528 2529 /* 2530 * Test sub-second timestamps only on Windows (assuming NTFS). Some other 2531 * platforms support sub-second timestamps, but that support is filesystem- 2532 * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps. 2533 */ 2534 #ifdef _WIN32 2535 mtime += 0.444; /* 1982-09-10 11:22:33.444 */ 2536 #endif 2537 2538 r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL); 2539 ASSERT(r == 0); 2540 ASSERT(req.result == 0); 2541 uv_fs_req_cleanup(&req); 2542 2543 r = uv_fs_stat(NULL, &req, path, NULL); 2544 ASSERT(r == 0); 2545 ASSERT(req.result == 0); 2546 check_utime(path, atime, mtime, /* test_lutime */ 0); 2547 uv_fs_req_cleanup(&req); 2548 2549 atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ 2550 checkme.path = path; 2551 checkme.atime = atime; 2552 checkme.mtime = mtime; 2553 2554 /* async utime */ 2555 utime_req.data = &checkme; 2556 r = uv_fs_utime(loop, &utime_req, path, atime, mtime, utime_cb); 2557 ASSERT(r == 0); 2558 uv_run(loop, UV_RUN_DEFAULT); 2559 ASSERT(utime_cb_count == 1); 2560 2561 /* Cleanup. */ 2562 unlink(path); 2563 2564 MAKE_VALGRIND_HAPPY(); 2565 return 0; 2566 } 2567 2568 2569 #ifdef _WIN32 2570 TEST_IMPL(fs_stat_root) { 2571 int r; 2572 2573 r = uv_fs_stat(NULL, &stat_req, "\\", NULL); 2574 ASSERT(r == 0); 2575 2576 r = uv_fs_stat(NULL, &stat_req, "..\\..\\..\\..\\..\\..\\..", NULL); 2577 ASSERT(r == 0); 2578 2579 r = uv_fs_stat(NULL, &stat_req, "..", NULL); 2580 ASSERT(r == 0); 2581 2582 r = uv_fs_stat(NULL, &stat_req, "..\\", NULL); 2583 ASSERT(r == 0); 2584 2585 /* stats the current directory on c: */ 2586 r = uv_fs_stat(NULL, &stat_req, "c:", NULL); 2587 ASSERT(r == 0); 2588 2589 r = uv_fs_stat(NULL, &stat_req, "c:\\", NULL); 2590 ASSERT(r == 0); 2591 2592 r = uv_fs_stat(NULL, &stat_req, "\\\\?\\C:\\", NULL); 2593 ASSERT(r == 0); 2594 2595 MAKE_VALGRIND_HAPPY(); 2596 return 0; 2597 } 2598 #endif 2599 2600 2601 TEST_IMPL(fs_futime) { 2602 utime_check_t checkme; 2603 const char* path = "test_file"; 2604 double atime; 2605 double mtime; 2606 uv_file file; 2607 uv_fs_t req; 2608 int r; 2609 #if defined(_AIX) && !defined(_AIX71) 2610 RETURN_SKIP("futime is not implemented for AIX versions below 7.1"); 2611 #endif 2612 2613 /* Setup. */ 2614 loop = uv_default_loop(); 2615 unlink(path); 2616 r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); 2617 ASSERT(r >= 0); 2618 ASSERT(req.result >= 0); 2619 uv_fs_req_cleanup(&req); 2620 uv_fs_close(loop, &req, r, NULL); 2621 2622 atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ 2623 2624 /* 2625 * Test sub-second timestamps only on Windows (assuming NTFS). Some other 2626 * platforms support sub-second timestamps, but that support is filesystem- 2627 * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps. 2628 */ 2629 #ifdef _WIN32 2630 mtime += 0.444; /* 1982-09-10 11:22:33.444 */ 2631 #endif 2632 2633 r = uv_fs_open(NULL, &req, path, O_RDWR, 0, NULL); 2634 ASSERT(r >= 0); 2635 ASSERT(req.result >= 0); 2636 file = req.result; /* FIXME probably not how it's supposed to be used */ 2637 uv_fs_req_cleanup(&req); 2638 2639 r = uv_fs_futime(NULL, &req, file, atime, mtime, NULL); 2640 #if defined(__CYGWIN__) || defined(__MSYS__) 2641 ASSERT(r == UV_ENOSYS); 2642 RETURN_SKIP("futime not supported on Cygwin"); 2643 #else 2644 ASSERT(r == 0); 2645 ASSERT(req.result == 0); 2646 #endif 2647 uv_fs_req_cleanup(&req); 2648 2649 r = uv_fs_stat(NULL, &req, path, NULL); 2650 ASSERT(r == 0); 2651 ASSERT(req.result == 0); 2652 check_utime(path, atime, mtime, /* test_lutime */ 0); 2653 uv_fs_req_cleanup(&req); 2654 2655 atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ 2656 2657 checkme.atime = atime; 2658 checkme.mtime = mtime; 2659 checkme.path = path; 2660 2661 /* async futime */ 2662 futime_req.data = &checkme; 2663 r = uv_fs_futime(loop, &futime_req, file, atime, mtime, futime_cb); 2664 ASSERT(r == 0); 2665 uv_run(loop, UV_RUN_DEFAULT); 2666 ASSERT(futime_cb_count == 1); 2667 2668 /* Cleanup. */ 2669 unlink(path); 2670 2671 MAKE_VALGRIND_HAPPY(); 2672 return 0; 2673 } 2674 2675 2676 TEST_IMPL(fs_lutime) { 2677 utime_check_t checkme; 2678 const char* path = "test_file"; 2679 const char* symlink_path = "test_file_symlink"; 2680 double atime; 2681 double mtime; 2682 uv_fs_t req; 2683 int r, s; 2684 2685 2686 /* Setup */ 2687 loop = uv_default_loop(); 2688 unlink(path); 2689 r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); 2690 ASSERT(r >= 0); 2691 ASSERT(req.result >= 0); 2692 uv_fs_req_cleanup(&req); 2693 uv_fs_close(loop, &req, r, NULL); 2694 2695 unlink(symlink_path); 2696 s = uv_fs_symlink(NULL, &req, path, symlink_path, 0, NULL); 2697 #ifdef _WIN32 2698 if (s == UV_EPERM) { 2699 /* 2700 * Creating a symlink before Windows 10 Creators Update was only allowed 2701 * when running elevated console (with admin rights) 2702 */ 2703 RETURN_SKIP( 2704 "Symlink creation requires elevated console (with admin rights)"); 2705 } 2706 #endif 2707 ASSERT(s == 0); 2708 ASSERT(req.result == 0); 2709 uv_fs_req_cleanup(&req); 2710 2711 /* Test the synchronous version. */ 2712 atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ 2713 2714 #ifdef _WIN32 2715 mtime += 0.444; /* 1982-09-10 11:22:33.444 */ 2716 #endif 2717 2718 checkme.atime = atime; 2719 checkme.mtime = mtime; 2720 checkme.path = symlink_path; 2721 req.data = &checkme; 2722 2723 r = uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL); 2724 #if (defined(_AIX) && !defined(_AIX71)) || \ 2725 defined(__MVS__) 2726 ASSERT(r == UV_ENOSYS); 2727 RETURN_SKIP("lutime is not implemented for z/OS and AIX versions below 7.1"); 2728 #endif 2729 ASSERT(r == 0); 2730 lutime_cb(&req); 2731 ASSERT(lutime_cb_count == 1); 2732 2733 /* Test the asynchronous version. */ 2734 atime = mtime = 1291404900; /* 2010-12-03 20:35:00 */ 2735 2736 checkme.atime = atime; 2737 checkme.mtime = mtime; 2738 checkme.path = symlink_path; 2739 2740 r = uv_fs_lutime(loop, &req, symlink_path, atime, mtime, lutime_cb); 2741 ASSERT(r == 0); 2742 uv_run(loop, UV_RUN_DEFAULT); 2743 ASSERT(lutime_cb_count == 2); 2744 2745 /* Cleanup. */ 2746 unlink(path); 2747 unlink(symlink_path); 2748 2749 MAKE_VALGRIND_HAPPY(); 2750 return 0; 2751 } 2752 2753 2754 TEST_IMPL(fs_stat_missing_path) { 2755 uv_fs_t req; 2756 int r; 2757 2758 loop = uv_default_loop(); 2759 2760 r = uv_fs_stat(NULL, &req, "non_existent_file", NULL); 2761 ASSERT(r == UV_ENOENT); 2762 ASSERT(req.result == UV_ENOENT); 2763 uv_fs_req_cleanup(&req); 2764 2765 MAKE_VALGRIND_HAPPY(); 2766 return 0; 2767 } 2768 2769 2770 TEST_IMPL(fs_scandir_empty_dir) { 2771 const char* path; 2772 uv_fs_t req; 2773 uv_dirent_t dent; 2774 int r; 2775 2776 path = "./empty_dir/"; 2777 loop = uv_default_loop(); 2778 2779 uv_fs_mkdir(NULL, &req, path, 0777, NULL); 2780 uv_fs_req_cleanup(&req); 2781 2782 /* Fill the req to ensure that required fields are cleaned up */ 2783 memset(&req, 0xdb, sizeof(req)); 2784 2785 r = uv_fs_scandir(NULL, &req, path, 0, NULL); 2786 ASSERT(r == 0); 2787 ASSERT(req.result == 0); 2788 ASSERT(req.ptr == NULL); 2789 ASSERT(UV_EOF == uv_fs_scandir_next(&req, &dent)); 2790 uv_fs_req_cleanup(&req); 2791 2792 r = uv_fs_scandir(loop, &scandir_req, path, 0, empty_scandir_cb); 2793 ASSERT(r == 0); 2794 2795 ASSERT(scandir_cb_count == 0); 2796 uv_run(loop, UV_RUN_DEFAULT); 2797 ASSERT(scandir_cb_count == 1); 2798 2799 uv_fs_rmdir(NULL, &req, path, NULL); 2800 uv_fs_req_cleanup(&req); 2801 2802 MAKE_VALGRIND_HAPPY(); 2803 return 0; 2804 } 2805 2806 2807 TEST_IMPL(fs_scandir_non_existent_dir) { 2808 const char* path; 2809 uv_fs_t req; 2810 uv_dirent_t dent; 2811 int r; 2812 2813 path = "./non_existent_dir/"; 2814 loop = uv_default_loop(); 2815 2816 uv_fs_rmdir(NULL, &req, path, NULL); 2817 uv_fs_req_cleanup(&req); 2818 2819 /* Fill the req to ensure that required fields are cleaned up */ 2820 memset(&req, 0xdb, sizeof(req)); 2821 2822 r = uv_fs_scandir(NULL, &req, path, 0, NULL); 2823 ASSERT(r == UV_ENOENT); 2824 ASSERT(req.result == UV_ENOENT); 2825 ASSERT(req.ptr == NULL); 2826 ASSERT(UV_ENOENT == uv_fs_scandir_next(&req, &dent)); 2827 uv_fs_req_cleanup(&req); 2828 2829 r = uv_fs_scandir(loop, &scandir_req, path, 0, non_existent_scandir_cb); 2830 ASSERT(r == 0); 2831 2832 ASSERT(scandir_cb_count == 0); 2833 uv_run(loop, UV_RUN_DEFAULT); 2834 ASSERT(scandir_cb_count == 1); 2835 2836 MAKE_VALGRIND_HAPPY(); 2837 return 0; 2838 } 2839 2840 TEST_IMPL(fs_scandir_file) { 2841 const char* path; 2842 int r; 2843 2844 path = "test/fixtures/empty_file"; 2845 loop = uv_default_loop(); 2846 2847 r = uv_fs_scandir(NULL, &scandir_req, path, 0, NULL); 2848 ASSERT(r == UV_ENOTDIR); 2849 uv_fs_req_cleanup(&scandir_req); 2850 2851 r = uv_fs_scandir(loop, &scandir_req, path, 0, file_scandir_cb); 2852 ASSERT(r == 0); 2853 2854 ASSERT(scandir_cb_count == 0); 2855 uv_run(loop, UV_RUN_DEFAULT); 2856 ASSERT(scandir_cb_count == 1); 2857 2858 MAKE_VALGRIND_HAPPY(); 2859 return 0; 2860 } 2861 2862 2863 TEST_IMPL(fs_open_dir) { 2864 const char* path; 2865 uv_fs_t req; 2866 int r, file; 2867 2868 path = "."; 2869 loop = uv_default_loop(); 2870 2871 r = uv_fs_open(NULL, &req, path, O_RDONLY, 0, NULL); 2872 ASSERT(r >= 0); 2873 ASSERT(req.result >= 0); 2874 ASSERT(req.ptr == NULL); 2875 file = r; 2876 uv_fs_req_cleanup(&req); 2877 2878 r = uv_fs_close(NULL, &req, file, NULL); 2879 ASSERT(r == 0); 2880 2881 r = uv_fs_open(loop, &req, path, O_RDONLY, 0, open_cb_simple); 2882 ASSERT(r == 0); 2883 2884 ASSERT(open_cb_count == 0); 2885 uv_run(loop, UV_RUN_DEFAULT); 2886 ASSERT(open_cb_count == 1); 2887 2888 MAKE_VALGRIND_HAPPY(); 2889 return 0; 2890 } 2891 2892 2893 static void fs_file_open_append(int add_flags) { 2894 int r; 2895 2896 /* Setup. */ 2897 unlink("test_file"); 2898 2899 loop = uv_default_loop(); 2900 2901 r = uv_fs_open(NULL, &open_req1, "test_file", 2902 O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); 2903 ASSERT(r >= 0); 2904 ASSERT(open_req1.result >= 0); 2905 uv_fs_req_cleanup(&open_req1); 2906 2907 iov = uv_buf_init(test_buf, sizeof(test_buf)); 2908 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); 2909 ASSERT(r >= 0); 2910 ASSERT(write_req.result >= 0); 2911 uv_fs_req_cleanup(&write_req); 2912 2913 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 2914 ASSERT(r == 0); 2915 ASSERT(close_req.result == 0); 2916 uv_fs_req_cleanup(&close_req); 2917 2918 r = uv_fs_open(NULL, &open_req1, "test_file", 2919 O_RDWR | O_APPEND | add_flags, 0, NULL); 2920 ASSERT(r >= 0); 2921 ASSERT(open_req1.result >= 0); 2922 uv_fs_req_cleanup(&open_req1); 2923 2924 iov = uv_buf_init(test_buf, sizeof(test_buf)); 2925 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); 2926 ASSERT(r >= 0); 2927 ASSERT(write_req.result >= 0); 2928 uv_fs_req_cleanup(&write_req); 2929 2930 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 2931 ASSERT(r == 0); 2932 ASSERT(close_req.result == 0); 2933 uv_fs_req_cleanup(&close_req); 2934 2935 r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 2936 S_IRUSR, NULL); 2937 ASSERT(r >= 0); 2938 ASSERT(open_req1.result >= 0); 2939 uv_fs_req_cleanup(&open_req1); 2940 2941 iov = uv_buf_init(buf, sizeof(buf)); 2942 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 2943 printf("read = %d\n", r); 2944 ASSERT(r == 26); 2945 ASSERT(read_req.result == 26); 2946 ASSERT(memcmp(buf, 2947 "test-buffer\n\0test-buffer\n\0", 2948 sizeof("test-buffer\n\0test-buffer\n\0") - 1) == 0); 2949 uv_fs_req_cleanup(&read_req); 2950 2951 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 2952 ASSERT(r == 0); 2953 ASSERT(close_req.result == 0); 2954 uv_fs_req_cleanup(&close_req); 2955 2956 /* Cleanup */ 2957 unlink("test_file"); 2958 } 2959 TEST_IMPL(fs_file_open_append) { 2960 fs_file_open_append(0); 2961 fs_file_open_append(UV_FS_O_FILEMAP); 2962 2963 MAKE_VALGRIND_HAPPY(); 2964 return 0; 2965 } 2966 2967 2968 TEST_IMPL(fs_rename_to_existing_file) { 2969 int r; 2970 2971 /* Setup. */ 2972 unlink("test_file"); 2973 unlink("test_file2"); 2974 2975 loop = uv_default_loop(); 2976 2977 r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, 2978 S_IWUSR | S_IRUSR, NULL); 2979 ASSERT(r >= 0); 2980 ASSERT(open_req1.result >= 0); 2981 uv_fs_req_cleanup(&open_req1); 2982 2983 iov = uv_buf_init(test_buf, sizeof(test_buf)); 2984 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); 2985 ASSERT(r >= 0); 2986 ASSERT(write_req.result >= 0); 2987 uv_fs_req_cleanup(&write_req); 2988 2989 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 2990 ASSERT(r == 0); 2991 ASSERT(close_req.result == 0); 2992 uv_fs_req_cleanup(&close_req); 2993 2994 r = uv_fs_open(NULL, &open_req1, "test_file2", O_WRONLY | O_CREAT, 2995 S_IWUSR | S_IRUSR, NULL); 2996 ASSERT(r >= 0); 2997 ASSERT(open_req1.result >= 0); 2998 uv_fs_req_cleanup(&open_req1); 2999 3000 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3001 ASSERT(r == 0); 3002 ASSERT(close_req.result == 0); 3003 uv_fs_req_cleanup(&close_req); 3004 3005 r = uv_fs_rename(NULL, &rename_req, "test_file", "test_file2", NULL); 3006 ASSERT(r == 0); 3007 ASSERT(rename_req.result == 0); 3008 uv_fs_req_cleanup(&rename_req); 3009 3010 r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY, 0, NULL); 3011 ASSERT(r >= 0); 3012 ASSERT(open_req1.result >= 0); 3013 uv_fs_req_cleanup(&open_req1); 3014 3015 memset(buf, 0, sizeof(buf)); 3016 iov = uv_buf_init(buf, sizeof(buf)); 3017 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 3018 ASSERT(r >= 0); 3019 ASSERT(read_req.result >= 0); 3020 ASSERT(strcmp(buf, test_buf) == 0); 3021 uv_fs_req_cleanup(&read_req); 3022 3023 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3024 ASSERT(r == 0); 3025 ASSERT(close_req.result == 0); 3026 uv_fs_req_cleanup(&close_req); 3027 3028 /* Cleanup */ 3029 unlink("test_file"); 3030 unlink("test_file2"); 3031 3032 MAKE_VALGRIND_HAPPY(); 3033 return 0; 3034 } 3035 3036 3037 static void fs_read_bufs(int add_flags) { 3038 char scratch[768]; 3039 uv_buf_t bufs[4]; 3040 3041 ASSERT(0 <= uv_fs_open(NULL, &open_req1, 3042 "test/fixtures/lorem_ipsum.txt", 3043 O_RDONLY | add_flags, 0, NULL)); 3044 ASSERT(open_req1.result >= 0); 3045 uv_fs_req_cleanup(&open_req1); 3046 3047 ASSERT(UV_EINVAL == uv_fs_read(NULL, &read_req, open_req1.result, 3048 NULL, 0, 0, NULL)); 3049 ASSERT(UV_EINVAL == uv_fs_read(NULL, &read_req, open_req1.result, 3050 NULL, 1, 0, NULL)); 3051 ASSERT(UV_EINVAL == uv_fs_read(NULL, &read_req, open_req1.result, 3052 bufs, 0, 0, NULL)); 3053 3054 bufs[0] = uv_buf_init(scratch + 0, 256); 3055 bufs[1] = uv_buf_init(scratch + 256, 256); 3056 bufs[2] = uv_buf_init(scratch + 512, 128); 3057 bufs[3] = uv_buf_init(scratch + 640, 128); 3058 3059 ASSERT(446 == uv_fs_read(NULL, 3060 &read_req, 3061 open_req1.result, 3062 bufs + 0, 3063 2, /* 2x 256 bytes. */ 3064 0, /* Positional read. */ 3065 NULL)); 3066 ASSERT(read_req.result == 446); 3067 uv_fs_req_cleanup(&read_req); 3068 3069 ASSERT(190 == uv_fs_read(NULL, 3070 &read_req, 3071 open_req1.result, 3072 bufs + 2, 3073 2, /* 2x 128 bytes. */ 3074 256, /* Positional read. */ 3075 NULL)); 3076 ASSERT(read_req.result == /* 446 - 256 */ 190); 3077 uv_fs_req_cleanup(&read_req); 3078 3079 ASSERT(0 == memcmp(bufs[1].base + 0, bufs[2].base, 128)); 3080 ASSERT(0 == memcmp(bufs[1].base + 128, bufs[3].base, 190 - 128)); 3081 3082 ASSERT(0 == uv_fs_close(NULL, &close_req, open_req1.result, NULL)); 3083 ASSERT(close_req.result == 0); 3084 uv_fs_req_cleanup(&close_req); 3085 } 3086 TEST_IMPL(fs_read_bufs) { 3087 fs_read_bufs(0); 3088 fs_read_bufs(UV_FS_O_FILEMAP); 3089 3090 MAKE_VALGRIND_HAPPY(); 3091 return 0; 3092 } 3093 3094 3095 static void fs_read_file_eof(int add_flags) { 3096 #if defined(__CYGWIN__) || defined(__MSYS__) 3097 RETURN_SKIP("Cygwin pread at EOF may (incorrectly) return data!"); 3098 #endif 3099 int r; 3100 3101 /* Setup. */ 3102 unlink("test_file"); 3103 3104 loop = uv_default_loop(); 3105 3106 r = uv_fs_open(NULL, &open_req1, "test_file", 3107 O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); 3108 ASSERT(r >= 0); 3109 ASSERT(open_req1.result >= 0); 3110 uv_fs_req_cleanup(&open_req1); 3111 3112 iov = uv_buf_init(test_buf, sizeof(test_buf)); 3113 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); 3114 ASSERT(r >= 0); 3115 ASSERT(write_req.result >= 0); 3116 uv_fs_req_cleanup(&write_req); 3117 3118 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3119 ASSERT(r == 0); 3120 ASSERT(close_req.result == 0); 3121 uv_fs_req_cleanup(&close_req); 3122 3123 r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 0, 3124 NULL); 3125 ASSERT(r >= 0); 3126 ASSERT(open_req1.result >= 0); 3127 uv_fs_req_cleanup(&open_req1); 3128 3129 memset(buf, 0, sizeof(buf)); 3130 iov = uv_buf_init(buf, sizeof(buf)); 3131 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 3132 ASSERT(r >= 0); 3133 ASSERT(read_req.result >= 0); 3134 ASSERT(strcmp(buf, test_buf) == 0); 3135 uv_fs_req_cleanup(&read_req); 3136 3137 iov = uv_buf_init(buf, sizeof(buf)); 3138 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 3139 read_req.result, NULL); 3140 ASSERT(r == 0); 3141 ASSERT(read_req.result == 0); 3142 uv_fs_req_cleanup(&read_req); 3143 3144 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3145 ASSERT(r == 0); 3146 ASSERT(close_req.result == 0); 3147 uv_fs_req_cleanup(&close_req); 3148 3149 /* Cleanup */ 3150 unlink("test_file"); 3151 } 3152 TEST_IMPL(fs_read_file_eof) { 3153 fs_read_file_eof(0); 3154 fs_read_file_eof(UV_FS_O_FILEMAP); 3155 3156 MAKE_VALGRIND_HAPPY(); 3157 return 0; 3158 } 3159 3160 3161 static void fs_write_multiple_bufs(int add_flags) { 3162 uv_buf_t iovs[2]; 3163 int r; 3164 3165 /* Setup. */ 3166 unlink("test_file"); 3167 3168 loop = uv_default_loop(); 3169 3170 r = uv_fs_open(NULL, &open_req1, "test_file", 3171 O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); 3172 ASSERT(r >= 0); 3173 ASSERT(open_req1.result >= 0); 3174 uv_fs_req_cleanup(&open_req1); 3175 3176 iovs[0] = uv_buf_init(test_buf, sizeof(test_buf)); 3177 iovs[1] = uv_buf_init(test_buf2, sizeof(test_buf2)); 3178 r = uv_fs_write(NULL, &write_req, open_req1.result, iovs, 2, 0, NULL); 3179 ASSERT(r >= 0); 3180 ASSERT(write_req.result >= 0); 3181 uv_fs_req_cleanup(&write_req); 3182 3183 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3184 ASSERT(r == 0); 3185 ASSERT(close_req.result == 0); 3186 uv_fs_req_cleanup(&close_req); 3187 3188 r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 0, 3189 NULL); 3190 ASSERT(r >= 0); 3191 ASSERT(open_req1.result >= 0); 3192 uv_fs_req_cleanup(&open_req1); 3193 3194 memset(buf, 0, sizeof(buf)); 3195 memset(buf2, 0, sizeof(buf2)); 3196 /* Read the strings back to separate buffers. */ 3197 iovs[0] = uv_buf_init(buf, sizeof(test_buf)); 3198 iovs[1] = uv_buf_init(buf2, sizeof(test_buf2)); 3199 ASSERT(lseek(open_req1.result, 0, SEEK_CUR) == 0); 3200 r = uv_fs_read(NULL, &read_req, open_req1.result, iovs, 2, -1, NULL); 3201 ASSERT(r >= 0); 3202 ASSERT(read_req.result == sizeof(test_buf) + sizeof(test_buf2)); 3203 ASSERT(strcmp(buf, test_buf) == 0); 3204 ASSERT(strcmp(buf2, test_buf2) == 0); 3205 uv_fs_req_cleanup(&read_req); 3206 3207 iov = uv_buf_init(buf, sizeof(buf)); 3208 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 3209 ASSERT(r == 0); 3210 ASSERT(read_req.result == 0); 3211 uv_fs_req_cleanup(&read_req); 3212 3213 /* Read the strings back to separate buffers. */ 3214 iovs[0] = uv_buf_init(buf, sizeof(test_buf)); 3215 iovs[1] = uv_buf_init(buf2, sizeof(test_buf2)); 3216 r = uv_fs_read(NULL, &read_req, open_req1.result, iovs, 2, 0, NULL); 3217 ASSERT(r >= 0); 3218 if (read_req.result == sizeof(test_buf)) { 3219 /* Infer that preadv is not available. */ 3220 uv_fs_req_cleanup(&read_req); 3221 r = uv_fs_read(NULL, &read_req, open_req1.result, &iovs[1], 1, read_req.result, NULL); 3222 ASSERT(r >= 0); 3223 ASSERT(read_req.result == sizeof(test_buf2)); 3224 } else { 3225 ASSERT(read_req.result == sizeof(test_buf) + sizeof(test_buf2)); 3226 } 3227 ASSERT(strcmp(buf, test_buf) == 0); 3228 ASSERT(strcmp(buf2, test_buf2) == 0); 3229 uv_fs_req_cleanup(&read_req); 3230 3231 iov = uv_buf_init(buf, sizeof(buf)); 3232 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 3233 sizeof(test_buf) + sizeof(test_buf2), NULL); 3234 ASSERT(r == 0); 3235 ASSERT(read_req.result == 0); 3236 uv_fs_req_cleanup(&read_req); 3237 3238 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3239 ASSERT(r == 0); 3240 ASSERT(close_req.result == 0); 3241 uv_fs_req_cleanup(&close_req); 3242 3243 /* Cleanup */ 3244 unlink("test_file"); 3245 } 3246 TEST_IMPL(fs_write_multiple_bufs) { 3247 fs_write_multiple_bufs(0); 3248 fs_write_multiple_bufs(UV_FS_O_FILEMAP); 3249 3250 MAKE_VALGRIND_HAPPY(); 3251 return 0; 3252 } 3253 3254 3255 static void fs_write_alotof_bufs(int add_flags) { 3256 size_t iovcount; 3257 size_t iovmax; 3258 uv_buf_t* iovs; 3259 char* buffer; 3260 size_t index; 3261 int r; 3262 3263 iovcount = 54321; 3264 3265 /* Setup. */ 3266 unlink("test_file"); 3267 3268 loop = uv_default_loop(); 3269 3270 iovs = malloc(sizeof(*iovs) * iovcount); 3271 ASSERT(iovs != NULL); 3272 iovmax = uv_test_getiovmax(); 3273 3274 r = uv_fs_open(NULL, 3275 &open_req1, 3276 "test_file", 3277 O_RDWR | O_CREAT | add_flags, 3278 S_IWUSR | S_IRUSR, 3279 NULL); 3280 ASSERT(r >= 0); 3281 ASSERT(open_req1.result >= 0); 3282 uv_fs_req_cleanup(&open_req1); 3283 3284 for (index = 0; index < iovcount; ++index) 3285 iovs[index] = uv_buf_init(test_buf, sizeof(test_buf)); 3286 3287 r = uv_fs_write(NULL, 3288 &write_req, 3289 open_req1.result, 3290 iovs, 3291 iovcount, 3292 -1, 3293 NULL); 3294 ASSERT(r >= 0); 3295 ASSERT((size_t)write_req.result == sizeof(test_buf) * iovcount); 3296 uv_fs_req_cleanup(&write_req); 3297 3298 /* Read the strings back to separate buffers. */ 3299 buffer = malloc(sizeof(test_buf) * iovcount); 3300 ASSERT(buffer != NULL); 3301 3302 for (index = 0; index < iovcount; ++index) 3303 iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf), 3304 sizeof(test_buf)); 3305 3306 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3307 ASSERT(r == 0); 3308 ASSERT(close_req.result == 0); 3309 uv_fs_req_cleanup(&close_req); 3310 3311 r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 0, 3312 NULL); 3313 ASSERT(r >= 0); 3314 ASSERT(open_req1.result >= 0); 3315 uv_fs_req_cleanup(&open_req1); 3316 3317 r = uv_fs_read(NULL, &read_req, open_req1.result, iovs, iovcount, -1, NULL); 3318 if (iovcount > iovmax) 3319 iovcount = iovmax; 3320 ASSERT(r >= 0); 3321 ASSERT((size_t)read_req.result == sizeof(test_buf) * iovcount); 3322 3323 for (index = 0; index < iovcount; ++index) 3324 ASSERT(strncmp(buffer + index * sizeof(test_buf), 3325 test_buf, 3326 sizeof(test_buf)) == 0); 3327 3328 uv_fs_req_cleanup(&read_req); 3329 free(buffer); 3330 3331 ASSERT(lseek(open_req1.result, write_req.result, SEEK_SET) == write_req.result); 3332 iov = uv_buf_init(buf, sizeof(buf)); 3333 r = uv_fs_read(NULL, 3334 &read_req, 3335 open_req1.result, 3336 &iov, 3337 1, 3338 -1, 3339 NULL); 3340 ASSERT(r == 0); 3341 ASSERT(read_req.result == 0); 3342 uv_fs_req_cleanup(&read_req); 3343 3344 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3345 ASSERT(r == 0); 3346 ASSERT(close_req.result == 0); 3347 uv_fs_req_cleanup(&close_req); 3348 3349 /* Cleanup */ 3350 unlink("test_file"); 3351 free(iovs); 3352 } 3353 TEST_IMPL(fs_write_alotof_bufs) { 3354 fs_write_alotof_bufs(0); 3355 fs_write_alotof_bufs(UV_FS_O_FILEMAP); 3356 3357 MAKE_VALGRIND_HAPPY(); 3358 return 0; 3359 } 3360 3361 3362 static void fs_write_alotof_bufs_with_offset(int add_flags) { 3363 size_t iovcount; 3364 size_t iovmax; 3365 uv_buf_t* iovs; 3366 char* buffer; 3367 size_t index; 3368 int r; 3369 int64_t offset; 3370 char* filler; 3371 int filler_len; 3372 3373 filler = "0123456789"; 3374 filler_len = strlen(filler); 3375 iovcount = 54321; 3376 3377 /* Setup. */ 3378 unlink("test_file"); 3379 3380 loop = uv_default_loop(); 3381 3382 iovs = malloc(sizeof(*iovs) * iovcount); 3383 ASSERT(iovs != NULL); 3384 iovmax = uv_test_getiovmax(); 3385 3386 r = uv_fs_open(NULL, 3387 &open_req1, 3388 "test_file", 3389 O_RDWR | O_CREAT | add_flags, 3390 S_IWUSR | S_IRUSR, 3391 NULL); 3392 ASSERT(r >= 0); 3393 ASSERT(open_req1.result >= 0); 3394 uv_fs_req_cleanup(&open_req1); 3395 3396 iov = uv_buf_init(filler, filler_len); 3397 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); 3398 ASSERT(r == filler_len); 3399 ASSERT(write_req.result == filler_len); 3400 uv_fs_req_cleanup(&write_req); 3401 offset = (int64_t)r; 3402 3403 for (index = 0; index < iovcount; ++index) 3404 iovs[index] = uv_buf_init(test_buf, sizeof(test_buf)); 3405 3406 r = uv_fs_write(NULL, 3407 &write_req, 3408 open_req1.result, 3409 iovs, 3410 iovcount, 3411 offset, 3412 NULL); 3413 ASSERT(r >= 0); 3414 ASSERT((size_t)write_req.result == sizeof(test_buf) * iovcount); 3415 uv_fs_req_cleanup(&write_req); 3416 3417 /* Read the strings back to separate buffers. */ 3418 buffer = malloc(sizeof(test_buf) * iovcount); 3419 ASSERT(buffer != NULL); 3420 3421 for (index = 0; index < iovcount; ++index) 3422 iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf), 3423 sizeof(test_buf)); 3424 3425 r = uv_fs_read(NULL, &read_req, open_req1.result, 3426 iovs, iovcount, offset, NULL); 3427 ASSERT(r >= 0); 3428 if (r == sizeof(test_buf)) 3429 iovcount = 1; /* Infer that preadv is not available. */ 3430 else if (iovcount > iovmax) 3431 iovcount = iovmax; 3432 ASSERT((size_t)read_req.result == sizeof(test_buf) * iovcount); 3433 3434 for (index = 0; index < iovcount; ++index) 3435 ASSERT(strncmp(buffer + index * sizeof(test_buf), 3436 test_buf, 3437 sizeof(test_buf)) == 0); 3438 3439 uv_fs_req_cleanup(&read_req); 3440 free(buffer); 3441 3442 r = uv_fs_stat(NULL, &stat_req, "test_file", NULL); 3443 ASSERT(r == 0); 3444 ASSERT((int64_t)((uv_stat_t*)stat_req.ptr)->st_size == 3445 offset + (int64_t)write_req.result); 3446 uv_fs_req_cleanup(&stat_req); 3447 3448 iov = uv_buf_init(buf, sizeof(buf)); 3449 r = uv_fs_read(NULL, 3450 &read_req, 3451 open_req1.result, 3452 &iov, 3453 1, 3454 offset + write_req.result, 3455 NULL); 3456 ASSERT(r == 0); 3457 ASSERT(read_req.result == 0); 3458 uv_fs_req_cleanup(&read_req); 3459 3460 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3461 ASSERT(r == 0); 3462 ASSERT(close_req.result == 0); 3463 uv_fs_req_cleanup(&close_req); 3464 3465 /* Cleanup */ 3466 unlink("test_file"); 3467 free(iovs); 3468 } 3469 TEST_IMPL(fs_write_alotof_bufs_with_offset) { 3470 fs_write_alotof_bufs_with_offset(0); 3471 fs_write_alotof_bufs_with_offset(UV_FS_O_FILEMAP); 3472 3473 MAKE_VALGRIND_HAPPY(); 3474 return 0; 3475 } 3476 3477 TEST_IMPL(fs_read_dir) { 3478 int r; 3479 char buf[2]; 3480 loop = uv_default_loop(); 3481 3482 /* Setup */ 3483 rmdir("test_dir"); 3484 r = uv_fs_mkdir(loop, &mkdir_req, "test_dir", 0755, mkdir_cb); 3485 ASSERT(r == 0); 3486 uv_run(loop, UV_RUN_DEFAULT); 3487 ASSERT(mkdir_cb_count == 1); 3488 /* Setup Done Here */ 3489 3490 /* Get a file descriptor for the directory */ 3491 r = uv_fs_open(loop, 3492 &open_req1, 3493 "test_dir", 3494 UV_FS_O_RDONLY | UV_FS_O_DIRECTORY, 3495 S_IWUSR | S_IRUSR, 3496 NULL); 3497 ASSERT(r >= 0); 3498 uv_fs_req_cleanup(&open_req1); 3499 3500 /* Try to read data from the directory */ 3501 iov = uv_buf_init(buf, sizeof(buf)); 3502 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 0, NULL); 3503 #if defined(__FreeBSD__) || \ 3504 defined(__OpenBSD__) || \ 3505 defined(__NetBSD__) || \ 3506 defined(__DragonFly__) || \ 3507 defined(_AIX) || \ 3508 defined(__sun) || \ 3509 defined(__MVS__) 3510 /* 3511 * As of now, these operating systems support reading from a directory, 3512 * that too depends on the filesystem this temporary test directory is 3513 * created on. That is why this assertion is a bit lenient. 3514 */ 3515 ASSERT((r >= 0) || (r == UV_EISDIR)); 3516 #else 3517 ASSERT(r == UV_EISDIR); 3518 #endif 3519 uv_fs_req_cleanup(&read_req); 3520 3521 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3522 ASSERT(r == 0); 3523 uv_fs_req_cleanup(&close_req); 3524 3525 /* Cleanup */ 3526 rmdir("test_dir"); 3527 3528 MAKE_VALGRIND_HAPPY(); 3529 return 0; 3530 } 3531 3532 #ifdef _WIN32 3533 3534 TEST_IMPL(fs_partial_read) { 3535 RETURN_SKIP("Test not implemented on Windows."); 3536 } 3537 3538 TEST_IMPL(fs_partial_write) { 3539 RETURN_SKIP("Test not implemented on Windows."); 3540 } 3541 3542 #else /* !_WIN32 */ 3543 3544 struct thread_ctx { 3545 pthread_t pid; 3546 int fd; 3547 char* data; 3548 int size; 3549 int interval; 3550 int doread; 3551 }; 3552 3553 static void thread_main(void* arg) { 3554 const struct thread_ctx* ctx; 3555 int size; 3556 char* data; 3557 3558 ctx = (struct thread_ctx*)arg; 3559 size = ctx->size; 3560 data = ctx->data; 3561 3562 while (size > 0) { 3563 ssize_t result; 3564 int nbytes; 3565 nbytes = size < ctx->interval ? size : ctx->interval; 3566 if (ctx->doread) { 3567 result = write(ctx->fd, data, nbytes); 3568 /* Should not see EINTR (or other errors) */ 3569 ASSERT(result == nbytes); 3570 } else { 3571 result = read(ctx->fd, data, nbytes); 3572 /* Should not see EINTR (or other errors), 3573 * but might get a partial read if we are faster than the writer 3574 */ 3575 ASSERT(result > 0 && result <= nbytes); 3576 } 3577 3578 pthread_kill(ctx->pid, SIGUSR1); 3579 size -= result; 3580 data += result; 3581 } 3582 } 3583 3584 static void sig_func(uv_signal_t* handle, int signum) { 3585 uv_signal_stop(handle); 3586 } 3587 3588 static size_t uv_test_fs_buf_offset(uv_buf_t* bufs, size_t size) { 3589 size_t offset; 3590 /* Figure out which bufs are done */ 3591 for (offset = 0; size > 0 && bufs[offset].len <= size; ++offset) 3592 size -= bufs[offset].len; 3593 3594 /* Fix a partial read/write */ 3595 if (size > 0) { 3596 bufs[offset].base += size; 3597 bufs[offset].len -= size; 3598 } 3599 return offset; 3600 } 3601 3602 static void test_fs_partial(int doread) { 3603 struct thread_ctx ctx; 3604 uv_thread_t thread; 3605 uv_signal_t signal; 3606 int pipe_fds[2]; 3607 size_t iovcount; 3608 uv_buf_t* iovs; 3609 char* buffer; 3610 size_t index; 3611 3612 iovcount = 54321; 3613 3614 iovs = malloc(sizeof(*iovs) * iovcount); 3615 ASSERT(iovs != NULL); 3616 3617 ctx.pid = pthread_self(); 3618 ctx.doread = doread; 3619 ctx.interval = 1000; 3620 ctx.size = sizeof(test_buf) * iovcount; 3621 ctx.data = malloc(ctx.size); 3622 ASSERT(ctx.data != NULL); 3623 buffer = malloc(ctx.size); 3624 ASSERT(buffer != NULL); 3625 3626 for (index = 0; index < iovcount; ++index) 3627 iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf), sizeof(test_buf)); 3628 3629 loop = uv_default_loop(); 3630 3631 ASSERT(0 == uv_signal_init(loop, &signal)); 3632 ASSERT(0 == uv_signal_start(&signal, sig_func, SIGUSR1)); 3633 3634 ASSERT(0 == pipe(pipe_fds)); 3635 3636 ctx.fd = pipe_fds[doread]; 3637 ASSERT(0 == uv_thread_create(&thread, thread_main, &ctx)); 3638 3639 if (doread) { 3640 uv_buf_t* read_iovs; 3641 int nread; 3642 read_iovs = iovs; 3643 nread = 0; 3644 while (nread < ctx.size) { 3645 int result; 3646 result = uv_fs_read(loop, &read_req, pipe_fds[0], read_iovs, iovcount, -1, NULL); 3647 if (result > 0) { 3648 size_t read_iovcount; 3649 read_iovcount = uv_test_fs_buf_offset(read_iovs, result); 3650 read_iovs += read_iovcount; 3651 iovcount -= read_iovcount; 3652 nread += result; 3653 } else { 3654 ASSERT(result == UV_EINTR); 3655 } 3656 uv_fs_req_cleanup(&read_req); 3657 } 3658 } else { 3659 int result; 3660 result = uv_fs_write(loop, &write_req, pipe_fds[1], iovs, iovcount, -1, NULL); 3661 ASSERT(write_req.result == result); 3662 ASSERT(result == ctx.size); 3663 uv_fs_req_cleanup(&write_req); 3664 } 3665 3666 ASSERT(0 == memcmp(buffer, ctx.data, ctx.size)); 3667 3668 ASSERT(0 == uv_thread_join(&thread)); 3669 ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); 3670 3671 ASSERT(0 == close(pipe_fds[1])); 3672 uv_close((uv_handle_t*) &signal, NULL); 3673 3674 { /* Make sure we read everything that we wrote. */ 3675 int result; 3676 result = uv_fs_read(loop, &read_req, pipe_fds[0], iovs, 1, -1, NULL); 3677 ASSERT(result == 0); 3678 uv_fs_req_cleanup(&read_req); 3679 } 3680 ASSERT(0 == close(pipe_fds[0])); 3681 3682 free(iovs); 3683 free(buffer); 3684 free(ctx.data); 3685 3686 MAKE_VALGRIND_HAPPY(); 3687 } 3688 3689 TEST_IMPL(fs_partial_read) { 3690 test_fs_partial(1); 3691 return 0; 3692 } 3693 3694 TEST_IMPL(fs_partial_write) { 3695 test_fs_partial(0); 3696 return 0; 3697 } 3698 3699 #endif/* _WIN32 */ 3700 3701 TEST_IMPL(fs_read_write_null_arguments) { 3702 int r; 3703 3704 r = uv_fs_read(NULL, &read_req, 0, NULL, 0, -1, NULL); 3705 ASSERT(r == UV_EINVAL); 3706 uv_fs_req_cleanup(&read_req); 3707 3708 r = uv_fs_write(NULL, &write_req, 0, NULL, 0, -1, NULL); 3709 /* Validate some memory management on failed input validation before sending 3710 fs work to the thread pool. */ 3711 ASSERT(r == UV_EINVAL); 3712 ASSERT(write_req.path == NULL); 3713 ASSERT(write_req.ptr == NULL); 3714 #ifdef _WIN32 3715 ASSERT(write_req.file.pathw == NULL); 3716 ASSERT(write_req.fs.info.new_pathw == NULL); 3717 ASSERT(write_req.fs.info.bufs == NULL); 3718 #else 3719 ASSERT(write_req.new_path == NULL); 3720 ASSERT(write_req.bufs == NULL); 3721 #endif 3722 uv_fs_req_cleanup(&write_req); 3723 3724 iov = uv_buf_init(NULL, 0); 3725 r = uv_fs_read(NULL, &read_req, 0, &iov, 0, -1, NULL); 3726 ASSERT(r == UV_EINVAL); 3727 uv_fs_req_cleanup(&read_req); 3728 3729 iov = uv_buf_init(NULL, 0); 3730 r = uv_fs_write(NULL, &write_req, 0, &iov, 0, -1, NULL); 3731 ASSERT(r == UV_EINVAL); 3732 uv_fs_req_cleanup(&write_req); 3733 3734 /* If the arguments are invalid, the loop should not be kept open */ 3735 loop = uv_default_loop(); 3736 3737 r = uv_fs_read(loop, &read_req, 0, NULL, 0, -1, fail_cb); 3738 ASSERT(r == UV_EINVAL); 3739 uv_run(loop, UV_RUN_DEFAULT); 3740 uv_fs_req_cleanup(&read_req); 3741 3742 r = uv_fs_write(loop, &write_req, 0, NULL, 0, -1, fail_cb); 3743 ASSERT(r == UV_EINVAL); 3744 uv_run(loop, UV_RUN_DEFAULT); 3745 uv_fs_req_cleanup(&write_req); 3746 3747 iov = uv_buf_init(NULL, 0); 3748 r = uv_fs_read(loop, &read_req, 0, &iov, 0, -1, fail_cb); 3749 ASSERT(r == UV_EINVAL); 3750 uv_run(loop, UV_RUN_DEFAULT); 3751 uv_fs_req_cleanup(&read_req); 3752 3753 iov = uv_buf_init(NULL, 0); 3754 r = uv_fs_write(loop, &write_req, 0, &iov, 0, -1, fail_cb); 3755 ASSERT(r == UV_EINVAL); 3756 uv_run(loop, UV_RUN_DEFAULT); 3757 uv_fs_req_cleanup(&write_req); 3758 3759 return 0; 3760 } 3761 3762 3763 TEST_IMPL(get_osfhandle_valid_handle) { 3764 int r; 3765 uv_os_fd_t fd; 3766 3767 /* Setup. */ 3768 unlink("test_file"); 3769 3770 loop = uv_default_loop(); 3771 3772 r = uv_fs_open(NULL, 3773 &open_req1, 3774 "test_file", 3775 O_RDWR | O_CREAT, 3776 S_IWUSR | S_IRUSR, 3777 NULL); 3778 ASSERT(r >= 0); 3779 ASSERT(open_req1.result >= 0); 3780 uv_fs_req_cleanup(&open_req1); 3781 3782 fd = uv_get_osfhandle(open_req1.result); 3783 #ifdef _WIN32 3784 ASSERT(fd != INVALID_HANDLE_VALUE); 3785 #else 3786 ASSERT(fd >= 0); 3787 #endif 3788 3789 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3790 ASSERT(r == 0); 3791 ASSERT(close_req.result == 0); 3792 uv_fs_req_cleanup(&close_req); 3793 3794 /* Cleanup. */ 3795 unlink("test_file"); 3796 3797 MAKE_VALGRIND_HAPPY(); 3798 return 0; 3799 } 3800 3801 TEST_IMPL(open_osfhandle_valid_handle) { 3802 int r; 3803 uv_os_fd_t handle; 3804 int fd; 3805 3806 /* Setup. */ 3807 unlink("test_file"); 3808 3809 loop = uv_default_loop(); 3810 3811 r = uv_fs_open(NULL, 3812 &open_req1, 3813 "test_file", 3814 O_RDWR | O_CREAT, 3815 S_IWUSR | S_IRUSR, 3816 NULL); 3817 ASSERT(r >= 0); 3818 ASSERT(open_req1.result >= 0); 3819 uv_fs_req_cleanup(&open_req1); 3820 3821 handle = uv_get_osfhandle(open_req1.result); 3822 #ifdef _WIN32 3823 ASSERT(handle != INVALID_HANDLE_VALUE); 3824 #else 3825 ASSERT(handle >= 0); 3826 #endif 3827 3828 fd = uv_open_osfhandle(handle); 3829 #ifdef _WIN32 3830 ASSERT(fd > 0); 3831 #else 3832 ASSERT(fd == open_req1.result); 3833 #endif 3834 3835 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3836 ASSERT(r == 0); 3837 ASSERT(close_req.result == 0); 3838 uv_fs_req_cleanup(&close_req); 3839 3840 /* Cleanup. */ 3841 unlink("test_file"); 3842 3843 MAKE_VALGRIND_HAPPY(); 3844 return 0; 3845 } 3846 3847 TEST_IMPL(fs_file_pos_after_op_with_offset) { 3848 int r; 3849 3850 /* Setup. */ 3851 unlink("test_file"); 3852 loop = uv_default_loop(); 3853 3854 r = uv_fs_open(loop, 3855 &open_req1, 3856 "test_file", 3857 O_RDWR | O_CREAT, 3858 S_IWUSR | S_IRUSR, 3859 NULL); 3860 ASSERT(r > 0); 3861 uv_fs_req_cleanup(&open_req1); 3862 3863 iov = uv_buf_init(test_buf, sizeof(test_buf)); 3864 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 0, NULL); 3865 ASSERT(r == sizeof(test_buf)); 3866 ASSERT(lseek(open_req1.result, 0, SEEK_CUR) == 0); 3867 uv_fs_req_cleanup(&write_req); 3868 3869 iov = uv_buf_init(buf, sizeof(buf)); 3870 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 0, NULL); 3871 ASSERT(r == sizeof(test_buf)); 3872 ASSERT(strcmp(buf, test_buf) == 0); 3873 ASSERT(lseek(open_req1.result, 0, SEEK_CUR) == 0); 3874 uv_fs_req_cleanup(&read_req); 3875 3876 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3877 ASSERT(r == 0); 3878 uv_fs_req_cleanup(&close_req); 3879 3880 /* Cleanup */ 3881 unlink("test_file"); 3882 3883 MAKE_VALGRIND_HAPPY(); 3884 return 0; 3885 } 3886 3887 #ifdef _WIN32 3888 static void fs_file_pos_common() { 3889 int r; 3890 3891 iov = uv_buf_init("abc", 3); 3892 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); 3893 ASSERT(r == 3); 3894 uv_fs_req_cleanup(&write_req); 3895 3896 /* Read with offset should not change the position */ 3897 iov = uv_buf_init(buf, 1); 3898 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 1, NULL); 3899 ASSERT(r == 1); 3900 ASSERT(buf[0] == 'b'); 3901 uv_fs_req_cleanup(&read_req); 3902 3903 iov = uv_buf_init(buf, sizeof(buf)); 3904 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 3905 ASSERT(r == 0); 3906 uv_fs_req_cleanup(&read_req); 3907 3908 /* Write without offset should change the position */ 3909 iov = uv_buf_init("d", 1); 3910 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); 3911 ASSERT(r == 1); 3912 uv_fs_req_cleanup(&write_req); 3913 3914 iov = uv_buf_init(buf, sizeof(buf)); 3915 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 3916 ASSERT(r == 0); 3917 uv_fs_req_cleanup(&read_req); 3918 } 3919 3920 static void fs_file_pos_close_check(const char *contents, int size) { 3921 int r; 3922 3923 /* Close */ 3924 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3925 ASSERT(r == 0); 3926 uv_fs_req_cleanup(&close_req); 3927 3928 /* Confirm file contents */ 3929 r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL); 3930 ASSERT(r >= 0); 3931 ASSERT(open_req1.result >= 0); 3932 uv_fs_req_cleanup(&open_req1); 3933 3934 iov = uv_buf_init(buf, sizeof(buf)); 3935 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 3936 ASSERT(r == size); 3937 ASSERT(strncmp(buf, contents, size) == 0); 3938 uv_fs_req_cleanup(&read_req); 3939 3940 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 3941 ASSERT(r == 0); 3942 uv_fs_req_cleanup(&close_req); 3943 3944 /* Cleanup */ 3945 unlink("test_file"); 3946 } 3947 3948 static void fs_file_pos_write(int add_flags) { 3949 int r; 3950 3951 /* Setup. */ 3952 unlink("test_file"); 3953 3954 r = uv_fs_open(NULL, 3955 &open_req1, 3956 "test_file", 3957 O_TRUNC | O_CREAT | O_RDWR | add_flags, 3958 S_IWUSR | S_IRUSR, 3959 NULL); 3960 ASSERT(r > 0); 3961 uv_fs_req_cleanup(&open_req1); 3962 3963 fs_file_pos_common(); 3964 3965 /* Write with offset should not change the position */ 3966 iov = uv_buf_init("e", 1); 3967 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 1, NULL); 3968 ASSERT(r == 1); 3969 uv_fs_req_cleanup(&write_req); 3970 3971 iov = uv_buf_init(buf, sizeof(buf)); 3972 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 3973 ASSERT(r == 0); 3974 uv_fs_req_cleanup(&read_req); 3975 3976 fs_file_pos_close_check("aecd", 4); 3977 } 3978 TEST_IMPL(fs_file_pos_write) { 3979 fs_file_pos_write(0); 3980 fs_file_pos_write(UV_FS_O_FILEMAP); 3981 3982 MAKE_VALGRIND_HAPPY(); 3983 return 0; 3984 } 3985 3986 static void fs_file_pos_append(int add_flags) { 3987 int r; 3988 3989 /* Setup. */ 3990 unlink("test_file"); 3991 3992 r = uv_fs_open(NULL, 3993 &open_req1, 3994 "test_file", 3995 O_APPEND | O_CREAT | O_RDWR | add_flags, 3996 S_IWUSR | S_IRUSR, 3997 NULL); 3998 ASSERT(r > 0); 3999 uv_fs_req_cleanup(&open_req1); 4000 4001 fs_file_pos_common(); 4002 4003 /* Write with offset appends (ignoring offset) 4004 * but does not change the position */ 4005 iov = uv_buf_init("e", 1); 4006 r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 1, NULL); 4007 ASSERT(r == 1); 4008 uv_fs_req_cleanup(&write_req); 4009 4010 iov = uv_buf_init(buf, sizeof(buf)); 4011 r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); 4012 ASSERT(r == 1); 4013 ASSERT(buf[0] == 'e'); 4014 uv_fs_req_cleanup(&read_req); 4015 4016 fs_file_pos_close_check("abcde", 5); 4017 } 4018 TEST_IMPL(fs_file_pos_append) { 4019 fs_file_pos_append(0); 4020 fs_file_pos_append(UV_FS_O_FILEMAP); 4021 4022 MAKE_VALGRIND_HAPPY(); 4023 return 0; 4024 } 4025 #endif 4026 4027 TEST_IMPL(fs_null_req) { 4028 /* Verify that all fs functions return UV_EINVAL when the request is NULL. */ 4029 int r; 4030 4031 r = uv_fs_open(NULL, NULL, NULL, 0, 0, NULL); 4032 ASSERT(r == UV_EINVAL); 4033 4034 r = uv_fs_close(NULL, NULL, 0, NULL); 4035 ASSERT(r == UV_EINVAL); 4036 4037 r = uv_fs_read(NULL, NULL, 0, NULL, 0, -1, NULL); 4038 ASSERT(r == UV_EINVAL); 4039 4040 r = uv_fs_write(NULL, NULL, 0, NULL, 0, -1, NULL); 4041 ASSERT(r == UV_EINVAL); 4042 4043 r = uv_fs_unlink(NULL, NULL, NULL, NULL); 4044 ASSERT(r == UV_EINVAL); 4045 4046 r = uv_fs_mkdir(NULL, NULL, NULL, 0, NULL); 4047 ASSERT(r == UV_EINVAL); 4048 4049 r = uv_fs_mkdtemp(NULL, NULL, NULL, NULL); 4050 ASSERT(r == UV_EINVAL); 4051 4052 r = uv_fs_mkstemp(NULL, NULL, NULL, NULL); 4053 ASSERT(r == UV_EINVAL); 4054 4055 r = uv_fs_rmdir(NULL, NULL, NULL, NULL); 4056 ASSERT(r == UV_EINVAL); 4057 4058 r = uv_fs_scandir(NULL, NULL, NULL, 0, NULL); 4059 ASSERT(r == UV_EINVAL); 4060 4061 r = uv_fs_link(NULL, NULL, NULL, NULL, NULL); 4062 ASSERT(r == UV_EINVAL); 4063 4064 r = uv_fs_symlink(NULL, NULL, NULL, NULL, 0, NULL); 4065 ASSERT(r == UV_EINVAL); 4066 4067 r = uv_fs_readlink(NULL, NULL, NULL, NULL); 4068 ASSERT(r == UV_EINVAL); 4069 4070 r = uv_fs_realpath(NULL, NULL, NULL, NULL); 4071 ASSERT(r == UV_EINVAL); 4072 4073 r = uv_fs_chown(NULL, NULL, NULL, 0, 0, NULL); 4074 ASSERT(r == UV_EINVAL); 4075 4076 r = uv_fs_fchown(NULL, NULL, 0, 0, 0, NULL); 4077 ASSERT(r == UV_EINVAL); 4078 4079 r = uv_fs_stat(NULL, NULL, NULL, NULL); 4080 ASSERT(r == UV_EINVAL); 4081 4082 r = uv_fs_lstat(NULL, NULL, NULL, NULL); 4083 ASSERT(r == UV_EINVAL); 4084 4085 r = uv_fs_fstat(NULL, NULL, 0, NULL); 4086 ASSERT(r == UV_EINVAL); 4087 4088 r = uv_fs_rename(NULL, NULL, NULL, NULL, NULL); 4089 ASSERT(r == UV_EINVAL); 4090 4091 r = uv_fs_fsync(NULL, NULL, 0, NULL); 4092 ASSERT(r == UV_EINVAL); 4093 4094 r = uv_fs_fdatasync(NULL, NULL, 0, NULL); 4095 ASSERT(r == UV_EINVAL); 4096 4097 r = uv_fs_ftruncate(NULL, NULL, 0, 0, NULL); 4098 ASSERT(r == UV_EINVAL); 4099 4100 r = uv_fs_copyfile(NULL, NULL, NULL, NULL, 0, NULL); 4101 ASSERT(r == UV_EINVAL); 4102 4103 r = uv_fs_sendfile(NULL, NULL, 0, 0, 0, 0, NULL); 4104 ASSERT(r == UV_EINVAL); 4105 4106 r = uv_fs_access(NULL, NULL, NULL, 0, NULL); 4107 ASSERT(r == UV_EINVAL); 4108 4109 r = uv_fs_chmod(NULL, NULL, NULL, 0, NULL); 4110 ASSERT(r == UV_EINVAL); 4111 4112 r = uv_fs_fchmod(NULL, NULL, 0, 0, NULL); 4113 ASSERT(r == UV_EINVAL); 4114 4115 r = uv_fs_utime(NULL, NULL, NULL, 0.0, 0.0, NULL); 4116 ASSERT(r == UV_EINVAL); 4117 4118 r = uv_fs_futime(NULL, NULL, 0, 0.0, 0.0, NULL); 4119 ASSERT(r == UV_EINVAL); 4120 4121 r = uv_fs_statfs(NULL, NULL, NULL, NULL); 4122 ASSERT(r == UV_EINVAL); 4123 4124 /* This should be a no-op. */ 4125 uv_fs_req_cleanup(NULL); 4126 4127 return 0; 4128 } 4129 4130 #ifdef _WIN32 4131 TEST_IMPL(fs_exclusive_sharing_mode) { 4132 int r; 4133 4134 /* Setup. */ 4135 unlink("test_file"); 4136 4137 ASSERT(UV_FS_O_EXLOCK > 0); 4138 4139 r = uv_fs_open(NULL, 4140 &open_req1, 4141 "test_file", 4142 O_RDWR | O_CREAT | UV_FS_O_EXLOCK, 4143 S_IWUSR | S_IRUSR, 4144 NULL); 4145 ASSERT(r >= 0); 4146 ASSERT(open_req1.result >= 0); 4147 uv_fs_req_cleanup(&open_req1); 4148 4149 r = uv_fs_open(NULL, 4150 &open_req2, 4151 "test_file", 4152 O_RDONLY | UV_FS_O_EXLOCK, 4153 S_IWUSR | S_IRUSR, 4154 NULL); 4155 ASSERT(r < 0); 4156 ASSERT(open_req2.result < 0); 4157 uv_fs_req_cleanup(&open_req2); 4158 4159 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 4160 ASSERT(r == 0); 4161 ASSERT(close_req.result == 0); 4162 uv_fs_req_cleanup(&close_req); 4163 4164 r = uv_fs_open(NULL, 4165 &open_req2, 4166 "test_file", 4167 O_RDONLY | UV_FS_O_EXLOCK, 4168 S_IWUSR | S_IRUSR, 4169 NULL); 4170 ASSERT(r >= 0); 4171 ASSERT(open_req2.result >= 0); 4172 uv_fs_req_cleanup(&open_req2); 4173 4174 r = uv_fs_close(NULL, &close_req, open_req2.result, NULL); 4175 ASSERT(r == 0); 4176 ASSERT(close_req.result == 0); 4177 uv_fs_req_cleanup(&close_req); 4178 4179 /* Cleanup */ 4180 unlink("test_file"); 4181 4182 MAKE_VALGRIND_HAPPY(); 4183 return 0; 4184 } 4185 #endif 4186 4187 #ifdef _WIN32 4188 TEST_IMPL(fs_file_flag_no_buffering) { 4189 int r; 4190 4191 /* Setup. */ 4192 unlink("test_file"); 4193 4194 ASSERT(UV_FS_O_APPEND > 0); 4195 ASSERT(UV_FS_O_CREAT > 0); 4196 ASSERT(UV_FS_O_DIRECT > 0); 4197 ASSERT(UV_FS_O_RDWR > 0); 4198 4199 /* FILE_APPEND_DATA must be excluded from FILE_GENERIC_WRITE: */ 4200 r = uv_fs_open(NULL, 4201 &open_req1, 4202 "test_file", 4203 UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_DIRECT, 4204 S_IWUSR | S_IRUSR, 4205 NULL); 4206 ASSERT(r >= 0); 4207 ASSERT(open_req1.result >= 0); 4208 uv_fs_req_cleanup(&open_req1); 4209 4210 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 4211 ASSERT(r == 0); 4212 ASSERT(close_req.result == 0); 4213 uv_fs_req_cleanup(&close_req); 4214 4215 /* FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually exclusive: */ 4216 r = uv_fs_open(NULL, 4217 &open_req2, 4218 "test_file", 4219 UV_FS_O_APPEND | UV_FS_O_DIRECT, 4220 S_IWUSR | S_IRUSR, 4221 NULL); 4222 ASSERT(r == UV_EINVAL); 4223 ASSERT(open_req2.result == UV_EINVAL); 4224 uv_fs_req_cleanup(&open_req2); 4225 4226 /* Cleanup */ 4227 unlink("test_file"); 4228 4229 MAKE_VALGRIND_HAPPY(); 4230 return 0; 4231 } 4232 #endif 4233 4234 #ifdef _WIN32 4235 int call_icacls(const char* command, ...) { 4236 char icacls_command[1024]; 4237 va_list args; 4238 4239 va_start(args, command); 4240 vsnprintf(icacls_command, ARRAYSIZE(icacls_command), command, args); 4241 va_end(args); 4242 return system(icacls_command); 4243 } 4244 4245 TEST_IMPL(fs_open_readonly_acl) { 4246 uv_passwd_t pwd; 4247 uv_fs_t req; 4248 int r; 4249 4250 /* 4251 Based on Node.js test from 4252 https://github.com/nodejs/node/commit/3ba81e34e86a5c32658e218cb6e65b13e8326bc5 4253 4254 If anything goes wrong, you can delte the test_fle_icacls with: 4255 4256 icacls test_file_icacls /remove "%USERNAME%" /inheritance:e 4257 attrib -r test_file_icacls 4258 del test_file_icacls 4259 */ 4260 4261 /* Setup - clear the ACL and remove the file */ 4262 loop = uv_default_loop(); 4263 r = uv_os_get_passwd(&pwd); 4264 ASSERT(r == 0); 4265 call_icacls("icacls test_file_icacls /remove \"%s\" /inheritance:e", 4266 pwd.username); 4267 uv_fs_chmod(loop, &req, "test_file_icacls", S_IWUSR, NULL); 4268 unlink("test_file_icacls"); 4269 4270 /* Create the file */ 4271 r = uv_fs_open(loop, 4272 &open_req1, 4273 "test_file_icacls", 4274 O_RDONLY | O_CREAT, 4275 S_IRUSR, 4276 NULL); 4277 ASSERT(r >= 0); 4278 ASSERT(open_req1.result >= 0); 4279 uv_fs_req_cleanup(&open_req1); 4280 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 4281 ASSERT(r == 0); 4282 ASSERT(close_req.result == 0); 4283 uv_fs_req_cleanup(&close_req); 4284 4285 /* Set up ACL */ 4286 r = call_icacls("icacls test_file_icacls /inheritance:r /remove \"%s\"", 4287 pwd.username); 4288 if (r != 0) { 4289 goto acl_cleanup; 4290 } 4291 r = call_icacls("icacls test_file_icacls /grant \"%s\":RX", pwd.username); 4292 if (r != 0) { 4293 goto acl_cleanup; 4294 } 4295 4296 /* Try opening the file */ 4297 r = uv_fs_open(NULL, &open_req1, "test_file_icacls", O_RDONLY, 0, NULL); 4298 if (r < 0) { 4299 goto acl_cleanup; 4300 } 4301 uv_fs_req_cleanup(&open_req1); 4302 r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); 4303 if (r != 0) { 4304 goto acl_cleanup; 4305 } 4306 uv_fs_req_cleanup(&close_req); 4307 4308 acl_cleanup: 4309 /* Cleanup */ 4310 call_icacls("icacls test_file_icacls /remove \"%s\" /inheritance:e", 4311 pwd.username); 4312 unlink("test_file_icacls"); 4313 uv_os_free_passwd(&pwd); 4314 ASSERT(r == 0); 4315 MAKE_VALGRIND_HAPPY(); 4316 return 0; 4317 } 4318 #endif 4319 4320 #ifdef _WIN32 4321 TEST_IMPL(fs_fchmod_archive_readonly) { 4322 uv_fs_t req; 4323 uv_file file; 4324 int r; 4325 /* Test clearing read-only flag from files with Archive flag cleared */ 4326 4327 /* Setup*/ 4328 unlink("test_file"); 4329 r = uv_fs_open(NULL, 4330 &req, 4331 "test_file", 4332 O_WRONLY | O_CREAT, 4333 S_IWUSR | S_IRUSR, 4334 NULL); 4335 ASSERT(r >= 0); 4336 ASSERT(req.result >= 0); 4337 file = req.result; 4338 uv_fs_req_cleanup(&req); 4339 r = uv_fs_close(NULL, &req, file, NULL); 4340 ASSERT(r == 0); 4341 uv_fs_req_cleanup(&req); 4342 /* Make the file read-only and clear archive flag */ 4343 r = SetFileAttributes("test_file", FILE_ATTRIBUTE_READONLY); 4344 ASSERT(r != 0); 4345 check_permission("test_file", 0400); 4346 /* Try fchmod */ 4347 r = uv_fs_open(NULL, &req, "test_file", O_RDONLY, 0, NULL); 4348 ASSERT(r >= 0); 4349 ASSERT(req.result >= 0); 4350 file = req.result; 4351 uv_fs_req_cleanup(&req); 4352 r = uv_fs_fchmod(NULL, &req, file, S_IWUSR, NULL); 4353 ASSERT(r == 0); 4354 ASSERT(req.result == 0); 4355 uv_fs_req_cleanup(&req); 4356 r = uv_fs_close(NULL, &req, file, NULL); 4357 ASSERT(r == 0); 4358 uv_fs_req_cleanup(&req); 4359 check_permission("test_file", S_IWUSR); 4360 4361 /* Restore Archive flag for rest of the tests */ 4362 r = SetFileAttributes("test_file", FILE_ATTRIBUTE_ARCHIVE); 4363 ASSERT(r != 0); 4364 4365 return 0; 4366 } 4367 4368 TEST_IMPL(fs_invalid_mkdir_name) { 4369 uv_loop_t* loop; 4370 uv_fs_t req; 4371 int r; 4372 4373 loop = uv_default_loop(); 4374 r = uv_fs_mkdir(loop, &req, "invalid>", 0, NULL); 4375 ASSERT(r == UV_EINVAL); 4376 4377 return 0; 4378 } 4379 #endif 4380 4381 TEST_IMPL(fs_statfs) { 4382 uv_fs_t req; 4383 int r; 4384 4385 loop = uv_default_loop(); 4386 4387 /* Test the synchronous version. */ 4388 r = uv_fs_statfs(NULL, &req, ".", NULL); 4389 ASSERT(r == 0); 4390 statfs_cb(&req); 4391 ASSERT(statfs_cb_count == 1); 4392 4393 /* Test the asynchronous version. */ 4394 r = uv_fs_statfs(loop, &req, ".", statfs_cb); 4395 ASSERT(r == 0); 4396 uv_run(loop, UV_RUN_DEFAULT); 4397 ASSERT(statfs_cb_count == 2); 4398 4399 return 0; 4400 } 4401 4402 TEST_IMPL(fs_get_system_error) { 4403 uv_fs_t req; 4404 int r; 4405 int system_error; 4406 4407 r = uv_fs_statfs(NULL, &req, "non_existing_file", NULL); 4408 ASSERT(r != 0); 4409 4410 system_error = uv_fs_get_system_error(&req); 4411 #ifdef _WIN32 4412 ASSERT(system_error == ERROR_FILE_NOT_FOUND); 4413 #else 4414 ASSERT(system_error == ENOENT); 4415 #endif 4416 4417 return 0; 4418 } 4419