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