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 
30 /* FIXME we shouldn't need to branch in this file */
31 #if defined(__unix__) || defined(__POSIX__) || \
32     defined(__APPLE__) || defined(_AIX) || defined(__MVS__)
33 #include <unistd.h> /* unlink, rmdir, etc. */
34 #else
35 # include <winioctl.h>
36 # include <direct.h>
37 # include <io.h>
38 # ifndef ERROR_SYMLINK_NOT_SUPPORTED
39 #  define ERROR_SYMLINK_NOT_SUPPORTED 1464
40 # endif
41 # define unlink _unlink
42 # define rmdir _rmdir
43 # define open _open
44 # define write _write
45 # define close _close
46 # ifndef stat
47 #  define stat _stati64
48 # endif
49 # ifndef lseek
50 #   define lseek _lseek
51 # endif
52 #endif
53 
54 #define TOO_LONG_NAME_LENGTH 65536
55 #define PATHMAX 1024
56 
57 typedef struct {
58   const char* path;
59   double atime;
60   double mtime;
61 } utime_check_t;
62 
63 
64 static int dummy_cb_count;
65 static int close_cb_count;
66 static int create_cb_count;
67 static int open_cb_count;
68 static int read_cb_count;
69 static int write_cb_count;
70 static int unlink_cb_count;
71 static int mkdir_cb_count;
72 static int mkdtemp_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 link_cb_count;
88 static int symlink_cb_count;
89 static int readlink_cb_count;
90 static int realpath_cb_count;
91 static int utime_cb_count;
92 static int futime_cb_count;
93 
94 static uv_loop_t* loop;
95 
96 static uv_fs_t open_req1;
97 static uv_fs_t open_req2;
98 static uv_fs_t read_req;
99 static uv_fs_t write_req;
100 static uv_fs_t unlink_req;
101 static uv_fs_t close_req;
102 static uv_fs_t mkdir_req;
103 static uv_fs_t mkdtemp_req1;
104 static uv_fs_t mkdtemp_req2;
105 static uv_fs_t rmdir_req;
106 static uv_fs_t scandir_req;
107 static uv_fs_t stat_req;
108 static uv_fs_t rename_req;
109 static uv_fs_t fsync_req;
110 static uv_fs_t fdatasync_req;
111 static uv_fs_t ftruncate_req;
112 static uv_fs_t sendfile_req;
113 static uv_fs_t utime_req;
114 static uv_fs_t futime_req;
115 
116 static char buf[32];
117 static char buf2[32];
118 static char test_buf[] = "test-buffer\n";
119 static char test_buf2[] = "second-buffer\n";
120 static uv_buf_t iov;
121 
122 #ifdef _WIN32
123 /*
124  * This tag and guid have no special meaning, and don't conflict with
125  * reserved ids.
126 */
127 static unsigned REPARSE_TAG = 0x9913;
128 static GUID REPARSE_GUID = {
129   0x1bf6205f, 0x46ae, 0x4527,
130   0xb1, 0x0c, 0xc5, 0x09, 0xb7, 0x55, 0x22, 0x80 };
131 #endif
132 
check_permission(const char * filename,unsigned int mode)133 static void check_permission(const char* filename, unsigned int mode) {
134   int r;
135   uv_fs_t req;
136   uv_stat_t* s;
137 
138   r = uv_fs_stat(NULL, &req, filename, NULL);
139   ASSERT(r == 0);
140   ASSERT(req.result == 0);
141 
142   s = &req.statbuf;
143 #if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__)
144   /*
145    * On Windows, chmod can only modify S_IWUSR (_S_IWRITE) bit,
146    * so only testing for the specified flags.
147    */
148   ASSERT((s->st_mode & 0777) & mode);
149 #else
150   ASSERT((s->st_mode & 0777) == mode);
151 #endif
152 
153   uv_fs_req_cleanup(&req);
154 }
155 
156 
dummy_cb(uv_fs_t * req)157 static void dummy_cb(uv_fs_t* req) {
158   (void) req;
159   dummy_cb_count++;
160 }
161 
162 
link_cb(uv_fs_t * req)163 static void link_cb(uv_fs_t* req) {
164   ASSERT(req->fs_type == UV_FS_LINK);
165   ASSERT(req->result == 0);
166   link_cb_count++;
167   uv_fs_req_cleanup(req);
168 }
169 
170 
symlink_cb(uv_fs_t * req)171 static void symlink_cb(uv_fs_t* req) {
172   ASSERT(req->fs_type == UV_FS_SYMLINK);
173   ASSERT(req->result == 0);
174   symlink_cb_count++;
175   uv_fs_req_cleanup(req);
176 }
177 
readlink_cb(uv_fs_t * req)178 static void readlink_cb(uv_fs_t* req) {
179   ASSERT(req->fs_type == UV_FS_READLINK);
180   ASSERT(req->result == 0);
181   ASSERT(strcmp(req->ptr, "test_file_symlink2") == 0);
182   readlink_cb_count++;
183   uv_fs_req_cleanup(req);
184 }
185 
186 
realpath_cb(uv_fs_t * req)187 static void realpath_cb(uv_fs_t* req) {
188   char test_file_abs_buf[PATHMAX];
189   size_t test_file_abs_size = sizeof(test_file_abs_buf);
190   ASSERT(req->fs_type == UV_FS_REALPATH);
191 #ifdef _WIN32
192   /*
193    * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
194    */
195   if (req->result == UV_ENOSYS) {
196     realpath_cb_count++;
197     uv_fs_req_cleanup(req);
198     return;
199   }
200 #endif
201   ASSERT(req->result == 0);
202 
203   uv_cwd(test_file_abs_buf, &test_file_abs_size);
204 #ifdef _WIN32
205   strcat(test_file_abs_buf, "\\test_file");
206   ASSERT(stricmp(req->ptr, test_file_abs_buf) == 0);
207 #else
208   strcat(test_file_abs_buf, "/test_file");
209   ASSERT(strcmp(req->ptr, test_file_abs_buf) == 0);
210 #endif
211   realpath_cb_count++;
212   uv_fs_req_cleanup(req);
213 }
214 
215 
access_cb(uv_fs_t * req)216 static void access_cb(uv_fs_t* req) {
217   ASSERT(req->fs_type == UV_FS_ACCESS);
218   access_cb_count++;
219   uv_fs_req_cleanup(req);
220 }
221 
222 
fchmod_cb(uv_fs_t * req)223 static void fchmod_cb(uv_fs_t* req) {
224   ASSERT(req->fs_type == UV_FS_FCHMOD);
225   ASSERT(req->result == 0);
226   fchmod_cb_count++;
227   uv_fs_req_cleanup(req);
228   check_permission("test_file", *(int*)req->data);
229 }
230 
231 
chmod_cb(uv_fs_t * req)232 static void chmod_cb(uv_fs_t* req) {
233   ASSERT(req->fs_type == UV_FS_CHMOD);
234   ASSERT(req->result == 0);
235   chmod_cb_count++;
236   uv_fs_req_cleanup(req);
237   check_permission("test_file", *(int*)req->data);
238 }
239 
240 
fchown_cb(uv_fs_t * req)241 static void fchown_cb(uv_fs_t* req) {
242   ASSERT(req->fs_type == UV_FS_FCHOWN);
243   ASSERT(req->result == 0);
244   fchown_cb_count++;
245   uv_fs_req_cleanup(req);
246 }
247 
248 
chown_cb(uv_fs_t * req)249 static void chown_cb(uv_fs_t* req) {
250   ASSERT(req->fs_type == UV_FS_CHOWN);
251   ASSERT(req->result == 0);
252   chown_cb_count++;
253   uv_fs_req_cleanup(req);
254 }
255 
chown_root_cb(uv_fs_t * req)256 static void chown_root_cb(uv_fs_t* req) {
257   ASSERT(req->fs_type == UV_FS_CHOWN);
258 #if defined(_WIN32) || defined(__MSYS__)
259   /* On windows, chown is a no-op and always succeeds. */
260   ASSERT(req->result == 0);
261 #else
262   /* On unix, chown'ing the root directory is not allowed -
263    * unless you're root, of course.
264    */
265   if (geteuid() == 0)
266     ASSERT(req->result == 0);
267   else
268 #   if defined(__CYGWIN__)
269     /* On Cygwin, uid 0 is invalid (no root). */
270     ASSERT(req->result == UV_EINVAL);
271 #   else
272     ASSERT(req->result == UV_EPERM);
273 #   endif
274 #endif
275   chown_cb_count++;
276   uv_fs_req_cleanup(req);
277 }
278 
unlink_cb(uv_fs_t * req)279 static void unlink_cb(uv_fs_t* req) {
280   ASSERT(req == &unlink_req);
281   ASSERT(req->fs_type == UV_FS_UNLINK);
282   ASSERT(req->result == 0);
283   unlink_cb_count++;
284   uv_fs_req_cleanup(req);
285 }
286 
fstat_cb(uv_fs_t * req)287 static void fstat_cb(uv_fs_t* req) {
288   uv_stat_t* s = req->ptr;
289   ASSERT(req->fs_type == UV_FS_FSTAT);
290   ASSERT(req->result == 0);
291   ASSERT(s->st_size == sizeof(test_buf));
292   uv_fs_req_cleanup(req);
293   fstat_cb_count++;
294 }
295 
296 
close_cb(uv_fs_t * req)297 static void close_cb(uv_fs_t* req) {
298   int r;
299   ASSERT(req == &close_req);
300   ASSERT(req->fs_type == UV_FS_CLOSE);
301   ASSERT(req->result == 0);
302   close_cb_count++;
303   uv_fs_req_cleanup(req);
304   if (close_cb_count == 3) {
305     r = uv_fs_unlink(loop, &unlink_req, "test_file2", unlink_cb);
306     ASSERT(r == 0);
307   }
308 }
309 
310 
ftruncate_cb(uv_fs_t * req)311 static void ftruncate_cb(uv_fs_t* req) {
312   int r;
313   ASSERT(req == &ftruncate_req);
314   ASSERT(req->fs_type == UV_FS_FTRUNCATE);
315   ASSERT(req->result == 0);
316   ftruncate_cb_count++;
317   uv_fs_req_cleanup(req);
318   r = uv_fs_close(loop, &close_req, open_req1.result, close_cb);
319   ASSERT(r == 0);
320 }
321 
fail_cb(uv_fs_t * req)322 static void fail_cb(uv_fs_t* req) {
323   FATAL("fail_cb should not have been called");
324 }
325 
read_cb(uv_fs_t * req)326 static void read_cb(uv_fs_t* req) {
327   int r;
328   ASSERT(req == &read_req);
329   ASSERT(req->fs_type == UV_FS_READ);
330   ASSERT(req->result >= 0);  /* FIXME(bnoordhuis) Check if requested size? */
331   read_cb_count++;
332   uv_fs_req_cleanup(req);
333   if (read_cb_count == 1) {
334     ASSERT(strcmp(buf, test_buf) == 0);
335     r = uv_fs_ftruncate(loop, &ftruncate_req, open_req1.result, 7,
336         ftruncate_cb);
337   } else {
338     ASSERT(strcmp(buf, "test-bu") == 0);
339     r = uv_fs_close(loop, &close_req, open_req1.result, close_cb);
340   }
341   ASSERT(r == 0);
342 }
343 
344 
open_cb(uv_fs_t * req)345 static void open_cb(uv_fs_t* req) {
346   int r;
347   ASSERT(req == &open_req1);
348   ASSERT(req->fs_type == UV_FS_OPEN);
349   if (req->result < 0) {
350     fprintf(stderr, "async open error: %d\n", (int) req->result);
351     ASSERT(0);
352   }
353   open_cb_count++;
354   ASSERT(req->path);
355   ASSERT(memcmp(req->path, "test_file2\0", 11) == 0);
356   uv_fs_req_cleanup(req);
357   memset(buf, 0, sizeof(buf));
358   iov = uv_buf_init(buf, sizeof(buf));
359   r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1,
360       read_cb);
361   ASSERT(r == 0);
362 }
363 
364 
open_cb_simple(uv_fs_t * req)365 static void open_cb_simple(uv_fs_t* req) {
366   ASSERT(req->fs_type == UV_FS_OPEN);
367   if (req->result < 0) {
368     fprintf(stderr, "async open error: %d\n", (int) req->result);
369     ASSERT(0);
370   }
371   open_cb_count++;
372   ASSERT(req->path);
373   uv_fs_req_cleanup(req);
374 }
375 
376 
fsync_cb(uv_fs_t * req)377 static void fsync_cb(uv_fs_t* req) {
378   int r;
379   ASSERT(req == &fsync_req);
380   ASSERT(req->fs_type == UV_FS_FSYNC);
381   ASSERT(req->result == 0);
382   fsync_cb_count++;
383   uv_fs_req_cleanup(req);
384   r = uv_fs_close(loop, &close_req, open_req1.result, close_cb);
385   ASSERT(r == 0);
386 }
387 
388 
fdatasync_cb(uv_fs_t * req)389 static void fdatasync_cb(uv_fs_t* req) {
390   int r;
391   ASSERT(req == &fdatasync_req);
392   ASSERT(req->fs_type == UV_FS_FDATASYNC);
393   ASSERT(req->result == 0);
394   fdatasync_cb_count++;
395   uv_fs_req_cleanup(req);
396   r = uv_fs_fsync(loop, &fsync_req, open_req1.result, fsync_cb);
397   ASSERT(r == 0);
398 }
399 
400 
write_cb(uv_fs_t * req)401 static void write_cb(uv_fs_t* req) {
402   int r;
403   ASSERT(req == &write_req);
404   ASSERT(req->fs_type == UV_FS_WRITE);
405   ASSERT(req->result >= 0);  /* FIXME(bnoordhuis) Check if requested size? */
406   write_cb_count++;
407   uv_fs_req_cleanup(req);
408   r = uv_fs_fdatasync(loop, &fdatasync_req, open_req1.result, fdatasync_cb);
409   ASSERT(r == 0);
410 }
411 
412 
create_cb(uv_fs_t * req)413 static void create_cb(uv_fs_t* req) {
414   int r;
415   ASSERT(req == &open_req1);
416   ASSERT(req->fs_type == UV_FS_OPEN);
417   ASSERT(req->result >= 0);
418   create_cb_count++;
419   uv_fs_req_cleanup(req);
420   iov = uv_buf_init(test_buf, sizeof(test_buf));
421   r = uv_fs_write(loop, &write_req, req->result, &iov, 1, -1, write_cb);
422   ASSERT(r == 0);
423 }
424 
425 
rename_cb(uv_fs_t * req)426 static void rename_cb(uv_fs_t* req) {
427   ASSERT(req == &rename_req);
428   ASSERT(req->fs_type == UV_FS_RENAME);
429   ASSERT(req->result == 0);
430   rename_cb_count++;
431   uv_fs_req_cleanup(req);
432 }
433 
434 
mkdir_cb(uv_fs_t * req)435 static void mkdir_cb(uv_fs_t* req) {
436   ASSERT(req == &mkdir_req);
437   ASSERT(req->fs_type == UV_FS_MKDIR);
438   ASSERT(req->result == 0);
439   mkdir_cb_count++;
440   ASSERT(req->path);
441   ASSERT(memcmp(req->path, "test_dir\0", 9) == 0);
442   uv_fs_req_cleanup(req);
443 }
444 
445 
check_mkdtemp_result(uv_fs_t * req)446 static void check_mkdtemp_result(uv_fs_t* req) {
447   int r;
448 
449   ASSERT(req->fs_type == UV_FS_MKDTEMP);
450   ASSERT(req->result == 0);
451   ASSERT(req->path);
452   ASSERT(strlen(req->path) == 15);
453   ASSERT(memcmp(req->path, "test_dir_", 9) == 0);
454   ASSERT(memcmp(req->path + 9, "XXXXXX", 6) != 0);
455   check_permission(req->path, 0700);
456 
457   /* Check if req->path is actually a directory */
458   r = uv_fs_stat(NULL, &stat_req, req->path, NULL);
459   ASSERT(r == 0);
460   ASSERT(((uv_stat_t*)stat_req.ptr)->st_mode & S_IFDIR);
461   uv_fs_req_cleanup(&stat_req);
462 }
463 
464 
mkdtemp_cb(uv_fs_t * req)465 static void mkdtemp_cb(uv_fs_t* req) {
466   ASSERT(req == &mkdtemp_req1);
467   check_mkdtemp_result(req);
468   mkdtemp_cb_count++;
469 }
470 
471 
rmdir_cb(uv_fs_t * req)472 static void rmdir_cb(uv_fs_t* req) {
473   ASSERT(req == &rmdir_req);
474   ASSERT(req->fs_type == UV_FS_RMDIR);
475   ASSERT(req->result == 0);
476   rmdir_cb_count++;
477   ASSERT(req->path);
478   ASSERT(memcmp(req->path, "test_dir\0", 9) == 0);
479   uv_fs_req_cleanup(req);
480 }
481 
482 
assert_is_file_type(uv_dirent_t dent)483 static void assert_is_file_type(uv_dirent_t dent) {
484 #ifdef HAVE_DIRENT_TYPES
485   /*
486    * For Apple and Windows, we know getdents is expected to work but for other
487    * environments, the filesystem dictates whether or not getdents supports
488    * returning the file type.
489    *
490    *   See:
491    *     http://man7.org/linux/man-pages/man2/getdents.2.html
492    *     https://github.com/libuv/libuv/issues/501
493    */
494   #if defined(__APPLE__) || defined(_WIN32)
495     ASSERT(dent.type == UV_DIRENT_FILE);
496   #else
497     ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN);
498   #endif
499 #else
500   ASSERT(dent.type == UV_DIRENT_UNKNOWN);
501 #endif
502 }
503 
504 
scandir_cb(uv_fs_t * req)505 static void scandir_cb(uv_fs_t* req) {
506   uv_dirent_t dent;
507   ASSERT(req == &scandir_req);
508   ASSERT(req->fs_type == UV_FS_SCANDIR);
509   ASSERT(req->result == 2);
510   ASSERT(req->ptr);
511 
512   while (UV_EOF != uv_fs_scandir_next(req, &dent)) {
513     ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0);
514     assert_is_file_type(dent);
515   }
516   scandir_cb_count++;
517   ASSERT(req->path);
518   ASSERT(memcmp(req->path, "test_dir\0", 9) == 0);
519   uv_fs_req_cleanup(req);
520   ASSERT(!req->ptr);
521 }
522 
523 
empty_scandir_cb(uv_fs_t * req)524 static void empty_scandir_cb(uv_fs_t* req) {
525   uv_dirent_t dent;
526 
527   ASSERT(req == &scandir_req);
528   ASSERT(req->fs_type == UV_FS_SCANDIR);
529   ASSERT(req->result == 0);
530   ASSERT(req->ptr == NULL);
531   ASSERT(UV_EOF == uv_fs_scandir_next(req, &dent));
532   uv_fs_req_cleanup(req);
533   scandir_cb_count++;
534 }
535 
non_existent_scandir_cb(uv_fs_t * req)536 static void non_existent_scandir_cb(uv_fs_t* req) {
537   uv_dirent_t dent;
538 
539   ASSERT(req == &scandir_req);
540   ASSERT(req->fs_type == UV_FS_SCANDIR);
541   ASSERT(req->result == UV_ENOENT);
542   ASSERT(req->ptr == NULL);
543   ASSERT(UV_ENOENT == uv_fs_scandir_next(req, &dent));
544   uv_fs_req_cleanup(req);
545   scandir_cb_count++;
546 }
547 
548 
file_scandir_cb(uv_fs_t * req)549 static void file_scandir_cb(uv_fs_t* req) {
550   ASSERT(req == &scandir_req);
551   ASSERT(req->fs_type == UV_FS_SCANDIR);
552   ASSERT(req->result == UV_ENOTDIR);
553   ASSERT(req->ptr == NULL);
554   uv_fs_req_cleanup(req);
555   scandir_cb_count++;
556 }
557 
558 
stat_cb(uv_fs_t * req)559 static void stat_cb(uv_fs_t* req) {
560   ASSERT(req == &stat_req);
561   ASSERT(req->fs_type == UV_FS_STAT || req->fs_type == UV_FS_LSTAT);
562   ASSERT(req->result == 0);
563   ASSERT(req->ptr);
564   stat_cb_count++;
565   uv_fs_req_cleanup(req);
566   ASSERT(!req->ptr);
567 }
568 
569 
sendfile_cb(uv_fs_t * req)570 static void sendfile_cb(uv_fs_t* req) {
571   ASSERT(req == &sendfile_req);
572   ASSERT(req->fs_type == UV_FS_SENDFILE);
573   ASSERT(req->result == 65546);
574   sendfile_cb_count++;
575   uv_fs_req_cleanup(req);
576 }
577 
578 
open_noent_cb(uv_fs_t * req)579 static void open_noent_cb(uv_fs_t* req) {
580   ASSERT(req->fs_type == UV_FS_OPEN);
581   ASSERT(req->result == UV_ENOENT);
582   open_cb_count++;
583   uv_fs_req_cleanup(req);
584 }
585 
open_nametoolong_cb(uv_fs_t * req)586 static void open_nametoolong_cb(uv_fs_t* req) {
587   ASSERT(req->fs_type == UV_FS_OPEN);
588   ASSERT(req->result == UV_ENAMETOOLONG);
589   open_cb_count++;
590   uv_fs_req_cleanup(req);
591 }
592 
open_loop_cb(uv_fs_t * req)593 static void open_loop_cb(uv_fs_t* req) {
594   ASSERT(req->fs_type == UV_FS_OPEN);
595   ASSERT(req->result == UV_ELOOP);
596   open_cb_count++;
597   uv_fs_req_cleanup(req);
598 }
599 
600 
TEST_IMPL(fs_file_noent)601 TEST_IMPL(fs_file_noent) {
602   uv_fs_t req;
603   int r;
604 
605   loop = uv_default_loop();
606 
607   r = uv_fs_open(NULL, &req, "does_not_exist", O_RDONLY, 0, NULL);
608   ASSERT(r == UV_ENOENT);
609   ASSERT(req.result == UV_ENOENT);
610   uv_fs_req_cleanup(&req);
611 
612   r = uv_fs_open(loop, &req, "does_not_exist", O_RDONLY, 0, open_noent_cb);
613   ASSERT(r == 0);
614 
615   ASSERT(open_cb_count == 0);
616   uv_run(loop, UV_RUN_DEFAULT);
617   ASSERT(open_cb_count == 1);
618 
619   /* TODO add EACCES test */
620 
621   MAKE_VALGRIND_HAPPY();
622   return 0;
623 }
624 
TEST_IMPL(fs_file_nametoolong)625 TEST_IMPL(fs_file_nametoolong) {
626   uv_fs_t req;
627   int r;
628   char name[TOO_LONG_NAME_LENGTH + 1];
629 
630   loop = uv_default_loop();
631 
632   memset(name, 'a', TOO_LONG_NAME_LENGTH);
633   name[TOO_LONG_NAME_LENGTH] = 0;
634 
635   r = uv_fs_open(NULL, &req, name, O_RDONLY, 0, NULL);
636   ASSERT(r == UV_ENAMETOOLONG);
637   ASSERT(req.result == UV_ENAMETOOLONG);
638   uv_fs_req_cleanup(&req);
639 
640   r = uv_fs_open(loop, &req, name, O_RDONLY, 0, open_nametoolong_cb);
641   ASSERT(r == 0);
642 
643   ASSERT(open_cb_count == 0);
644   uv_run(loop, UV_RUN_DEFAULT);
645   ASSERT(open_cb_count == 1);
646 
647   MAKE_VALGRIND_HAPPY();
648   return 0;
649 }
650 
TEST_IMPL(fs_file_loop)651 TEST_IMPL(fs_file_loop) {
652   uv_fs_t req;
653   int r;
654 
655   loop = uv_default_loop();
656 
657   unlink("test_symlink");
658   r = uv_fs_symlink(NULL, &req, "test_symlink", "test_symlink", 0, NULL);
659 #ifdef _WIN32
660   /*
661    * Windows XP and Server 2003 don't support symlinks; we'll get UV_ENOTSUP.
662    * Starting with vista they are supported, but only when elevated, otherwise
663    * we'll see UV_EPERM.
664    */
665   if (r == UV_ENOTSUP || r == UV_EPERM)
666     return 0;
667 #elif defined(__MSYS__)
668   /* MSYS2's approximation of symlinks with copies does not work for broken
669      links.  */
670   if (r == UV_ENOENT)
671     return 0;
672 #endif
673   ASSERT(r == 0);
674   uv_fs_req_cleanup(&req);
675 
676   r = uv_fs_open(NULL, &req, "test_symlink", O_RDONLY, 0, NULL);
677   ASSERT(r == UV_ELOOP);
678   ASSERT(req.result == UV_ELOOP);
679   uv_fs_req_cleanup(&req);
680 
681   r = uv_fs_open(loop, &req, "test_symlink", O_RDONLY, 0, open_loop_cb);
682   ASSERT(r == 0);
683 
684   ASSERT(open_cb_count == 0);
685   uv_run(loop, UV_RUN_DEFAULT);
686   ASSERT(open_cb_count == 1);
687 
688   unlink("test_symlink");
689 
690   MAKE_VALGRIND_HAPPY();
691   return 0;
692 }
693 
check_utime(const char * path,double atime,double mtime)694 static void check_utime(const char* path, double atime, double mtime) {
695   uv_stat_t* s;
696   uv_fs_t req;
697   int r;
698 
699   r = uv_fs_stat(loop, &req, path, NULL);
700   ASSERT(r == 0);
701 
702   ASSERT(req.result == 0);
703   s = &req.statbuf;
704 
705   ASSERT(s->st_atim.tv_sec + (s->st_atim.tv_nsec / 1000000000.0) == atime);
706   ASSERT(s->st_mtim.tv_sec + (s->st_mtim.tv_nsec / 1000000000.0) == mtime);
707 
708   uv_fs_req_cleanup(&req);
709 }
710 
711 
utime_cb(uv_fs_t * req)712 static void utime_cb(uv_fs_t* req) {
713   utime_check_t* c;
714 
715   ASSERT(req == &utime_req);
716   ASSERT(req->result == 0);
717   ASSERT(req->fs_type == UV_FS_UTIME);
718 
719   c = req->data;
720   check_utime(c->path, c->atime, c->mtime);
721 
722   uv_fs_req_cleanup(req);
723   utime_cb_count++;
724 }
725 
726 
futime_cb(uv_fs_t * req)727 static void futime_cb(uv_fs_t* req) {
728   utime_check_t* c;
729 
730   ASSERT(req == &futime_req);
731   ASSERT(req->result == 0);
732   ASSERT(req->fs_type == UV_FS_FUTIME);
733 
734   c = req->data;
735   check_utime(c->path, c->atime, c->mtime);
736 
737   uv_fs_req_cleanup(req);
738   futime_cb_count++;
739 }
740 
741 
TEST_IMPL(fs_file_async)742 TEST_IMPL(fs_file_async) {
743   int r;
744 
745   /* Setup. */
746   unlink("test_file");
747   unlink("test_file2");
748 
749   loop = uv_default_loop();
750 
751   r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
752       S_IRUSR | S_IWUSR, create_cb);
753   ASSERT(r == 0);
754   uv_run(loop, UV_RUN_DEFAULT);
755 
756   ASSERT(create_cb_count == 1);
757   ASSERT(write_cb_count == 1);
758   ASSERT(fsync_cb_count == 1);
759   ASSERT(fdatasync_cb_count == 1);
760   ASSERT(close_cb_count == 1);
761 
762   r = uv_fs_rename(loop, &rename_req, "test_file", "test_file2", rename_cb);
763   ASSERT(r == 0);
764 
765   uv_run(loop, UV_RUN_DEFAULT);
766   ASSERT(create_cb_count == 1);
767   ASSERT(write_cb_count == 1);
768   ASSERT(close_cb_count == 1);
769   ASSERT(rename_cb_count == 1);
770 
771   r = uv_fs_open(loop, &open_req1, "test_file2", O_RDWR, 0, open_cb);
772   ASSERT(r == 0);
773 
774   uv_run(loop, UV_RUN_DEFAULT);
775   ASSERT(open_cb_count == 1);
776   ASSERT(read_cb_count == 1);
777   ASSERT(close_cb_count == 2);
778   ASSERT(rename_cb_count == 1);
779   ASSERT(create_cb_count == 1);
780   ASSERT(write_cb_count == 1);
781   ASSERT(ftruncate_cb_count == 1);
782 
783   r = uv_fs_open(loop, &open_req1, "test_file2", O_RDONLY, 0, open_cb);
784   ASSERT(r == 0);
785 
786   uv_run(loop, UV_RUN_DEFAULT);
787   ASSERT(open_cb_count == 2);
788   ASSERT(read_cb_count == 2);
789   ASSERT(close_cb_count == 3);
790   ASSERT(rename_cb_count == 1);
791   ASSERT(unlink_cb_count == 1);
792   ASSERT(create_cb_count == 1);
793   ASSERT(write_cb_count == 1);
794   ASSERT(ftruncate_cb_count == 1);
795 
796   /* Cleanup. */
797   unlink("test_file");
798   unlink("test_file2");
799 
800   MAKE_VALGRIND_HAPPY();
801   return 0;
802 }
803 
804 
TEST_IMPL(fs_file_sync)805 TEST_IMPL(fs_file_sync) {
806   int r;
807 
808   /* Setup. */
809   unlink("test_file");
810   unlink("test_file2");
811 
812   loop = uv_default_loop();
813 
814   r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
815       S_IWUSR | S_IRUSR, NULL);
816   ASSERT(r >= 0);
817   ASSERT(open_req1.result >= 0);
818   uv_fs_req_cleanup(&open_req1);
819 
820   iov = uv_buf_init(test_buf, sizeof(test_buf));
821   r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
822   ASSERT(r >= 0);
823   ASSERT(write_req.result >= 0);
824   uv_fs_req_cleanup(&write_req);
825 
826   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
827   ASSERT(r == 0);
828   ASSERT(close_req.result == 0);
829   uv_fs_req_cleanup(&close_req);
830 
831   r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR, 0, NULL);
832   ASSERT(r >= 0);
833   ASSERT(open_req1.result >= 0);
834   uv_fs_req_cleanup(&open_req1);
835 
836   iov = uv_buf_init(buf, sizeof(buf));
837   r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
838   ASSERT(r >= 0);
839   ASSERT(read_req.result >= 0);
840   ASSERT(strcmp(buf, test_buf) == 0);
841   uv_fs_req_cleanup(&read_req);
842 
843   r = uv_fs_ftruncate(NULL, &ftruncate_req, open_req1.result, 7, NULL);
844   ASSERT(r == 0);
845   ASSERT(ftruncate_req.result == 0);
846   uv_fs_req_cleanup(&ftruncate_req);
847 
848   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
849   ASSERT(r == 0);
850   ASSERT(close_req.result == 0);
851   uv_fs_req_cleanup(&close_req);
852 
853   r = uv_fs_rename(NULL, &rename_req, "test_file", "test_file2", NULL);
854   ASSERT(r == 0);
855   ASSERT(rename_req.result == 0);
856   uv_fs_req_cleanup(&rename_req);
857 
858   r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY, 0, NULL);
859   ASSERT(r >= 0);
860   ASSERT(open_req1.result >= 0);
861   uv_fs_req_cleanup(&open_req1);
862 
863   memset(buf, 0, sizeof(buf));
864   iov = uv_buf_init(buf, sizeof(buf));
865   r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
866   ASSERT(r >= 0);
867   ASSERT(read_req.result >= 0);
868   ASSERT(strcmp(buf, "test-bu") == 0);
869   uv_fs_req_cleanup(&read_req);
870 
871   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
872   ASSERT(r == 0);
873   ASSERT(close_req.result == 0);
874   uv_fs_req_cleanup(&close_req);
875 
876   r = uv_fs_unlink(NULL, &unlink_req, "test_file2", NULL);
877   ASSERT(r == 0);
878   ASSERT(unlink_req.result == 0);
879   uv_fs_req_cleanup(&unlink_req);
880 
881   /* Cleanup */
882   unlink("test_file");
883   unlink("test_file2");
884 
885   MAKE_VALGRIND_HAPPY();
886   return 0;
887 }
888 
889 
TEST_IMPL(fs_file_write_null_buffer)890 TEST_IMPL(fs_file_write_null_buffer) {
891   int r;
892 
893   /* Setup. */
894   unlink("test_file");
895 
896   loop = uv_default_loop();
897 
898   r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT,
899       S_IWUSR | S_IRUSR, NULL);
900   ASSERT(r >= 0);
901   ASSERT(open_req1.result >= 0);
902   uv_fs_req_cleanup(&open_req1);
903 
904   iov = uv_buf_init(NULL, 0);
905   r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
906   ASSERT(r == 0);
907   ASSERT(write_req.result == 0);
908   uv_fs_req_cleanup(&write_req);
909 
910   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
911   ASSERT(r == 0);
912   ASSERT(close_req.result == 0);
913   uv_fs_req_cleanup(&close_req);
914 
915   unlink("test_file");
916 
917   MAKE_VALGRIND_HAPPY();
918   return 0;
919 }
920 
921 
TEST_IMPL(fs_async_dir)922 TEST_IMPL(fs_async_dir) {
923   int r;
924   uv_dirent_t dent;
925 
926   /* Setup */
927   unlink("test_dir/file1");
928   unlink("test_dir/file2");
929   rmdir("test_dir");
930 
931   loop = uv_default_loop();
932 
933   r = uv_fs_mkdir(loop, &mkdir_req, "test_dir", 0755, mkdir_cb);
934   ASSERT(r == 0);
935 
936   uv_run(loop, UV_RUN_DEFAULT);
937   ASSERT(mkdir_cb_count == 1);
938 
939   /* Create 2 files synchronously. */
940   r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT,
941       S_IWUSR | S_IRUSR, NULL);
942   ASSERT(r >= 0);
943   uv_fs_req_cleanup(&open_req1);
944   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
945   ASSERT(r == 0);
946   uv_fs_req_cleanup(&close_req);
947 
948   r = uv_fs_open(NULL, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT,
949       S_IWUSR | S_IRUSR, NULL);
950   ASSERT(r >= 0);
951   uv_fs_req_cleanup(&open_req1);
952   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
953   ASSERT(r == 0);
954   uv_fs_req_cleanup(&close_req);
955 
956   r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, scandir_cb);
957   ASSERT(r == 0);
958 
959   uv_run(loop, UV_RUN_DEFAULT);
960   ASSERT(scandir_cb_count == 1);
961 
962   /* sync uv_fs_scandir */
963   r = uv_fs_scandir(NULL, &scandir_req, "test_dir", 0, NULL);
964   ASSERT(r == 2);
965   ASSERT(scandir_req.result == 2);
966   ASSERT(scandir_req.ptr);
967   while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) {
968     ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0);
969     assert_is_file_type(dent);
970   }
971   uv_fs_req_cleanup(&scandir_req);
972   ASSERT(!scandir_req.ptr);
973 
974   r = uv_fs_stat(loop, &stat_req, "test_dir", stat_cb);
975   ASSERT(r == 0);
976   uv_run(loop, UV_RUN_DEFAULT);
977 
978   r = uv_fs_stat(loop, &stat_req, "test_dir/", stat_cb);
979   ASSERT(r == 0);
980   uv_run(loop, UV_RUN_DEFAULT);
981 
982   r = uv_fs_lstat(loop, &stat_req, "test_dir", stat_cb);
983   ASSERT(r == 0);
984   uv_run(loop, UV_RUN_DEFAULT);
985 
986   r = uv_fs_lstat(loop, &stat_req, "test_dir/", stat_cb);
987   ASSERT(r == 0);
988   uv_run(loop, UV_RUN_DEFAULT);
989 
990   ASSERT(stat_cb_count == 4);
991 
992   r = uv_fs_unlink(loop, &unlink_req, "test_dir/file1", unlink_cb);
993   ASSERT(r == 0);
994   uv_run(loop, UV_RUN_DEFAULT);
995   ASSERT(unlink_cb_count == 1);
996 
997   r = uv_fs_unlink(loop, &unlink_req, "test_dir/file2", unlink_cb);
998   ASSERT(r == 0);
999   uv_run(loop, UV_RUN_DEFAULT);
1000   ASSERT(unlink_cb_count == 2);
1001 
1002   r = uv_fs_rmdir(loop, &rmdir_req, "test_dir", rmdir_cb);
1003   ASSERT(r == 0);
1004   uv_run(loop, UV_RUN_DEFAULT);
1005   ASSERT(rmdir_cb_count == 1);
1006 
1007   /* Cleanup */
1008   unlink("test_dir/file1");
1009   unlink("test_dir/file2");
1010   rmdir("test_dir");
1011 
1012   MAKE_VALGRIND_HAPPY();
1013   return 0;
1014 }
1015 
1016 
TEST_IMPL(fs_async_sendfile)1017 TEST_IMPL(fs_async_sendfile) {
1018   int f, r;
1019   struct stat s1, s2;
1020 
1021   loop = uv_default_loop();
1022 
1023   /* Setup. */
1024   unlink("test_file");
1025   unlink("test_file2");
1026 
1027   f = open("test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR);
1028   ASSERT(f != -1);
1029 
1030   r = write(f, "begin\n", 6);
1031   ASSERT(r == 6);
1032 
1033   r = lseek(f, 65536, SEEK_CUR);
1034   ASSERT(r == 65542);
1035 
1036   r = write(f, "end\n", 4);
1037   ASSERT(r != -1);
1038 
1039   r = close(f);
1040   ASSERT(r == 0);
1041 
1042   /* Test starts here. */
1043   r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR, 0, NULL);
1044   ASSERT(r >= 0);
1045   ASSERT(open_req1.result >= 0);
1046   uv_fs_req_cleanup(&open_req1);
1047 
1048   r = uv_fs_open(NULL, &open_req2, "test_file2", O_WRONLY | O_CREAT,
1049       S_IWUSR | S_IRUSR, NULL);
1050   ASSERT(r >= 0);
1051   ASSERT(open_req2.result >= 0);
1052   uv_fs_req_cleanup(&open_req2);
1053 
1054   r = uv_fs_sendfile(loop, &sendfile_req, open_req2.result, open_req1.result,
1055       0, 131072, sendfile_cb);
1056   ASSERT(r == 0);
1057   uv_run(loop, UV_RUN_DEFAULT);
1058 
1059   ASSERT(sendfile_cb_count == 1);
1060 
1061   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
1062   ASSERT(r == 0);
1063   uv_fs_req_cleanup(&close_req);
1064   r = uv_fs_close(NULL, &close_req, open_req2.result, NULL);
1065   ASSERT(r == 0);
1066   uv_fs_req_cleanup(&close_req);
1067 
1068   stat("test_file", &s1);
1069   stat("test_file2", &s2);
1070   ASSERT(65546 == s2.st_size && s1.st_size == s2.st_size);
1071 
1072   /* Cleanup. */
1073   unlink("test_file");
1074   unlink("test_file2");
1075 
1076   MAKE_VALGRIND_HAPPY();
1077   return 0;
1078 }
1079 
1080 
TEST_IMPL(fs_mkdtemp)1081 TEST_IMPL(fs_mkdtemp) {
1082   int r;
1083   const char* path_template = "test_dir_XXXXXX";
1084 
1085   loop = uv_default_loop();
1086 
1087   r = uv_fs_mkdtemp(loop, &mkdtemp_req1, path_template, mkdtemp_cb);
1088   ASSERT(r == 0);
1089 
1090   uv_run(loop, UV_RUN_DEFAULT);
1091   ASSERT(mkdtemp_cb_count == 1);
1092 
1093   /* sync mkdtemp */
1094   r = uv_fs_mkdtemp(NULL, &mkdtemp_req2, path_template, NULL);
1095   ASSERT(r == 0);
1096   check_mkdtemp_result(&mkdtemp_req2);
1097 
1098   /* mkdtemp return different values on subsequent calls */
1099   ASSERT(strcmp(mkdtemp_req1.path, mkdtemp_req2.path) != 0);
1100 
1101   /* Cleanup */
1102   rmdir(mkdtemp_req1.path);
1103   rmdir(mkdtemp_req2.path);
1104   uv_fs_req_cleanup(&mkdtemp_req1);
1105   uv_fs_req_cleanup(&mkdtemp_req2);
1106 
1107   MAKE_VALGRIND_HAPPY();
1108   return 0;
1109 }
1110 
1111 
TEST_IMPL(fs_fstat)1112 TEST_IMPL(fs_fstat) {
1113   int r;
1114   uv_fs_t req;
1115   uv_file file;
1116   uv_stat_t* s;
1117 #ifndef _WIN32
1118   struct stat t;
1119 #endif
1120 
1121   /* Setup. */
1122   unlink("test_file");
1123 
1124   loop = uv_default_loop();
1125 
1126   r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT,
1127       S_IWUSR | S_IRUSR, NULL);
1128   ASSERT(r >= 0);
1129   ASSERT(req.result >= 0);
1130   file = req.result;
1131   uv_fs_req_cleanup(&req);
1132 
1133   iov = uv_buf_init(test_buf, sizeof(test_buf));
1134   r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL);
1135   ASSERT(r == sizeof(test_buf));
1136   ASSERT(req.result == sizeof(test_buf));
1137   uv_fs_req_cleanup(&req);
1138 
1139   r = uv_fs_fstat(NULL, &req, file, NULL);
1140   ASSERT(r == 0);
1141   ASSERT(req.result == 0);
1142   s = req.ptr;
1143   ASSERT(s->st_size == sizeof(test_buf));
1144 
1145 #ifndef _WIN32
1146   r = fstat(file, &t);
1147   ASSERT(r == 0);
1148 
1149   ASSERT(s->st_dev == (uint64_t) t.st_dev);
1150   ASSERT(s->st_mode == (uint64_t) t.st_mode);
1151   ASSERT(s->st_nlink == (uint64_t) t.st_nlink);
1152   ASSERT(s->st_uid == (uint64_t) t.st_uid);
1153   ASSERT(s->st_gid == (uint64_t) t.st_gid);
1154   ASSERT(s->st_rdev == (uint64_t) t.st_rdev);
1155   ASSERT(s->st_ino == (uint64_t) t.st_ino);
1156   ASSERT(s->st_size == (uint64_t) t.st_size);
1157   ASSERT(s->st_blksize == (uint64_t) t.st_blksize);
1158   ASSERT(s->st_blocks == (uint64_t) t.st_blocks);
1159 #if defined(__APPLE__)
1160   ASSERT(s->st_atim.tv_sec == t.st_atimespec.tv_sec);
1161   ASSERT(s->st_atim.tv_nsec == t.st_atimespec.tv_nsec);
1162   ASSERT(s->st_mtim.tv_sec == t.st_mtimespec.tv_sec);
1163   ASSERT(s->st_mtim.tv_nsec == t.st_mtimespec.tv_nsec);
1164   ASSERT(s->st_ctim.tv_sec == t.st_ctimespec.tv_sec);
1165   ASSERT(s->st_ctim.tv_nsec == t.st_ctimespec.tv_nsec);
1166   ASSERT(s->st_birthtim.tv_sec == t.st_birthtimespec.tv_sec);
1167   ASSERT(s->st_birthtim.tv_nsec == t.st_birthtimespec.tv_nsec);
1168   ASSERT(s->st_flags == t.st_flags);
1169   ASSERT(s->st_gen == t.st_gen);
1170 #elif defined(_AIX)
1171   ASSERT(s->st_atim.tv_sec == t.st_atime);
1172   ASSERT(s->st_atim.tv_nsec == 0);
1173   ASSERT(s->st_mtim.tv_sec == t.st_mtime);
1174   ASSERT(s->st_mtim.tv_nsec == 0);
1175   ASSERT(s->st_ctim.tv_sec == t.st_ctime);
1176   ASSERT(s->st_ctim.tv_nsec == 0);
1177 #elif defined(__ANDROID__)
1178   ASSERT(s->st_atim.tv_sec == t.st_atime);
1179   ASSERT(s->st_atim.tv_nsec == t.st_atimensec);
1180   ASSERT(s->st_mtim.tv_sec == t.st_mtime);
1181   ASSERT(s->st_mtim.tv_nsec == t.st_mtimensec);
1182   ASSERT(s->st_ctim.tv_sec == t.st_ctime);
1183   ASSERT(s->st_ctim.tv_nsec == t.st_ctimensec);
1184 #elif defined(__sun)           || \
1185       defined(__DragonFly__)   || \
1186       defined(__FreeBSD__)     || \
1187       defined(__OpenBSD__)     || \
1188       defined(__NetBSD__)      || \
1189       defined(_GNU_SOURCE)     || \
1190       defined(_BSD_SOURCE)     || \
1191       defined(_SVID_SOURCE)    || \
1192       defined(_XOPEN_SOURCE)   || \
1193       defined(_DEFAULT_SOURCE)
1194   ASSERT(s->st_atim.tv_sec == t.st_atim.tv_sec);
1195   ASSERT(s->st_atim.tv_nsec == t.st_atim.tv_nsec);
1196   ASSERT(s->st_mtim.tv_sec == t.st_mtim.tv_sec);
1197   ASSERT(s->st_mtim.tv_nsec == t.st_mtim.tv_nsec);
1198   ASSERT(s->st_ctim.tv_sec == t.st_ctim.tv_sec);
1199   ASSERT(s->st_ctim.tv_nsec == t.st_ctim.tv_nsec);
1200 # if defined(__FreeBSD__)    || \
1201      defined(__NetBSD__)
1202   ASSERT(s->st_birthtim.tv_sec == t.st_birthtim.tv_sec);
1203   ASSERT(s->st_birthtim.tv_nsec == t.st_birthtim.tv_nsec);
1204   ASSERT(s->st_flags == t.st_flags);
1205   ASSERT(s->st_gen == t.st_gen);
1206 # endif
1207 #else
1208   ASSERT(s->st_atim.tv_sec == t.st_atime);
1209   ASSERT(s->st_atim.tv_nsec == 0);
1210   ASSERT(s->st_mtim.tv_sec == t.st_mtime);
1211   ASSERT(s->st_mtim.tv_nsec == 0);
1212   ASSERT(s->st_ctim.tv_sec == t.st_ctime);
1213   ASSERT(s->st_ctim.tv_nsec == 0);
1214 #endif
1215 #endif
1216 
1217   uv_fs_req_cleanup(&req);
1218 
1219   /* Now do the uv_fs_fstat call asynchronously */
1220   r = uv_fs_fstat(loop, &req, file, fstat_cb);
1221   ASSERT(r == 0);
1222   uv_run(loop, UV_RUN_DEFAULT);
1223   ASSERT(fstat_cb_count == 1);
1224 
1225 
1226   r = uv_fs_close(NULL, &req, file, NULL);
1227   ASSERT(r == 0);
1228   ASSERT(req.result == 0);
1229   uv_fs_req_cleanup(&req);
1230 
1231   /*
1232    * Run the loop just to check we don't have make any extraneous uv_ref()
1233    * calls. This should drop out immediately.
1234    */
1235   uv_run(loop, UV_RUN_DEFAULT);
1236 
1237   /* Cleanup. */
1238   unlink("test_file");
1239 
1240   MAKE_VALGRIND_HAPPY();
1241   return 0;
1242 }
1243 
1244 
TEST_IMPL(fs_access)1245 TEST_IMPL(fs_access) {
1246   int r;
1247   uv_fs_t req;
1248   uv_file file;
1249 
1250   /* Setup. */
1251   unlink("test_file");
1252   rmdir("test_dir");
1253 
1254   loop = uv_default_loop();
1255 
1256   /* File should not exist */
1257   r = uv_fs_access(NULL, &req, "test_file", F_OK, NULL);
1258   ASSERT(r < 0);
1259   ASSERT(req.result < 0);
1260   uv_fs_req_cleanup(&req);
1261 
1262   /* File should not exist */
1263   r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb);
1264   ASSERT(r == 0);
1265   uv_run(loop, UV_RUN_DEFAULT);
1266   ASSERT(access_cb_count == 1);
1267   access_cb_count = 0; /* reset for the next test */
1268 
1269   /* Create file */
1270   r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT,
1271                  S_IWUSR | S_IRUSR, NULL);
1272   ASSERT(r >= 0);
1273   ASSERT(req.result >= 0);
1274   file = req.result;
1275   uv_fs_req_cleanup(&req);
1276 
1277   /* File should exist */
1278   r = uv_fs_access(NULL, &req, "test_file", F_OK, NULL);
1279   ASSERT(r == 0);
1280   ASSERT(req.result == 0);
1281   uv_fs_req_cleanup(&req);
1282 
1283   /* File should exist */
1284   r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb);
1285   ASSERT(r == 0);
1286   uv_run(loop, UV_RUN_DEFAULT);
1287   ASSERT(access_cb_count == 1);
1288   access_cb_count = 0; /* reset for the next test */
1289 
1290   /* Close file */
1291   r = uv_fs_close(NULL, &req, file, NULL);
1292   ASSERT(r == 0);
1293   ASSERT(req.result == 0);
1294   uv_fs_req_cleanup(&req);
1295 
1296   /* Directory access */
1297   r = uv_fs_mkdir(NULL, &req, "test_dir", 0777, NULL);
1298   ASSERT(r == 0);
1299   uv_fs_req_cleanup(&req);
1300 
1301   r = uv_fs_access(NULL, &req, "test_dir", W_OK, NULL);
1302   ASSERT(r == 0);
1303   ASSERT(req.result == 0);
1304   uv_fs_req_cleanup(&req);
1305 
1306   /*
1307    * Run the loop just to check we don't have make any extraneous uv_ref()
1308    * calls. This should drop out immediately.
1309    */
1310   uv_run(loop, UV_RUN_DEFAULT);
1311 
1312   /* Cleanup. */
1313   unlink("test_file");
1314   rmdir("test_dir");
1315 
1316   MAKE_VALGRIND_HAPPY();
1317   return 0;
1318 }
1319 
1320 
TEST_IMPL(fs_chmod)1321 TEST_IMPL(fs_chmod) {
1322   int r;
1323   uv_fs_t req;
1324   uv_file file;
1325 
1326   /* Setup. */
1327   unlink("test_file");
1328 
1329   loop = uv_default_loop();
1330 
1331   r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT,
1332       S_IWUSR | S_IRUSR, NULL);
1333   ASSERT(r >= 0);
1334   ASSERT(req.result >= 0);
1335   file = req.result;
1336   uv_fs_req_cleanup(&req);
1337 
1338   iov = uv_buf_init(test_buf, sizeof(test_buf));
1339   r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL);
1340   ASSERT(r == sizeof(test_buf));
1341   ASSERT(req.result == sizeof(test_buf));
1342   uv_fs_req_cleanup(&req);
1343 
1344 #ifndef _WIN32
1345   /* Make the file write-only */
1346   r = uv_fs_chmod(NULL, &req, "test_file", 0200, NULL);
1347   ASSERT(r == 0);
1348   ASSERT(req.result == 0);
1349   uv_fs_req_cleanup(&req);
1350 
1351   check_permission("test_file", 0200);
1352 #endif
1353 
1354   /* Make the file read-only */
1355   r = uv_fs_chmod(NULL, &req, "test_file", 0400, NULL);
1356   ASSERT(r == 0);
1357   ASSERT(req.result == 0);
1358   uv_fs_req_cleanup(&req);
1359 
1360   check_permission("test_file", 0400);
1361 
1362   /* Make the file read+write with sync uv_fs_fchmod */
1363   r = uv_fs_fchmod(NULL, &req, file, 0600, NULL);
1364   ASSERT(r == 0);
1365   ASSERT(req.result == 0);
1366   uv_fs_req_cleanup(&req);
1367 
1368   check_permission("test_file", 0600);
1369 
1370 #ifndef _WIN32
1371   /* async chmod */
1372   {
1373     static int mode = 0200;
1374     req.data = &mode;
1375   }
1376   r = uv_fs_chmod(loop, &req, "test_file", 0200, chmod_cb);
1377   ASSERT(r == 0);
1378   uv_run(loop, UV_RUN_DEFAULT);
1379   ASSERT(chmod_cb_count == 1);
1380   chmod_cb_count = 0; /* reset for the next test */
1381 #endif
1382 
1383   /* async chmod */
1384   {
1385     static int mode = 0400;
1386     req.data = &mode;
1387   }
1388   r = uv_fs_chmod(loop, &req, "test_file", 0400, chmod_cb);
1389   ASSERT(r == 0);
1390   uv_run(loop, UV_RUN_DEFAULT);
1391   ASSERT(chmod_cb_count == 1);
1392 
1393   /* async fchmod */
1394   {
1395     static int mode = 0600;
1396     req.data = &mode;
1397   }
1398   r = uv_fs_fchmod(loop, &req, file, 0600, fchmod_cb);
1399   ASSERT(r == 0);
1400   uv_run(loop, UV_RUN_DEFAULT);
1401   ASSERT(fchmod_cb_count == 1);
1402 
1403   close(file);
1404 
1405   /*
1406    * Run the loop just to check we don't have make any extraneous uv_ref()
1407    * calls. This should drop out immediately.
1408    */
1409   uv_run(loop, UV_RUN_DEFAULT);
1410 
1411   /* Cleanup. */
1412   unlink("test_file");
1413 
1414   MAKE_VALGRIND_HAPPY();
1415   return 0;
1416 }
1417 
1418 
TEST_IMPL(fs_unlink_readonly)1419 TEST_IMPL(fs_unlink_readonly) {
1420   int r;
1421   uv_fs_t req;
1422   uv_file file;
1423 
1424   /* Setup. */
1425   unlink("test_file");
1426 
1427   loop = uv_default_loop();
1428 
1429   r = uv_fs_open(NULL,
1430                  &req,
1431                  "test_file",
1432                  O_RDWR | O_CREAT,
1433                  S_IWUSR | S_IRUSR,
1434                  NULL);
1435   ASSERT(r >= 0);
1436   ASSERT(req.result >= 0);
1437   file = req.result;
1438   uv_fs_req_cleanup(&req);
1439 
1440   iov = uv_buf_init(test_buf, sizeof(test_buf));
1441   r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL);
1442   ASSERT(r == sizeof(test_buf));
1443   ASSERT(req.result == sizeof(test_buf));
1444   uv_fs_req_cleanup(&req);
1445 
1446   close(file);
1447 
1448   /* Make the file read-only */
1449   r = uv_fs_chmod(NULL, &req, "test_file", 0400, NULL);
1450   ASSERT(r == 0);
1451   ASSERT(req.result == 0);
1452   uv_fs_req_cleanup(&req);
1453 
1454   check_permission("test_file", 0400);
1455 
1456   /* Try to unlink the file */
1457   r = uv_fs_unlink(NULL, &req, "test_file", NULL);
1458   ASSERT(r == 0);
1459   ASSERT(req.result == 0);
1460   uv_fs_req_cleanup(&req);
1461 
1462   /*
1463   * Run the loop just to check we don't have make any extraneous uv_ref()
1464   * calls. This should drop out immediately.
1465   */
1466   uv_run(loop, UV_RUN_DEFAULT);
1467 
1468   /* Cleanup. */
1469   uv_fs_chmod(NULL, &req, "test_file", 0600, NULL);
1470   uv_fs_req_cleanup(&req);
1471   unlink("test_file");
1472 
1473   MAKE_VALGRIND_HAPPY();
1474   return 0;
1475 }
1476 
1477 
TEST_IMPL(fs_chown)1478 TEST_IMPL(fs_chown) {
1479   int r;
1480   uv_fs_t req;
1481   uv_file file;
1482 
1483   /* Setup. */
1484   unlink("test_file");
1485 
1486   loop = uv_default_loop();
1487 
1488   r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT,
1489       S_IWUSR | S_IRUSR, NULL);
1490   ASSERT(r >= 0);
1491   ASSERT(req.result >= 0);
1492   file = req.result;
1493   uv_fs_req_cleanup(&req);
1494 
1495   /* sync chown */
1496   r = uv_fs_chown(NULL, &req, "test_file", -1, -1, NULL);
1497   ASSERT(r == 0);
1498   ASSERT(req.result == 0);
1499   uv_fs_req_cleanup(&req);
1500 
1501   /* sync fchown */
1502   r = uv_fs_fchown(NULL, &req, file, -1, -1, NULL);
1503   ASSERT(r == 0);
1504   ASSERT(req.result == 0);
1505   uv_fs_req_cleanup(&req);
1506 
1507   /* async chown */
1508   r = uv_fs_chown(loop, &req, "test_file", -1, -1, chown_cb);
1509   ASSERT(r == 0);
1510   uv_run(loop, UV_RUN_DEFAULT);
1511   ASSERT(chown_cb_count == 1);
1512 
1513 #ifndef __MVS__
1514   /* chown to root (fail) */
1515   chown_cb_count = 0;
1516   r = uv_fs_chown(loop, &req, "test_file", 0, 0, chown_root_cb);
1517   ASSERT(r == 0);
1518   uv_run(loop, UV_RUN_DEFAULT);
1519   ASSERT(chown_cb_count == 1);
1520 #endif
1521 
1522   /* async fchown */
1523   r = uv_fs_fchown(loop, &req, file, -1, -1, fchown_cb);
1524   ASSERT(r == 0);
1525   uv_run(loop, UV_RUN_DEFAULT);
1526   ASSERT(fchown_cb_count == 1);
1527 
1528   close(file);
1529 
1530   /*
1531    * Run the loop just to check we don't have make any extraneous uv_ref()
1532    * calls. This should drop out immediately.
1533    */
1534   uv_run(loop, UV_RUN_DEFAULT);
1535 
1536   /* Cleanup. */
1537   unlink("test_file");
1538 
1539   MAKE_VALGRIND_HAPPY();
1540   return 0;
1541 }
1542 
1543 
TEST_IMPL(fs_link)1544 TEST_IMPL(fs_link) {
1545   int r;
1546   uv_fs_t req;
1547   uv_file file;
1548   uv_file link;
1549 
1550   /* Setup. */
1551   unlink("test_file");
1552   unlink("test_file_link");
1553   unlink("test_file_link2");
1554 
1555   loop = uv_default_loop();
1556 
1557   r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT,
1558       S_IWUSR | S_IRUSR, NULL);
1559   ASSERT(r >= 0);
1560   ASSERT(req.result >= 0);
1561   file = req.result;
1562   uv_fs_req_cleanup(&req);
1563 
1564   iov = uv_buf_init(test_buf, sizeof(test_buf));
1565   r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL);
1566   ASSERT(r == sizeof(test_buf));
1567   ASSERT(req.result == sizeof(test_buf));
1568   uv_fs_req_cleanup(&req);
1569 
1570   close(file);
1571 
1572   /* sync link */
1573   r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL);
1574   ASSERT(r == 0);
1575   ASSERT(req.result == 0);
1576   uv_fs_req_cleanup(&req);
1577 
1578   r = uv_fs_open(NULL, &req, "test_file_link", O_RDWR, 0, NULL);
1579   ASSERT(r >= 0);
1580   ASSERT(req.result >= 0);
1581   link = req.result;
1582   uv_fs_req_cleanup(&req);
1583 
1584   memset(buf, 0, sizeof(buf));
1585   iov = uv_buf_init(buf, sizeof(buf));
1586   r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL);
1587   ASSERT(r >= 0);
1588   ASSERT(req.result >= 0);
1589   ASSERT(strcmp(buf, test_buf) == 0);
1590 
1591   close(link);
1592 
1593   /* async link */
1594   r = uv_fs_link(loop, &req, "test_file", "test_file_link2", link_cb);
1595   ASSERT(r == 0);
1596   uv_run(loop, UV_RUN_DEFAULT);
1597   ASSERT(link_cb_count == 1);
1598 
1599   r = uv_fs_open(NULL, &req, "test_file_link2", O_RDWR, 0, NULL);
1600   ASSERT(r >= 0);
1601   ASSERT(req.result >= 0);
1602   link = req.result;
1603   uv_fs_req_cleanup(&req);
1604 
1605   memset(buf, 0, sizeof(buf));
1606   iov = uv_buf_init(buf, sizeof(buf));
1607   r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL);
1608   ASSERT(r >= 0);
1609   ASSERT(req.result >= 0);
1610   ASSERT(strcmp(buf, test_buf) == 0);
1611 
1612   close(link);
1613 
1614   /*
1615    * Run the loop just to check we don't have make any extraneous uv_ref()
1616    * calls. This should drop out immediately.
1617    */
1618   uv_run(loop, UV_RUN_DEFAULT);
1619 
1620   /* Cleanup. */
1621   unlink("test_file");
1622   unlink("test_file_link");
1623   unlink("test_file_link2");
1624 
1625   MAKE_VALGRIND_HAPPY();
1626   return 0;
1627 }
1628 
1629 
TEST_IMPL(fs_readlink)1630 TEST_IMPL(fs_readlink) {
1631   uv_fs_t req;
1632 
1633   loop = uv_default_loop();
1634   ASSERT(0 == uv_fs_readlink(loop, &req, "no_such_file", dummy_cb));
1635   ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
1636   ASSERT(dummy_cb_count == 1);
1637   ASSERT(req.ptr == NULL);
1638   ASSERT(req.result == UV_ENOENT);
1639   uv_fs_req_cleanup(&req);
1640 
1641   ASSERT(UV_ENOENT == uv_fs_readlink(NULL, &req, "no_such_file", NULL));
1642   ASSERT(req.ptr == NULL);
1643   ASSERT(req.result == UV_ENOENT);
1644   uv_fs_req_cleanup(&req);
1645 
1646   MAKE_VALGRIND_HAPPY();
1647   return 0;
1648 }
1649 
1650 
TEST_IMPL(fs_realpath)1651 TEST_IMPL(fs_realpath) {
1652   uv_fs_t req;
1653 
1654   loop = uv_default_loop();
1655   ASSERT(0 == uv_fs_realpath(loop, &req, "no_such_file", dummy_cb));
1656   ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
1657   ASSERT(dummy_cb_count == 1);
1658   ASSERT(req.ptr == NULL);
1659 #ifdef _WIN32
1660   /*
1661    * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
1662    */
1663   if (req.result == UV_ENOSYS) {
1664     uv_fs_req_cleanup(&req);
1665     RETURN_SKIP("realpath is not supported on Windows XP");
1666   }
1667 #endif
1668   ASSERT(req.result == UV_ENOENT);
1669   uv_fs_req_cleanup(&req);
1670 
1671   ASSERT(UV_ENOENT == uv_fs_realpath(NULL, &req, "no_such_file", NULL));
1672   ASSERT(req.ptr == NULL);
1673   ASSERT(req.result == UV_ENOENT);
1674   uv_fs_req_cleanup(&req);
1675 
1676   MAKE_VALGRIND_HAPPY();
1677   return 0;
1678 }
1679 
1680 
TEST_IMPL(fs_symlink)1681 TEST_IMPL(fs_symlink) {
1682   int r;
1683   uv_fs_t req;
1684   uv_file file;
1685   uv_file link;
1686   char test_file_abs_buf[PATHMAX];
1687   size_t test_file_abs_size;
1688 
1689   /* Setup. */
1690   unlink("test_file");
1691   unlink("test_file_symlink");
1692   unlink("test_file_symlink2");
1693   unlink("test_file_symlink_symlink");
1694   unlink("test_file_symlink2_symlink");
1695   test_file_abs_size = sizeof(test_file_abs_buf);
1696 #ifdef _WIN32
1697   uv_cwd(test_file_abs_buf, &test_file_abs_size);
1698   strcat(test_file_abs_buf, "\\test_file");
1699 #else
1700   uv_cwd(test_file_abs_buf, &test_file_abs_size);
1701   strcat(test_file_abs_buf, "/test_file");
1702 #endif
1703 
1704   loop = uv_default_loop();
1705 
1706   r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT,
1707       S_IWUSR | S_IRUSR, NULL);
1708   ASSERT(r >= 0);
1709   ASSERT(req.result >= 0);
1710   file = req.result;
1711   uv_fs_req_cleanup(&req);
1712 
1713   iov = uv_buf_init(test_buf, sizeof(test_buf));
1714   r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL);
1715   ASSERT(r == sizeof(test_buf));
1716   ASSERT(req.result == sizeof(test_buf));
1717   uv_fs_req_cleanup(&req);
1718 
1719   close(file);
1720 
1721   /* sync symlink */
1722   r = uv_fs_symlink(NULL, &req, "test_file", "test_file_symlink", 0, NULL);
1723 #ifdef _WIN32
1724   if (r < 0) {
1725     if (r == UV_ENOTSUP) {
1726       /*
1727        * Windows doesn't support symlinks on older versions.
1728        * We just pass the test and bail out early if we get ENOTSUP.
1729        */
1730       return 0;
1731     } else if (r == UV_EPERM) {
1732       /*
1733        * Creating a symlink is only allowed when running elevated.
1734        * We pass the test and bail out early if we get UV_EPERM.
1735        */
1736       return 0;
1737     }
1738   }
1739 #endif
1740   ASSERT(r == 0);
1741   ASSERT(req.result == 0);
1742   uv_fs_req_cleanup(&req);
1743 
1744   r = uv_fs_open(NULL, &req, "test_file_symlink", O_RDWR, 0, NULL);
1745   ASSERT(r >= 0);
1746   ASSERT(req.result >= 0);
1747   link = req.result;
1748   uv_fs_req_cleanup(&req);
1749 
1750   memset(buf, 0, sizeof(buf));
1751   iov = uv_buf_init(buf, sizeof(buf));
1752   r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL);
1753   ASSERT(r >= 0);
1754   ASSERT(req.result >= 0);
1755   ASSERT(strcmp(buf, test_buf) == 0);
1756 
1757   close(link);
1758 
1759   r = uv_fs_symlink(NULL,
1760                     &req,
1761                     "test_file_symlink",
1762                     "test_file_symlink_symlink",
1763                     0,
1764                     NULL);
1765   ASSERT(r == 0);
1766   uv_fs_req_cleanup(&req);
1767 
1768 #if defined(__MSYS__)
1769   RETURN_SKIP("symlink reading is not supported on MSYS2");
1770 #endif
1771 
1772   r = uv_fs_readlink(NULL, &req, "test_file_symlink_symlink", NULL);
1773   ASSERT(r == 0);
1774   ASSERT(strcmp(req.ptr, "test_file_symlink") == 0);
1775   uv_fs_req_cleanup(&req);
1776 
1777   r = uv_fs_realpath(NULL, &req, "test_file_symlink_symlink", NULL);
1778 #ifdef _WIN32
1779   /*
1780    * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
1781    */
1782   if (r == UV_ENOSYS) {
1783     uv_fs_req_cleanup(&req);
1784     RETURN_SKIP("realpath is not supported on Windows XP");
1785   }
1786 #endif
1787   ASSERT(r == 0);
1788 #ifdef _WIN32
1789   ASSERT(stricmp(req.ptr, test_file_abs_buf) == 0);
1790 #else
1791   ASSERT(strcmp(req.ptr, test_file_abs_buf) == 0);
1792 #endif
1793   uv_fs_req_cleanup(&req);
1794 
1795   /* async link */
1796   r = uv_fs_symlink(loop,
1797                     &req,
1798                     "test_file",
1799                     "test_file_symlink2",
1800                     0,
1801                     symlink_cb);
1802   ASSERT(r == 0);
1803   uv_run(loop, UV_RUN_DEFAULT);
1804   ASSERT(symlink_cb_count == 1);
1805 
1806   r = uv_fs_open(NULL, &req, "test_file_symlink2", O_RDWR, 0, NULL);
1807   ASSERT(r >= 0);
1808   ASSERT(req.result >= 0);
1809   link = req.result;
1810   uv_fs_req_cleanup(&req);
1811 
1812   memset(buf, 0, sizeof(buf));
1813   iov = uv_buf_init(buf, sizeof(buf));
1814   r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL);
1815   ASSERT(r >= 0);
1816   ASSERT(req.result >= 0);
1817   ASSERT(strcmp(buf, test_buf) == 0);
1818 
1819   close(link);
1820 
1821   r = uv_fs_symlink(NULL,
1822                     &req,
1823                     "test_file_symlink2",
1824                     "test_file_symlink2_symlink",
1825                     0,
1826                     NULL);
1827   ASSERT(r == 0);
1828   uv_fs_req_cleanup(&req);
1829 
1830   r = uv_fs_readlink(loop, &req, "test_file_symlink2_symlink", readlink_cb);
1831   ASSERT(r == 0);
1832   uv_run(loop, UV_RUN_DEFAULT);
1833   ASSERT(readlink_cb_count == 1);
1834 
1835   r = uv_fs_realpath(loop, &req, "test_file", realpath_cb);
1836 #ifdef _WIN32
1837   /*
1838    * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
1839    */
1840   if (r == UV_ENOSYS) {
1841     uv_fs_req_cleanup(&req);
1842     RETURN_SKIP("realpath is not supported on Windows XP");
1843   }
1844 #endif
1845   ASSERT(r == 0);
1846   uv_run(loop, UV_RUN_DEFAULT);
1847   ASSERT(realpath_cb_count == 1);
1848 
1849   /*
1850    * Run the loop just to check we don't have make any extraneous uv_ref()
1851    * calls. This should drop out immediately.
1852    */
1853   uv_run(loop, UV_RUN_DEFAULT);
1854 
1855   /* Cleanup. */
1856   unlink("test_file");
1857   unlink("test_file_symlink");
1858   unlink("test_file_symlink_symlink");
1859   unlink("test_file_symlink2");
1860   unlink("test_file_symlink2_symlink");
1861 
1862   MAKE_VALGRIND_HAPPY();
1863   return 0;
1864 }
1865 
1866 
test_symlink_dir_impl(int type)1867 int test_symlink_dir_impl(int type) {
1868   uv_fs_t req;
1869   int r;
1870   char* test_dir;
1871   uv_dirent_t dent;
1872   static char test_dir_abs_buf[PATHMAX];
1873   size_t test_dir_abs_size;
1874 
1875   /* set-up */
1876   unlink("test_dir/file1");
1877   unlink("test_dir/file2");
1878   rmdir("test_dir");
1879   rmdir("test_dir_symlink");
1880   test_dir_abs_size = sizeof(test_dir_abs_buf);
1881 
1882   loop = uv_default_loop();
1883 
1884   uv_fs_mkdir(NULL, &req, "test_dir", 0777, NULL);
1885   uv_fs_req_cleanup(&req);
1886 
1887 #ifdef _WIN32
1888   strcpy(test_dir_abs_buf, "\\\\?\\");
1889   uv_cwd(test_dir_abs_buf + 4, &test_dir_abs_size);
1890   test_dir_abs_size += 4;
1891   strcat(test_dir_abs_buf, "\\test_dir\\");
1892   test_dir_abs_size += strlen("\\test_dir\\");
1893   test_dir = test_dir_abs_buf;
1894 #else
1895   uv_cwd(test_dir_abs_buf, &test_dir_abs_size);
1896   strcat(test_dir_abs_buf, "/test_dir");
1897   test_dir_abs_size += strlen("/test_dir");
1898   test_dir = "test_dir";
1899 #endif
1900 
1901   r = uv_fs_symlink(NULL, &req, test_dir, "test_dir_symlink", type, NULL);
1902   if (type == UV_FS_SYMLINK_DIR && (r == UV_ENOTSUP || r == UV_EPERM)) {
1903     uv_fs_req_cleanup(&req);
1904     RETURN_SKIP("this version of Windows doesn't support unprivileged "
1905                 "creation of directory symlinks");
1906   }
1907   fprintf(stderr, "r == %i\n", r);
1908   ASSERT(r == 0);
1909   ASSERT(req.result == 0);
1910   uv_fs_req_cleanup(&req);
1911 
1912   r = uv_fs_stat(NULL, &req, "test_dir_symlink", NULL);
1913   ASSERT(r == 0);
1914   ASSERT(((uv_stat_t*)req.ptr)->st_mode & S_IFDIR);
1915   uv_fs_req_cleanup(&req);
1916 
1917   r = uv_fs_lstat(NULL, &req, "test_dir_symlink", NULL);
1918   ASSERT(r == 0);
1919 #if defined(__MSYS__)
1920   RETURN_SKIP("symlink reading is not supported on MSYS2");
1921 #endif
1922   ASSERT(((uv_stat_t*)req.ptr)->st_mode & S_IFLNK);
1923 #ifdef _WIN32
1924   ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir + 4));
1925 #else
1926   ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir));
1927 #endif
1928   uv_fs_req_cleanup(&req);
1929 
1930   r = uv_fs_readlink(NULL, &req, "test_dir_symlink", NULL);
1931   ASSERT(r == 0);
1932 #ifdef _WIN32
1933   ASSERT(strcmp(req.ptr, test_dir + 4) == 0);
1934 #else
1935   ASSERT(strcmp(req.ptr, test_dir) == 0);
1936 #endif
1937   uv_fs_req_cleanup(&req);
1938 
1939   r = uv_fs_realpath(NULL, &req, "test_dir_symlink", NULL);
1940 #ifdef _WIN32
1941   /*
1942    * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
1943    */
1944   if (r == UV_ENOSYS) {
1945     uv_fs_req_cleanup(&req);
1946     RETURN_SKIP("realpath is not supported on Windows XP");
1947   }
1948 #endif
1949   ASSERT(r == 0);
1950 #ifdef _WIN32
1951   ASSERT(strlen(req.ptr) == test_dir_abs_size - 5);
1952   ASSERT(strnicmp(req.ptr, test_dir + 4, test_dir_abs_size - 5) == 0);
1953 #else
1954   ASSERT(strcmp(req.ptr, test_dir_abs_buf) == 0);
1955 #endif
1956   uv_fs_req_cleanup(&req);
1957 
1958   r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT,
1959       S_IWUSR | S_IRUSR, NULL);
1960   ASSERT(r >= 0);
1961   uv_fs_req_cleanup(&open_req1);
1962   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
1963   ASSERT(r == 0);
1964   uv_fs_req_cleanup(&close_req);
1965 
1966   r = uv_fs_open(NULL, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT,
1967       S_IWUSR | S_IRUSR, NULL);
1968   ASSERT(r >= 0);
1969   uv_fs_req_cleanup(&open_req1);
1970   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
1971   ASSERT(r == 0);
1972   uv_fs_req_cleanup(&close_req);
1973 
1974   r = uv_fs_scandir(NULL, &scandir_req, "test_dir_symlink", 0, NULL);
1975   ASSERT(r == 2);
1976   ASSERT(scandir_req.result == 2);
1977   ASSERT(scandir_req.ptr);
1978   while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) {
1979     ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0);
1980     assert_is_file_type(dent);
1981   }
1982   uv_fs_req_cleanup(&scandir_req);
1983   ASSERT(!scandir_req.ptr);
1984 
1985   /* unlink will remove the directory symlink */
1986   r = uv_fs_unlink(NULL, &req, "test_dir_symlink", NULL);
1987   ASSERT(r == 0);
1988   uv_fs_req_cleanup(&req);
1989 
1990   r = uv_fs_scandir(NULL, &scandir_req, "test_dir_symlink", 0, NULL);
1991   ASSERT(r == UV_ENOENT);
1992   uv_fs_req_cleanup(&scandir_req);
1993 
1994   r = uv_fs_scandir(NULL, &scandir_req, "test_dir", 0, NULL);
1995   ASSERT(r == 2);
1996   ASSERT(scandir_req.result == 2);
1997   ASSERT(scandir_req.ptr);
1998   while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) {
1999     ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0);
2000     assert_is_file_type(dent);
2001   }
2002   uv_fs_req_cleanup(&scandir_req);
2003   ASSERT(!scandir_req.ptr);
2004 
2005   /* clean-up */
2006   unlink("test_dir/file1");
2007   unlink("test_dir/file2");
2008   rmdir("test_dir");
2009   rmdir("test_dir_symlink");
2010 
2011   MAKE_VALGRIND_HAPPY();
2012   return 0;
2013 }
2014 
TEST_IMPL(fs_symlink_dir)2015 TEST_IMPL(fs_symlink_dir) {
2016   return test_symlink_dir_impl(UV_FS_SYMLINK_DIR);
2017 }
2018 
TEST_IMPL(fs_symlink_junction)2019 TEST_IMPL(fs_symlink_junction) {
2020   return test_symlink_dir_impl(UV_FS_SYMLINK_JUNCTION);
2021 }
2022 
2023 #ifdef _WIN32
TEST_IMPL(fs_non_symlink_reparse_point)2024 TEST_IMPL(fs_non_symlink_reparse_point) {
2025   uv_fs_t req;
2026   int r;
2027   HANDLE file_handle;
2028   REPARSE_GUID_DATA_BUFFER reparse_buffer;
2029   DWORD bytes_returned;
2030   uv_dirent_t dent;
2031 
2032   /* set-up */
2033   unlink("test_dir/test_file");
2034   rmdir("test_dir");
2035 
2036   loop = uv_default_loop();
2037 
2038   uv_fs_mkdir(NULL, &req, "test_dir", 0777, NULL);
2039   uv_fs_req_cleanup(&req);
2040 
2041   file_handle = CreateFile("test_dir/test_file",
2042                            GENERIC_WRITE | FILE_WRITE_ATTRIBUTES,
2043                            0,
2044                            NULL,
2045                            CREATE_ALWAYS,
2046                            FILE_FLAG_OPEN_REPARSE_POINT |
2047                              FILE_FLAG_BACKUP_SEMANTICS,
2048                            NULL);
2049   ASSERT(file_handle != INVALID_HANDLE_VALUE);
2050 
2051   memset(&reparse_buffer, 0, REPARSE_GUID_DATA_BUFFER_HEADER_SIZE);
2052   reparse_buffer.ReparseTag = REPARSE_TAG;
2053   reparse_buffer.ReparseDataLength = 0;
2054   reparse_buffer.ReparseGuid = REPARSE_GUID;
2055 
2056   r = DeviceIoControl(file_handle,
2057                       FSCTL_SET_REPARSE_POINT,
2058                       &reparse_buffer,
2059                       REPARSE_GUID_DATA_BUFFER_HEADER_SIZE,
2060                       NULL,
2061                       0,
2062                       &bytes_returned,
2063                       NULL);
2064   ASSERT(r != 0);
2065 
2066   CloseHandle(file_handle);
2067 
2068   r = uv_fs_readlink(NULL, &req, "test_dir/test_file", NULL);
2069   ASSERT(r == UV_EINVAL && GetLastError() == ERROR_SYMLINK_NOT_SUPPORTED);
2070   uv_fs_req_cleanup(&req);
2071 
2072 /*
2073   Placeholder tests for exercising the behavior fixed in issue #995.
2074   To run, update the path with the IP address of a Mac with the hard drive
2075   shared via SMB as "Macintosh HD".
2076 
2077   r = uv_fs_stat(NULL, &req, "\\\\<mac_ip>\\Macintosh HD\\.DS_Store", NULL);
2078   ASSERT(r == 0);
2079   uv_fs_req_cleanup(&req);
2080 
2081   r = uv_fs_lstat(NULL, &req, "\\\\<mac_ip>\\Macintosh HD\\.DS_Store", NULL);
2082   ASSERT(r == 0);
2083   uv_fs_req_cleanup(&req);
2084 */
2085 
2086 /*
2087   uv_fs_stat and uv_fs_lstat can only work on non-symlink reparse
2088   points when a minifilter driver is registered which intercepts
2089   associated filesystem requests. Installing a driver is beyond
2090   the scope of this test.
2091 
2092   r = uv_fs_stat(NULL, &req, "test_dir/test_file", NULL);
2093   ASSERT(r == 0);
2094   uv_fs_req_cleanup(&req);
2095 
2096   r = uv_fs_lstat(NULL, &req, "test_dir/test_file", NULL);
2097   ASSERT(r == 0);
2098   uv_fs_req_cleanup(&req);
2099 */
2100 
2101   r = uv_fs_scandir(NULL, &scandir_req, "test_dir", 0, NULL);
2102   ASSERT(r == 1);
2103   ASSERT(scandir_req.result == 1);
2104   ASSERT(scandir_req.ptr);
2105   while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) {
2106     ASSERT(strcmp(dent.name, "test_file") == 0);
2107     /* uv_fs_scandir incorrectly identifies non-symlink reparse points
2108        as links because it doesn't open the file and verify the reparse
2109        point tag. The PowerShell Get-ChildItem command shares this
2110        behavior, so it's reasonable to leave it as is. */
2111     ASSERT(dent.type == UV_DIRENT_LINK);
2112   }
2113   uv_fs_req_cleanup(&scandir_req);
2114   ASSERT(!scandir_req.ptr);
2115 
2116   /* clean-up */
2117   unlink("test_dir/test_file");
2118   rmdir("test_dir");
2119 
2120   MAKE_VALGRIND_HAPPY();
2121   return 0;
2122 }
2123 #endif
2124 
2125 
TEST_IMPL(fs_utime)2126 TEST_IMPL(fs_utime) {
2127   utime_check_t checkme;
2128   const char* path = "test_file";
2129   double atime;
2130   double mtime;
2131   uv_fs_t req;
2132   int r;
2133 
2134   /* Setup. */
2135   loop = uv_default_loop();
2136   unlink(path);
2137   r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL);
2138   ASSERT(r >= 0);
2139   ASSERT(req.result >= 0);
2140   uv_fs_req_cleanup(&req);
2141   close(r);
2142 
2143   atime = mtime = 400497753; /* 1982-09-10 11:22:33 */
2144 
2145   /*
2146    * Test sub-second timestamps only on Windows (assuming NTFS). Some other
2147    * platforms support sub-second timestamps, but that support is filesystem-
2148    * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps.
2149    */
2150 #ifdef _WIN32
2151   mtime += 0.444;            /* 1982-09-10 11:22:33.444 */
2152 #endif
2153 
2154   r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL);
2155   ASSERT(r == 0);
2156   ASSERT(req.result == 0);
2157   uv_fs_req_cleanup(&req);
2158 
2159   r = uv_fs_stat(NULL, &req, path, NULL);
2160   ASSERT(r == 0);
2161   ASSERT(req.result == 0);
2162   check_utime(path, atime, mtime);
2163   uv_fs_req_cleanup(&req);
2164 
2165   atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
2166   checkme.path = path;
2167   checkme.atime = atime;
2168   checkme.mtime = mtime;
2169 
2170   /* async utime */
2171   utime_req.data = &checkme;
2172   r = uv_fs_utime(loop, &utime_req, path, atime, mtime, utime_cb);
2173   ASSERT(r == 0);
2174   uv_run(loop, UV_RUN_DEFAULT);
2175   ASSERT(utime_cb_count == 1);
2176 
2177   /* Cleanup. */
2178   unlink(path);
2179 
2180   MAKE_VALGRIND_HAPPY();
2181   return 0;
2182 }
2183 
2184 
2185 #ifdef _WIN32
TEST_IMPL(fs_stat_root)2186 TEST_IMPL(fs_stat_root) {
2187   int r;
2188 
2189   r = uv_fs_stat(NULL, &stat_req, "\\", NULL);
2190   ASSERT(r == 0);
2191 
2192   r = uv_fs_stat(NULL, &stat_req, "..\\..\\..\\..\\..\\..\\..", NULL);
2193   ASSERT(r == 0);
2194 
2195   r = uv_fs_stat(NULL, &stat_req, "..", NULL);
2196   ASSERT(r == 0);
2197 
2198   r = uv_fs_stat(NULL, &stat_req, "..\\", NULL);
2199   ASSERT(r == 0);
2200 
2201   /* stats the current directory on c: */
2202   r = uv_fs_stat(NULL, &stat_req, "c:", NULL);
2203   ASSERT(r == 0);
2204 
2205   r = uv_fs_stat(NULL, &stat_req, "c:\\", NULL);
2206   ASSERT(r == 0);
2207 
2208   r = uv_fs_stat(NULL, &stat_req, "\\\\?\\C:\\", NULL);
2209   ASSERT(r == 0);
2210 
2211   MAKE_VALGRIND_HAPPY();
2212   return 0;
2213 }
2214 #endif
2215 
2216 
TEST_IMPL(fs_futime)2217 TEST_IMPL(fs_futime) {
2218 #if defined(_AIX) && !defined(_AIX71)
2219   RETURN_SKIP("futime is not implemented for AIX versions below 7.1");
2220 #else
2221   utime_check_t checkme;
2222   const char* path = "test_file";
2223   double atime;
2224   double mtime;
2225   uv_file file;
2226   uv_fs_t req;
2227   int r;
2228 
2229   /* Setup. */
2230   loop = uv_default_loop();
2231   unlink(path);
2232   r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL);
2233   ASSERT(r >= 0);
2234   ASSERT(req.result >= 0);
2235   uv_fs_req_cleanup(&req);
2236   close(r);
2237 
2238   atime = mtime = 400497753; /* 1982-09-10 11:22:33 */
2239 
2240   /*
2241    * Test sub-second timestamps only on Windows (assuming NTFS). Some other
2242    * platforms support sub-second timestamps, but that support is filesystem-
2243    * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps.
2244    */
2245 #ifdef _WIN32
2246   mtime += 0.444;            /* 1982-09-10 11:22:33.444 */
2247 #endif
2248 
2249   r = uv_fs_open(NULL, &req, path, O_RDWR, 0, NULL);
2250   ASSERT(r >= 0);
2251   ASSERT(req.result >= 0);
2252   file = req.result; /* FIXME probably not how it's supposed to be used */
2253   uv_fs_req_cleanup(&req);
2254 
2255   r = uv_fs_futime(NULL, &req, file, atime, mtime, NULL);
2256 #if defined(__CYGWIN__) || defined(__MSYS__)
2257   ASSERT(r == UV_ENOSYS);
2258   RETURN_SKIP("futime not supported on Cygwin");
2259 #else
2260   ASSERT(r == 0);
2261   ASSERT(req.result == 0);
2262 #endif
2263   uv_fs_req_cleanup(&req);
2264 
2265   r = uv_fs_stat(NULL, &req, path, NULL);
2266   ASSERT(r == 0);
2267   ASSERT(req.result == 0);
2268   check_utime(path, atime, mtime);
2269   uv_fs_req_cleanup(&req);
2270 
2271   atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
2272 
2273   checkme.atime = atime;
2274   checkme.mtime = mtime;
2275   checkme.path = path;
2276 
2277   /* async futime */
2278   futime_req.data = &checkme;
2279   r = uv_fs_futime(loop, &futime_req, file, atime, mtime, futime_cb);
2280   ASSERT(r == 0);
2281   uv_run(loop, UV_RUN_DEFAULT);
2282   ASSERT(futime_cb_count == 1);
2283 
2284   /* Cleanup. */
2285   unlink(path);
2286 
2287   MAKE_VALGRIND_HAPPY();
2288   return 0;
2289 #endif
2290 }
2291 
2292 
TEST_IMPL(fs_stat_missing_path)2293 TEST_IMPL(fs_stat_missing_path) {
2294   uv_fs_t req;
2295   int r;
2296 
2297   loop = uv_default_loop();
2298 
2299   r = uv_fs_stat(NULL, &req, "non_existent_file", NULL);
2300   ASSERT(r == UV_ENOENT);
2301   ASSERT(req.result == UV_ENOENT);
2302   uv_fs_req_cleanup(&req);
2303 
2304   MAKE_VALGRIND_HAPPY();
2305   return 0;
2306 }
2307 
2308 
TEST_IMPL(fs_scandir_empty_dir)2309 TEST_IMPL(fs_scandir_empty_dir) {
2310   const char* path;
2311   uv_fs_t req;
2312   uv_dirent_t dent;
2313   int r;
2314 
2315   path = "./empty_dir/";
2316   loop = uv_default_loop();
2317 
2318   uv_fs_mkdir(NULL, &req, path, 0777, NULL);
2319   uv_fs_req_cleanup(&req);
2320 
2321   /* Fill the req to ensure that required fields are cleaned up */
2322   memset(&req, 0xdb, sizeof(req));
2323 
2324   r = uv_fs_scandir(NULL, &req, path, 0, NULL);
2325   ASSERT(r == 0);
2326   ASSERT(req.result == 0);
2327   ASSERT(req.ptr == NULL);
2328   ASSERT(UV_EOF == uv_fs_scandir_next(&req, &dent));
2329   uv_fs_req_cleanup(&req);
2330 
2331   r = uv_fs_scandir(loop, &scandir_req, path, 0, empty_scandir_cb);
2332   ASSERT(r == 0);
2333 
2334   ASSERT(scandir_cb_count == 0);
2335   uv_run(loop, UV_RUN_DEFAULT);
2336   ASSERT(scandir_cb_count == 1);
2337 
2338   uv_fs_rmdir(NULL, &req, path, NULL);
2339   uv_fs_req_cleanup(&req);
2340 
2341   MAKE_VALGRIND_HAPPY();
2342   return 0;
2343 }
2344 
2345 
TEST_IMPL(fs_scandir_non_existent_dir)2346 TEST_IMPL(fs_scandir_non_existent_dir) {
2347   const char* path;
2348   uv_fs_t req;
2349   uv_dirent_t dent;
2350   int r;
2351 
2352   path = "./non_existent_dir/";
2353   loop = uv_default_loop();
2354 
2355   uv_fs_rmdir(NULL, &req, path, NULL);
2356   uv_fs_req_cleanup(&req);
2357 
2358   /* Fill the req to ensure that required fields are cleaned up */
2359   memset(&req, 0xdb, sizeof(req));
2360 
2361   r = uv_fs_scandir(NULL, &req, path, 0, NULL);
2362   ASSERT(r == UV_ENOENT);
2363   ASSERT(req.result == UV_ENOENT);
2364   ASSERT(req.ptr == NULL);
2365   ASSERT(UV_ENOENT == uv_fs_scandir_next(&req, &dent));
2366   uv_fs_req_cleanup(&req);
2367 
2368   r = uv_fs_scandir(loop, &scandir_req, path, 0, non_existent_scandir_cb);
2369   ASSERT(r == 0);
2370 
2371   ASSERT(scandir_cb_count == 0);
2372   uv_run(loop, UV_RUN_DEFAULT);
2373   ASSERT(scandir_cb_count == 1);
2374 
2375   MAKE_VALGRIND_HAPPY();
2376   return 0;
2377 }
2378 
TEST_IMPL(fs_scandir_file)2379 TEST_IMPL(fs_scandir_file) {
2380   const char* path;
2381   int r;
2382 
2383   path = "test/fixtures/empty_file";
2384   loop = uv_default_loop();
2385 
2386   r = uv_fs_scandir(NULL, &scandir_req, path, 0, NULL);
2387   ASSERT(r == UV_ENOTDIR);
2388   uv_fs_req_cleanup(&scandir_req);
2389 
2390   r = uv_fs_scandir(loop, &scandir_req, path, 0, file_scandir_cb);
2391   ASSERT(r == 0);
2392 
2393   ASSERT(scandir_cb_count == 0);
2394   uv_run(loop, UV_RUN_DEFAULT);
2395   ASSERT(scandir_cb_count == 1);
2396 
2397   MAKE_VALGRIND_HAPPY();
2398   return 0;
2399 }
2400 
2401 
TEST_IMPL(fs_open_dir)2402 TEST_IMPL(fs_open_dir) {
2403   const char* path;
2404   uv_fs_t req;
2405   int r, file;
2406 
2407   path = ".";
2408   loop = uv_default_loop();
2409 
2410   r = uv_fs_open(NULL, &req, path, O_RDONLY, 0, NULL);
2411   ASSERT(r >= 0);
2412   ASSERT(req.result >= 0);
2413   ASSERT(req.ptr == NULL);
2414   file = r;
2415   uv_fs_req_cleanup(&req);
2416 
2417   r = uv_fs_close(NULL, &req, file, NULL);
2418   ASSERT(r == 0);
2419 
2420   r = uv_fs_open(loop, &req, path, O_RDONLY, 0, open_cb_simple);
2421   ASSERT(r == 0);
2422 
2423   ASSERT(open_cb_count == 0);
2424   uv_run(loop, UV_RUN_DEFAULT);
2425   ASSERT(open_cb_count == 1);
2426 
2427   MAKE_VALGRIND_HAPPY();
2428   return 0;
2429 }
2430 
2431 
TEST_IMPL(fs_file_open_append)2432 TEST_IMPL(fs_file_open_append) {
2433   int r;
2434 
2435   /* Setup. */
2436   unlink("test_file");
2437 
2438   loop = uv_default_loop();
2439 
2440   r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT,
2441       S_IWUSR | S_IRUSR, NULL);
2442   ASSERT(r >= 0);
2443   ASSERT(open_req1.result >= 0);
2444   uv_fs_req_cleanup(&open_req1);
2445 
2446   iov = uv_buf_init(test_buf, sizeof(test_buf));
2447   r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
2448   ASSERT(r >= 0);
2449   ASSERT(write_req.result >= 0);
2450   uv_fs_req_cleanup(&write_req);
2451 
2452   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2453   ASSERT(r == 0);
2454   ASSERT(close_req.result == 0);
2455   uv_fs_req_cleanup(&close_req);
2456 
2457   r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR | O_APPEND, 0, NULL);
2458   ASSERT(r >= 0);
2459   ASSERT(open_req1.result >= 0);
2460   uv_fs_req_cleanup(&open_req1);
2461 
2462   iov = uv_buf_init(test_buf, sizeof(test_buf));
2463   r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
2464   ASSERT(r >= 0);
2465   ASSERT(write_req.result >= 0);
2466   uv_fs_req_cleanup(&write_req);
2467 
2468   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2469   ASSERT(r == 0);
2470   ASSERT(close_req.result == 0);
2471   uv_fs_req_cleanup(&close_req);
2472 
2473   r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, S_IRUSR, NULL);
2474   ASSERT(r >= 0);
2475   ASSERT(open_req1.result >= 0);
2476   uv_fs_req_cleanup(&open_req1);
2477 
2478   iov = uv_buf_init(buf, sizeof(buf));
2479   r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
2480   printf("read = %d\n", r);
2481   ASSERT(r == 26);
2482   ASSERT(read_req.result == 26);
2483   ASSERT(memcmp(buf,
2484                 "test-buffer\n\0test-buffer\n\0",
2485                 sizeof("test-buffer\n\0test-buffer\n\0") - 1) == 0);
2486   uv_fs_req_cleanup(&read_req);
2487 
2488   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2489   ASSERT(r == 0);
2490   ASSERT(close_req.result == 0);
2491   uv_fs_req_cleanup(&close_req);
2492 
2493   /* Cleanup */
2494   unlink("test_file");
2495 
2496   MAKE_VALGRIND_HAPPY();
2497   return 0;
2498 }
2499 
2500 
TEST_IMPL(fs_rename_to_existing_file)2501 TEST_IMPL(fs_rename_to_existing_file) {
2502   int r;
2503 
2504   /* Setup. */
2505   unlink("test_file");
2506   unlink("test_file2");
2507 
2508   loop = uv_default_loop();
2509 
2510   r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT,
2511       S_IWUSR | S_IRUSR, NULL);
2512   ASSERT(r >= 0);
2513   ASSERT(open_req1.result >= 0);
2514   uv_fs_req_cleanup(&open_req1);
2515 
2516   iov = uv_buf_init(test_buf, sizeof(test_buf));
2517   r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
2518   ASSERT(r >= 0);
2519   ASSERT(write_req.result >= 0);
2520   uv_fs_req_cleanup(&write_req);
2521 
2522   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2523   ASSERT(r == 0);
2524   ASSERT(close_req.result == 0);
2525   uv_fs_req_cleanup(&close_req);
2526 
2527   r = uv_fs_open(NULL, &open_req1, "test_file2", O_WRONLY | O_CREAT,
2528       S_IWUSR | S_IRUSR, NULL);
2529   ASSERT(r >= 0);
2530   ASSERT(open_req1.result >= 0);
2531   uv_fs_req_cleanup(&open_req1);
2532 
2533   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2534   ASSERT(r == 0);
2535   ASSERT(close_req.result == 0);
2536   uv_fs_req_cleanup(&close_req);
2537 
2538   r = uv_fs_rename(NULL, &rename_req, "test_file", "test_file2", NULL);
2539   ASSERT(r == 0);
2540   ASSERT(rename_req.result == 0);
2541   uv_fs_req_cleanup(&rename_req);
2542 
2543   r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY, 0, NULL);
2544   ASSERT(r >= 0);
2545   ASSERT(open_req1.result >= 0);
2546   uv_fs_req_cleanup(&open_req1);
2547 
2548   memset(buf, 0, sizeof(buf));
2549   iov = uv_buf_init(buf, sizeof(buf));
2550   r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
2551   ASSERT(r >= 0);
2552   ASSERT(read_req.result >= 0);
2553   ASSERT(strcmp(buf, test_buf) == 0);
2554   uv_fs_req_cleanup(&read_req);
2555 
2556   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2557   ASSERT(r == 0);
2558   ASSERT(close_req.result == 0);
2559   uv_fs_req_cleanup(&close_req);
2560 
2561   /* Cleanup */
2562   unlink("test_file");
2563   unlink("test_file2");
2564 
2565   MAKE_VALGRIND_HAPPY();
2566   return 0;
2567 }
2568 
2569 
TEST_IMPL(fs_read_file_eof)2570 TEST_IMPL(fs_read_file_eof) {
2571 #if defined(__CYGWIN__) || defined(__MSYS__)
2572   RETURN_SKIP("Cygwin pread at EOF may (incorrectly) return data!");
2573 #endif
2574   int r;
2575 
2576   /* Setup. */
2577   unlink("test_file");
2578 
2579   loop = uv_default_loop();
2580 
2581   r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT,
2582       S_IWUSR | S_IRUSR, NULL);
2583   ASSERT(r >= 0);
2584   ASSERT(open_req1.result >= 0);
2585   uv_fs_req_cleanup(&open_req1);
2586 
2587   iov = uv_buf_init(test_buf, sizeof(test_buf));
2588   r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
2589   ASSERT(r >= 0);
2590   ASSERT(write_req.result >= 0);
2591   uv_fs_req_cleanup(&write_req);
2592 
2593   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2594   ASSERT(r == 0);
2595   ASSERT(close_req.result == 0);
2596   uv_fs_req_cleanup(&close_req);
2597 
2598   r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL);
2599   ASSERT(r >= 0);
2600   ASSERT(open_req1.result >= 0);
2601   uv_fs_req_cleanup(&open_req1);
2602 
2603   memset(buf, 0, sizeof(buf));
2604   iov = uv_buf_init(buf, sizeof(buf));
2605   r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
2606   ASSERT(r >= 0);
2607   ASSERT(read_req.result >= 0);
2608   ASSERT(strcmp(buf, test_buf) == 0);
2609   uv_fs_req_cleanup(&read_req);
2610 
2611   iov = uv_buf_init(buf, sizeof(buf));
2612   r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1,
2613                  read_req.result, NULL);
2614   ASSERT(r == 0);
2615   ASSERT(read_req.result == 0);
2616   uv_fs_req_cleanup(&read_req);
2617 
2618   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2619   ASSERT(r == 0);
2620   ASSERT(close_req.result == 0);
2621   uv_fs_req_cleanup(&close_req);
2622 
2623   /* Cleanup */
2624   unlink("test_file");
2625 
2626   MAKE_VALGRIND_HAPPY();
2627   return 0;
2628 }
2629 
2630 
TEST_IMPL(fs_write_multiple_bufs)2631 TEST_IMPL(fs_write_multiple_bufs) {
2632   uv_buf_t iovs[2];
2633   int r;
2634 
2635   /* Setup. */
2636   unlink("test_file");
2637 
2638   loop = uv_default_loop();
2639 
2640   r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT,
2641       S_IWUSR | S_IRUSR, NULL);
2642   ASSERT(r >= 0);
2643   ASSERT(open_req1.result >= 0);
2644   uv_fs_req_cleanup(&open_req1);
2645 
2646   iovs[0] = uv_buf_init(test_buf, sizeof(test_buf));
2647   iovs[1] = uv_buf_init(test_buf2, sizeof(test_buf2));
2648   r = uv_fs_write(NULL, &write_req, open_req1.result, iovs, 2, 0, NULL);
2649   ASSERT(r >= 0);
2650   ASSERT(write_req.result >= 0);
2651   uv_fs_req_cleanup(&write_req);
2652 
2653   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2654   ASSERT(r == 0);
2655   ASSERT(close_req.result == 0);
2656   uv_fs_req_cleanup(&close_req);
2657 
2658   r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL);
2659   ASSERT(r >= 0);
2660   ASSERT(open_req1.result >= 0);
2661   uv_fs_req_cleanup(&open_req1);
2662 
2663   memset(buf, 0, sizeof(buf));
2664   memset(buf2, 0, sizeof(buf2));
2665   /* Read the strings back to separate buffers. */
2666   iovs[0] = uv_buf_init(buf, sizeof(test_buf));
2667   iovs[1] = uv_buf_init(buf2, sizeof(test_buf2));
2668   r = uv_fs_read(NULL, &read_req, open_req1.result, iovs, 2, 0, NULL);
2669   ASSERT(r >= 0);
2670   ASSERT(read_req.result >= 0);
2671   ASSERT(strcmp(buf, test_buf) == 0);
2672   ASSERT(strcmp(buf2, test_buf2) == 0);
2673   uv_fs_req_cleanup(&read_req);
2674 
2675   iov = uv_buf_init(buf, sizeof(buf));
2676   r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1,
2677                  read_req.result, NULL);
2678   ASSERT(r == 0);
2679   ASSERT(read_req.result == 0);
2680   uv_fs_req_cleanup(&read_req);
2681 
2682   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2683   ASSERT(r == 0);
2684   ASSERT(close_req.result == 0);
2685   uv_fs_req_cleanup(&close_req);
2686 
2687   /* Cleanup */
2688   unlink("test_file");
2689 
2690   MAKE_VALGRIND_HAPPY();
2691   return 0;
2692 }
2693 
2694 
TEST_IMPL(fs_write_alotof_bufs)2695 TEST_IMPL(fs_write_alotof_bufs) {
2696   const size_t iovcount = 54321;
2697   uv_buf_t* iovs;
2698   char* buffer;
2699   size_t index;
2700   int r;
2701 
2702   /* Setup. */
2703   unlink("test_file");
2704 
2705   loop = uv_default_loop();
2706 
2707   iovs = malloc(sizeof(*iovs) * iovcount);
2708   ASSERT(iovs != NULL);
2709 
2710   r = uv_fs_open(NULL,
2711                  &open_req1,
2712                  "test_file",
2713                  O_RDWR | O_CREAT,
2714                  S_IWUSR | S_IRUSR,
2715                  NULL);
2716   ASSERT(r >= 0);
2717   ASSERT(open_req1.result >= 0);
2718   uv_fs_req_cleanup(&open_req1);
2719 
2720   for (index = 0; index < iovcount; ++index)
2721     iovs[index] = uv_buf_init(test_buf, sizeof(test_buf));
2722 
2723   r = uv_fs_write(NULL,
2724                   &write_req,
2725                   open_req1.result,
2726                   iovs,
2727                   iovcount,
2728                   -1,
2729                   NULL);
2730   ASSERT(r >= 0);
2731   ASSERT((size_t)write_req.result == sizeof(test_buf) * iovcount);
2732   uv_fs_req_cleanup(&write_req);
2733 
2734   /* Read the strings back to separate buffers. */
2735   buffer = malloc(sizeof(test_buf) * iovcount);
2736   ASSERT(buffer != NULL);
2737 
2738   for (index = 0; index < iovcount; ++index)
2739     iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf),
2740                               sizeof(test_buf));
2741 
2742   r = uv_fs_read(NULL, &read_req, open_req1.result, iovs, iovcount, 0, NULL);
2743   ASSERT(r >= 0);
2744   ASSERT((size_t)read_req.result == sizeof(test_buf) * iovcount);
2745 
2746   for (index = 0; index < iovcount; ++index)
2747     ASSERT(strncmp(buffer + index * sizeof(test_buf),
2748                    test_buf,
2749                    sizeof(test_buf)) == 0);
2750 
2751   uv_fs_req_cleanup(&read_req);
2752   free(buffer);
2753 
2754   iov = uv_buf_init(buf, sizeof(buf));
2755   r = uv_fs_read(NULL,
2756                  &read_req,
2757                  open_req1.result,
2758                  &iov,
2759                  1,
2760                  read_req.result,
2761                  NULL);
2762   ASSERT(r == 0);
2763   ASSERT(read_req.result == 0);
2764   uv_fs_req_cleanup(&read_req);
2765 
2766   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2767   ASSERT(r == 0);
2768   ASSERT(close_req.result == 0);
2769   uv_fs_req_cleanup(&close_req);
2770 
2771   /* Cleanup */
2772   unlink("test_file");
2773   free(iovs);
2774 
2775   MAKE_VALGRIND_HAPPY();
2776   return 0;
2777 }
2778 
2779 
TEST_IMPL(fs_write_alotof_bufs_with_offset)2780 TEST_IMPL(fs_write_alotof_bufs_with_offset) {
2781   const size_t iovcount = 54321;
2782   uv_buf_t* iovs;
2783   char* buffer;
2784   size_t index;
2785   int r;
2786   int64_t offset;
2787   char* filler = "0123456789";
2788   int filler_len = strlen(filler);
2789 
2790   /* Setup. */
2791   unlink("test_file");
2792 
2793   loop = uv_default_loop();
2794 
2795   iovs = malloc(sizeof(*iovs) * iovcount);
2796   ASSERT(iovs != NULL);
2797 
2798   r = uv_fs_open(NULL,
2799                  &open_req1,
2800                  "test_file",
2801                  O_RDWR | O_CREAT,
2802                  S_IWUSR | S_IRUSR,
2803                  NULL);
2804   ASSERT(r >= 0);
2805   ASSERT(open_req1.result >= 0);
2806   uv_fs_req_cleanup(&open_req1);
2807 
2808   iov = uv_buf_init(filler, filler_len);
2809   r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
2810   ASSERT(r == filler_len);
2811   ASSERT(write_req.result == filler_len);
2812   uv_fs_req_cleanup(&write_req);
2813   offset = (int64_t)r;
2814 
2815   for (index = 0; index < iovcount; ++index)
2816     iovs[index] = uv_buf_init(test_buf, sizeof(test_buf));
2817 
2818   r = uv_fs_write(NULL,
2819                   &write_req,
2820                   open_req1.result,
2821                   iovs,
2822                   iovcount,
2823                   offset,
2824                   NULL);
2825   ASSERT(r >= 0);
2826   ASSERT((size_t)write_req.result == sizeof(test_buf) * iovcount);
2827   uv_fs_req_cleanup(&write_req);
2828 
2829   /* Read the strings back to separate buffers. */
2830   buffer = malloc(sizeof(test_buf) * iovcount);
2831   ASSERT(buffer != NULL);
2832 
2833   for (index = 0; index < iovcount; ++index)
2834     iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf),
2835                               sizeof(test_buf));
2836 
2837   r = uv_fs_read(NULL, &read_req, open_req1.result,
2838                  iovs, iovcount, offset, NULL);
2839   ASSERT(r >= 0);
2840   ASSERT((size_t)read_req.result == sizeof(test_buf) * iovcount);
2841 
2842   for (index = 0; index < iovcount; ++index)
2843     ASSERT(strncmp(buffer + index * sizeof(test_buf),
2844                    test_buf,
2845                    sizeof(test_buf)) == 0);
2846 
2847   uv_fs_req_cleanup(&read_req);
2848   free(buffer);
2849 
2850   r = uv_fs_stat(NULL, &stat_req, "test_file", NULL);
2851   ASSERT(r == 0);
2852   ASSERT((int64_t)((uv_stat_t*)stat_req.ptr)->st_size ==
2853          offset + (int64_t)(iovcount * sizeof(test_buf)));
2854   uv_fs_req_cleanup(&stat_req);
2855 
2856   iov = uv_buf_init(buf, sizeof(buf));
2857   r = uv_fs_read(NULL,
2858                  &read_req,
2859                  open_req1.result,
2860                  &iov,
2861                  1,
2862                  read_req.result + offset,
2863                  NULL);
2864   ASSERT(r == 0);
2865   ASSERT(read_req.result == 0);
2866   uv_fs_req_cleanup(&read_req);
2867 
2868   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2869   ASSERT(r == 0);
2870   ASSERT(close_req.result == 0);
2871   uv_fs_req_cleanup(&close_req);
2872 
2873   /* Cleanup */
2874   unlink("test_file");
2875   free(iovs);
2876 
2877   MAKE_VALGRIND_HAPPY();
2878   return 0;
2879 }
2880 
2881 
TEST_IMPL(fs_read_write_null_arguments)2882 TEST_IMPL(fs_read_write_null_arguments) {
2883   int r;
2884 
2885   r = uv_fs_read(NULL, &read_req, 0, NULL, 0, -1, NULL);
2886   ASSERT(r == UV_EINVAL);
2887   uv_fs_req_cleanup(&read_req);
2888 
2889   r = uv_fs_write(NULL, &write_req, 0, NULL, 0, -1, NULL);
2890   /* Validate some memory management on failed input validation before sending
2891      fs work to the thread pool. */
2892   ASSERT(r == UV_EINVAL);
2893   ASSERT(write_req.path == NULL);
2894   ASSERT(write_req.ptr == NULL);
2895 #ifdef _WIN32
2896   ASSERT(write_req.file.pathw == NULL);
2897   ASSERT(write_req.fs.info.new_pathw == NULL);
2898   ASSERT(write_req.fs.info.bufs == NULL);
2899 #else
2900   ASSERT(write_req.new_path == NULL);
2901   ASSERT(write_req.bufs == NULL);
2902 #endif
2903   uv_fs_req_cleanup(&write_req);
2904 
2905   iov = uv_buf_init(NULL, 0);
2906   r = uv_fs_read(NULL, &read_req, 0, &iov, 0, -1, NULL);
2907   ASSERT(r == UV_EINVAL);
2908   uv_fs_req_cleanup(&read_req);
2909 
2910   iov = uv_buf_init(NULL, 0);
2911   r = uv_fs_write(NULL, &write_req, 0, &iov, 0, -1, NULL);
2912   ASSERT(r == UV_EINVAL);
2913   uv_fs_req_cleanup(&write_req);
2914 
2915   /* If the arguments are invalid, the loop should not be kept open */
2916   loop = uv_default_loop();
2917 
2918   r = uv_fs_read(loop, &read_req, 0, NULL, 0, -1, fail_cb);
2919   ASSERT(r == UV_EINVAL);
2920   uv_run(loop, UV_RUN_DEFAULT);
2921   uv_fs_req_cleanup(&read_req);
2922 
2923   r = uv_fs_write(loop, &write_req, 0, NULL, 0, -1, fail_cb);
2924   ASSERT(r == UV_EINVAL);
2925   uv_run(loop, UV_RUN_DEFAULT);
2926   uv_fs_req_cleanup(&write_req);
2927 
2928   iov = uv_buf_init(NULL, 0);
2929   r = uv_fs_read(loop, &read_req, 0, &iov, 0, -1, fail_cb);
2930   ASSERT(r == UV_EINVAL);
2931   uv_run(loop, UV_RUN_DEFAULT);
2932   uv_fs_req_cleanup(&read_req);
2933 
2934   iov = uv_buf_init(NULL, 0);
2935   r = uv_fs_write(loop, &write_req, 0, &iov, 0, -1, fail_cb);
2936   ASSERT(r == UV_EINVAL);
2937   uv_run(loop, UV_RUN_DEFAULT);
2938   uv_fs_req_cleanup(&write_req);
2939 
2940   return 0;
2941 }
2942 
2943 
TEST_IMPL(get_osfhandle_valid_handle)2944 TEST_IMPL(get_osfhandle_valid_handle) {
2945   int r;
2946   uv_os_fd_t fd;
2947 
2948   /* Setup. */
2949   unlink("test_file");
2950 
2951   loop = uv_default_loop();
2952 
2953   r = uv_fs_open(NULL,
2954                  &open_req1,
2955                  "test_file",
2956                  O_RDWR | O_CREAT,
2957                  S_IWUSR | S_IRUSR,
2958                  NULL);
2959   ASSERT(r >= 0);
2960   ASSERT(open_req1.result >= 0);
2961   uv_fs_req_cleanup(&open_req1);
2962 
2963   fd = uv_get_osfhandle(open_req1.result);
2964 #ifdef _WIN32
2965   ASSERT(fd != INVALID_HANDLE_VALUE);
2966 #else
2967   ASSERT(fd >= 0);
2968 #endif
2969 
2970   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
2971   ASSERT(r == 0);
2972   ASSERT(close_req.result == 0);
2973   uv_fs_req_cleanup(&close_req);
2974 
2975   /* Cleanup. */
2976   unlink("test_file");
2977 
2978   MAKE_VALGRIND_HAPPY();
2979   return 0;
2980 }
2981 
TEST_IMPL(fs_file_pos_after_op_with_offset)2982 TEST_IMPL(fs_file_pos_after_op_with_offset) {
2983   int r;
2984 
2985   /* Setup. */
2986   unlink("test_file");
2987   loop = uv_default_loop();
2988 
2989   r = uv_fs_open(loop,
2990                  &open_req1,
2991                  "test_file",
2992                  O_RDWR | O_CREAT,
2993                  S_IWUSR | S_IRUSR,
2994                  NULL);
2995   ASSERT(r > 0);
2996   uv_fs_req_cleanup(&open_req1);
2997 
2998   iov = uv_buf_init(test_buf, sizeof(test_buf));
2999   r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 0, NULL);
3000   ASSERT(r == sizeof(test_buf));
3001   ASSERT(lseek(open_req1.result, 0, SEEK_CUR) == 0);
3002   uv_fs_req_cleanup(&write_req);
3003 
3004   iov = uv_buf_init(buf, sizeof(buf));
3005   r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 0, NULL);
3006   ASSERT(r == sizeof(test_buf));
3007   ASSERT(strcmp(buf, test_buf) == 0);
3008   ASSERT(lseek(open_req1.result, 0, SEEK_CUR) == 0);
3009   uv_fs_req_cleanup(&read_req);
3010 
3011   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
3012   ASSERT(r == 0);
3013   uv_fs_req_cleanup(&close_req);
3014 
3015   /* Cleanup */
3016   unlink("test_file");
3017 
3018   MAKE_VALGRIND_HAPPY();
3019   return 0;
3020 }
3021 
TEST_IMPL(fs_null_req)3022 TEST_IMPL(fs_null_req) {
3023   /* Verify that all fs functions return UV_EINVAL when the request is NULL. */
3024   int r;
3025 
3026   r = uv_fs_open(NULL, NULL, NULL, 0, 0, NULL);
3027   ASSERT(r == UV_EINVAL);
3028 
3029   r = uv_fs_close(NULL, NULL, 0, NULL);
3030   ASSERT(r == UV_EINVAL);
3031 
3032   r = uv_fs_read(NULL, NULL, 0, NULL, 0, -1, NULL);
3033   ASSERT(r == UV_EINVAL);
3034 
3035   r = uv_fs_write(NULL, NULL, 0, NULL, 0, -1, NULL);
3036   ASSERT(r == UV_EINVAL);
3037 
3038   r = uv_fs_unlink(NULL, NULL, NULL, NULL);
3039   ASSERT(r == UV_EINVAL);
3040 
3041   r = uv_fs_mkdir(NULL, NULL, NULL, 0, NULL);
3042   ASSERT(r == UV_EINVAL);
3043 
3044   r = uv_fs_mkdtemp(NULL, NULL, NULL, NULL);
3045   ASSERT(r == UV_EINVAL);
3046 
3047   r = uv_fs_rmdir(NULL, NULL, NULL, NULL);
3048   ASSERT(r == UV_EINVAL);
3049 
3050   r = uv_fs_scandir(NULL, NULL, NULL, 0, NULL);
3051   ASSERT(r == UV_EINVAL);
3052 
3053   r = uv_fs_link(NULL, NULL, NULL, NULL, NULL);
3054   ASSERT(r == UV_EINVAL);
3055 
3056   r = uv_fs_symlink(NULL, NULL, NULL, NULL, 0, NULL);
3057   ASSERT(r == UV_EINVAL);
3058 
3059   r = uv_fs_readlink(NULL, NULL, NULL, NULL);
3060   ASSERT(r == UV_EINVAL);
3061 
3062   r = uv_fs_realpath(NULL, NULL, NULL, NULL);
3063   ASSERT(r == UV_EINVAL);
3064 
3065   r = uv_fs_chown(NULL, NULL, NULL, 0, 0, NULL);
3066   ASSERT(r == UV_EINVAL);
3067 
3068   r = uv_fs_fchown(NULL, NULL, 0, 0, 0, NULL);
3069   ASSERT(r == UV_EINVAL);
3070 
3071   r = uv_fs_stat(NULL, NULL, NULL, NULL);
3072   ASSERT(r == UV_EINVAL);
3073 
3074   r = uv_fs_lstat(NULL, NULL, NULL, NULL);
3075   ASSERT(r == UV_EINVAL);
3076 
3077   r = uv_fs_fstat(NULL, NULL, 0, NULL);
3078   ASSERT(r == UV_EINVAL);
3079 
3080   r = uv_fs_rename(NULL, NULL, NULL, NULL, NULL);
3081   ASSERT(r == UV_EINVAL);
3082 
3083   r = uv_fs_fsync(NULL, NULL, 0, NULL);
3084   ASSERT(r == UV_EINVAL);
3085 
3086   r = uv_fs_fdatasync(NULL, NULL, 0, NULL);
3087   ASSERT(r == UV_EINVAL);
3088 
3089   r = uv_fs_ftruncate(NULL, NULL, 0, 0, NULL);
3090   ASSERT(r == UV_EINVAL);
3091 
3092   r = uv_fs_copyfile(NULL, NULL, NULL, NULL, 0, NULL);
3093   ASSERT(r == UV_EINVAL);
3094 
3095   r = uv_fs_sendfile(NULL, NULL, 0, 0, 0, 0, NULL);
3096   ASSERT(r == UV_EINVAL);
3097 
3098   r = uv_fs_access(NULL, NULL, NULL, 0, NULL);
3099   ASSERT(r == UV_EINVAL);
3100 
3101   r = uv_fs_chmod(NULL, NULL, NULL, 0, NULL);
3102   ASSERT(r == UV_EINVAL);
3103 
3104   r = uv_fs_fchmod(NULL, NULL, 0, 0, NULL);
3105   ASSERT(r == UV_EINVAL);
3106 
3107   r = uv_fs_utime(NULL, NULL, NULL, 0.0, 0.0, NULL);
3108   ASSERT(r == UV_EINVAL);
3109 
3110   r = uv_fs_futime(NULL, NULL, 0, 0.0, 0.0, NULL);
3111   ASSERT(r == UV_EINVAL);
3112 
3113   /* This should be a no-op. */
3114   uv_fs_req_cleanup(NULL);
3115 
3116   return 0;
3117 }
3118 
3119 #ifdef _WIN32
TEST_IMPL(fs_exclusive_sharing_mode)3120 TEST_IMPL(fs_exclusive_sharing_mode) {
3121   int r;
3122 
3123   /* Setup. */
3124   unlink("test_file");
3125 
3126   ASSERT(UV_FS_O_EXLOCK > 0);
3127 
3128   r = uv_fs_open(NULL,
3129                  &open_req1,
3130                  "test_file",
3131                  O_RDWR | O_CREAT | UV_FS_O_EXLOCK,
3132                  S_IWUSR | S_IRUSR,
3133                  NULL);
3134   ASSERT(r >= 0);
3135   ASSERT(open_req1.result >= 0);
3136   uv_fs_req_cleanup(&open_req1);
3137 
3138   r = uv_fs_open(NULL,
3139                  &open_req2,
3140                  "test_file",
3141                  O_RDONLY | UV_FS_O_EXLOCK,
3142                  S_IWUSR | S_IRUSR,
3143                  NULL);
3144   ASSERT(r < 0);
3145   ASSERT(open_req2.result < 0);
3146   uv_fs_req_cleanup(&open_req2);
3147 
3148   r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
3149   ASSERT(r == 0);
3150   ASSERT(close_req.result == 0);
3151   uv_fs_req_cleanup(&close_req);
3152 
3153   r = uv_fs_open(NULL,
3154                  &open_req2,
3155                  "test_file",
3156                  O_RDONLY | UV_FS_O_EXLOCK,
3157                  S_IWUSR | S_IRUSR,
3158                  NULL);
3159   ASSERT(r >= 0);
3160   ASSERT(open_req2.result >= 0);
3161   uv_fs_req_cleanup(&open_req2);
3162 
3163   r = uv_fs_close(NULL, &close_req, open_req2.result, NULL);
3164   ASSERT(r == 0);
3165   ASSERT(close_req.result == 0);
3166   uv_fs_req_cleanup(&close_req);
3167 
3168   /* Cleanup */
3169   unlink("test_file");
3170 
3171   MAKE_VALGRIND_HAPPY();
3172   return 0;
3173 }
3174 #endif
3175