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