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 /* Caveat emptor: this file deviates from the libuv convention of returning
23  * negated errno codes. Most uv_fs_*() functions map directly to the system
24  * call of the same name. For more complex wrappers, it's easier to just
25  * return -1 with errno set. The dispatcher in uv__fs_work() takes care of
26  * getting the errno to the right place (req->result or as the return value.)
27  */
28 
29 #include "uv.h"
30 #include "internal.h"
31 
32 #include <errno.h>
33 #include <dlfcn.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <limits.h> /* PATH_MAX */
38 
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/stat.h>
42 #include <sys/time.h>
43 #include <sys/uio.h>
44 #include <pthread.h>
45 #include <unistd.h>
46 #include <fcntl.h>
47 #include <poll.h>
48 
49 #if defined(__DragonFly__)        ||                                      \
50     defined(__FreeBSD__)          ||                                      \
51     defined(__FreeBSD_kernel__)   ||                                      \
52     defined(__OpenBSD__)          ||                                      \
53     defined(__NetBSD__)
54 # define HAVE_PREADV 1
55 #else
56 # define HAVE_PREADV 0
57 #endif
58 
59 #if defined(__linux__) || defined(__sun)
60 # include <sys/sendfile.h>
61 #endif
62 
63 #if defined(__APPLE__)
64 # include <sys/sysctl.h>
65 #elif defined(__linux__) && !defined(FICLONE)
66 # include <sys/ioctl.h>
67 # define FICLONE _IOW(0x94, 9, int)
68 #endif
69 
70 #if defined(_AIX) && !defined(_AIX71)
71 # include <utime.h>
72 #endif
73 
74 #if defined(__APPLE__)            ||                                      \
75     defined(__DragonFly__)        ||                                      \
76     defined(__FreeBSD__)          ||                                      \
77     defined(__FreeBSD_kernel__)   ||                                      \
78     defined(__OpenBSD__)          ||                                      \
79     defined(__NetBSD__)
80 # include <sys/param.h>
81 # include <sys/mount.h>
82 #elif defined(__sun) || defined(__MVS__) || defined(__NetBSD__) || defined(__HAIKU__)
83 # include <sys/statvfs.h>
84 #else
85 # include <sys/statfs.h>
86 #endif
87 
88 #if defined(_AIX) && _XOPEN_SOURCE <= 600
89 extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
90 #endif
91 
92 #define INIT(subtype)                                                         \
93   do {                                                                        \
94     if (req == NULL)                                                          \
95       return UV_EINVAL;                                                       \
96     UV_REQ_INIT(req, UV_FS);                                                  \
97     req->fs_type = UV_FS_ ## subtype;                                         \
98     req->result = 0;                                                          \
99     req->ptr = NULL;                                                          \
100     req->loop = loop;                                                         \
101     req->path = NULL;                                                         \
102     req->new_path = NULL;                                                     \
103     req->bufs = NULL;                                                         \
104     req->cb = cb;                                                             \
105   }                                                                           \
106   while (0)
107 
108 #define PATH                                                                  \
109   do {                                                                        \
110     assert(path != NULL);                                                     \
111     if (cb == NULL) {                                                         \
112       req->path = path;                                                       \
113     } else {                                                                  \
114       req->path = uv__strdup(path);                                           \
115       if (req->path == NULL)                                                  \
116         return UV_ENOMEM;                                                     \
117     }                                                                         \
118   }                                                                           \
119   while (0)
120 
121 #define PATH2                                                                 \
122   do {                                                                        \
123     if (cb == NULL) {                                                         \
124       req->path = path;                                                       \
125       req->new_path = new_path;                                               \
126     } else {                                                                  \
127       size_t path_len;                                                        \
128       size_t new_path_len;                                                    \
129       path_len = strlen(path) + 1;                                            \
130       new_path_len = strlen(new_path) + 1;                                    \
131       req->path = uv__malloc(path_len + new_path_len);                        \
132       if (req->path == NULL)                                                  \
133         return UV_ENOMEM;                                                     \
134       req->new_path = req->path + path_len;                                   \
135       memcpy((void*) req->path, path, path_len);                              \
136       memcpy((void*) req->new_path, new_path, new_path_len);                  \
137     }                                                                         \
138   }                                                                           \
139   while (0)
140 
141 #define POST                                                                  \
142   do {                                                                        \
143     if (cb != NULL) {                                                         \
144       uv__req_register(loop, req);                                            \
145       uv__work_submit(loop,                                                   \
146                       &req->work_req,                                         \
147                       UV__WORK_FAST_IO,                                       \
148                       uv__fs_work,                                            \
149                       uv__fs_done);                                           \
150       return 0;                                                               \
151     }                                                                         \
152     else {                                                                    \
153       uv__fs_work(&req->work_req);                                            \
154       return req->result;                                                     \
155     }                                                                         \
156   }                                                                           \
157   while (0)
158 
159 
uv__fs_close(int fd)160 static int uv__fs_close(int fd) {
161   int rc;
162 
163   rc = uv__close_nocancel(fd);
164   if (rc == -1)
165     if (errno == EINTR || errno == EINPROGRESS)
166       rc = 0;  /* The close is in progress, not an error. */
167 
168   return rc;
169 }
170 
171 
uv__fs_fsync(uv_fs_t * req)172 static ssize_t uv__fs_fsync(uv_fs_t* req) {
173 #if defined(__APPLE__)
174   /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
175    * to the drive platters. This is in contrast to Linux's fdatasync and fsync
176    * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
177    * for flushing buffered data to permanent storage. If F_FULLFSYNC is not
178    * supported by the file system we fall back to F_BARRIERFSYNC or fsync().
179    * This is the same approach taken by sqlite, except sqlite does not issue
180    * an F_BARRIERFSYNC call.
181    */
182   int r;
183 
184   r = fcntl(req->file, F_FULLFSYNC);
185   if (r != 0)
186     r = fcntl(req->file, 85 /* F_BARRIERFSYNC */);  /* fsync + barrier */
187   if (r != 0)
188     r = fsync(req->file);
189   return r;
190 #else
191   return fsync(req->file);
192 #endif
193 }
194 
195 
uv__fs_fdatasync(uv_fs_t * req)196 static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
197 #if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
198   return fdatasync(req->file);
199 #elif defined(__APPLE__)
200   /* See the comment in uv__fs_fsync. */
201   return uv__fs_fsync(req);
202 #else
203   return fsync(req->file);
204 #endif
205 }
206 
207 
UV_UNUSED(static struct timespec uv__fs_to_timespec (double time))208 UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
209   struct timespec ts;
210   ts.tv_sec  = time;
211   ts.tv_nsec = (uint64_t)(time * 1000000) % 1000000 * 1000;
212   return ts;
213 }
214 
UV_UNUSED(static struct timeval uv__fs_to_timeval (double time))215 UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
216   struct timeval tv;
217   tv.tv_sec  = time;
218   tv.tv_usec = (uint64_t)(time * 1000000) % 1000000;
219   return tv;
220 }
221 
uv__fs_futime(uv_fs_t * req)222 static ssize_t uv__fs_futime(uv_fs_t* req) {
223 #if defined(__linux__)                                                        \
224     || defined(_AIX71)                                                        \
225     || defined(__HAIKU__)
226   /* utimesat() has nanosecond resolution but we stick to microseconds
227    * for the sake of consistency with other platforms.
228    */
229   struct timespec ts[2];
230   ts[0] = uv__fs_to_timespec(req->atime);
231   ts[1] = uv__fs_to_timespec(req->mtime);
232 #if defined(__ANDROID_API__) && __ANDROID_API__ < 21
233   return utimensat(req->file, NULL, ts, 0);
234 #else
235   return futimens(req->file, ts);
236 #endif
237 #elif defined(__APPLE__)                                                      \
238     || defined(__DragonFly__)                                                 \
239     || defined(__FreeBSD__)                                                   \
240     || defined(__FreeBSD_kernel__)                                            \
241     || defined(__NetBSD__)                                                    \
242     || defined(__OpenBSD__)                                                   \
243     || defined(__sun)
244   struct timeval tv[2];
245   tv[0] = uv__fs_to_timeval(req->atime);
246   tv[1] = uv__fs_to_timeval(req->mtime);
247 # if defined(__sun)
248   return futimesat(req->file, NULL, tv);
249 # else
250   return futimes(req->file, tv);
251 # endif
252 #elif defined(__MVS__)
253   attrib_t atr;
254   memset(&atr, 0, sizeof(atr));
255   atr.att_mtimechg = 1;
256   atr.att_atimechg = 1;
257   atr.att_mtime = req->mtime;
258   atr.att_atime = req->atime;
259   return __fchattr(req->file, &atr, sizeof(atr));
260 #else
261   errno = ENOSYS;
262   return -1;
263 #endif
264 }
265 
266 
uv__fs_mkdtemp(uv_fs_t * req)267 static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
268   return mkdtemp((char*) req->path) ? 0 : -1;
269 }
270 
271 
272 static int (*uv__mkostemp)(char*, int);
273 
274 
uv__mkostemp_initonce(void)275 static void uv__mkostemp_initonce(void) {
276   /* z/os doesn't have RTLD_DEFAULT but that's okay
277    * because it doesn't have mkostemp(O_CLOEXEC) either.
278    */
279 #ifdef RTLD_DEFAULT
280   uv__mkostemp = (int (*)(char*, int)) dlsym(RTLD_DEFAULT, "mkostemp");
281 
282   /* We don't care about errors, but we do want to clean them up.
283    * If there has been no error, then dlerror() will just return
284    * NULL.
285    */
286   dlerror();
287 #endif  /* RTLD_DEFAULT */
288 }
289 
290 
uv__fs_mkstemp(uv_fs_t * req)291 static int uv__fs_mkstemp(uv_fs_t* req) {
292   static uv_once_t once = UV_ONCE_INIT;
293   int r;
294 #ifdef O_CLOEXEC
295   static int no_cloexec_support;
296 #endif
297   static const char pattern[] = "XXXXXX";
298   static const size_t pattern_size = sizeof(pattern) - 1;
299   char* path;
300   size_t path_length;
301 
302   path = (char*) req->path;
303   path_length = strlen(path);
304 
305   /* EINVAL can be returned for 2 reasons:
306       1. The template's last 6 characters were not XXXXXX
307       2. open() didn't support O_CLOEXEC
308      We want to avoid going to the fallback path in case
309      of 1, so it's manually checked before. */
310   if (path_length < pattern_size ||
311       strcmp(path + path_length - pattern_size, pattern)) {
312     errno = EINVAL;
313     return -1;
314   }
315 
316   uv_once(&once, uv__mkostemp_initonce);
317 
318 #ifdef O_CLOEXEC
319   if (no_cloexec_support == 0 && uv__mkostemp != NULL) {
320     r = uv__mkostemp(path, O_CLOEXEC);
321 
322     if (r >= 0)
323       return r;
324 
325     /* If mkostemp() returns EINVAL, it means the kernel doesn't
326        support O_CLOEXEC, so we just fallback to mkstemp() below. */
327     if (errno != EINVAL)
328       return r;
329 
330     /* We set the static variable so that next calls don't even
331        try to use mkostemp. */
332     no_cloexec_support = 1;
333   }
334 #endif  /* O_CLOEXEC */
335 
336   if (req->cb != NULL)
337     uv_rwlock_rdlock(&req->loop->cloexec_lock);
338 
339   r = mkstemp(path);
340 
341   /* In case of failure `uv__cloexec` will leave error in `errno`,
342    * so it is enough to just set `r` to `-1`.
343    */
344   if (r >= 0 && uv__cloexec(r, 1) != 0) {
345     r = uv__close(r);
346     if (r != 0)
347       abort();
348     r = -1;
349   }
350 
351   if (req->cb != NULL)
352     uv_rwlock_rdunlock(&req->loop->cloexec_lock);
353 
354   return r;
355 }
356 
357 
uv__fs_open(uv_fs_t * req)358 static ssize_t uv__fs_open(uv_fs_t* req) {
359 #ifdef O_CLOEXEC
360   return open(req->path, req->flags | O_CLOEXEC, req->mode);
361 #else  /* O_CLOEXEC */
362   int r;
363 
364   if (req->cb != NULL)
365     uv_rwlock_rdlock(&req->loop->cloexec_lock);
366 
367   r = open(req->path, req->flags, req->mode);
368 
369   /* In case of failure `uv__cloexec` will leave error in `errno`,
370    * so it is enough to just set `r` to `-1`.
371    */
372   if (r >= 0 && uv__cloexec(r, 1) != 0) {
373     r = uv__close(r);
374     if (r != 0)
375       abort();
376     r = -1;
377   }
378 
379   if (req->cb != NULL)
380     uv_rwlock_rdunlock(&req->loop->cloexec_lock);
381 
382   return r;
383 #endif  /* O_CLOEXEC */
384 }
385 
386 
387 #if !HAVE_PREADV
uv__fs_preadv(uv_file fd,uv_buf_t * bufs,unsigned int nbufs,off_t off)388 static ssize_t uv__fs_preadv(uv_file fd,
389                              uv_buf_t* bufs,
390                              unsigned int nbufs,
391                              off_t off) {
392   uv_buf_t* buf;
393   uv_buf_t* end;
394   ssize_t result;
395   ssize_t rc;
396   size_t pos;
397 
398   assert(nbufs > 0);
399 
400   result = 0;
401   pos = 0;
402   buf = bufs + 0;
403   end = bufs + nbufs;
404 
405   for (;;) {
406     do
407       rc = pread(fd, buf->base + pos, buf->len - pos, off + result);
408     while (rc == -1 && errno == EINTR);
409 
410     if (rc == 0)
411       break;
412 
413     if (rc == -1 && result == 0)
414       return UV__ERR(errno);
415 
416     if (rc == -1)
417       break;  /* We read some data so return that, ignore the error. */
418 
419     pos += rc;
420     result += rc;
421 
422     if (pos < buf->len)
423       continue;
424 
425     pos = 0;
426     buf += 1;
427 
428     if (buf == end)
429       break;
430   }
431 
432   return result;
433 }
434 #endif
435 
436 
uv__fs_read(uv_fs_t * req)437 static ssize_t uv__fs_read(uv_fs_t* req) {
438 #if defined(__linux__)
439   static int no_preadv;
440 #endif
441   unsigned int iovmax;
442   ssize_t result;
443 
444   iovmax = uv__getiovmax();
445   if (req->nbufs > iovmax)
446     req->nbufs = iovmax;
447 
448   if (req->off < 0) {
449     if (req->nbufs == 1)
450       result = read(req->file, req->bufs[0].base, req->bufs[0].len);
451     else
452       result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
453   } else {
454     if (req->nbufs == 1) {
455       result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
456       goto done;
457     }
458 
459 #if HAVE_PREADV
460     result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
461 #else
462 # if defined(__linux__)
463     if (no_preadv) retry:
464 # endif
465     {
466       result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off);
467     }
468 # if defined(__linux__)
469     else {
470       result = uv__preadv(req->file,
471                           (struct iovec*)req->bufs,
472                           req->nbufs,
473                           req->off);
474       if (result == -1 && errno == ENOSYS) {
475         no_preadv = 1;
476         goto retry;
477       }
478     }
479 # endif
480 #endif
481   }
482 
483 done:
484   /* Early cleanup of bufs allocation, since we're done with it. */
485   if (req->bufs != req->bufsml)
486     uv__free(req->bufs);
487 
488   req->bufs = NULL;
489   req->nbufs = 0;
490 
491 #ifdef __PASE__
492   /* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
493   if (result == -1 && errno == EOPNOTSUPP) {
494     struct stat buf;
495     ssize_t rc;
496     rc = fstat(req->file, &buf);
497     if (rc == 0 && S_ISDIR(buf.st_mode)) {
498       errno = EISDIR;
499     }
500   }
501 #endif
502 
503   return result;
504 }
505 
506 
507 #if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)
508 #define UV_CONST_DIRENT uv__dirent_t
509 #else
510 #define UV_CONST_DIRENT const uv__dirent_t
511 #endif
512 
513 
uv__fs_scandir_filter(UV_CONST_DIRENT * dent)514 static int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) {
515   return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
516 }
517 
518 
uv__fs_scandir_sort(UV_CONST_DIRENT ** a,UV_CONST_DIRENT ** b)519 static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
520   return strcmp((*a)->d_name, (*b)->d_name);
521 }
522 
523 
uv__fs_scandir(uv_fs_t * req)524 static ssize_t uv__fs_scandir(uv_fs_t* req) {
525   uv__dirent_t** dents;
526   int n;
527 
528   dents = NULL;
529   n = scandir(req->path, &dents, uv__fs_scandir_filter, uv__fs_scandir_sort);
530 
531   /* NOTE: We will use nbufs as an index field */
532   req->nbufs = 0;
533 
534   if (n == 0) {
535     /* OS X still needs to deallocate some memory.
536      * Memory was allocated using the system allocator, so use free() here.
537      */
538     free(dents);
539     dents = NULL;
540   } else if (n == -1) {
541     return n;
542   }
543 
544   req->ptr = dents;
545 
546   return n;
547 }
548 
uv__fs_opendir(uv_fs_t * req)549 static int uv__fs_opendir(uv_fs_t* req) {
550   uv_dir_t* dir;
551 
552   dir = uv__malloc(sizeof(*dir));
553   if (dir == NULL)
554     goto error;
555 
556   dir->dir = opendir(req->path);
557   if (dir->dir == NULL)
558     goto error;
559 
560   req->ptr = dir;
561   return 0;
562 
563 error:
564   uv__free(dir);
565   req->ptr = NULL;
566   return -1;
567 }
568 
uv__fs_readdir(uv_fs_t * req)569 static int uv__fs_readdir(uv_fs_t* req) {
570   uv_dir_t* dir;
571   uv_dirent_t* dirent;
572   struct dirent* res;
573   unsigned int dirent_idx;
574   unsigned int i;
575 
576   dir = req->ptr;
577   dirent_idx = 0;
578 
579   while (dirent_idx < dir->nentries) {
580     /* readdir() returns NULL on end of directory, as well as on error. errno
581        is used to differentiate between the two conditions. */
582     errno = 0;
583     res = readdir(dir->dir);
584 
585     if (res == NULL) {
586       if (errno != 0)
587         goto error;
588       break;
589     }
590 
591     if (strcmp(res->d_name, ".") == 0 || strcmp(res->d_name, "..") == 0)
592       continue;
593 
594     dirent = &dir->dirents[dirent_idx];
595     dirent->name = uv__strdup(res->d_name);
596 
597     if (dirent->name == NULL)
598       goto error;
599 
600     dirent->type = uv__fs_get_dirent_type(res);
601     ++dirent_idx;
602   }
603 
604   return dirent_idx;
605 
606 error:
607   for (i = 0; i < dirent_idx; ++i) {
608     uv__free((char*) dir->dirents[i].name);
609     dir->dirents[i].name = NULL;
610   }
611 
612   return -1;
613 }
614 
uv__fs_closedir(uv_fs_t * req)615 static int uv__fs_closedir(uv_fs_t* req) {
616   uv_dir_t* dir;
617 
618   dir = req->ptr;
619 
620   if (dir->dir != NULL) {
621     closedir(dir->dir);
622     dir->dir = NULL;
623   }
624 
625   uv__free(req->ptr);
626   req->ptr = NULL;
627   return 0;
628 }
629 
uv__fs_statfs(uv_fs_t * req)630 static int uv__fs_statfs(uv_fs_t* req) {
631   uv_statfs_t* stat_fs;
632 #if defined(__sun) || defined(__MVS__) || defined(__NetBSD__) || defined(__HAIKU__)
633   struct statvfs buf;
634 
635   if (0 != statvfs(req->path, &buf))
636 #else
637   struct statfs buf;
638 
639   if (0 != statfs(req->path, &buf))
640 #endif /* defined(__sun) */
641     return -1;
642 
643   stat_fs = uv__malloc(sizeof(*stat_fs));
644   if (stat_fs == NULL) {
645     errno = ENOMEM;
646     return -1;
647   }
648 
649 #if defined(__sun) || defined(__MVS__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
650   stat_fs->f_type = 0;  /* f_type is not supported. */
651 #else
652   stat_fs->f_type = buf.f_type;
653 #endif
654   stat_fs->f_bsize = buf.f_bsize;
655   stat_fs->f_blocks = buf.f_blocks;
656   stat_fs->f_bfree = buf.f_bfree;
657   stat_fs->f_bavail = buf.f_bavail;
658   stat_fs->f_files = buf.f_files;
659   stat_fs->f_ffree = buf.f_ffree;
660   req->ptr = stat_fs;
661   return 0;
662 }
663 
uv__fs_pathmax_size(const char * path)664 static ssize_t uv__fs_pathmax_size(const char* path) {
665   ssize_t pathmax;
666 
667   pathmax = pathconf(path, _PC_PATH_MAX);
668 
669   if (pathmax == -1)
670     pathmax = UV__PATH_MAX;
671 
672   return pathmax;
673 }
674 
uv__fs_readlink(uv_fs_t * req)675 static ssize_t uv__fs_readlink(uv_fs_t* req) {
676   ssize_t maxlen;
677   ssize_t len;
678   char* buf;
679 
680 #if defined(_POSIX_PATH_MAX) || defined(PATH_MAX)
681   maxlen = uv__fs_pathmax_size(req->path);
682 #else
683   /* We may not have a real PATH_MAX.  Read size of link.  */
684   struct stat st;
685   int ret;
686   ret = lstat(req->path, &st);
687   if (ret != 0)
688     return -1;
689   if (!S_ISLNK(st.st_mode)) {
690     errno = EINVAL;
691     return -1;
692   }
693 
694   maxlen = st.st_size;
695 
696   /* According to readlink(2) lstat can report st_size == 0
697      for some symlinks, such as those in /proc or /sys.  */
698   if (maxlen == 0)
699     maxlen = uv__fs_pathmax_size(req->path);
700 #endif
701 
702   buf = uv__malloc(maxlen);
703 
704   if (buf == NULL) {
705     errno = ENOMEM;
706     return -1;
707   }
708 
709 #if defined(__MVS__)
710   len = os390_readlink(req->path, buf, maxlen);
711 #else
712   len = readlink(req->path, buf, maxlen);
713 #endif
714 
715   if (len == -1) {
716     uv__free(buf);
717     return -1;
718   }
719 
720   /* Uncommon case: resize to make room for the trailing nul byte. */
721   if (len == maxlen) {
722     buf = uv__reallocf(buf, len + 1);
723 
724     if (buf == NULL)
725       return -1;
726   }
727 
728   buf[len] = '\0';
729   req->ptr = buf;
730 
731   return 0;
732 }
733 
uv__fs_realpath(uv_fs_t * req)734 static ssize_t uv__fs_realpath(uv_fs_t* req) {
735   char* buf;
736 
737 #if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
738   buf = realpath(req->path, NULL);
739   if (buf == NULL)
740     return -1;
741 #else
742   ssize_t len;
743 
744   len = uv__fs_pathmax_size(req->path);
745   buf = uv__malloc(len + 1);
746 
747   if (buf == NULL) {
748     errno = ENOMEM;
749     return -1;
750   }
751 
752   if (realpath(req->path, buf) == NULL) {
753     uv__free(buf);
754     return -1;
755   }
756 #endif
757 
758   req->ptr = buf;
759 
760   return 0;
761 }
762 
uv__fs_sendfile_emul(uv_fs_t * req)763 static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
764   struct pollfd pfd;
765   int use_pread;
766   off_t offset;
767   ssize_t nsent;
768   ssize_t nread;
769   ssize_t nwritten;
770   size_t buflen;
771   size_t len;
772   ssize_t n;
773   int in_fd;
774   int out_fd;
775   char buf[8192];
776 
777   len = req->bufsml[0].len;
778   in_fd = req->flags;
779   out_fd = req->file;
780   offset = req->off;
781   use_pread = 1;
782 
783   /* Here are the rules regarding errors:
784    *
785    * 1. Read errors are reported only if nsent==0, otherwise we return nsent.
786    *    The user needs to know that some data has already been sent, to stop
787    *    them from sending it twice.
788    *
789    * 2. Write errors are always reported. Write errors are bad because they
790    *    mean data loss: we've read data but now we can't write it out.
791    *
792    * We try to use pread() and fall back to regular read() if the source fd
793    * doesn't support positional reads, for example when it's a pipe fd.
794    *
795    * If we get EAGAIN when writing to the target fd, we poll() on it until
796    * it becomes writable again.
797    *
798    * FIXME: If we get a write error when use_pread==1, it should be safe to
799    *        return the number of sent bytes instead of an error because pread()
800    *        is, in theory, idempotent. However, special files in /dev or /proc
801    *        may support pread() but not necessarily return the same data on
802    *        successive reads.
803    *
804    * FIXME: There is no way now to signal that we managed to send *some* data
805    *        before a write error.
806    */
807   for (nsent = 0; (size_t) nsent < len; ) {
808     buflen = len - nsent;
809 
810     if (buflen > sizeof(buf))
811       buflen = sizeof(buf);
812 
813     do
814       if (use_pread)
815         nread = pread(in_fd, buf, buflen, offset);
816       else
817         nread = read(in_fd, buf, buflen);
818     while (nread == -1 && errno == EINTR);
819 
820     if (nread == 0)
821       goto out;
822 
823     if (nread == -1) {
824       if (use_pread && nsent == 0 && (errno == EIO || errno == ESPIPE)) {
825         use_pread = 0;
826         continue;
827       }
828 
829       if (nsent == 0)
830         nsent = -1;
831 
832       goto out;
833     }
834 
835     for (nwritten = 0; nwritten < nread; ) {
836       do
837         n = write(out_fd, buf + nwritten, nread - nwritten);
838       while (n == -1 && errno == EINTR);
839 
840       if (n != -1) {
841         nwritten += n;
842         continue;
843       }
844 
845       if (errno != EAGAIN && errno != EWOULDBLOCK) {
846         nsent = -1;
847         goto out;
848       }
849 
850       pfd.fd = out_fd;
851       pfd.events = POLLOUT;
852       pfd.revents = 0;
853 
854       do
855         n = poll(&pfd, 1, -1);
856       while (n == -1 && errno == EINTR);
857 
858       if (n == -1 || (pfd.revents & ~POLLOUT) != 0) {
859         errno = EIO;
860         nsent = -1;
861         goto out;
862       }
863     }
864 
865     offset += nread;
866     nsent += nread;
867   }
868 
869 out:
870   if (nsent != -1)
871     req->off = offset;
872 
873   return nsent;
874 }
875 
876 
uv__fs_sendfile(uv_fs_t * req)877 static ssize_t uv__fs_sendfile(uv_fs_t* req) {
878   int in_fd;
879   int out_fd;
880 
881   in_fd = req->flags;
882   out_fd = req->file;
883 
884 #if defined(__linux__) || defined(__sun)
885   {
886     off_t off;
887     ssize_t r;
888 
889     off = req->off;
890     r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len);
891 
892     /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
893      * it still writes out data. Fortunately, we can detect it by checking if
894      * the offset has been updated.
895      */
896     if (r != -1 || off > req->off) {
897       r = off - req->off;
898       req->off = off;
899       return r;
900     }
901 
902     if (errno == EINVAL ||
903         errno == EIO ||
904         errno == ENOTSOCK ||
905         errno == EXDEV) {
906       errno = 0;
907       return uv__fs_sendfile_emul(req);
908     }
909 
910     return -1;
911   }
912 #elif defined(__APPLE__)           || \
913       defined(__DragonFly__)       || \
914       defined(__FreeBSD__)         || \
915       defined(__FreeBSD_kernel__)
916   {
917     off_t len;
918     ssize_t r;
919 
920     /* sendfile() on FreeBSD and Darwin returns EAGAIN if the target fd is in
921      * non-blocking mode and not all data could be written. If a non-zero
922      * number of bytes have been sent, we don't consider it an error.
923      */
924 
925 #if defined(__FreeBSD__) || defined(__DragonFly__)
926     len = 0;
927     r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
928 #elif defined(__FreeBSD_kernel__)
929     len = 0;
930     r = bsd_sendfile(in_fd,
931                      out_fd,
932                      req->off,
933                      req->bufsml[0].len,
934                      NULL,
935                      &len,
936                      0);
937 #else
938     /* The darwin sendfile takes len as an input for the length to send,
939      * so make sure to initialize it with the caller's value. */
940     len = req->bufsml[0].len;
941     r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
942 #endif
943 
944      /*
945      * The man page for sendfile(2) on DragonFly states that `len` contains
946      * a meaningful value ONLY in case of EAGAIN and EINTR.
947      * Nothing is said about it's value in case of other errors, so better
948      * not depend on the potential wrong assumption that is was not modified
949      * by the syscall.
950      */
951     if (r == 0 || ((errno == EAGAIN || errno == EINTR) && len != 0)) {
952       req->off += len;
953       return (ssize_t) len;
954     }
955 
956     if (errno == EINVAL ||
957         errno == EIO ||
958         errno == ENOTSOCK ||
959         errno == EXDEV) {
960       errno = 0;
961       return uv__fs_sendfile_emul(req);
962     }
963 
964     return -1;
965   }
966 #else
967   /* Squelch compiler warnings. */
968   (void) &in_fd;
969   (void) &out_fd;
970 
971   return uv__fs_sendfile_emul(req);
972 #endif
973 }
974 
975 
uv__fs_utime(uv_fs_t * req)976 static ssize_t uv__fs_utime(uv_fs_t* req) {
977 #if defined(__linux__)                                                         \
978     || defined(_AIX71)                                                         \
979     || defined(__sun)                                                          \
980     || defined(__HAIKU__)
981   /* utimesat() has nanosecond resolution but we stick to microseconds
982    * for the sake of consistency with other platforms.
983    */
984   struct timespec ts[2];
985   ts[0] = uv__fs_to_timespec(req->atime);
986   ts[1] = uv__fs_to_timespec(req->mtime);
987   return utimensat(AT_FDCWD, req->path, ts, 0);
988 #elif defined(__APPLE__)                                                      \
989     || defined(__DragonFly__)                                                 \
990     || defined(__FreeBSD__)                                                   \
991     || defined(__FreeBSD_kernel__)                                            \
992     || defined(__NetBSD__)                                                    \
993     || defined(__OpenBSD__)
994   struct timeval tv[2];
995   tv[0] = uv__fs_to_timeval(req->atime);
996   tv[1] = uv__fs_to_timeval(req->mtime);
997   return utimes(req->path, tv);
998 #elif defined(_AIX)                                                           \
999     && !defined(_AIX71)
1000   struct utimbuf buf;
1001   buf.actime = req->atime;
1002   buf.modtime = req->mtime;
1003   return utime(req->path, &buf);
1004 #elif defined(__MVS__)
1005   attrib_t atr;
1006   memset(&atr, 0, sizeof(atr));
1007   atr.att_mtimechg = 1;
1008   atr.att_atimechg = 1;
1009   atr.att_mtime = req->mtime;
1010   atr.att_atime = req->atime;
1011   return __lchattr((char*) req->path, &atr, sizeof(atr));
1012 #else
1013   errno = ENOSYS;
1014   return -1;
1015 #endif
1016 }
1017 
1018 
uv__fs_lutime(uv_fs_t * req)1019 static ssize_t uv__fs_lutime(uv_fs_t* req) {
1020 #if defined(__linux__)            ||                                           \
1021     defined(_AIX71)               ||                                           \
1022     defined(__sun)                ||                                           \
1023     defined(__HAIKU__)
1024   struct timespec ts[2];
1025   ts[0] = uv__fs_to_timespec(req->atime);
1026   ts[1] = uv__fs_to_timespec(req->mtime);
1027   return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW);
1028 #elif defined(__APPLE__)          ||                                          \
1029       defined(__DragonFly__)      ||                                          \
1030       defined(__FreeBSD__)        ||                                          \
1031       defined(__FreeBSD_kernel__) ||                                          \
1032       defined(__NetBSD__)
1033   struct timeval tv[2];
1034   tv[0] = uv__fs_to_timeval(req->atime);
1035   tv[1] = uv__fs_to_timeval(req->mtime);
1036   return lutimes(req->path, tv);
1037 #else
1038   errno = ENOSYS;
1039   return -1;
1040 #endif
1041 }
1042 
1043 
uv__fs_write(uv_fs_t * req)1044 static ssize_t uv__fs_write(uv_fs_t* req) {
1045 #if defined(__linux__)
1046   static int no_pwritev;
1047 #endif
1048   ssize_t r;
1049 
1050   /* Serialize writes on OS X, concurrent write() and pwrite() calls result in
1051    * data loss. We can't use a per-file descriptor lock, the descriptor may be
1052    * a dup().
1053    */
1054 #if defined(__APPLE__)
1055   static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1056 
1057   if (pthread_mutex_lock(&lock))
1058     abort();
1059 #endif
1060 
1061   if (req->off < 0) {
1062     if (req->nbufs == 1)
1063       r = write(req->file, req->bufs[0].base, req->bufs[0].len);
1064     else
1065       r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
1066   } else {
1067     if (req->nbufs == 1) {
1068       r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
1069       goto done;
1070     }
1071 #if HAVE_PREADV
1072     r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
1073 #else
1074 # if defined(__linux__)
1075     if (no_pwritev) retry:
1076 # endif
1077     {
1078       r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
1079     }
1080 # if defined(__linux__)
1081     else {
1082       r = uv__pwritev(req->file,
1083                       (struct iovec*) req->bufs,
1084                       req->nbufs,
1085                       req->off);
1086       if (r == -1 && errno == ENOSYS) {
1087         no_pwritev = 1;
1088         goto retry;
1089       }
1090     }
1091 # endif
1092 #endif
1093   }
1094 
1095 done:
1096 #if defined(__APPLE__)
1097   if (pthread_mutex_unlock(&lock))
1098     abort();
1099 #endif
1100 
1101   return r;
1102 }
1103 
uv__fs_copyfile(uv_fs_t * req)1104 static ssize_t uv__fs_copyfile(uv_fs_t* req) {
1105   uv_fs_t fs_req;
1106   uv_file srcfd;
1107   uv_file dstfd;
1108   struct stat src_statsbuf;
1109   struct stat dst_statsbuf;
1110   int dst_flags;
1111   int result;
1112   int err;
1113   size_t bytes_to_send;
1114   int64_t in_offset;
1115   ssize_t bytes_written;
1116 
1117   dstfd = -1;
1118   err = 0;
1119 
1120   /* Open the source file. */
1121   srcfd = uv_fs_open(NULL, &fs_req, req->path, O_RDONLY, 0, NULL);
1122   uv_fs_req_cleanup(&fs_req);
1123 
1124   if (srcfd < 0)
1125     return srcfd;
1126 
1127   /* Get the source file's mode. */
1128   if (fstat(srcfd, &src_statsbuf)) {
1129     err = UV__ERR(errno);
1130     goto out;
1131   }
1132 
1133   dst_flags = O_WRONLY | O_CREAT | O_TRUNC;
1134 
1135   if (req->flags & UV_FS_COPYFILE_EXCL)
1136     dst_flags |= O_EXCL;
1137 
1138   /* Open the destination file. */
1139   dstfd = uv_fs_open(NULL,
1140                      &fs_req,
1141                      req->new_path,
1142                      dst_flags,
1143                      src_statsbuf.st_mode,
1144                      NULL);
1145   uv_fs_req_cleanup(&fs_req);
1146 
1147   if (dstfd < 0) {
1148     err = dstfd;
1149     goto out;
1150   }
1151 
1152   /* Get the destination file's mode. */
1153   if (fstat(dstfd, &dst_statsbuf)) {
1154     err = UV__ERR(errno);
1155     goto out;
1156   }
1157 
1158   /* Check if srcfd and dstfd refer to the same file */
1159   if (src_statsbuf.st_dev == dst_statsbuf.st_dev &&
1160       src_statsbuf.st_ino == dst_statsbuf.st_ino) {
1161     goto out;
1162   }
1163 
1164   if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
1165     err = UV__ERR(errno);
1166 #ifdef __linux__
1167     if (err != UV_EPERM)
1168       goto out;
1169 
1170     {
1171       struct statfs s;
1172 
1173       /* fchmod() on CIFS shares always fails with EPERM unless the share is
1174        * mounted with "noperm". As fchmod() is a meaningless operation on such
1175        * shares anyway, detect that condition and squelch the error.
1176        */
1177       if (fstatfs(dstfd, &s) == -1)
1178         goto out;
1179 
1180       if (s.f_type != /* CIFS */ 0xFF534D42u)
1181         goto out;
1182     }
1183 
1184     err = 0;
1185 #else  /* !__linux__ */
1186     goto out;
1187 #endif  /* !__linux__ */
1188   }
1189 
1190 #ifdef FICLONE
1191   if (req->flags & UV_FS_COPYFILE_FICLONE ||
1192       req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
1193     if (ioctl(dstfd, FICLONE, srcfd) == 0) {
1194       /* ioctl() with FICLONE succeeded. */
1195       goto out;
1196     }
1197     /* If an error occurred and force was set, return the error to the caller;
1198      * fall back to sendfile() when force was not set. */
1199     if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
1200       err = UV__ERR(errno);
1201       goto out;
1202     }
1203   }
1204 #else
1205   if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
1206     err = UV_ENOSYS;
1207     goto out;
1208   }
1209 #endif
1210 
1211   bytes_to_send = src_statsbuf.st_size;
1212   in_offset = 0;
1213   while (bytes_to_send != 0) {
1214     uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_to_send, NULL);
1215     bytes_written = fs_req.result;
1216     uv_fs_req_cleanup(&fs_req);
1217 
1218     if (bytes_written < 0) {
1219       err = bytes_written;
1220       break;
1221     }
1222 
1223     bytes_to_send -= bytes_written;
1224     in_offset += bytes_written;
1225   }
1226 
1227 out:
1228   if (err < 0)
1229     result = err;
1230   else
1231     result = 0;
1232 
1233   /* Close the source file. */
1234   err = uv__close_nocheckstdio(srcfd);
1235 
1236   /* Don't overwrite any existing errors. */
1237   if (err != 0 && result == 0)
1238     result = err;
1239 
1240   /* Close the destination file if it is open. */
1241   if (dstfd >= 0) {
1242     err = uv__close_nocheckstdio(dstfd);
1243 
1244     /* Don't overwrite any existing errors. */
1245     if (err != 0 && result == 0)
1246       result = err;
1247 
1248     /* Remove the destination file if something went wrong. */
1249     if (result != 0) {
1250       uv_fs_unlink(NULL, &fs_req, req->new_path, NULL);
1251       /* Ignore the unlink return value, as an error already happened. */
1252       uv_fs_req_cleanup(&fs_req);
1253     }
1254   }
1255 
1256   if (result == 0)
1257     return 0;
1258 
1259   errno = UV__ERR(result);
1260   return -1;
1261 }
1262 
uv__to_stat(struct stat * src,uv_stat_t * dst)1263 static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
1264   dst->st_dev = src->st_dev;
1265   dst->st_mode = src->st_mode;
1266   dst->st_nlink = src->st_nlink;
1267   dst->st_uid = src->st_uid;
1268   dst->st_gid = src->st_gid;
1269   dst->st_rdev = src->st_rdev;
1270   dst->st_ino = src->st_ino;
1271   dst->st_size = src->st_size;
1272   dst->st_blksize = src->st_blksize;
1273   dst->st_blocks = src->st_blocks;
1274 
1275 #if defined(__APPLE__)
1276   dst->st_atim.tv_sec = src->st_atimespec.tv_sec;
1277   dst->st_atim.tv_nsec = src->st_atimespec.tv_nsec;
1278   dst->st_mtim.tv_sec = src->st_mtimespec.tv_sec;
1279   dst->st_mtim.tv_nsec = src->st_mtimespec.tv_nsec;
1280   dst->st_ctim.tv_sec = src->st_ctimespec.tv_sec;
1281   dst->st_ctim.tv_nsec = src->st_ctimespec.tv_nsec;
1282   dst->st_birthtim.tv_sec = src->st_birthtimespec.tv_sec;
1283   dst->st_birthtim.tv_nsec = src->st_birthtimespec.tv_nsec;
1284   dst->st_flags = src->st_flags;
1285   dst->st_gen = src->st_gen;
1286 #elif defined(__ANDROID__)
1287   dst->st_atim.tv_sec = src->st_atime;
1288   dst->st_atim.tv_nsec = src->st_atimensec;
1289   dst->st_mtim.tv_sec = src->st_mtime;
1290   dst->st_mtim.tv_nsec = src->st_mtimensec;
1291   dst->st_ctim.tv_sec = src->st_ctime;
1292   dst->st_ctim.tv_nsec = src->st_ctimensec;
1293   dst->st_birthtim.tv_sec = src->st_ctime;
1294   dst->st_birthtim.tv_nsec = src->st_ctimensec;
1295   dst->st_flags = 0;
1296   dst->st_gen = 0;
1297 #elif !defined(_AIX) && (       \
1298     defined(__DragonFly__)   || \
1299     defined(__FreeBSD__)     || \
1300     defined(__OpenBSD__)     || \
1301     defined(__NetBSD__)      || \
1302     defined(_GNU_SOURCE)     || \
1303     defined(_BSD_SOURCE)     || \
1304     defined(_SVID_SOURCE)    || \
1305     defined(_XOPEN_SOURCE)   || \
1306     defined(_DEFAULT_SOURCE))
1307   dst->st_atim.tv_sec = src->st_atim.tv_sec;
1308   dst->st_atim.tv_nsec = src->st_atim.tv_nsec;
1309   dst->st_mtim.tv_sec = src->st_mtim.tv_sec;
1310   dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
1311   dst->st_ctim.tv_sec = src->st_ctim.tv_sec;
1312   dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
1313 # if defined(__FreeBSD__)    || \
1314      defined(__NetBSD__)
1315   dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec;
1316   dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec;
1317   dst->st_flags = src->st_flags;
1318   dst->st_gen = src->st_gen;
1319 # else
1320   dst->st_birthtim.tv_sec = src->st_ctim.tv_sec;
1321   dst->st_birthtim.tv_nsec = src->st_ctim.tv_nsec;
1322   dst->st_flags = 0;
1323   dst->st_gen = 0;
1324 # endif
1325 #else
1326   dst->st_atim.tv_sec = src->st_atime;
1327   dst->st_atim.tv_nsec = 0;
1328   dst->st_mtim.tv_sec = src->st_mtime;
1329   dst->st_mtim.tv_nsec = 0;
1330   dst->st_ctim.tv_sec = src->st_ctime;
1331   dst->st_ctim.tv_nsec = 0;
1332   dst->st_birthtim.tv_sec = src->st_ctime;
1333   dst->st_birthtim.tv_nsec = 0;
1334   dst->st_flags = 0;
1335   dst->st_gen = 0;
1336 #endif
1337 }
1338 
1339 
uv__fs_statx(int fd,const char * path,int is_fstat,int is_lstat,uv_stat_t * buf)1340 static int uv__fs_statx(int fd,
1341                         const char* path,
1342                         int is_fstat,
1343                         int is_lstat,
1344                         uv_stat_t* buf) {
1345   STATIC_ASSERT(UV_ENOSYS != -1);
1346 #ifdef __linux__
1347   static int no_statx;
1348   struct uv__statx statxbuf;
1349   int dirfd;
1350   int flags;
1351   int mode;
1352   int rc;
1353 
1354   if (no_statx)
1355     return UV_ENOSYS;
1356 
1357   dirfd = AT_FDCWD;
1358   flags = 0; /* AT_STATX_SYNC_AS_STAT */
1359   mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */
1360 
1361   if (is_fstat) {
1362     dirfd = fd;
1363     flags |= 0x1000; /* AT_EMPTY_PATH */
1364   }
1365 
1366   if (is_lstat)
1367     flags |= AT_SYMLINK_NOFOLLOW;
1368 
1369   rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
1370 
1371   switch (rc) {
1372   case 0:
1373     break;
1374   case -1:
1375     /* EPERM happens when a seccomp filter rejects the system call.
1376      * Has been observed with libseccomp < 2.3.3 and docker < 18.04.
1377      */
1378     if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
1379       return -1;
1380     /* Fall through. */
1381   default:
1382     /* Normally on success, zero is returned and On error, -1 is returned.
1383      * Observed on S390 RHEL running in a docker container with statx not
1384      * implemented, rc might return 1 with 0 set as the error code in which
1385      * case we return ENOSYS.
1386      */
1387     no_statx = 1;
1388     return UV_ENOSYS;
1389   }
1390 
1391   buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;
1392   buf->st_mode = statxbuf.stx_mode;
1393   buf->st_nlink = statxbuf.stx_nlink;
1394   buf->st_uid = statxbuf.stx_uid;
1395   buf->st_gid = statxbuf.stx_gid;
1396   buf->st_rdev = statxbuf.stx_rdev_major;
1397   buf->st_ino = statxbuf.stx_ino;
1398   buf->st_size = statxbuf.stx_size;
1399   buf->st_blksize = statxbuf.stx_blksize;
1400   buf->st_blocks = statxbuf.stx_blocks;
1401   buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec;
1402   buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec;
1403   buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec;
1404   buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec;
1405   buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec;
1406   buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec;
1407   buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec;
1408   buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec;
1409   buf->st_flags = 0;
1410   buf->st_gen = 0;
1411 
1412   return 0;
1413 #else
1414   return UV_ENOSYS;
1415 #endif /* __linux__ */
1416 }
1417 
1418 
uv__fs_stat(const char * path,uv_stat_t * buf)1419 static int uv__fs_stat(const char *path, uv_stat_t *buf) {
1420   struct stat pbuf;
1421   int ret;
1422 
1423   ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf);
1424   if (ret != UV_ENOSYS)
1425     return ret;
1426 
1427   ret = stat(path, &pbuf);
1428   if (ret == 0)
1429     uv__to_stat(&pbuf, buf);
1430 
1431   return ret;
1432 }
1433 
1434 
uv__fs_lstat(const char * path,uv_stat_t * buf)1435 static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
1436   struct stat pbuf;
1437   int ret;
1438 
1439   ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf);
1440   if (ret != UV_ENOSYS)
1441     return ret;
1442 
1443   ret = lstat(path, &pbuf);
1444   if (ret == 0)
1445     uv__to_stat(&pbuf, buf);
1446 
1447   return ret;
1448 }
1449 
1450 
uv__fs_fstat(int fd,uv_stat_t * buf)1451 static int uv__fs_fstat(int fd, uv_stat_t *buf) {
1452   struct stat pbuf;
1453   int ret;
1454 
1455   ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf);
1456   if (ret != UV_ENOSYS)
1457     return ret;
1458 
1459   ret = fstat(fd, &pbuf);
1460   if (ret == 0)
1461     uv__to_stat(&pbuf, buf);
1462 
1463   return ret;
1464 }
1465 
uv__fs_buf_offset(uv_buf_t * bufs,size_t size)1466 static size_t uv__fs_buf_offset(uv_buf_t* bufs, size_t size) {
1467   size_t offset;
1468   /* Figure out which bufs are done */
1469   for (offset = 0; size > 0 && bufs[offset].len <= size; ++offset)
1470     size -= bufs[offset].len;
1471 
1472   /* Fix a partial read/write */
1473   if (size > 0) {
1474     bufs[offset].base += size;
1475     bufs[offset].len -= size;
1476   }
1477   return offset;
1478 }
1479 
uv__fs_write_all(uv_fs_t * req)1480 static ssize_t uv__fs_write_all(uv_fs_t* req) {
1481   unsigned int iovmax;
1482   unsigned int nbufs;
1483   uv_buf_t* bufs;
1484   ssize_t total;
1485   ssize_t result;
1486 
1487   iovmax = uv__getiovmax();
1488   nbufs = req->nbufs;
1489   bufs = req->bufs;
1490   total = 0;
1491 
1492   while (nbufs > 0) {
1493     req->nbufs = nbufs;
1494     if (req->nbufs > iovmax)
1495       req->nbufs = iovmax;
1496 
1497     do
1498       result = uv__fs_write(req);
1499     while (result < 0 && errno == EINTR);
1500 
1501     if (result <= 0) {
1502       if (total == 0)
1503         total = result;
1504       break;
1505     }
1506 
1507     if (req->off >= 0)
1508       req->off += result;
1509 
1510     req->nbufs = uv__fs_buf_offset(req->bufs, result);
1511     req->bufs += req->nbufs;
1512     nbufs -= req->nbufs;
1513     total += result;
1514   }
1515 
1516   if (bufs != req->bufsml)
1517     uv__free(bufs);
1518 
1519   req->bufs = NULL;
1520   req->nbufs = 0;
1521 
1522   return total;
1523 }
1524 
1525 
uv__fs_work(struct uv__work * w)1526 static void uv__fs_work(struct uv__work* w) {
1527   int retry_on_eintr;
1528   uv_fs_t* req;
1529   ssize_t r;
1530 
1531   req = container_of(w, uv_fs_t, work_req);
1532   retry_on_eintr = !(req->fs_type == UV_FS_CLOSE ||
1533                      req->fs_type == UV_FS_READ);
1534 
1535   do {
1536     errno = 0;
1537 
1538 #define X(type, action)                                                       \
1539   case UV_FS_ ## type:                                                        \
1540     r = action;                                                               \
1541     break;
1542 
1543     switch (req->fs_type) {
1544     X(ACCESS, access(req->path, req->flags));
1545     X(CHMOD, chmod(req->path, req->mode));
1546     X(CHOWN, chown(req->path, req->uid, req->gid));
1547     X(CLOSE, uv__fs_close(req->file));
1548     X(COPYFILE, uv__fs_copyfile(req));
1549     X(FCHMOD, fchmod(req->file, req->mode));
1550     X(FCHOWN, fchown(req->file, req->uid, req->gid));
1551     X(LCHOWN, lchown(req->path, req->uid, req->gid));
1552     X(FDATASYNC, uv__fs_fdatasync(req));
1553     X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
1554     X(FSYNC, uv__fs_fsync(req));
1555     X(FTRUNCATE, ftruncate(req->file, req->off));
1556     X(FUTIME, uv__fs_futime(req));
1557     X(LUTIME, uv__fs_lutime(req));
1558     X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
1559     X(LINK, link(req->path, req->new_path));
1560     X(MKDIR, mkdir(req->path, req->mode));
1561     X(MKDTEMP, uv__fs_mkdtemp(req));
1562     X(MKSTEMP, uv__fs_mkstemp(req));
1563     X(OPEN, uv__fs_open(req));
1564     X(READ, uv__fs_read(req));
1565     X(SCANDIR, uv__fs_scandir(req));
1566     X(OPENDIR, uv__fs_opendir(req));
1567     X(READDIR, uv__fs_readdir(req));
1568     X(CLOSEDIR, uv__fs_closedir(req));
1569     X(READLINK, uv__fs_readlink(req));
1570     X(REALPATH, uv__fs_realpath(req));
1571     X(RENAME, rename(req->path, req->new_path));
1572     X(RMDIR, rmdir(req->path));
1573     X(SENDFILE, uv__fs_sendfile(req));
1574     X(STAT, uv__fs_stat(req->path, &req->statbuf));
1575     X(STATFS, uv__fs_statfs(req));
1576     X(SYMLINK, symlink(req->path, req->new_path));
1577     X(UNLINK, unlink(req->path));
1578     X(UTIME, uv__fs_utime(req));
1579     X(WRITE, uv__fs_write_all(req));
1580     default: abort();
1581     }
1582 #undef X
1583   } while (r == -1 && errno == EINTR && retry_on_eintr);
1584 
1585   if (r == -1)
1586     req->result = UV__ERR(errno);
1587   else
1588     req->result = r;
1589 
1590   if (r == 0 && (req->fs_type == UV_FS_STAT ||
1591                  req->fs_type == UV_FS_FSTAT ||
1592                  req->fs_type == UV_FS_LSTAT)) {
1593     req->ptr = &req->statbuf;
1594   }
1595 }
1596 
1597 
uv__fs_done(struct uv__work * w,int status)1598 static void uv__fs_done(struct uv__work* w, int status) {
1599   uv_fs_t* req;
1600 
1601   req = container_of(w, uv_fs_t, work_req);
1602   uv__req_unregister(req->loop, req);
1603 
1604   if (status == UV_ECANCELED) {
1605     assert(req->result == 0);
1606     req->result = UV_ECANCELED;
1607   }
1608 
1609   req->cb(req);
1610 }
1611 
1612 
uv_fs_access(uv_loop_t * loop,uv_fs_t * req,const char * path,int flags,uv_fs_cb cb)1613 int uv_fs_access(uv_loop_t* loop,
1614                  uv_fs_t* req,
1615                  const char* path,
1616                  int flags,
1617                  uv_fs_cb cb) {
1618   INIT(ACCESS);
1619   PATH;
1620   req->flags = flags;
1621   POST;
1622 }
1623 
1624 
uv_fs_chmod(uv_loop_t * loop,uv_fs_t * req,const char * path,int mode,uv_fs_cb cb)1625 int uv_fs_chmod(uv_loop_t* loop,
1626                 uv_fs_t* req,
1627                 const char* path,
1628                 int mode,
1629                 uv_fs_cb cb) {
1630   INIT(CHMOD);
1631   PATH;
1632   req->mode = mode;
1633   POST;
1634 }
1635 
1636 
uv_fs_chown(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_uid_t uid,uv_gid_t gid,uv_fs_cb cb)1637 int uv_fs_chown(uv_loop_t* loop,
1638                 uv_fs_t* req,
1639                 const char* path,
1640                 uv_uid_t uid,
1641                 uv_gid_t gid,
1642                 uv_fs_cb cb) {
1643   INIT(CHOWN);
1644   PATH;
1645   req->uid = uid;
1646   req->gid = gid;
1647   POST;
1648 }
1649 
1650 
uv_fs_close(uv_loop_t * loop,uv_fs_t * req,uv_file file,uv_fs_cb cb)1651 int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1652   INIT(CLOSE);
1653   req->file = file;
1654   POST;
1655 }
1656 
1657 
uv_fs_fchmod(uv_loop_t * loop,uv_fs_t * req,uv_file file,int mode,uv_fs_cb cb)1658 int uv_fs_fchmod(uv_loop_t* loop,
1659                  uv_fs_t* req,
1660                  uv_file file,
1661                  int mode,
1662                  uv_fs_cb cb) {
1663   INIT(FCHMOD);
1664   req->file = file;
1665   req->mode = mode;
1666   POST;
1667 }
1668 
1669 
uv_fs_fchown(uv_loop_t * loop,uv_fs_t * req,uv_file file,uv_uid_t uid,uv_gid_t gid,uv_fs_cb cb)1670 int uv_fs_fchown(uv_loop_t* loop,
1671                  uv_fs_t* req,
1672                  uv_file file,
1673                  uv_uid_t uid,
1674                  uv_gid_t gid,
1675                  uv_fs_cb cb) {
1676   INIT(FCHOWN);
1677   req->file = file;
1678   req->uid = uid;
1679   req->gid = gid;
1680   POST;
1681 }
1682 
1683 
uv_fs_lchown(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_uid_t uid,uv_gid_t gid,uv_fs_cb cb)1684 int uv_fs_lchown(uv_loop_t* loop,
1685                  uv_fs_t* req,
1686                  const char* path,
1687                  uv_uid_t uid,
1688                  uv_gid_t gid,
1689                  uv_fs_cb cb) {
1690   INIT(LCHOWN);
1691   PATH;
1692   req->uid = uid;
1693   req->gid = gid;
1694   POST;
1695 }
1696 
1697 
uv_fs_fdatasync(uv_loop_t * loop,uv_fs_t * req,uv_file file,uv_fs_cb cb)1698 int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1699   INIT(FDATASYNC);
1700   req->file = file;
1701   POST;
1702 }
1703 
1704 
uv_fs_fstat(uv_loop_t * loop,uv_fs_t * req,uv_file file,uv_fs_cb cb)1705 int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1706   INIT(FSTAT);
1707   req->file = file;
1708   POST;
1709 }
1710 
1711 
uv_fs_fsync(uv_loop_t * loop,uv_fs_t * req,uv_file file,uv_fs_cb cb)1712 int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1713   INIT(FSYNC);
1714   req->file = file;
1715   POST;
1716 }
1717 
1718 
uv_fs_ftruncate(uv_loop_t * loop,uv_fs_t * req,uv_file file,int64_t off,uv_fs_cb cb)1719 int uv_fs_ftruncate(uv_loop_t* loop,
1720                     uv_fs_t* req,
1721                     uv_file file,
1722                     int64_t off,
1723                     uv_fs_cb cb) {
1724   INIT(FTRUNCATE);
1725   req->file = file;
1726   req->off = off;
1727   POST;
1728 }
1729 
1730 
uv_fs_futime(uv_loop_t * loop,uv_fs_t * req,uv_file file,double atime,double mtime,uv_fs_cb cb)1731 int uv_fs_futime(uv_loop_t* loop,
1732                  uv_fs_t* req,
1733                  uv_file file,
1734                  double atime,
1735                  double mtime,
1736                  uv_fs_cb cb) {
1737   INIT(FUTIME);
1738   req->file = file;
1739   req->atime = atime;
1740   req->mtime = mtime;
1741   POST;
1742 }
1743 
uv_fs_lutime(uv_loop_t * loop,uv_fs_t * req,const char * path,double atime,double mtime,uv_fs_cb cb)1744 int uv_fs_lutime(uv_loop_t* loop,
1745                  uv_fs_t* req,
1746                  const char* path,
1747                  double atime,
1748                  double mtime,
1749                  uv_fs_cb cb) {
1750   INIT(LUTIME);
1751   PATH;
1752   req->atime = atime;
1753   req->mtime = mtime;
1754   POST;
1755 }
1756 
1757 
uv_fs_lstat(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_fs_cb cb)1758 int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1759   INIT(LSTAT);
1760   PATH;
1761   POST;
1762 }
1763 
1764 
uv_fs_link(uv_loop_t * loop,uv_fs_t * req,const char * path,const char * new_path,uv_fs_cb cb)1765 int uv_fs_link(uv_loop_t* loop,
1766                uv_fs_t* req,
1767                const char* path,
1768                const char* new_path,
1769                uv_fs_cb cb) {
1770   INIT(LINK);
1771   PATH2;
1772   POST;
1773 }
1774 
1775 
uv_fs_mkdir(uv_loop_t * loop,uv_fs_t * req,const char * path,int mode,uv_fs_cb cb)1776 int uv_fs_mkdir(uv_loop_t* loop,
1777                 uv_fs_t* req,
1778                 const char* path,
1779                 int mode,
1780                 uv_fs_cb cb) {
1781   INIT(MKDIR);
1782   PATH;
1783   req->mode = mode;
1784   POST;
1785 }
1786 
1787 
uv_fs_mkdtemp(uv_loop_t * loop,uv_fs_t * req,const char * tpl,uv_fs_cb cb)1788 int uv_fs_mkdtemp(uv_loop_t* loop,
1789                   uv_fs_t* req,
1790                   const char* tpl,
1791                   uv_fs_cb cb) {
1792   INIT(MKDTEMP);
1793   req->path = uv__strdup(tpl);
1794   if (req->path == NULL)
1795     return UV_ENOMEM;
1796   POST;
1797 }
1798 
1799 
uv_fs_mkstemp(uv_loop_t * loop,uv_fs_t * req,const char * tpl,uv_fs_cb cb)1800 int uv_fs_mkstemp(uv_loop_t* loop,
1801                   uv_fs_t* req,
1802                   const char* tpl,
1803                   uv_fs_cb cb) {
1804   INIT(MKSTEMP);
1805   req->path = uv__strdup(tpl);
1806   if (req->path == NULL)
1807     return UV_ENOMEM;
1808   POST;
1809 }
1810 
1811 
uv_fs_open(uv_loop_t * loop,uv_fs_t * req,const char * path,int flags,int mode,uv_fs_cb cb)1812 int uv_fs_open(uv_loop_t* loop,
1813                uv_fs_t* req,
1814                const char* path,
1815                int flags,
1816                int mode,
1817                uv_fs_cb cb) {
1818   INIT(OPEN);
1819   PATH;
1820   req->flags = flags;
1821   req->mode = mode;
1822   POST;
1823 }
1824 
1825 
uv_fs_read(uv_loop_t * loop,uv_fs_t * req,uv_file file,const uv_buf_t bufs[],unsigned int nbufs,int64_t off,uv_fs_cb cb)1826 int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
1827                uv_file file,
1828                const uv_buf_t bufs[],
1829                unsigned int nbufs,
1830                int64_t off,
1831                uv_fs_cb cb) {
1832   INIT(READ);
1833 
1834   if (bufs == NULL || nbufs == 0)
1835     return UV_EINVAL;
1836 
1837   req->file = file;
1838 
1839   req->nbufs = nbufs;
1840   req->bufs = req->bufsml;
1841   if (nbufs > ARRAY_SIZE(req->bufsml))
1842     req->bufs = uv__malloc(nbufs * sizeof(*bufs));
1843 
1844   if (req->bufs == NULL)
1845     return UV_ENOMEM;
1846 
1847   memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
1848 
1849   req->off = off;
1850   POST;
1851 }
1852 
1853 
uv_fs_scandir(uv_loop_t * loop,uv_fs_t * req,const char * path,int flags,uv_fs_cb cb)1854 int uv_fs_scandir(uv_loop_t* loop,
1855                   uv_fs_t* req,
1856                   const char* path,
1857                   int flags,
1858                   uv_fs_cb cb) {
1859   INIT(SCANDIR);
1860   PATH;
1861   req->flags = flags;
1862   POST;
1863 }
1864 
uv_fs_opendir(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_fs_cb cb)1865 int uv_fs_opendir(uv_loop_t* loop,
1866                   uv_fs_t* req,
1867                   const char* path,
1868                   uv_fs_cb cb) {
1869   INIT(OPENDIR);
1870   PATH;
1871   POST;
1872 }
1873 
uv_fs_readdir(uv_loop_t * loop,uv_fs_t * req,uv_dir_t * dir,uv_fs_cb cb)1874 int uv_fs_readdir(uv_loop_t* loop,
1875                   uv_fs_t* req,
1876                   uv_dir_t* dir,
1877                   uv_fs_cb cb) {
1878   INIT(READDIR);
1879 
1880   if (dir == NULL || dir->dir == NULL || dir->dirents == NULL)
1881     return UV_EINVAL;
1882 
1883   req->ptr = dir;
1884   POST;
1885 }
1886 
uv_fs_closedir(uv_loop_t * loop,uv_fs_t * req,uv_dir_t * dir,uv_fs_cb cb)1887 int uv_fs_closedir(uv_loop_t* loop,
1888                    uv_fs_t* req,
1889                    uv_dir_t* dir,
1890                    uv_fs_cb cb) {
1891   INIT(CLOSEDIR);
1892 
1893   if (dir == NULL)
1894     return UV_EINVAL;
1895 
1896   req->ptr = dir;
1897   POST;
1898 }
1899 
uv_fs_readlink(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_fs_cb cb)1900 int uv_fs_readlink(uv_loop_t* loop,
1901                    uv_fs_t* req,
1902                    const char* path,
1903                    uv_fs_cb cb) {
1904   INIT(READLINK);
1905   PATH;
1906   POST;
1907 }
1908 
1909 
uv_fs_realpath(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_fs_cb cb)1910 int uv_fs_realpath(uv_loop_t* loop,
1911                   uv_fs_t* req,
1912                   const char * path,
1913                   uv_fs_cb cb) {
1914   INIT(REALPATH);
1915   PATH;
1916   POST;
1917 }
1918 
1919 
uv_fs_rename(uv_loop_t * loop,uv_fs_t * req,const char * path,const char * new_path,uv_fs_cb cb)1920 int uv_fs_rename(uv_loop_t* loop,
1921                  uv_fs_t* req,
1922                  const char* path,
1923                  const char* new_path,
1924                  uv_fs_cb cb) {
1925   INIT(RENAME);
1926   PATH2;
1927   POST;
1928 }
1929 
1930 
uv_fs_rmdir(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_fs_cb cb)1931 int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1932   INIT(RMDIR);
1933   PATH;
1934   POST;
1935 }
1936 
1937 
uv_fs_sendfile(uv_loop_t * loop,uv_fs_t * req,uv_file out_fd,uv_file in_fd,int64_t off,size_t len,uv_fs_cb cb)1938 int uv_fs_sendfile(uv_loop_t* loop,
1939                    uv_fs_t* req,
1940                    uv_file out_fd,
1941                    uv_file in_fd,
1942                    int64_t off,
1943                    size_t len,
1944                    uv_fs_cb cb) {
1945   INIT(SENDFILE);
1946   req->flags = in_fd; /* hack */
1947   req->file = out_fd;
1948   req->off = off;
1949   req->bufsml[0].len = len;
1950   POST;
1951 }
1952 
1953 
uv_fs_stat(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_fs_cb cb)1954 int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1955   INIT(STAT);
1956   PATH;
1957   POST;
1958 }
1959 
1960 
uv_fs_symlink(uv_loop_t * loop,uv_fs_t * req,const char * path,const char * new_path,int flags,uv_fs_cb cb)1961 int uv_fs_symlink(uv_loop_t* loop,
1962                   uv_fs_t* req,
1963                   const char* path,
1964                   const char* new_path,
1965                   int flags,
1966                   uv_fs_cb cb) {
1967   INIT(SYMLINK);
1968   PATH2;
1969   req->flags = flags;
1970   POST;
1971 }
1972 
1973 
uv_fs_unlink(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_fs_cb cb)1974 int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1975   INIT(UNLINK);
1976   PATH;
1977   POST;
1978 }
1979 
1980 
uv_fs_utime(uv_loop_t * loop,uv_fs_t * req,const char * path,double atime,double mtime,uv_fs_cb cb)1981 int uv_fs_utime(uv_loop_t* loop,
1982                 uv_fs_t* req,
1983                 const char* path,
1984                 double atime,
1985                 double mtime,
1986                 uv_fs_cb cb) {
1987   INIT(UTIME);
1988   PATH;
1989   req->atime = atime;
1990   req->mtime = mtime;
1991   POST;
1992 }
1993 
1994 
uv_fs_write(uv_loop_t * loop,uv_fs_t * req,uv_file file,const uv_buf_t bufs[],unsigned int nbufs,int64_t off,uv_fs_cb cb)1995 int uv_fs_write(uv_loop_t* loop,
1996                 uv_fs_t* req,
1997                 uv_file file,
1998                 const uv_buf_t bufs[],
1999                 unsigned int nbufs,
2000                 int64_t off,
2001                 uv_fs_cb cb) {
2002   INIT(WRITE);
2003 
2004   if (bufs == NULL || nbufs == 0)
2005     return UV_EINVAL;
2006 
2007   req->file = file;
2008 
2009   req->nbufs = nbufs;
2010   req->bufs = req->bufsml;
2011   if (nbufs > ARRAY_SIZE(req->bufsml))
2012     req->bufs = uv__malloc(nbufs * sizeof(*bufs));
2013 
2014   if (req->bufs == NULL)
2015     return UV_ENOMEM;
2016 
2017   memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
2018 
2019   req->off = off;
2020   POST;
2021 }
2022 
2023 
uv_fs_req_cleanup(uv_fs_t * req)2024 void uv_fs_req_cleanup(uv_fs_t* req) {
2025   if (req == NULL)
2026     return;
2027 
2028   /* Only necessary for asychronous requests, i.e., requests with a callback.
2029    * Synchronous ones don't copy their arguments and have req->path and
2030    * req->new_path pointing to user-owned memory.  UV_FS_MKDTEMP and
2031    * UV_FS_MKSTEMP are the exception to the rule, they always allocate memory.
2032    */
2033   if (req->path != NULL &&
2034       (req->cb != NULL ||
2035         req->fs_type == UV_FS_MKDTEMP || req->fs_type == UV_FS_MKSTEMP))
2036     uv__free((void*) req->path);  /* Memory is shared with req->new_path. */
2037 
2038   req->path = NULL;
2039   req->new_path = NULL;
2040 
2041   if (req->fs_type == UV_FS_READDIR && req->ptr != NULL)
2042     uv__fs_readdir_cleanup(req);
2043 
2044   if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
2045     uv__fs_scandir_cleanup(req);
2046 
2047   if (req->bufs != req->bufsml)
2048     uv__free(req->bufs);
2049   req->bufs = NULL;
2050 
2051   if (req->fs_type != UV_FS_OPENDIR && req->ptr != &req->statbuf)
2052     uv__free(req->ptr);
2053   req->ptr = NULL;
2054 }
2055 
2056 
uv_fs_copyfile(uv_loop_t * loop,uv_fs_t * req,const char * path,const char * new_path,int flags,uv_fs_cb cb)2057 int uv_fs_copyfile(uv_loop_t* loop,
2058                    uv_fs_t* req,
2059                    const char* path,
2060                    const char* new_path,
2061                    int flags,
2062                    uv_fs_cb cb) {
2063   INIT(COPYFILE);
2064 
2065   if (flags & ~(UV_FS_COPYFILE_EXCL |
2066                 UV_FS_COPYFILE_FICLONE |
2067                 UV_FS_COPYFILE_FICLONE_FORCE)) {
2068     return UV_EINVAL;
2069   }
2070 
2071   PATH2;
2072   req->flags = flags;
2073   POST;
2074 }
2075 
2076 
uv_fs_statfs(uv_loop_t * loop,uv_fs_t * req,const char * path,uv_fs_cb cb)2077 int uv_fs_statfs(uv_loop_t* loop,
2078                  uv_fs_t* req,
2079                  const char* path,
2080                  uv_fs_cb cb) {
2081   INIT(STATFS);
2082   PATH;
2083   POST;
2084 }
2085