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