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