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