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