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