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