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