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