11cb0ef41Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
41cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
51cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the
61cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
71cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
81cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
91cb0ef41Sopenharmony_ci *
101cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
111cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software.
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
141cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
161cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
171cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
181cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
191cb0ef41Sopenharmony_ci * IN THE SOFTWARE.
201cb0ef41Sopenharmony_ci */
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci/* Caveat emptor: this file deviates from the libuv convention of returning
231cb0ef41Sopenharmony_ci * negated errno codes. Most uv_fs_*() functions map directly to the system
241cb0ef41Sopenharmony_ci * call of the same name. For more complex wrappers, it's easier to just
251cb0ef41Sopenharmony_ci * return -1 with errno set. The dispatcher in uv__fs_work() takes care of
261cb0ef41Sopenharmony_ci * getting the errno to the right place (req->result or as the return value.)
271cb0ef41Sopenharmony_ci */
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci#include "uv.h"
301cb0ef41Sopenharmony_ci#include "internal.h"
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci#include <errno.h>
331cb0ef41Sopenharmony_ci#include <dlfcn.h>
341cb0ef41Sopenharmony_ci#include <stdio.h>
351cb0ef41Sopenharmony_ci#include <stdlib.h>
361cb0ef41Sopenharmony_ci#include <string.h>
371cb0ef41Sopenharmony_ci#include <limits.h> /* PATH_MAX */
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci#include <sys/types.h>
401cb0ef41Sopenharmony_ci#include <sys/socket.h>
411cb0ef41Sopenharmony_ci#include <sys/stat.h>
421cb0ef41Sopenharmony_ci#include <sys/time.h>
431cb0ef41Sopenharmony_ci#include <sys/uio.h>
441cb0ef41Sopenharmony_ci#include <pthread.h>
451cb0ef41Sopenharmony_ci#include <unistd.h>
461cb0ef41Sopenharmony_ci#include <fcntl.h>
471cb0ef41Sopenharmony_ci#include <poll.h>
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci#if defined(__DragonFly__)        ||                                      \
501cb0ef41Sopenharmony_ci    defined(__FreeBSD__)          ||                                      \
511cb0ef41Sopenharmony_ci    defined(__FreeBSD_kernel__)   ||                                      \
521cb0ef41Sopenharmony_ci    defined(__OpenBSD__)          ||                                      \
531cb0ef41Sopenharmony_ci    defined(__NetBSD__)
541cb0ef41Sopenharmony_ci# define HAVE_PREADV 1
551cb0ef41Sopenharmony_ci#else
561cb0ef41Sopenharmony_ci# define HAVE_PREADV 0
571cb0ef41Sopenharmony_ci#endif
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci#if defined(__linux__)
601cb0ef41Sopenharmony_ci# include "sys/utsname.h"
611cb0ef41Sopenharmony_ci#endif
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci#if defined(__linux__) || defined(__sun)
641cb0ef41Sopenharmony_ci# include <sys/sendfile.h>
651cb0ef41Sopenharmony_ci# include <sys/sysmacros.h>
661cb0ef41Sopenharmony_ci#endif
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci#if defined(__APPLE__)
691cb0ef41Sopenharmony_ci# include <sys/sysctl.h>
701cb0ef41Sopenharmony_ci#elif defined(__linux__) && !defined(FICLONE)
711cb0ef41Sopenharmony_ci# include <sys/ioctl.h>
721cb0ef41Sopenharmony_ci# define FICLONE _IOW(0x94, 9, int)
731cb0ef41Sopenharmony_ci#endif
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci#if defined(_AIX) && !defined(_AIX71)
761cb0ef41Sopenharmony_ci# include <utime.h>
771cb0ef41Sopenharmony_ci#endif
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci#if defined(__APPLE__)            ||                                      \
801cb0ef41Sopenharmony_ci    defined(__DragonFly__)        ||                                      \
811cb0ef41Sopenharmony_ci    defined(__FreeBSD__)          ||                                      \
821cb0ef41Sopenharmony_ci    defined(__FreeBSD_kernel__)   ||                                      \
831cb0ef41Sopenharmony_ci    defined(__OpenBSD__)          ||                                      \
841cb0ef41Sopenharmony_ci    defined(__NetBSD__)
851cb0ef41Sopenharmony_ci# include <sys/param.h>
861cb0ef41Sopenharmony_ci# include <sys/mount.h>
871cb0ef41Sopenharmony_ci#elif defined(__sun)      || \
881cb0ef41Sopenharmony_ci      defined(__MVS__)    || \
891cb0ef41Sopenharmony_ci      defined(__NetBSD__) || \
901cb0ef41Sopenharmony_ci      defined(__HAIKU__)  || \
911cb0ef41Sopenharmony_ci      defined(__QNX__)
921cb0ef41Sopenharmony_ci# include <sys/statvfs.h>
931cb0ef41Sopenharmony_ci#else
941cb0ef41Sopenharmony_ci# include <sys/statfs.h>
951cb0ef41Sopenharmony_ci#endif
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci#if defined(_AIX) && _XOPEN_SOURCE <= 600
981cb0ef41Sopenharmony_ciextern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
991cb0ef41Sopenharmony_ci#endif
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci#define INIT(subtype)                                                         \
1021cb0ef41Sopenharmony_ci  do {                                                                        \
1031cb0ef41Sopenharmony_ci    if (req == NULL)                                                          \
1041cb0ef41Sopenharmony_ci      return UV_EINVAL;                                                       \
1051cb0ef41Sopenharmony_ci    UV_REQ_INIT(req, UV_FS);                                                  \
1061cb0ef41Sopenharmony_ci    req->fs_type = UV_FS_ ## subtype;                                         \
1071cb0ef41Sopenharmony_ci    req->result = 0;                                                          \
1081cb0ef41Sopenharmony_ci    req->ptr = NULL;                                                          \
1091cb0ef41Sopenharmony_ci    req->loop = loop;                                                         \
1101cb0ef41Sopenharmony_ci    req->path = NULL;                                                         \
1111cb0ef41Sopenharmony_ci    req->new_path = NULL;                                                     \
1121cb0ef41Sopenharmony_ci    req->bufs = NULL;                                                         \
1131cb0ef41Sopenharmony_ci    req->cb = cb;                                                             \
1141cb0ef41Sopenharmony_ci  }                                                                           \
1151cb0ef41Sopenharmony_ci  while (0)
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci#define PATH                                                                  \
1181cb0ef41Sopenharmony_ci  do {                                                                        \
1191cb0ef41Sopenharmony_ci    assert(path != NULL);                                                     \
1201cb0ef41Sopenharmony_ci    if (cb == NULL) {                                                         \
1211cb0ef41Sopenharmony_ci      req->path = path;                                                       \
1221cb0ef41Sopenharmony_ci    } else {                                                                  \
1231cb0ef41Sopenharmony_ci      req->path = uv__strdup(path);                                           \
1241cb0ef41Sopenharmony_ci      if (req->path == NULL)                                                  \
1251cb0ef41Sopenharmony_ci        return UV_ENOMEM;                                                     \
1261cb0ef41Sopenharmony_ci    }                                                                         \
1271cb0ef41Sopenharmony_ci  }                                                                           \
1281cb0ef41Sopenharmony_ci  while (0)
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci#define PATH2                                                                 \
1311cb0ef41Sopenharmony_ci  do {                                                                        \
1321cb0ef41Sopenharmony_ci    if (cb == NULL) {                                                         \
1331cb0ef41Sopenharmony_ci      req->path = path;                                                       \
1341cb0ef41Sopenharmony_ci      req->new_path = new_path;                                               \
1351cb0ef41Sopenharmony_ci    } else {                                                                  \
1361cb0ef41Sopenharmony_ci      size_t path_len;                                                        \
1371cb0ef41Sopenharmony_ci      size_t new_path_len;                                                    \
1381cb0ef41Sopenharmony_ci      path_len = strlen(path) + 1;                                            \
1391cb0ef41Sopenharmony_ci      new_path_len = strlen(new_path) + 1;                                    \
1401cb0ef41Sopenharmony_ci      req->path = uv__malloc(path_len + new_path_len);                        \
1411cb0ef41Sopenharmony_ci      if (req->path == NULL)                                                  \
1421cb0ef41Sopenharmony_ci        return UV_ENOMEM;                                                     \
1431cb0ef41Sopenharmony_ci      req->new_path = req->path + path_len;                                   \
1441cb0ef41Sopenharmony_ci      memcpy((void*) req->path, path, path_len);                              \
1451cb0ef41Sopenharmony_ci      memcpy((void*) req->new_path, new_path, new_path_len);                  \
1461cb0ef41Sopenharmony_ci    }                                                                         \
1471cb0ef41Sopenharmony_ci  }                                                                           \
1481cb0ef41Sopenharmony_ci  while (0)
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci#define POST                                                                  \
1511cb0ef41Sopenharmony_ci  do {                                                                        \
1521cb0ef41Sopenharmony_ci    if (cb != NULL) {                                                         \
1531cb0ef41Sopenharmony_ci      uv__req_register(loop, req);                                            \
1541cb0ef41Sopenharmony_ci      uv__work_submit(loop,                                                   \
1551cb0ef41Sopenharmony_ci                      &req->work_req,                                         \
1561cb0ef41Sopenharmony_ci                      UV__WORK_FAST_IO,                                       \
1571cb0ef41Sopenharmony_ci                      uv__fs_work,                                            \
1581cb0ef41Sopenharmony_ci                      uv__fs_done);                                           \
1591cb0ef41Sopenharmony_ci      return 0;                                                               \
1601cb0ef41Sopenharmony_ci    }                                                                         \
1611cb0ef41Sopenharmony_ci    else {                                                                    \
1621cb0ef41Sopenharmony_ci      uv__fs_work(&req->work_req);                                            \
1631cb0ef41Sopenharmony_ci      return req->result;                                                     \
1641cb0ef41Sopenharmony_ci    }                                                                         \
1651cb0ef41Sopenharmony_ci  }                                                                           \
1661cb0ef41Sopenharmony_ci  while (0)
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_cistatic int uv__fs_close(int fd) {
1701cb0ef41Sopenharmony_ci  int rc;
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  rc = uv__close_nocancel(fd);
1731cb0ef41Sopenharmony_ci  if (rc == -1)
1741cb0ef41Sopenharmony_ci    if (errno == EINTR || errno == EINPROGRESS)
1751cb0ef41Sopenharmony_ci      rc = 0;  /* The close is in progress, not an error. */
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  return rc;
1781cb0ef41Sopenharmony_ci}
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_cistatic ssize_t uv__fs_fsync(uv_fs_t* req) {
1821cb0ef41Sopenharmony_ci#if defined(__APPLE__)
1831cb0ef41Sopenharmony_ci  /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
1841cb0ef41Sopenharmony_ci   * to the drive platters. This is in contrast to Linux's fdatasync and fsync
1851cb0ef41Sopenharmony_ci   * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
1861cb0ef41Sopenharmony_ci   * for flushing buffered data to permanent storage. If F_FULLFSYNC is not
1871cb0ef41Sopenharmony_ci   * supported by the file system we fall back to F_BARRIERFSYNC or fsync().
1881cb0ef41Sopenharmony_ci   * This is the same approach taken by sqlite, except sqlite does not issue
1891cb0ef41Sopenharmony_ci   * an F_BARRIERFSYNC call.
1901cb0ef41Sopenharmony_ci   */
1911cb0ef41Sopenharmony_ci  int r;
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci  r = fcntl(req->file, F_FULLFSYNC);
1941cb0ef41Sopenharmony_ci  if (r != 0)
1951cb0ef41Sopenharmony_ci    r = fcntl(req->file, 85 /* F_BARRIERFSYNC */);  /* fsync + barrier */
1961cb0ef41Sopenharmony_ci  if (r != 0)
1971cb0ef41Sopenharmony_ci    r = fsync(req->file);
1981cb0ef41Sopenharmony_ci  return r;
1991cb0ef41Sopenharmony_ci#else
2001cb0ef41Sopenharmony_ci  return fsync(req->file);
2011cb0ef41Sopenharmony_ci#endif
2021cb0ef41Sopenharmony_ci}
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_cistatic ssize_t uv__fs_fdatasync(uv_fs_t* req) {
2061cb0ef41Sopenharmony_ci#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
2071cb0ef41Sopenharmony_ci  return fdatasync(req->file);
2081cb0ef41Sopenharmony_ci#elif defined(__APPLE__)
2091cb0ef41Sopenharmony_ci  /* See the comment in uv__fs_fsync. */
2101cb0ef41Sopenharmony_ci  return uv__fs_fsync(req);
2111cb0ef41Sopenharmony_ci#else
2121cb0ef41Sopenharmony_ci  return fsync(req->file);
2131cb0ef41Sopenharmony_ci#endif
2141cb0ef41Sopenharmony_ci}
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ciUV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
2181cb0ef41Sopenharmony_ci  struct timespec ts;
2191cb0ef41Sopenharmony_ci  ts.tv_sec  = time;
2201cb0ef41Sopenharmony_ci  ts.tv_nsec = (time - ts.tv_sec) * 1e9;
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci /* TODO(bnoordhuis) Remove this. utimesat() has nanosecond resolution but we
2231cb0ef41Sopenharmony_ci  * stick to microsecond resolution for the sake of consistency with other
2241cb0ef41Sopenharmony_ci  * platforms. I'm the original author of this compatibility hack but I'm
2251cb0ef41Sopenharmony_ci  * less convinced it's useful nowadays.
2261cb0ef41Sopenharmony_ci  */
2271cb0ef41Sopenharmony_ci  ts.tv_nsec -= ts.tv_nsec % 1000;
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  if (ts.tv_nsec < 0) {
2301cb0ef41Sopenharmony_ci    ts.tv_nsec += 1e9;
2311cb0ef41Sopenharmony_ci    ts.tv_sec -= 1;
2321cb0ef41Sopenharmony_ci  }
2331cb0ef41Sopenharmony_ci  return ts;
2341cb0ef41Sopenharmony_ci}
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ciUV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
2371cb0ef41Sopenharmony_ci  struct timeval tv;
2381cb0ef41Sopenharmony_ci  tv.tv_sec  = time;
2391cb0ef41Sopenharmony_ci  tv.tv_usec = (time - tv.tv_sec) * 1e6;
2401cb0ef41Sopenharmony_ci  if (tv.tv_usec < 0) {
2411cb0ef41Sopenharmony_ci    tv.tv_usec += 1e6;
2421cb0ef41Sopenharmony_ci    tv.tv_sec -= 1;
2431cb0ef41Sopenharmony_ci  }
2441cb0ef41Sopenharmony_ci  return tv;
2451cb0ef41Sopenharmony_ci}
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_cistatic ssize_t uv__fs_futime(uv_fs_t* req) {
2481cb0ef41Sopenharmony_ci#if defined(__linux__)                                                        \
2491cb0ef41Sopenharmony_ci    || defined(_AIX71)                                                        \
2501cb0ef41Sopenharmony_ci    || defined(__HAIKU__)                                                     \
2511cb0ef41Sopenharmony_ci    || defined(__GNU__)
2521cb0ef41Sopenharmony_ci  struct timespec ts[2];
2531cb0ef41Sopenharmony_ci  ts[0] = uv__fs_to_timespec(req->atime);
2541cb0ef41Sopenharmony_ci  ts[1] = uv__fs_to_timespec(req->mtime);
2551cb0ef41Sopenharmony_ci  return futimens(req->file, ts);
2561cb0ef41Sopenharmony_ci#elif defined(__APPLE__)                                                      \
2571cb0ef41Sopenharmony_ci    || defined(__DragonFly__)                                                 \
2581cb0ef41Sopenharmony_ci    || defined(__FreeBSD__)                                                   \
2591cb0ef41Sopenharmony_ci    || defined(__FreeBSD_kernel__)                                            \
2601cb0ef41Sopenharmony_ci    || defined(__NetBSD__)                                                    \
2611cb0ef41Sopenharmony_ci    || defined(__OpenBSD__)                                                   \
2621cb0ef41Sopenharmony_ci    || defined(__sun)
2631cb0ef41Sopenharmony_ci  struct timeval tv[2];
2641cb0ef41Sopenharmony_ci  tv[0] = uv__fs_to_timeval(req->atime);
2651cb0ef41Sopenharmony_ci  tv[1] = uv__fs_to_timeval(req->mtime);
2661cb0ef41Sopenharmony_ci# if defined(__sun)
2671cb0ef41Sopenharmony_ci  return futimesat(req->file, NULL, tv);
2681cb0ef41Sopenharmony_ci# else
2691cb0ef41Sopenharmony_ci  return futimes(req->file, tv);
2701cb0ef41Sopenharmony_ci# endif
2711cb0ef41Sopenharmony_ci#elif defined(__MVS__)
2721cb0ef41Sopenharmony_ci  attrib_t atr;
2731cb0ef41Sopenharmony_ci  memset(&atr, 0, sizeof(atr));
2741cb0ef41Sopenharmony_ci  atr.att_mtimechg = 1;
2751cb0ef41Sopenharmony_ci  atr.att_atimechg = 1;
2761cb0ef41Sopenharmony_ci  atr.att_mtime = req->mtime;
2771cb0ef41Sopenharmony_ci  atr.att_atime = req->atime;
2781cb0ef41Sopenharmony_ci  return __fchattr(req->file, &atr, sizeof(atr));
2791cb0ef41Sopenharmony_ci#else
2801cb0ef41Sopenharmony_ci  errno = ENOSYS;
2811cb0ef41Sopenharmony_ci  return -1;
2821cb0ef41Sopenharmony_ci#endif
2831cb0ef41Sopenharmony_ci}
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_cistatic ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
2871cb0ef41Sopenharmony_ci  return mkdtemp((char*) req->path) ? 0 : -1;
2881cb0ef41Sopenharmony_ci}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_cistatic int (*uv__mkostemp)(char*, int);
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_cistatic void uv__mkostemp_initonce(void) {
2951cb0ef41Sopenharmony_ci  /* z/os doesn't have RTLD_DEFAULT but that's okay
2961cb0ef41Sopenharmony_ci   * because it doesn't have mkostemp(O_CLOEXEC) either.
2971cb0ef41Sopenharmony_ci   */
2981cb0ef41Sopenharmony_ci#ifdef RTLD_DEFAULT
2991cb0ef41Sopenharmony_ci  uv__mkostemp = (int (*)(char*, int)) dlsym(RTLD_DEFAULT, "mkostemp");
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci  /* We don't care about errors, but we do want to clean them up.
3021cb0ef41Sopenharmony_ci   * If there has been no error, then dlerror() will just return
3031cb0ef41Sopenharmony_ci   * NULL.
3041cb0ef41Sopenharmony_ci   */
3051cb0ef41Sopenharmony_ci  dlerror();
3061cb0ef41Sopenharmony_ci#endif  /* RTLD_DEFAULT */
3071cb0ef41Sopenharmony_ci}
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_cistatic int uv__fs_mkstemp(uv_fs_t* req) {
3111cb0ef41Sopenharmony_ci  static uv_once_t once = UV_ONCE_INIT;
3121cb0ef41Sopenharmony_ci  int r;
3131cb0ef41Sopenharmony_ci#ifdef O_CLOEXEC
3141cb0ef41Sopenharmony_ci  static int no_cloexec_support;
3151cb0ef41Sopenharmony_ci#endif
3161cb0ef41Sopenharmony_ci  static const char pattern[] = "XXXXXX";
3171cb0ef41Sopenharmony_ci  static const size_t pattern_size = sizeof(pattern) - 1;
3181cb0ef41Sopenharmony_ci  char* path;
3191cb0ef41Sopenharmony_ci  size_t path_length;
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci  path = (char*) req->path;
3221cb0ef41Sopenharmony_ci  path_length = strlen(path);
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci  /* EINVAL can be returned for 2 reasons:
3251cb0ef41Sopenharmony_ci      1. The template's last 6 characters were not XXXXXX
3261cb0ef41Sopenharmony_ci      2. open() didn't support O_CLOEXEC
3271cb0ef41Sopenharmony_ci     We want to avoid going to the fallback path in case
3281cb0ef41Sopenharmony_ci     of 1, so it's manually checked before. */
3291cb0ef41Sopenharmony_ci  if (path_length < pattern_size ||
3301cb0ef41Sopenharmony_ci      strcmp(path + path_length - pattern_size, pattern)) {
3311cb0ef41Sopenharmony_ci    errno = EINVAL;
3321cb0ef41Sopenharmony_ci    r = -1;
3331cb0ef41Sopenharmony_ci    goto clobber;
3341cb0ef41Sopenharmony_ci  }
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ci  uv_once(&once, uv__mkostemp_initonce);
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci#ifdef O_CLOEXEC
3391cb0ef41Sopenharmony_ci  if (uv__load_relaxed(&no_cloexec_support) == 0 && uv__mkostemp != NULL) {
3401cb0ef41Sopenharmony_ci    r = uv__mkostemp(path, O_CLOEXEC);
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci    if (r >= 0)
3431cb0ef41Sopenharmony_ci      return r;
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ci    /* If mkostemp() returns EINVAL, it means the kernel doesn't
3461cb0ef41Sopenharmony_ci       support O_CLOEXEC, so we just fallback to mkstemp() below. */
3471cb0ef41Sopenharmony_ci    if (errno != EINVAL)
3481cb0ef41Sopenharmony_ci      goto clobber;
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ci    /* We set the static variable so that next calls don't even
3511cb0ef41Sopenharmony_ci       try to use mkostemp. */
3521cb0ef41Sopenharmony_ci    uv__store_relaxed(&no_cloexec_support, 1);
3531cb0ef41Sopenharmony_ci  }
3541cb0ef41Sopenharmony_ci#endif  /* O_CLOEXEC */
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci  if (req->cb != NULL)
3571cb0ef41Sopenharmony_ci    uv_rwlock_rdlock(&req->loop->cloexec_lock);
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci  r = mkstemp(path);
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci  /* In case of failure `uv__cloexec` will leave error in `errno`,
3621cb0ef41Sopenharmony_ci   * so it is enough to just set `r` to `-1`.
3631cb0ef41Sopenharmony_ci   */
3641cb0ef41Sopenharmony_ci  if (r >= 0 && uv__cloexec(r, 1) != 0) {
3651cb0ef41Sopenharmony_ci    r = uv__close(r);
3661cb0ef41Sopenharmony_ci    if (r != 0)
3671cb0ef41Sopenharmony_ci      abort();
3681cb0ef41Sopenharmony_ci    r = -1;
3691cb0ef41Sopenharmony_ci  }
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_ci  if (req->cb != NULL)
3721cb0ef41Sopenharmony_ci    uv_rwlock_rdunlock(&req->loop->cloexec_lock);
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ciclobber:
3751cb0ef41Sopenharmony_ci  if (r < 0)
3761cb0ef41Sopenharmony_ci    path[0] = '\0';
3771cb0ef41Sopenharmony_ci  return r;
3781cb0ef41Sopenharmony_ci}
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_cistatic ssize_t uv__fs_open(uv_fs_t* req) {
3821cb0ef41Sopenharmony_ci#ifdef O_CLOEXEC
3831cb0ef41Sopenharmony_ci  return open(req->path, req->flags | O_CLOEXEC, req->mode);
3841cb0ef41Sopenharmony_ci#else  /* O_CLOEXEC */
3851cb0ef41Sopenharmony_ci  int r;
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci  if (req->cb != NULL)
3881cb0ef41Sopenharmony_ci    uv_rwlock_rdlock(&req->loop->cloexec_lock);
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ci  r = open(req->path, req->flags, req->mode);
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci  /* In case of failure `uv__cloexec` will leave error in `errno`,
3931cb0ef41Sopenharmony_ci   * so it is enough to just set `r` to `-1`.
3941cb0ef41Sopenharmony_ci   */
3951cb0ef41Sopenharmony_ci  if (r >= 0 && uv__cloexec(r, 1) != 0) {
3961cb0ef41Sopenharmony_ci    r = uv__close(r);
3971cb0ef41Sopenharmony_ci    if (r != 0)
3981cb0ef41Sopenharmony_ci      abort();
3991cb0ef41Sopenharmony_ci    r = -1;
4001cb0ef41Sopenharmony_ci  }
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  if (req->cb != NULL)
4031cb0ef41Sopenharmony_ci    uv_rwlock_rdunlock(&req->loop->cloexec_lock);
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci  return r;
4061cb0ef41Sopenharmony_ci#endif  /* O_CLOEXEC */
4071cb0ef41Sopenharmony_ci}
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ci#if !HAVE_PREADV
4111cb0ef41Sopenharmony_cistatic ssize_t uv__fs_preadv(uv_file fd,
4121cb0ef41Sopenharmony_ci                             uv_buf_t* bufs,
4131cb0ef41Sopenharmony_ci                             unsigned int nbufs,
4141cb0ef41Sopenharmony_ci                             off_t off) {
4151cb0ef41Sopenharmony_ci  uv_buf_t* buf;
4161cb0ef41Sopenharmony_ci  uv_buf_t* end;
4171cb0ef41Sopenharmony_ci  ssize_t result;
4181cb0ef41Sopenharmony_ci  ssize_t rc;
4191cb0ef41Sopenharmony_ci  size_t pos;
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci  assert(nbufs > 0);
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci  result = 0;
4241cb0ef41Sopenharmony_ci  pos = 0;
4251cb0ef41Sopenharmony_ci  buf = bufs + 0;
4261cb0ef41Sopenharmony_ci  end = bufs + nbufs;
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci  for (;;) {
4291cb0ef41Sopenharmony_ci    do
4301cb0ef41Sopenharmony_ci      rc = pread(fd, buf->base + pos, buf->len - pos, off + result);
4311cb0ef41Sopenharmony_ci    while (rc == -1 && errno == EINTR);
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ci    if (rc == 0)
4341cb0ef41Sopenharmony_ci      break;
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci    if (rc == -1 && result == 0)
4371cb0ef41Sopenharmony_ci      return UV__ERR(errno);
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_ci    if (rc == -1)
4401cb0ef41Sopenharmony_ci      break;  /* We read some data so return that, ignore the error. */
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_ci    pos += rc;
4431cb0ef41Sopenharmony_ci    result += rc;
4441cb0ef41Sopenharmony_ci
4451cb0ef41Sopenharmony_ci    if (pos < buf->len)
4461cb0ef41Sopenharmony_ci      continue;
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci    pos = 0;
4491cb0ef41Sopenharmony_ci    buf += 1;
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci    if (buf == end)
4521cb0ef41Sopenharmony_ci      break;
4531cb0ef41Sopenharmony_ci  }
4541cb0ef41Sopenharmony_ci
4551cb0ef41Sopenharmony_ci  return result;
4561cb0ef41Sopenharmony_ci}
4571cb0ef41Sopenharmony_ci#endif
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_cistatic ssize_t uv__fs_read(uv_fs_t* req) {
4611cb0ef41Sopenharmony_ci#if defined(__linux__)
4621cb0ef41Sopenharmony_ci  static int no_preadv;
4631cb0ef41Sopenharmony_ci#endif
4641cb0ef41Sopenharmony_ci  unsigned int iovmax;
4651cb0ef41Sopenharmony_ci  ssize_t result;
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci  iovmax = uv__getiovmax();
4681cb0ef41Sopenharmony_ci  if (req->nbufs > iovmax)
4691cb0ef41Sopenharmony_ci    req->nbufs = iovmax;
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ci  if (req->off < 0) {
4721cb0ef41Sopenharmony_ci    if (req->nbufs == 1)
4731cb0ef41Sopenharmony_ci      result = read(req->file, req->bufs[0].base, req->bufs[0].len);
4741cb0ef41Sopenharmony_ci    else
4751cb0ef41Sopenharmony_ci      result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
4761cb0ef41Sopenharmony_ci  } else {
4771cb0ef41Sopenharmony_ci    if (req->nbufs == 1) {
4781cb0ef41Sopenharmony_ci      result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
4791cb0ef41Sopenharmony_ci      goto done;
4801cb0ef41Sopenharmony_ci    }
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ci#if HAVE_PREADV
4831cb0ef41Sopenharmony_ci    result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
4841cb0ef41Sopenharmony_ci#else
4851cb0ef41Sopenharmony_ci# if defined(__linux__)
4861cb0ef41Sopenharmony_ci    if (uv__load_relaxed(&no_preadv)) retry:
4871cb0ef41Sopenharmony_ci# endif
4881cb0ef41Sopenharmony_ci    {
4891cb0ef41Sopenharmony_ci      result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off);
4901cb0ef41Sopenharmony_ci    }
4911cb0ef41Sopenharmony_ci# if defined(__linux__)
4921cb0ef41Sopenharmony_ci    else {
4931cb0ef41Sopenharmony_ci      result = uv__preadv(req->file,
4941cb0ef41Sopenharmony_ci                          (struct iovec*)req->bufs,
4951cb0ef41Sopenharmony_ci                          req->nbufs,
4961cb0ef41Sopenharmony_ci                          req->off);
4971cb0ef41Sopenharmony_ci      if (result == -1 && errno == ENOSYS) {
4981cb0ef41Sopenharmony_ci        uv__store_relaxed(&no_preadv, 1);
4991cb0ef41Sopenharmony_ci        goto retry;
5001cb0ef41Sopenharmony_ci      }
5011cb0ef41Sopenharmony_ci    }
5021cb0ef41Sopenharmony_ci# endif
5031cb0ef41Sopenharmony_ci#endif
5041cb0ef41Sopenharmony_ci  }
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_cidone:
5071cb0ef41Sopenharmony_ci  /* Early cleanup of bufs allocation, since we're done with it. */
5081cb0ef41Sopenharmony_ci  if (req->bufs != req->bufsml)
5091cb0ef41Sopenharmony_ci    uv__free(req->bufs);
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci  req->bufs = NULL;
5121cb0ef41Sopenharmony_ci  req->nbufs = 0;
5131cb0ef41Sopenharmony_ci
5141cb0ef41Sopenharmony_ci#ifdef __PASE__
5151cb0ef41Sopenharmony_ci  /* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
5161cb0ef41Sopenharmony_ci  if (result == -1 && errno == EOPNOTSUPP) {
5171cb0ef41Sopenharmony_ci    struct stat buf;
5181cb0ef41Sopenharmony_ci    ssize_t rc;
5191cb0ef41Sopenharmony_ci    rc = fstat(req->file, &buf);
5201cb0ef41Sopenharmony_ci    if (rc == 0 && S_ISDIR(buf.st_mode)) {
5211cb0ef41Sopenharmony_ci      errno = EISDIR;
5221cb0ef41Sopenharmony_ci    }
5231cb0ef41Sopenharmony_ci  }
5241cb0ef41Sopenharmony_ci#endif
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_ci  return result;
5271cb0ef41Sopenharmony_ci}
5281cb0ef41Sopenharmony_ci
5291cb0ef41Sopenharmony_ci
5301cb0ef41Sopenharmony_ci#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)
5311cb0ef41Sopenharmony_ci#define UV_CONST_DIRENT uv__dirent_t
5321cb0ef41Sopenharmony_ci#else
5331cb0ef41Sopenharmony_ci#define UV_CONST_DIRENT const uv__dirent_t
5341cb0ef41Sopenharmony_ci#endif
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_cistatic int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) {
5381cb0ef41Sopenharmony_ci  return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
5391cb0ef41Sopenharmony_ci}
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_cistatic int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
5431cb0ef41Sopenharmony_ci  return strcmp((*a)->d_name, (*b)->d_name);
5441cb0ef41Sopenharmony_ci}
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_cistatic ssize_t uv__fs_scandir(uv_fs_t* req) {
5481cb0ef41Sopenharmony_ci  uv__dirent_t** dents;
5491cb0ef41Sopenharmony_ci  int n;
5501cb0ef41Sopenharmony_ci
5511cb0ef41Sopenharmony_ci  dents = NULL;
5521cb0ef41Sopenharmony_ci  n = scandir(req->path, &dents, uv__fs_scandir_filter, uv__fs_scandir_sort);
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  /* NOTE: We will use nbufs as an index field */
5551cb0ef41Sopenharmony_ci  req->nbufs = 0;
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci  if (n == 0) {
5581cb0ef41Sopenharmony_ci    /* OS X still needs to deallocate some memory.
5591cb0ef41Sopenharmony_ci     * Memory was allocated using the system allocator, so use free() here.
5601cb0ef41Sopenharmony_ci     */
5611cb0ef41Sopenharmony_ci    free(dents);
5621cb0ef41Sopenharmony_ci    dents = NULL;
5631cb0ef41Sopenharmony_ci  } else if (n == -1) {
5641cb0ef41Sopenharmony_ci    return n;
5651cb0ef41Sopenharmony_ci  }
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ci  req->ptr = dents;
5681cb0ef41Sopenharmony_ci
5691cb0ef41Sopenharmony_ci  return n;
5701cb0ef41Sopenharmony_ci}
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_cistatic int uv__fs_opendir(uv_fs_t* req) {
5731cb0ef41Sopenharmony_ci  uv_dir_t* dir;
5741cb0ef41Sopenharmony_ci
5751cb0ef41Sopenharmony_ci  dir = uv__malloc(sizeof(*dir));
5761cb0ef41Sopenharmony_ci  if (dir == NULL)
5771cb0ef41Sopenharmony_ci    goto error;
5781cb0ef41Sopenharmony_ci
5791cb0ef41Sopenharmony_ci  dir->dir = opendir(req->path);
5801cb0ef41Sopenharmony_ci  if (dir->dir == NULL)
5811cb0ef41Sopenharmony_ci    goto error;
5821cb0ef41Sopenharmony_ci
5831cb0ef41Sopenharmony_ci  req->ptr = dir;
5841cb0ef41Sopenharmony_ci  return 0;
5851cb0ef41Sopenharmony_ci
5861cb0ef41Sopenharmony_cierror:
5871cb0ef41Sopenharmony_ci  uv__free(dir);
5881cb0ef41Sopenharmony_ci  req->ptr = NULL;
5891cb0ef41Sopenharmony_ci  return -1;
5901cb0ef41Sopenharmony_ci}
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_cistatic int uv__fs_readdir(uv_fs_t* req) {
5931cb0ef41Sopenharmony_ci  uv_dir_t* dir;
5941cb0ef41Sopenharmony_ci  uv_dirent_t* dirent;
5951cb0ef41Sopenharmony_ci  struct dirent* res;
5961cb0ef41Sopenharmony_ci  unsigned int dirent_idx;
5971cb0ef41Sopenharmony_ci  unsigned int i;
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  dir = req->ptr;
6001cb0ef41Sopenharmony_ci  dirent_idx = 0;
6011cb0ef41Sopenharmony_ci
6021cb0ef41Sopenharmony_ci  while (dirent_idx < dir->nentries) {
6031cb0ef41Sopenharmony_ci    /* readdir() returns NULL on end of directory, as well as on error. errno
6041cb0ef41Sopenharmony_ci       is used to differentiate between the two conditions. */
6051cb0ef41Sopenharmony_ci    errno = 0;
6061cb0ef41Sopenharmony_ci    res = readdir(dir->dir);
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_ci    if (res == NULL) {
6091cb0ef41Sopenharmony_ci      if (errno != 0)
6101cb0ef41Sopenharmony_ci        goto error;
6111cb0ef41Sopenharmony_ci      break;
6121cb0ef41Sopenharmony_ci    }
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci    if (strcmp(res->d_name, ".") == 0 || strcmp(res->d_name, "..") == 0)
6151cb0ef41Sopenharmony_ci      continue;
6161cb0ef41Sopenharmony_ci
6171cb0ef41Sopenharmony_ci    dirent = &dir->dirents[dirent_idx];
6181cb0ef41Sopenharmony_ci    dirent->name = uv__strdup(res->d_name);
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_ci    if (dirent->name == NULL)
6211cb0ef41Sopenharmony_ci      goto error;
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_ci    dirent->type = uv__fs_get_dirent_type(res);
6241cb0ef41Sopenharmony_ci    ++dirent_idx;
6251cb0ef41Sopenharmony_ci  }
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci  return dirent_idx;
6281cb0ef41Sopenharmony_ci
6291cb0ef41Sopenharmony_cierror:
6301cb0ef41Sopenharmony_ci  for (i = 0; i < dirent_idx; ++i) {
6311cb0ef41Sopenharmony_ci    uv__free((char*) dir->dirents[i].name);
6321cb0ef41Sopenharmony_ci    dir->dirents[i].name = NULL;
6331cb0ef41Sopenharmony_ci  }
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci  return -1;
6361cb0ef41Sopenharmony_ci}
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_cistatic int uv__fs_closedir(uv_fs_t* req) {
6391cb0ef41Sopenharmony_ci  uv_dir_t* dir;
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci  dir = req->ptr;
6421cb0ef41Sopenharmony_ci
6431cb0ef41Sopenharmony_ci  if (dir->dir != NULL) {
6441cb0ef41Sopenharmony_ci    closedir(dir->dir);
6451cb0ef41Sopenharmony_ci    dir->dir = NULL;
6461cb0ef41Sopenharmony_ci  }
6471cb0ef41Sopenharmony_ci
6481cb0ef41Sopenharmony_ci  uv__free(req->ptr);
6491cb0ef41Sopenharmony_ci  req->ptr = NULL;
6501cb0ef41Sopenharmony_ci  return 0;
6511cb0ef41Sopenharmony_ci}
6521cb0ef41Sopenharmony_ci
6531cb0ef41Sopenharmony_cistatic int uv__fs_statfs(uv_fs_t* req) {
6541cb0ef41Sopenharmony_ci  uv_statfs_t* stat_fs;
6551cb0ef41Sopenharmony_ci#if defined(__sun)      || \
6561cb0ef41Sopenharmony_ci    defined(__MVS__)    || \
6571cb0ef41Sopenharmony_ci    defined(__NetBSD__) || \
6581cb0ef41Sopenharmony_ci    defined(__HAIKU__)  || \
6591cb0ef41Sopenharmony_ci    defined(__QNX__)
6601cb0ef41Sopenharmony_ci  struct statvfs buf;
6611cb0ef41Sopenharmony_ci
6621cb0ef41Sopenharmony_ci  if (0 != statvfs(req->path, &buf))
6631cb0ef41Sopenharmony_ci#else
6641cb0ef41Sopenharmony_ci  struct statfs buf;
6651cb0ef41Sopenharmony_ci
6661cb0ef41Sopenharmony_ci  if (0 != statfs(req->path, &buf))
6671cb0ef41Sopenharmony_ci#endif /* defined(__sun) */
6681cb0ef41Sopenharmony_ci    return -1;
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci  stat_fs = uv__malloc(sizeof(*stat_fs));
6711cb0ef41Sopenharmony_ci  if (stat_fs == NULL) {
6721cb0ef41Sopenharmony_ci    errno = ENOMEM;
6731cb0ef41Sopenharmony_ci    return -1;
6741cb0ef41Sopenharmony_ci  }
6751cb0ef41Sopenharmony_ci
6761cb0ef41Sopenharmony_ci#if defined(__sun)        || \
6771cb0ef41Sopenharmony_ci    defined(__MVS__)      || \
6781cb0ef41Sopenharmony_ci    defined(__OpenBSD__)  || \
6791cb0ef41Sopenharmony_ci    defined(__NetBSD__)   || \
6801cb0ef41Sopenharmony_ci    defined(__HAIKU__)    || \
6811cb0ef41Sopenharmony_ci    defined(__QNX__)
6821cb0ef41Sopenharmony_ci  stat_fs->f_type = 0;  /* f_type is not supported. */
6831cb0ef41Sopenharmony_ci#else
6841cb0ef41Sopenharmony_ci  stat_fs->f_type = buf.f_type;
6851cb0ef41Sopenharmony_ci#endif
6861cb0ef41Sopenharmony_ci  stat_fs->f_bsize = buf.f_bsize;
6871cb0ef41Sopenharmony_ci  stat_fs->f_blocks = buf.f_blocks;
6881cb0ef41Sopenharmony_ci  stat_fs->f_bfree = buf.f_bfree;
6891cb0ef41Sopenharmony_ci  stat_fs->f_bavail = buf.f_bavail;
6901cb0ef41Sopenharmony_ci  stat_fs->f_files = buf.f_files;
6911cb0ef41Sopenharmony_ci  stat_fs->f_ffree = buf.f_ffree;
6921cb0ef41Sopenharmony_ci  req->ptr = stat_fs;
6931cb0ef41Sopenharmony_ci  return 0;
6941cb0ef41Sopenharmony_ci}
6951cb0ef41Sopenharmony_ci
6961cb0ef41Sopenharmony_cistatic ssize_t uv__fs_pathmax_size(const char* path) {
6971cb0ef41Sopenharmony_ci  ssize_t pathmax;
6981cb0ef41Sopenharmony_ci
6991cb0ef41Sopenharmony_ci  pathmax = pathconf(path, _PC_PATH_MAX);
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_ci  if (pathmax == -1)
7021cb0ef41Sopenharmony_ci    pathmax = UV__PATH_MAX;
7031cb0ef41Sopenharmony_ci
7041cb0ef41Sopenharmony_ci  return pathmax;
7051cb0ef41Sopenharmony_ci}
7061cb0ef41Sopenharmony_ci
7071cb0ef41Sopenharmony_cistatic ssize_t uv__fs_readlink(uv_fs_t* req) {
7081cb0ef41Sopenharmony_ci  ssize_t maxlen;
7091cb0ef41Sopenharmony_ci  ssize_t len;
7101cb0ef41Sopenharmony_ci  char* buf;
7111cb0ef41Sopenharmony_ci
7121cb0ef41Sopenharmony_ci#if defined(_POSIX_PATH_MAX) || defined(PATH_MAX)
7131cb0ef41Sopenharmony_ci  maxlen = uv__fs_pathmax_size(req->path);
7141cb0ef41Sopenharmony_ci#else
7151cb0ef41Sopenharmony_ci  /* We may not have a real PATH_MAX.  Read size of link.  */
7161cb0ef41Sopenharmony_ci  struct stat st;
7171cb0ef41Sopenharmony_ci  int ret;
7181cb0ef41Sopenharmony_ci  ret = lstat(req->path, &st);
7191cb0ef41Sopenharmony_ci  if (ret != 0)
7201cb0ef41Sopenharmony_ci    return -1;
7211cb0ef41Sopenharmony_ci  if (!S_ISLNK(st.st_mode)) {
7221cb0ef41Sopenharmony_ci    errno = EINVAL;
7231cb0ef41Sopenharmony_ci    return -1;
7241cb0ef41Sopenharmony_ci  }
7251cb0ef41Sopenharmony_ci
7261cb0ef41Sopenharmony_ci  maxlen = st.st_size;
7271cb0ef41Sopenharmony_ci
7281cb0ef41Sopenharmony_ci  /* According to readlink(2) lstat can report st_size == 0
7291cb0ef41Sopenharmony_ci     for some symlinks, such as those in /proc or /sys.  */
7301cb0ef41Sopenharmony_ci  if (maxlen == 0)
7311cb0ef41Sopenharmony_ci    maxlen = uv__fs_pathmax_size(req->path);
7321cb0ef41Sopenharmony_ci#endif
7331cb0ef41Sopenharmony_ci
7341cb0ef41Sopenharmony_ci  buf = uv__malloc(maxlen);
7351cb0ef41Sopenharmony_ci
7361cb0ef41Sopenharmony_ci  if (buf == NULL) {
7371cb0ef41Sopenharmony_ci    errno = ENOMEM;
7381cb0ef41Sopenharmony_ci    return -1;
7391cb0ef41Sopenharmony_ci  }
7401cb0ef41Sopenharmony_ci
7411cb0ef41Sopenharmony_ci#if defined(__MVS__)
7421cb0ef41Sopenharmony_ci  len = os390_readlink(req->path, buf, maxlen);
7431cb0ef41Sopenharmony_ci#else
7441cb0ef41Sopenharmony_ci  len = readlink(req->path, buf, maxlen);
7451cb0ef41Sopenharmony_ci#endif
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_ci  if (len == -1) {
7481cb0ef41Sopenharmony_ci    uv__free(buf);
7491cb0ef41Sopenharmony_ci    return -1;
7501cb0ef41Sopenharmony_ci  }
7511cb0ef41Sopenharmony_ci
7521cb0ef41Sopenharmony_ci  /* Uncommon case: resize to make room for the trailing nul byte. */
7531cb0ef41Sopenharmony_ci  if (len == maxlen) {
7541cb0ef41Sopenharmony_ci    buf = uv__reallocf(buf, len + 1);
7551cb0ef41Sopenharmony_ci
7561cb0ef41Sopenharmony_ci    if (buf == NULL)
7571cb0ef41Sopenharmony_ci      return -1;
7581cb0ef41Sopenharmony_ci  }
7591cb0ef41Sopenharmony_ci
7601cb0ef41Sopenharmony_ci  buf[len] = '\0';
7611cb0ef41Sopenharmony_ci  req->ptr = buf;
7621cb0ef41Sopenharmony_ci
7631cb0ef41Sopenharmony_ci  return 0;
7641cb0ef41Sopenharmony_ci}
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_cistatic ssize_t uv__fs_realpath(uv_fs_t* req) {
7671cb0ef41Sopenharmony_ci  char* buf;
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_ci#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
7701cb0ef41Sopenharmony_ci  buf = realpath(req->path, NULL);
7711cb0ef41Sopenharmony_ci  if (buf == NULL)
7721cb0ef41Sopenharmony_ci    return -1;
7731cb0ef41Sopenharmony_ci#else
7741cb0ef41Sopenharmony_ci  ssize_t len;
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci  len = uv__fs_pathmax_size(req->path);
7771cb0ef41Sopenharmony_ci  buf = uv__malloc(len + 1);
7781cb0ef41Sopenharmony_ci
7791cb0ef41Sopenharmony_ci  if (buf == NULL) {
7801cb0ef41Sopenharmony_ci    errno = ENOMEM;
7811cb0ef41Sopenharmony_ci    return -1;
7821cb0ef41Sopenharmony_ci  }
7831cb0ef41Sopenharmony_ci
7841cb0ef41Sopenharmony_ci  if (realpath(req->path, buf) == NULL) {
7851cb0ef41Sopenharmony_ci    uv__free(buf);
7861cb0ef41Sopenharmony_ci    return -1;
7871cb0ef41Sopenharmony_ci  }
7881cb0ef41Sopenharmony_ci#endif
7891cb0ef41Sopenharmony_ci
7901cb0ef41Sopenharmony_ci  req->ptr = buf;
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_ci  return 0;
7931cb0ef41Sopenharmony_ci}
7941cb0ef41Sopenharmony_ci
7951cb0ef41Sopenharmony_cistatic ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
7961cb0ef41Sopenharmony_ci  struct pollfd pfd;
7971cb0ef41Sopenharmony_ci  int use_pread;
7981cb0ef41Sopenharmony_ci  off_t offset;
7991cb0ef41Sopenharmony_ci  ssize_t nsent;
8001cb0ef41Sopenharmony_ci  ssize_t nread;
8011cb0ef41Sopenharmony_ci  ssize_t nwritten;
8021cb0ef41Sopenharmony_ci  size_t buflen;
8031cb0ef41Sopenharmony_ci  size_t len;
8041cb0ef41Sopenharmony_ci  ssize_t n;
8051cb0ef41Sopenharmony_ci  int in_fd;
8061cb0ef41Sopenharmony_ci  int out_fd;
8071cb0ef41Sopenharmony_ci  char buf[8192];
8081cb0ef41Sopenharmony_ci
8091cb0ef41Sopenharmony_ci  len = req->bufsml[0].len;
8101cb0ef41Sopenharmony_ci  in_fd = req->flags;
8111cb0ef41Sopenharmony_ci  out_fd = req->file;
8121cb0ef41Sopenharmony_ci  offset = req->off;
8131cb0ef41Sopenharmony_ci  use_pread = 1;
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_ci  /* Here are the rules regarding errors:
8161cb0ef41Sopenharmony_ci   *
8171cb0ef41Sopenharmony_ci   * 1. Read errors are reported only if nsent==0, otherwise we return nsent.
8181cb0ef41Sopenharmony_ci   *    The user needs to know that some data has already been sent, to stop
8191cb0ef41Sopenharmony_ci   *    them from sending it twice.
8201cb0ef41Sopenharmony_ci   *
8211cb0ef41Sopenharmony_ci   * 2. Write errors are always reported. Write errors are bad because they
8221cb0ef41Sopenharmony_ci   *    mean data loss: we've read data but now we can't write it out.
8231cb0ef41Sopenharmony_ci   *
8241cb0ef41Sopenharmony_ci   * We try to use pread() and fall back to regular read() if the source fd
8251cb0ef41Sopenharmony_ci   * doesn't support positional reads, for example when it's a pipe fd.
8261cb0ef41Sopenharmony_ci   *
8271cb0ef41Sopenharmony_ci   * If we get EAGAIN when writing to the target fd, we poll() on it until
8281cb0ef41Sopenharmony_ci   * it becomes writable again.
8291cb0ef41Sopenharmony_ci   *
8301cb0ef41Sopenharmony_ci   * FIXME: If we get a write error when use_pread==1, it should be safe to
8311cb0ef41Sopenharmony_ci   *        return the number of sent bytes instead of an error because pread()
8321cb0ef41Sopenharmony_ci   *        is, in theory, idempotent. However, special files in /dev or /proc
8331cb0ef41Sopenharmony_ci   *        may support pread() but not necessarily return the same data on
8341cb0ef41Sopenharmony_ci   *        successive reads.
8351cb0ef41Sopenharmony_ci   *
8361cb0ef41Sopenharmony_ci   * FIXME: There is no way now to signal that we managed to send *some* data
8371cb0ef41Sopenharmony_ci   *        before a write error.
8381cb0ef41Sopenharmony_ci   */
8391cb0ef41Sopenharmony_ci  for (nsent = 0; (size_t) nsent < len; ) {
8401cb0ef41Sopenharmony_ci    buflen = len - nsent;
8411cb0ef41Sopenharmony_ci
8421cb0ef41Sopenharmony_ci    if (buflen > sizeof(buf))
8431cb0ef41Sopenharmony_ci      buflen = sizeof(buf);
8441cb0ef41Sopenharmony_ci
8451cb0ef41Sopenharmony_ci    do
8461cb0ef41Sopenharmony_ci      if (use_pread)
8471cb0ef41Sopenharmony_ci        nread = pread(in_fd, buf, buflen, offset);
8481cb0ef41Sopenharmony_ci      else
8491cb0ef41Sopenharmony_ci        nread = read(in_fd, buf, buflen);
8501cb0ef41Sopenharmony_ci    while (nread == -1 && errno == EINTR);
8511cb0ef41Sopenharmony_ci
8521cb0ef41Sopenharmony_ci    if (nread == 0)
8531cb0ef41Sopenharmony_ci      goto out;
8541cb0ef41Sopenharmony_ci
8551cb0ef41Sopenharmony_ci    if (nread == -1) {
8561cb0ef41Sopenharmony_ci      if (use_pread && nsent == 0 && (errno == EIO || errno == ESPIPE)) {
8571cb0ef41Sopenharmony_ci        use_pread = 0;
8581cb0ef41Sopenharmony_ci        continue;
8591cb0ef41Sopenharmony_ci      }
8601cb0ef41Sopenharmony_ci
8611cb0ef41Sopenharmony_ci      if (nsent == 0)
8621cb0ef41Sopenharmony_ci        nsent = -1;
8631cb0ef41Sopenharmony_ci
8641cb0ef41Sopenharmony_ci      goto out;
8651cb0ef41Sopenharmony_ci    }
8661cb0ef41Sopenharmony_ci
8671cb0ef41Sopenharmony_ci    for (nwritten = 0; nwritten < nread; ) {
8681cb0ef41Sopenharmony_ci      do
8691cb0ef41Sopenharmony_ci        n = write(out_fd, buf + nwritten, nread - nwritten);
8701cb0ef41Sopenharmony_ci      while (n == -1 && errno == EINTR);
8711cb0ef41Sopenharmony_ci
8721cb0ef41Sopenharmony_ci      if (n != -1) {
8731cb0ef41Sopenharmony_ci        nwritten += n;
8741cb0ef41Sopenharmony_ci        continue;
8751cb0ef41Sopenharmony_ci      }
8761cb0ef41Sopenharmony_ci
8771cb0ef41Sopenharmony_ci      if (errno != EAGAIN && errno != EWOULDBLOCK) {
8781cb0ef41Sopenharmony_ci        nsent = -1;
8791cb0ef41Sopenharmony_ci        goto out;
8801cb0ef41Sopenharmony_ci      }
8811cb0ef41Sopenharmony_ci
8821cb0ef41Sopenharmony_ci      pfd.fd = out_fd;
8831cb0ef41Sopenharmony_ci      pfd.events = POLLOUT;
8841cb0ef41Sopenharmony_ci      pfd.revents = 0;
8851cb0ef41Sopenharmony_ci
8861cb0ef41Sopenharmony_ci      do
8871cb0ef41Sopenharmony_ci        n = poll(&pfd, 1, -1);
8881cb0ef41Sopenharmony_ci      while (n == -1 && errno == EINTR);
8891cb0ef41Sopenharmony_ci
8901cb0ef41Sopenharmony_ci      if (n == -1 || (pfd.revents & ~POLLOUT) != 0) {
8911cb0ef41Sopenharmony_ci        errno = EIO;
8921cb0ef41Sopenharmony_ci        nsent = -1;
8931cb0ef41Sopenharmony_ci        goto out;
8941cb0ef41Sopenharmony_ci      }
8951cb0ef41Sopenharmony_ci    }
8961cb0ef41Sopenharmony_ci
8971cb0ef41Sopenharmony_ci    offset += nread;
8981cb0ef41Sopenharmony_ci    nsent += nread;
8991cb0ef41Sopenharmony_ci  }
9001cb0ef41Sopenharmony_ci
9011cb0ef41Sopenharmony_ciout:
9021cb0ef41Sopenharmony_ci  if (nsent != -1)
9031cb0ef41Sopenharmony_ci    req->off = offset;
9041cb0ef41Sopenharmony_ci
9051cb0ef41Sopenharmony_ci  return nsent;
9061cb0ef41Sopenharmony_ci}
9071cb0ef41Sopenharmony_ci
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_ci#ifdef __linux__
9101cb0ef41Sopenharmony_cistatic unsigned uv__kernel_version(void) {
9111cb0ef41Sopenharmony_ci  static unsigned cached_version;
9121cb0ef41Sopenharmony_ci  struct utsname u;
9131cb0ef41Sopenharmony_ci  unsigned version;
9141cb0ef41Sopenharmony_ci  unsigned major;
9151cb0ef41Sopenharmony_ci  unsigned minor;
9161cb0ef41Sopenharmony_ci  unsigned patch;
9171cb0ef41Sopenharmony_ci
9181cb0ef41Sopenharmony_ci  version = uv__load_relaxed(&cached_version);
9191cb0ef41Sopenharmony_ci  if (version != 0)
9201cb0ef41Sopenharmony_ci    return version;
9211cb0ef41Sopenharmony_ci
9221cb0ef41Sopenharmony_ci  if (-1 == uname(&u))
9231cb0ef41Sopenharmony_ci    return 0;
9241cb0ef41Sopenharmony_ci
9251cb0ef41Sopenharmony_ci  if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch))
9261cb0ef41Sopenharmony_ci    return 0;
9271cb0ef41Sopenharmony_ci
9281cb0ef41Sopenharmony_ci  version = major * 65536 + minor * 256 + patch;
9291cb0ef41Sopenharmony_ci  uv__store_relaxed(&cached_version, version);
9301cb0ef41Sopenharmony_ci
9311cb0ef41Sopenharmony_ci  return version;
9321cb0ef41Sopenharmony_ci}
9331cb0ef41Sopenharmony_ci
9341cb0ef41Sopenharmony_ci
9351cb0ef41Sopenharmony_ci/* Pre-4.20 kernels have a bug where CephFS uses the RADOS copy-from command
9361cb0ef41Sopenharmony_ci * in copy_file_range() when it shouldn't. There is no workaround except to
9371cb0ef41Sopenharmony_ci * fall back to a regular copy.
9381cb0ef41Sopenharmony_ci */
9391cb0ef41Sopenharmony_cistatic int uv__is_buggy_cephfs(int fd) {
9401cb0ef41Sopenharmony_ci  struct statfs s;
9411cb0ef41Sopenharmony_ci
9421cb0ef41Sopenharmony_ci  if (-1 == fstatfs(fd, &s))
9431cb0ef41Sopenharmony_ci    return 0;
9441cb0ef41Sopenharmony_ci
9451cb0ef41Sopenharmony_ci  if (s.f_type != /* CephFS */ 0xC36400)
9461cb0ef41Sopenharmony_ci    return 0;
9471cb0ef41Sopenharmony_ci
9481cb0ef41Sopenharmony_ci  return uv__kernel_version() < /* 4.20.0 */ 0x041400;
9491cb0ef41Sopenharmony_ci}
9501cb0ef41Sopenharmony_ci
9511cb0ef41Sopenharmony_ci
9521cb0ef41Sopenharmony_cistatic int uv__is_cifs_or_smb(int fd) {
9531cb0ef41Sopenharmony_ci  struct statfs s;
9541cb0ef41Sopenharmony_ci
9551cb0ef41Sopenharmony_ci  if (-1 == fstatfs(fd, &s))
9561cb0ef41Sopenharmony_ci    return 0;
9571cb0ef41Sopenharmony_ci
9581cb0ef41Sopenharmony_ci  switch ((unsigned) s.f_type) {
9591cb0ef41Sopenharmony_ci  case 0x0000517Bu:  /* SMB */
9601cb0ef41Sopenharmony_ci  case 0xFE534D42u:  /* SMB2 */
9611cb0ef41Sopenharmony_ci  case 0xFF534D42u:  /* CIFS */
9621cb0ef41Sopenharmony_ci    return 1;
9631cb0ef41Sopenharmony_ci  }
9641cb0ef41Sopenharmony_ci
9651cb0ef41Sopenharmony_ci  return 0;
9661cb0ef41Sopenharmony_ci}
9671cb0ef41Sopenharmony_ci
9681cb0ef41Sopenharmony_ci
9691cb0ef41Sopenharmony_cistatic ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off,
9701cb0ef41Sopenharmony_ci                                          int out_fd, size_t len) {
9711cb0ef41Sopenharmony_ci  static int no_copy_file_range_support;
9721cb0ef41Sopenharmony_ci  ssize_t r;
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ci  if (uv__load_relaxed(&no_copy_file_range_support)) {
9751cb0ef41Sopenharmony_ci    errno = ENOSYS;
9761cb0ef41Sopenharmony_ci    return -1;
9771cb0ef41Sopenharmony_ci  }
9781cb0ef41Sopenharmony_ci
9791cb0ef41Sopenharmony_ci  r = uv__fs_copy_file_range(in_fd, off, out_fd, NULL, len, 0);
9801cb0ef41Sopenharmony_ci
9811cb0ef41Sopenharmony_ci  if (r != -1)
9821cb0ef41Sopenharmony_ci    return r;
9831cb0ef41Sopenharmony_ci
9841cb0ef41Sopenharmony_ci  switch (errno) {
9851cb0ef41Sopenharmony_ci  case EACCES:
9861cb0ef41Sopenharmony_ci    /* Pre-4.20 kernels have a bug where CephFS uses the RADOS
9871cb0ef41Sopenharmony_ci     * copy-from command when it shouldn't.
9881cb0ef41Sopenharmony_ci     */
9891cb0ef41Sopenharmony_ci    if (uv__is_buggy_cephfs(in_fd))
9901cb0ef41Sopenharmony_ci      errno = ENOSYS;  /* Use fallback. */
9911cb0ef41Sopenharmony_ci    break;
9921cb0ef41Sopenharmony_ci  case ENOSYS:
9931cb0ef41Sopenharmony_ci    uv__store_relaxed(&no_copy_file_range_support, 1);
9941cb0ef41Sopenharmony_ci    break;
9951cb0ef41Sopenharmony_ci  case EPERM:
9961cb0ef41Sopenharmony_ci    /* It's been reported that CIFS spuriously fails.
9971cb0ef41Sopenharmony_ci     * Consider it a transient error.
9981cb0ef41Sopenharmony_ci     */
9991cb0ef41Sopenharmony_ci    if (uv__is_cifs_or_smb(out_fd))
10001cb0ef41Sopenharmony_ci      errno = ENOSYS;  /* Use fallback. */
10011cb0ef41Sopenharmony_ci    break;
10021cb0ef41Sopenharmony_ci  case ENOTSUP:
10031cb0ef41Sopenharmony_ci  case EXDEV:
10041cb0ef41Sopenharmony_ci    /* ENOTSUP - it could work on another file system type.
10051cb0ef41Sopenharmony_ci     * EXDEV - it will not work when in_fd and out_fd are not on the same
10061cb0ef41Sopenharmony_ci     *         mounted filesystem (pre Linux 5.3)
10071cb0ef41Sopenharmony_ci     */
10081cb0ef41Sopenharmony_ci    errno = ENOSYS;  /* Use fallback. */
10091cb0ef41Sopenharmony_ci    break;
10101cb0ef41Sopenharmony_ci  }
10111cb0ef41Sopenharmony_ci
10121cb0ef41Sopenharmony_ci  return -1;
10131cb0ef41Sopenharmony_ci}
10141cb0ef41Sopenharmony_ci
10151cb0ef41Sopenharmony_ci#endif  /* __linux__ */
10161cb0ef41Sopenharmony_ci
10171cb0ef41Sopenharmony_ci
10181cb0ef41Sopenharmony_cistatic ssize_t uv__fs_sendfile(uv_fs_t* req) {
10191cb0ef41Sopenharmony_ci  int in_fd;
10201cb0ef41Sopenharmony_ci  int out_fd;
10211cb0ef41Sopenharmony_ci
10221cb0ef41Sopenharmony_ci  in_fd = req->flags;
10231cb0ef41Sopenharmony_ci  out_fd = req->file;
10241cb0ef41Sopenharmony_ci
10251cb0ef41Sopenharmony_ci#if defined(__linux__) || defined(__sun)
10261cb0ef41Sopenharmony_ci  {
10271cb0ef41Sopenharmony_ci    off_t off;
10281cb0ef41Sopenharmony_ci    ssize_t r;
10291cb0ef41Sopenharmony_ci    size_t len;
10301cb0ef41Sopenharmony_ci    int try_sendfile;
10311cb0ef41Sopenharmony_ci
10321cb0ef41Sopenharmony_ci    off = req->off;
10331cb0ef41Sopenharmony_ci    len = req->bufsml[0].len;
10341cb0ef41Sopenharmony_ci    try_sendfile = 1;
10351cb0ef41Sopenharmony_ci
10361cb0ef41Sopenharmony_ci#ifdef __linux__
10371cb0ef41Sopenharmony_ci    r = uv__fs_try_copy_file_range(in_fd, &off, out_fd, len);
10381cb0ef41Sopenharmony_ci    try_sendfile = (r == -1 && errno == ENOSYS);
10391cb0ef41Sopenharmony_ci#endif
10401cb0ef41Sopenharmony_ci
10411cb0ef41Sopenharmony_ci    if (try_sendfile)
10421cb0ef41Sopenharmony_ci      r = sendfile(out_fd, in_fd, &off, len);
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ci    /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
10451cb0ef41Sopenharmony_ci     * it still writes out data. Fortunately, we can detect it by checking if
10461cb0ef41Sopenharmony_ci     * the offset has been updated.
10471cb0ef41Sopenharmony_ci     */
10481cb0ef41Sopenharmony_ci    if (r != -1 || off > req->off) {
10491cb0ef41Sopenharmony_ci      r = off - req->off;
10501cb0ef41Sopenharmony_ci      req->off = off;
10511cb0ef41Sopenharmony_ci      return r;
10521cb0ef41Sopenharmony_ci    }
10531cb0ef41Sopenharmony_ci
10541cb0ef41Sopenharmony_ci    if (errno == EINVAL ||
10551cb0ef41Sopenharmony_ci        errno == EIO ||
10561cb0ef41Sopenharmony_ci        errno == ENOTSOCK ||
10571cb0ef41Sopenharmony_ci        errno == EXDEV) {
10581cb0ef41Sopenharmony_ci      errno = 0;
10591cb0ef41Sopenharmony_ci      return uv__fs_sendfile_emul(req);
10601cb0ef41Sopenharmony_ci    }
10611cb0ef41Sopenharmony_ci
10621cb0ef41Sopenharmony_ci    return -1;
10631cb0ef41Sopenharmony_ci  }
10641cb0ef41Sopenharmony_ci#elif defined(__APPLE__)           || \
10651cb0ef41Sopenharmony_ci      defined(__DragonFly__)       || \
10661cb0ef41Sopenharmony_ci      defined(__FreeBSD__)         || \
10671cb0ef41Sopenharmony_ci      defined(__FreeBSD_kernel__)
10681cb0ef41Sopenharmony_ci  {
10691cb0ef41Sopenharmony_ci    off_t len;
10701cb0ef41Sopenharmony_ci    ssize_t r;
10711cb0ef41Sopenharmony_ci
10721cb0ef41Sopenharmony_ci    /* sendfile() on FreeBSD and Darwin returns EAGAIN if the target fd is in
10731cb0ef41Sopenharmony_ci     * non-blocking mode and not all data could be written. If a non-zero
10741cb0ef41Sopenharmony_ci     * number of bytes have been sent, we don't consider it an error.
10751cb0ef41Sopenharmony_ci     */
10761cb0ef41Sopenharmony_ci
10771cb0ef41Sopenharmony_ci#if defined(__FreeBSD__) || defined(__DragonFly__)
10781cb0ef41Sopenharmony_ci#if defined(__FreeBSD__)
10791cb0ef41Sopenharmony_ci    off_t off;
10801cb0ef41Sopenharmony_ci
10811cb0ef41Sopenharmony_ci    off = req->off;
10821cb0ef41Sopenharmony_ci    r = uv__fs_copy_file_range(in_fd, &off, out_fd, NULL, req->bufsml[0].len, 0);
10831cb0ef41Sopenharmony_ci    if (r >= 0) {
10841cb0ef41Sopenharmony_ci        r = off - req->off;
10851cb0ef41Sopenharmony_ci        req->off = off;
10861cb0ef41Sopenharmony_ci        return r;
10871cb0ef41Sopenharmony_ci    }
10881cb0ef41Sopenharmony_ci#endif
10891cb0ef41Sopenharmony_ci    len = 0;
10901cb0ef41Sopenharmony_ci    r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
10911cb0ef41Sopenharmony_ci#elif defined(__FreeBSD_kernel__)
10921cb0ef41Sopenharmony_ci    len = 0;
10931cb0ef41Sopenharmony_ci    r = bsd_sendfile(in_fd,
10941cb0ef41Sopenharmony_ci                     out_fd,
10951cb0ef41Sopenharmony_ci                     req->off,
10961cb0ef41Sopenharmony_ci                     req->bufsml[0].len,
10971cb0ef41Sopenharmony_ci                     NULL,
10981cb0ef41Sopenharmony_ci                     &len,
10991cb0ef41Sopenharmony_ci                     0);
11001cb0ef41Sopenharmony_ci#else
11011cb0ef41Sopenharmony_ci    /* The darwin sendfile takes len as an input for the length to send,
11021cb0ef41Sopenharmony_ci     * so make sure to initialize it with the caller's value. */
11031cb0ef41Sopenharmony_ci    len = req->bufsml[0].len;
11041cb0ef41Sopenharmony_ci    r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
11051cb0ef41Sopenharmony_ci#endif
11061cb0ef41Sopenharmony_ci
11071cb0ef41Sopenharmony_ci     /*
11081cb0ef41Sopenharmony_ci     * The man page for sendfile(2) on DragonFly states that `len` contains
11091cb0ef41Sopenharmony_ci     * a meaningful value ONLY in case of EAGAIN and EINTR.
11101cb0ef41Sopenharmony_ci     * Nothing is said about it's value in case of other errors, so better
11111cb0ef41Sopenharmony_ci     * not depend on the potential wrong assumption that is was not modified
11121cb0ef41Sopenharmony_ci     * by the syscall.
11131cb0ef41Sopenharmony_ci     */
11141cb0ef41Sopenharmony_ci    if (r == 0 || ((errno == EAGAIN || errno == EINTR) && len != 0)) {
11151cb0ef41Sopenharmony_ci      req->off += len;
11161cb0ef41Sopenharmony_ci      return (ssize_t) len;
11171cb0ef41Sopenharmony_ci    }
11181cb0ef41Sopenharmony_ci
11191cb0ef41Sopenharmony_ci    if (errno == EINVAL ||
11201cb0ef41Sopenharmony_ci        errno == EIO ||
11211cb0ef41Sopenharmony_ci        errno == ENOTSOCK ||
11221cb0ef41Sopenharmony_ci        errno == EXDEV) {
11231cb0ef41Sopenharmony_ci      errno = 0;
11241cb0ef41Sopenharmony_ci      return uv__fs_sendfile_emul(req);
11251cb0ef41Sopenharmony_ci    }
11261cb0ef41Sopenharmony_ci
11271cb0ef41Sopenharmony_ci    return -1;
11281cb0ef41Sopenharmony_ci  }
11291cb0ef41Sopenharmony_ci#else
11301cb0ef41Sopenharmony_ci  /* Squelch compiler warnings. */
11311cb0ef41Sopenharmony_ci  (void) &in_fd;
11321cb0ef41Sopenharmony_ci  (void) &out_fd;
11331cb0ef41Sopenharmony_ci
11341cb0ef41Sopenharmony_ci  return uv__fs_sendfile_emul(req);
11351cb0ef41Sopenharmony_ci#endif
11361cb0ef41Sopenharmony_ci}
11371cb0ef41Sopenharmony_ci
11381cb0ef41Sopenharmony_ci
11391cb0ef41Sopenharmony_cistatic ssize_t uv__fs_utime(uv_fs_t* req) {
11401cb0ef41Sopenharmony_ci#if defined(__linux__)                                                         \
11411cb0ef41Sopenharmony_ci    || defined(_AIX71)                                                         \
11421cb0ef41Sopenharmony_ci    || defined(__sun)                                                          \
11431cb0ef41Sopenharmony_ci    || defined(__HAIKU__)
11441cb0ef41Sopenharmony_ci  struct timespec ts[2];
11451cb0ef41Sopenharmony_ci  ts[0] = uv__fs_to_timespec(req->atime);
11461cb0ef41Sopenharmony_ci  ts[1] = uv__fs_to_timespec(req->mtime);
11471cb0ef41Sopenharmony_ci  return utimensat(AT_FDCWD, req->path, ts, 0);
11481cb0ef41Sopenharmony_ci#elif defined(__APPLE__)                                                      \
11491cb0ef41Sopenharmony_ci    || defined(__DragonFly__)                                                 \
11501cb0ef41Sopenharmony_ci    || defined(__FreeBSD__)                                                   \
11511cb0ef41Sopenharmony_ci    || defined(__FreeBSD_kernel__)                                            \
11521cb0ef41Sopenharmony_ci    || defined(__NetBSD__)                                                    \
11531cb0ef41Sopenharmony_ci    || defined(__OpenBSD__)
11541cb0ef41Sopenharmony_ci  struct timeval tv[2];
11551cb0ef41Sopenharmony_ci  tv[0] = uv__fs_to_timeval(req->atime);
11561cb0ef41Sopenharmony_ci  tv[1] = uv__fs_to_timeval(req->mtime);
11571cb0ef41Sopenharmony_ci  return utimes(req->path, tv);
11581cb0ef41Sopenharmony_ci#elif defined(_AIX)                                                           \
11591cb0ef41Sopenharmony_ci    && !defined(_AIX71)
11601cb0ef41Sopenharmony_ci  struct utimbuf buf;
11611cb0ef41Sopenharmony_ci  buf.actime = req->atime;
11621cb0ef41Sopenharmony_ci  buf.modtime = req->mtime;
11631cb0ef41Sopenharmony_ci  return utime(req->path, &buf);
11641cb0ef41Sopenharmony_ci#elif defined(__MVS__)
11651cb0ef41Sopenharmony_ci  attrib_t atr;
11661cb0ef41Sopenharmony_ci  memset(&atr, 0, sizeof(atr));
11671cb0ef41Sopenharmony_ci  atr.att_mtimechg = 1;
11681cb0ef41Sopenharmony_ci  atr.att_atimechg = 1;
11691cb0ef41Sopenharmony_ci  atr.att_mtime = req->mtime;
11701cb0ef41Sopenharmony_ci  atr.att_atime = req->atime;
11711cb0ef41Sopenharmony_ci  return __lchattr((char*) req->path, &atr, sizeof(atr));
11721cb0ef41Sopenharmony_ci#else
11731cb0ef41Sopenharmony_ci  errno = ENOSYS;
11741cb0ef41Sopenharmony_ci  return -1;
11751cb0ef41Sopenharmony_ci#endif
11761cb0ef41Sopenharmony_ci}
11771cb0ef41Sopenharmony_ci
11781cb0ef41Sopenharmony_ci
11791cb0ef41Sopenharmony_cistatic ssize_t uv__fs_lutime(uv_fs_t* req) {
11801cb0ef41Sopenharmony_ci#if defined(__linux__)            ||                                           \
11811cb0ef41Sopenharmony_ci    defined(_AIX71)               ||                                           \
11821cb0ef41Sopenharmony_ci    defined(__sun)                ||                                           \
11831cb0ef41Sopenharmony_ci    defined(__HAIKU__)            ||                                           \
11841cb0ef41Sopenharmony_ci    defined(__GNU__)              ||                                           \
11851cb0ef41Sopenharmony_ci    defined(__OpenBSD__)
11861cb0ef41Sopenharmony_ci  struct timespec ts[2];
11871cb0ef41Sopenharmony_ci  ts[0] = uv__fs_to_timespec(req->atime);
11881cb0ef41Sopenharmony_ci  ts[1] = uv__fs_to_timespec(req->mtime);
11891cb0ef41Sopenharmony_ci  return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW);
11901cb0ef41Sopenharmony_ci#elif defined(__APPLE__)          ||                                          \
11911cb0ef41Sopenharmony_ci      defined(__DragonFly__)      ||                                          \
11921cb0ef41Sopenharmony_ci      defined(__FreeBSD__)        ||                                          \
11931cb0ef41Sopenharmony_ci      defined(__FreeBSD_kernel__) ||                                          \
11941cb0ef41Sopenharmony_ci      defined(__NetBSD__)
11951cb0ef41Sopenharmony_ci  struct timeval tv[2];
11961cb0ef41Sopenharmony_ci  tv[0] = uv__fs_to_timeval(req->atime);
11971cb0ef41Sopenharmony_ci  tv[1] = uv__fs_to_timeval(req->mtime);
11981cb0ef41Sopenharmony_ci  return lutimes(req->path, tv);
11991cb0ef41Sopenharmony_ci#else
12001cb0ef41Sopenharmony_ci  errno = ENOSYS;
12011cb0ef41Sopenharmony_ci  return -1;
12021cb0ef41Sopenharmony_ci#endif
12031cb0ef41Sopenharmony_ci}
12041cb0ef41Sopenharmony_ci
12051cb0ef41Sopenharmony_ci
12061cb0ef41Sopenharmony_cistatic ssize_t uv__fs_write(uv_fs_t* req) {
12071cb0ef41Sopenharmony_ci#if defined(__linux__)
12081cb0ef41Sopenharmony_ci  static int no_pwritev;
12091cb0ef41Sopenharmony_ci#endif
12101cb0ef41Sopenharmony_ci  ssize_t r;
12111cb0ef41Sopenharmony_ci
12121cb0ef41Sopenharmony_ci  /* Serialize writes on OS X, concurrent write() and pwrite() calls result in
12131cb0ef41Sopenharmony_ci   * data loss. We can't use a per-file descriptor lock, the descriptor may be
12141cb0ef41Sopenharmony_ci   * a dup().
12151cb0ef41Sopenharmony_ci   */
12161cb0ef41Sopenharmony_ci#if defined(__APPLE__)
12171cb0ef41Sopenharmony_ci  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
12181cb0ef41Sopenharmony_ci
12191cb0ef41Sopenharmony_ci  if (pthread_mutex_lock(&lock))
12201cb0ef41Sopenharmony_ci    abort();
12211cb0ef41Sopenharmony_ci#endif
12221cb0ef41Sopenharmony_ci
12231cb0ef41Sopenharmony_ci  if (req->off < 0) {
12241cb0ef41Sopenharmony_ci    if (req->nbufs == 1)
12251cb0ef41Sopenharmony_ci      r = write(req->file, req->bufs[0].base, req->bufs[0].len);
12261cb0ef41Sopenharmony_ci    else
12271cb0ef41Sopenharmony_ci      r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
12281cb0ef41Sopenharmony_ci  } else {
12291cb0ef41Sopenharmony_ci    if (req->nbufs == 1) {
12301cb0ef41Sopenharmony_ci      r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
12311cb0ef41Sopenharmony_ci      goto done;
12321cb0ef41Sopenharmony_ci    }
12331cb0ef41Sopenharmony_ci#if HAVE_PREADV
12341cb0ef41Sopenharmony_ci    r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
12351cb0ef41Sopenharmony_ci#else
12361cb0ef41Sopenharmony_ci# if defined(__linux__)
12371cb0ef41Sopenharmony_ci    if (no_pwritev) retry:
12381cb0ef41Sopenharmony_ci# endif
12391cb0ef41Sopenharmony_ci    {
12401cb0ef41Sopenharmony_ci      r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
12411cb0ef41Sopenharmony_ci    }
12421cb0ef41Sopenharmony_ci# if defined(__linux__)
12431cb0ef41Sopenharmony_ci    else {
12441cb0ef41Sopenharmony_ci      r = uv__pwritev(req->file,
12451cb0ef41Sopenharmony_ci                      (struct iovec*) req->bufs,
12461cb0ef41Sopenharmony_ci                      req->nbufs,
12471cb0ef41Sopenharmony_ci                      req->off);
12481cb0ef41Sopenharmony_ci      if (r == -1 && errno == ENOSYS) {
12491cb0ef41Sopenharmony_ci        no_pwritev = 1;
12501cb0ef41Sopenharmony_ci        goto retry;
12511cb0ef41Sopenharmony_ci      }
12521cb0ef41Sopenharmony_ci    }
12531cb0ef41Sopenharmony_ci# endif
12541cb0ef41Sopenharmony_ci#endif
12551cb0ef41Sopenharmony_ci  }
12561cb0ef41Sopenharmony_ci
12571cb0ef41Sopenharmony_cidone:
12581cb0ef41Sopenharmony_ci#if defined(__APPLE__)
12591cb0ef41Sopenharmony_ci  if (pthread_mutex_unlock(&lock))
12601cb0ef41Sopenharmony_ci    abort();
12611cb0ef41Sopenharmony_ci#endif
12621cb0ef41Sopenharmony_ci
12631cb0ef41Sopenharmony_ci  return r;
12641cb0ef41Sopenharmony_ci}
12651cb0ef41Sopenharmony_ci
12661cb0ef41Sopenharmony_cistatic ssize_t uv__fs_copyfile(uv_fs_t* req) {
12671cb0ef41Sopenharmony_ci  uv_fs_t fs_req;
12681cb0ef41Sopenharmony_ci  uv_file srcfd;
12691cb0ef41Sopenharmony_ci  uv_file dstfd;
12701cb0ef41Sopenharmony_ci  struct stat src_statsbuf;
12711cb0ef41Sopenharmony_ci  struct stat dst_statsbuf;
12721cb0ef41Sopenharmony_ci  int dst_flags;
12731cb0ef41Sopenharmony_ci  int result;
12741cb0ef41Sopenharmony_ci  int err;
12751cb0ef41Sopenharmony_ci  off_t bytes_to_send;
12761cb0ef41Sopenharmony_ci  off_t in_offset;
12771cb0ef41Sopenharmony_ci  off_t bytes_written;
12781cb0ef41Sopenharmony_ci  size_t bytes_chunk;
12791cb0ef41Sopenharmony_ci
12801cb0ef41Sopenharmony_ci  dstfd = -1;
12811cb0ef41Sopenharmony_ci  err = 0;
12821cb0ef41Sopenharmony_ci
12831cb0ef41Sopenharmony_ci  /* Open the source file. */
12841cb0ef41Sopenharmony_ci  srcfd = uv_fs_open(NULL, &fs_req, req->path, O_RDONLY, 0, NULL);
12851cb0ef41Sopenharmony_ci  uv_fs_req_cleanup(&fs_req);
12861cb0ef41Sopenharmony_ci
12871cb0ef41Sopenharmony_ci  if (srcfd < 0)
12881cb0ef41Sopenharmony_ci    return srcfd;
12891cb0ef41Sopenharmony_ci
12901cb0ef41Sopenharmony_ci  /* Get the source file's mode. */
12911cb0ef41Sopenharmony_ci  if (fstat(srcfd, &src_statsbuf)) {
12921cb0ef41Sopenharmony_ci    err = UV__ERR(errno);
12931cb0ef41Sopenharmony_ci    goto out;
12941cb0ef41Sopenharmony_ci  }
12951cb0ef41Sopenharmony_ci
12961cb0ef41Sopenharmony_ci  dst_flags = O_WRONLY | O_CREAT;
12971cb0ef41Sopenharmony_ci
12981cb0ef41Sopenharmony_ci  if (req->flags & UV_FS_COPYFILE_EXCL)
12991cb0ef41Sopenharmony_ci    dst_flags |= O_EXCL;
13001cb0ef41Sopenharmony_ci
13011cb0ef41Sopenharmony_ci  /* Open the destination file. */
13021cb0ef41Sopenharmony_ci  dstfd = uv_fs_open(NULL,
13031cb0ef41Sopenharmony_ci                     &fs_req,
13041cb0ef41Sopenharmony_ci                     req->new_path,
13051cb0ef41Sopenharmony_ci                     dst_flags,
13061cb0ef41Sopenharmony_ci                     src_statsbuf.st_mode,
13071cb0ef41Sopenharmony_ci                     NULL);
13081cb0ef41Sopenharmony_ci  uv_fs_req_cleanup(&fs_req);
13091cb0ef41Sopenharmony_ci
13101cb0ef41Sopenharmony_ci  if (dstfd < 0) {
13111cb0ef41Sopenharmony_ci    err = dstfd;
13121cb0ef41Sopenharmony_ci    goto out;
13131cb0ef41Sopenharmony_ci  }
13141cb0ef41Sopenharmony_ci
13151cb0ef41Sopenharmony_ci  /* If the file is not being opened exclusively, verify that the source and
13161cb0ef41Sopenharmony_ci     destination are not the same file. If they are the same, bail out early. */
13171cb0ef41Sopenharmony_ci  if ((req->flags & UV_FS_COPYFILE_EXCL) == 0) {
13181cb0ef41Sopenharmony_ci    /* Get the destination file's mode. */
13191cb0ef41Sopenharmony_ci    if (fstat(dstfd, &dst_statsbuf)) {
13201cb0ef41Sopenharmony_ci      err = UV__ERR(errno);
13211cb0ef41Sopenharmony_ci      goto out;
13221cb0ef41Sopenharmony_ci    }
13231cb0ef41Sopenharmony_ci
13241cb0ef41Sopenharmony_ci    /* Check if srcfd and dstfd refer to the same file */
13251cb0ef41Sopenharmony_ci    if (src_statsbuf.st_dev == dst_statsbuf.st_dev &&
13261cb0ef41Sopenharmony_ci        src_statsbuf.st_ino == dst_statsbuf.st_ino) {
13271cb0ef41Sopenharmony_ci      goto out;
13281cb0ef41Sopenharmony_ci    }
13291cb0ef41Sopenharmony_ci
13301cb0ef41Sopenharmony_ci    /* Truncate the file in case the destination already existed. */
13311cb0ef41Sopenharmony_ci    if (ftruncate(dstfd, 0) != 0) {
13321cb0ef41Sopenharmony_ci      err = UV__ERR(errno);
13331cb0ef41Sopenharmony_ci      goto out;
13341cb0ef41Sopenharmony_ci    }
13351cb0ef41Sopenharmony_ci  }
13361cb0ef41Sopenharmony_ci
13371cb0ef41Sopenharmony_ci  if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
13381cb0ef41Sopenharmony_ci    err = UV__ERR(errno);
13391cb0ef41Sopenharmony_ci#ifdef __linux__
13401cb0ef41Sopenharmony_ci    /* fchmod() on CIFS shares always fails with EPERM unless the share is
13411cb0ef41Sopenharmony_ci     * mounted with "noperm". As fchmod() is a meaningless operation on such
13421cb0ef41Sopenharmony_ci     * shares anyway, detect that condition and squelch the error.
13431cb0ef41Sopenharmony_ci     */
13441cb0ef41Sopenharmony_ci    if (err != UV_EPERM)
13451cb0ef41Sopenharmony_ci      goto out;
13461cb0ef41Sopenharmony_ci
13471cb0ef41Sopenharmony_ci    if (!uv__is_cifs_or_smb(dstfd))
13481cb0ef41Sopenharmony_ci      goto out;
13491cb0ef41Sopenharmony_ci
13501cb0ef41Sopenharmony_ci    err = 0;
13511cb0ef41Sopenharmony_ci#else  /* !__linux__ */
13521cb0ef41Sopenharmony_ci    goto out;
13531cb0ef41Sopenharmony_ci#endif  /* !__linux__ */
13541cb0ef41Sopenharmony_ci  }
13551cb0ef41Sopenharmony_ci
13561cb0ef41Sopenharmony_ci#ifdef FICLONE
13571cb0ef41Sopenharmony_ci  if (req->flags & UV_FS_COPYFILE_FICLONE ||
13581cb0ef41Sopenharmony_ci      req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
13591cb0ef41Sopenharmony_ci    if (ioctl(dstfd, FICLONE, srcfd) == 0) {
13601cb0ef41Sopenharmony_ci      /* ioctl() with FICLONE succeeded. */
13611cb0ef41Sopenharmony_ci      goto out;
13621cb0ef41Sopenharmony_ci    }
13631cb0ef41Sopenharmony_ci    /* If an error occurred and force was set, return the error to the caller;
13641cb0ef41Sopenharmony_ci     * fall back to sendfile() when force was not set. */
13651cb0ef41Sopenharmony_ci    if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
13661cb0ef41Sopenharmony_ci      err = UV__ERR(errno);
13671cb0ef41Sopenharmony_ci      goto out;
13681cb0ef41Sopenharmony_ci    }
13691cb0ef41Sopenharmony_ci  }
13701cb0ef41Sopenharmony_ci#else
13711cb0ef41Sopenharmony_ci  if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
13721cb0ef41Sopenharmony_ci    err = UV_ENOSYS;
13731cb0ef41Sopenharmony_ci    goto out;
13741cb0ef41Sopenharmony_ci  }
13751cb0ef41Sopenharmony_ci#endif
13761cb0ef41Sopenharmony_ci
13771cb0ef41Sopenharmony_ci  bytes_to_send = src_statsbuf.st_size;
13781cb0ef41Sopenharmony_ci  in_offset = 0;
13791cb0ef41Sopenharmony_ci  while (bytes_to_send != 0) {
13801cb0ef41Sopenharmony_ci    bytes_chunk = SSIZE_MAX;
13811cb0ef41Sopenharmony_ci    if (bytes_to_send < (off_t) bytes_chunk)
13821cb0ef41Sopenharmony_ci      bytes_chunk = bytes_to_send;
13831cb0ef41Sopenharmony_ci    uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_chunk, NULL);
13841cb0ef41Sopenharmony_ci    bytes_written = fs_req.result;
13851cb0ef41Sopenharmony_ci    uv_fs_req_cleanup(&fs_req);
13861cb0ef41Sopenharmony_ci
13871cb0ef41Sopenharmony_ci    if (bytes_written < 0) {
13881cb0ef41Sopenharmony_ci      err = bytes_written;
13891cb0ef41Sopenharmony_ci      break;
13901cb0ef41Sopenharmony_ci    }
13911cb0ef41Sopenharmony_ci
13921cb0ef41Sopenharmony_ci    bytes_to_send -= bytes_written;
13931cb0ef41Sopenharmony_ci    in_offset += bytes_written;
13941cb0ef41Sopenharmony_ci  }
13951cb0ef41Sopenharmony_ci
13961cb0ef41Sopenharmony_ciout:
13971cb0ef41Sopenharmony_ci  if (err < 0)
13981cb0ef41Sopenharmony_ci    result = err;
13991cb0ef41Sopenharmony_ci  else
14001cb0ef41Sopenharmony_ci    result = 0;
14011cb0ef41Sopenharmony_ci
14021cb0ef41Sopenharmony_ci  /* Close the source file. */
14031cb0ef41Sopenharmony_ci  err = uv__close_nocheckstdio(srcfd);
14041cb0ef41Sopenharmony_ci
14051cb0ef41Sopenharmony_ci  /* Don't overwrite any existing errors. */
14061cb0ef41Sopenharmony_ci  if (err != 0 && result == 0)
14071cb0ef41Sopenharmony_ci    result = err;
14081cb0ef41Sopenharmony_ci
14091cb0ef41Sopenharmony_ci  /* Close the destination file if it is open. */
14101cb0ef41Sopenharmony_ci  if (dstfd >= 0) {
14111cb0ef41Sopenharmony_ci    err = uv__close_nocheckstdio(dstfd);
14121cb0ef41Sopenharmony_ci
14131cb0ef41Sopenharmony_ci    /* Don't overwrite any existing errors. */
14141cb0ef41Sopenharmony_ci    if (err != 0 && result == 0)
14151cb0ef41Sopenharmony_ci      result = err;
14161cb0ef41Sopenharmony_ci
14171cb0ef41Sopenharmony_ci    /* Remove the destination file if something went wrong. */
14181cb0ef41Sopenharmony_ci    if (result != 0) {
14191cb0ef41Sopenharmony_ci      uv_fs_unlink(NULL, &fs_req, req->new_path, NULL);
14201cb0ef41Sopenharmony_ci      /* Ignore the unlink return value, as an error already happened. */
14211cb0ef41Sopenharmony_ci      uv_fs_req_cleanup(&fs_req);
14221cb0ef41Sopenharmony_ci    }
14231cb0ef41Sopenharmony_ci  }
14241cb0ef41Sopenharmony_ci
14251cb0ef41Sopenharmony_ci  if (result == 0)
14261cb0ef41Sopenharmony_ci    return 0;
14271cb0ef41Sopenharmony_ci
14281cb0ef41Sopenharmony_ci  errno = UV__ERR(result);
14291cb0ef41Sopenharmony_ci  return -1;
14301cb0ef41Sopenharmony_ci}
14311cb0ef41Sopenharmony_ci
14321cb0ef41Sopenharmony_cistatic void uv__to_stat(struct stat* src, uv_stat_t* dst) {
14331cb0ef41Sopenharmony_ci  dst->st_dev = src->st_dev;
14341cb0ef41Sopenharmony_ci  dst->st_mode = src->st_mode;
14351cb0ef41Sopenharmony_ci  dst->st_nlink = src->st_nlink;
14361cb0ef41Sopenharmony_ci  dst->st_uid = src->st_uid;
14371cb0ef41Sopenharmony_ci  dst->st_gid = src->st_gid;
14381cb0ef41Sopenharmony_ci  dst->st_rdev = src->st_rdev;
14391cb0ef41Sopenharmony_ci  dst->st_ino = src->st_ino;
14401cb0ef41Sopenharmony_ci  dst->st_size = src->st_size;
14411cb0ef41Sopenharmony_ci  dst->st_blksize = src->st_blksize;
14421cb0ef41Sopenharmony_ci  dst->st_blocks = src->st_blocks;
14431cb0ef41Sopenharmony_ci
14441cb0ef41Sopenharmony_ci#if defined(__APPLE__)
14451cb0ef41Sopenharmony_ci  dst->st_atim.tv_sec = src->st_atimespec.tv_sec;
14461cb0ef41Sopenharmony_ci  dst->st_atim.tv_nsec = src->st_atimespec.tv_nsec;
14471cb0ef41Sopenharmony_ci  dst->st_mtim.tv_sec = src->st_mtimespec.tv_sec;
14481cb0ef41Sopenharmony_ci  dst->st_mtim.tv_nsec = src->st_mtimespec.tv_nsec;
14491cb0ef41Sopenharmony_ci  dst->st_ctim.tv_sec = src->st_ctimespec.tv_sec;
14501cb0ef41Sopenharmony_ci  dst->st_ctim.tv_nsec = src->st_ctimespec.tv_nsec;
14511cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_sec = src->st_birthtimespec.tv_sec;
14521cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_nsec = src->st_birthtimespec.tv_nsec;
14531cb0ef41Sopenharmony_ci  dst->st_flags = src->st_flags;
14541cb0ef41Sopenharmony_ci  dst->st_gen = src->st_gen;
14551cb0ef41Sopenharmony_ci#elif defined(__ANDROID__)
14561cb0ef41Sopenharmony_ci  dst->st_atim.tv_sec = src->st_atime;
14571cb0ef41Sopenharmony_ci  dst->st_atim.tv_nsec = src->st_atimensec;
14581cb0ef41Sopenharmony_ci  dst->st_mtim.tv_sec = src->st_mtime;
14591cb0ef41Sopenharmony_ci  dst->st_mtim.tv_nsec = src->st_mtimensec;
14601cb0ef41Sopenharmony_ci  dst->st_ctim.tv_sec = src->st_ctime;
14611cb0ef41Sopenharmony_ci  dst->st_ctim.tv_nsec = src->st_ctimensec;
14621cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_sec = src->st_ctime;
14631cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_nsec = src->st_ctimensec;
14641cb0ef41Sopenharmony_ci  dst->st_flags = 0;
14651cb0ef41Sopenharmony_ci  dst->st_gen = 0;
14661cb0ef41Sopenharmony_ci#elif !defined(_AIX) &&         \
14671cb0ef41Sopenharmony_ci    !defined(__MVS__) && (      \
14681cb0ef41Sopenharmony_ci    defined(__DragonFly__)   || \
14691cb0ef41Sopenharmony_ci    defined(__FreeBSD__)     || \
14701cb0ef41Sopenharmony_ci    defined(__OpenBSD__)     || \
14711cb0ef41Sopenharmony_ci    defined(__NetBSD__)      || \
14721cb0ef41Sopenharmony_ci    defined(_GNU_SOURCE)     || \
14731cb0ef41Sopenharmony_ci    defined(_BSD_SOURCE)     || \
14741cb0ef41Sopenharmony_ci    defined(_SVID_SOURCE)    || \
14751cb0ef41Sopenharmony_ci    defined(_XOPEN_SOURCE)   || \
14761cb0ef41Sopenharmony_ci    defined(_DEFAULT_SOURCE))
14771cb0ef41Sopenharmony_ci  dst->st_atim.tv_sec = src->st_atim.tv_sec;
14781cb0ef41Sopenharmony_ci  dst->st_atim.tv_nsec = src->st_atim.tv_nsec;
14791cb0ef41Sopenharmony_ci  dst->st_mtim.tv_sec = src->st_mtim.tv_sec;
14801cb0ef41Sopenharmony_ci  dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
14811cb0ef41Sopenharmony_ci  dst->st_ctim.tv_sec = src->st_ctim.tv_sec;
14821cb0ef41Sopenharmony_ci  dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
14831cb0ef41Sopenharmony_ci# if defined(__FreeBSD__)    || \
14841cb0ef41Sopenharmony_ci     defined(__NetBSD__)
14851cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec;
14861cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec;
14871cb0ef41Sopenharmony_ci  dst->st_flags = src->st_flags;
14881cb0ef41Sopenharmony_ci  dst->st_gen = src->st_gen;
14891cb0ef41Sopenharmony_ci# else
14901cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_sec = src->st_ctim.tv_sec;
14911cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_nsec = src->st_ctim.tv_nsec;
14921cb0ef41Sopenharmony_ci  dst->st_flags = 0;
14931cb0ef41Sopenharmony_ci  dst->st_gen = 0;
14941cb0ef41Sopenharmony_ci# endif
14951cb0ef41Sopenharmony_ci#else
14961cb0ef41Sopenharmony_ci  dst->st_atim.tv_sec = src->st_atime;
14971cb0ef41Sopenharmony_ci  dst->st_atim.tv_nsec = 0;
14981cb0ef41Sopenharmony_ci  dst->st_mtim.tv_sec = src->st_mtime;
14991cb0ef41Sopenharmony_ci  dst->st_mtim.tv_nsec = 0;
15001cb0ef41Sopenharmony_ci  dst->st_ctim.tv_sec = src->st_ctime;
15011cb0ef41Sopenharmony_ci  dst->st_ctim.tv_nsec = 0;
15021cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_sec = src->st_ctime;
15031cb0ef41Sopenharmony_ci  dst->st_birthtim.tv_nsec = 0;
15041cb0ef41Sopenharmony_ci  dst->st_flags = 0;
15051cb0ef41Sopenharmony_ci  dst->st_gen = 0;
15061cb0ef41Sopenharmony_ci#endif
15071cb0ef41Sopenharmony_ci}
15081cb0ef41Sopenharmony_ci
15091cb0ef41Sopenharmony_ci
15101cb0ef41Sopenharmony_cistatic int uv__fs_statx(int fd,
15111cb0ef41Sopenharmony_ci                        const char* path,
15121cb0ef41Sopenharmony_ci                        int is_fstat,
15131cb0ef41Sopenharmony_ci                        int is_lstat,
15141cb0ef41Sopenharmony_ci                        uv_stat_t* buf) {
15151cb0ef41Sopenharmony_ci  STATIC_ASSERT(UV_ENOSYS != -1);
15161cb0ef41Sopenharmony_ci#ifdef __linux__
15171cb0ef41Sopenharmony_ci  static int no_statx;
15181cb0ef41Sopenharmony_ci  struct uv__statx statxbuf;
15191cb0ef41Sopenharmony_ci  int dirfd;
15201cb0ef41Sopenharmony_ci  int flags;
15211cb0ef41Sopenharmony_ci  int mode;
15221cb0ef41Sopenharmony_ci  int rc;
15231cb0ef41Sopenharmony_ci
15241cb0ef41Sopenharmony_ci  if (uv__load_relaxed(&no_statx))
15251cb0ef41Sopenharmony_ci    return UV_ENOSYS;
15261cb0ef41Sopenharmony_ci
15271cb0ef41Sopenharmony_ci  dirfd = AT_FDCWD;
15281cb0ef41Sopenharmony_ci  flags = 0; /* AT_STATX_SYNC_AS_STAT */
15291cb0ef41Sopenharmony_ci  mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */
15301cb0ef41Sopenharmony_ci
15311cb0ef41Sopenharmony_ci  if (is_fstat) {
15321cb0ef41Sopenharmony_ci    dirfd = fd;
15331cb0ef41Sopenharmony_ci    flags |= 0x1000; /* AT_EMPTY_PATH */
15341cb0ef41Sopenharmony_ci  }
15351cb0ef41Sopenharmony_ci
15361cb0ef41Sopenharmony_ci  if (is_lstat)
15371cb0ef41Sopenharmony_ci    flags |= AT_SYMLINK_NOFOLLOW;
15381cb0ef41Sopenharmony_ci
15391cb0ef41Sopenharmony_ci  rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
15401cb0ef41Sopenharmony_ci
15411cb0ef41Sopenharmony_ci  switch (rc) {
15421cb0ef41Sopenharmony_ci  case 0:
15431cb0ef41Sopenharmony_ci    break;
15441cb0ef41Sopenharmony_ci  case -1:
15451cb0ef41Sopenharmony_ci    /* EPERM happens when a seccomp filter rejects the system call.
15461cb0ef41Sopenharmony_ci     * Has been observed with libseccomp < 2.3.3 and docker < 18.04.
15471cb0ef41Sopenharmony_ci     * EOPNOTSUPP is used on DVS exported filesystems
15481cb0ef41Sopenharmony_ci     */
15491cb0ef41Sopenharmony_ci    if (errno != EINVAL && errno != EPERM && errno != ENOSYS && errno != EOPNOTSUPP)
15501cb0ef41Sopenharmony_ci      return -1;
15511cb0ef41Sopenharmony_ci    /* Fall through. */
15521cb0ef41Sopenharmony_ci  default:
15531cb0ef41Sopenharmony_ci    /* Normally on success, zero is returned and On error, -1 is returned.
15541cb0ef41Sopenharmony_ci     * Observed on S390 RHEL running in a docker container with statx not
15551cb0ef41Sopenharmony_ci     * implemented, rc might return 1 with 0 set as the error code in which
15561cb0ef41Sopenharmony_ci     * case we return ENOSYS.
15571cb0ef41Sopenharmony_ci     */
15581cb0ef41Sopenharmony_ci    uv__store_relaxed(&no_statx, 1);
15591cb0ef41Sopenharmony_ci    return UV_ENOSYS;
15601cb0ef41Sopenharmony_ci  }
15611cb0ef41Sopenharmony_ci
15621cb0ef41Sopenharmony_ci  buf->st_dev = makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor);
15631cb0ef41Sopenharmony_ci  buf->st_mode = statxbuf.stx_mode;
15641cb0ef41Sopenharmony_ci  buf->st_nlink = statxbuf.stx_nlink;
15651cb0ef41Sopenharmony_ci  buf->st_uid = statxbuf.stx_uid;
15661cb0ef41Sopenharmony_ci  buf->st_gid = statxbuf.stx_gid;
15671cb0ef41Sopenharmony_ci  buf->st_rdev = makedev(statxbuf.stx_rdev_major, statxbuf.stx_rdev_minor);
15681cb0ef41Sopenharmony_ci  buf->st_ino = statxbuf.stx_ino;
15691cb0ef41Sopenharmony_ci  buf->st_size = statxbuf.stx_size;
15701cb0ef41Sopenharmony_ci  buf->st_blksize = statxbuf.stx_blksize;
15711cb0ef41Sopenharmony_ci  buf->st_blocks = statxbuf.stx_blocks;
15721cb0ef41Sopenharmony_ci  buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec;
15731cb0ef41Sopenharmony_ci  buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec;
15741cb0ef41Sopenharmony_ci  buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec;
15751cb0ef41Sopenharmony_ci  buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec;
15761cb0ef41Sopenharmony_ci  buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec;
15771cb0ef41Sopenharmony_ci  buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec;
15781cb0ef41Sopenharmony_ci  buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec;
15791cb0ef41Sopenharmony_ci  buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec;
15801cb0ef41Sopenharmony_ci  buf->st_flags = 0;
15811cb0ef41Sopenharmony_ci  buf->st_gen = 0;
15821cb0ef41Sopenharmony_ci
15831cb0ef41Sopenharmony_ci  return 0;
15841cb0ef41Sopenharmony_ci#else
15851cb0ef41Sopenharmony_ci  return UV_ENOSYS;
15861cb0ef41Sopenharmony_ci#endif /* __linux__ */
15871cb0ef41Sopenharmony_ci}
15881cb0ef41Sopenharmony_ci
15891cb0ef41Sopenharmony_ci
15901cb0ef41Sopenharmony_cistatic int uv__fs_stat(const char *path, uv_stat_t *buf) {
15911cb0ef41Sopenharmony_ci  struct stat pbuf;
15921cb0ef41Sopenharmony_ci  int ret;
15931cb0ef41Sopenharmony_ci
15941cb0ef41Sopenharmony_ci  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf);
15951cb0ef41Sopenharmony_ci  if (ret != UV_ENOSYS)
15961cb0ef41Sopenharmony_ci    return ret;
15971cb0ef41Sopenharmony_ci
15981cb0ef41Sopenharmony_ci  ret = stat(path, &pbuf);
15991cb0ef41Sopenharmony_ci  if (ret == 0)
16001cb0ef41Sopenharmony_ci    uv__to_stat(&pbuf, buf);
16011cb0ef41Sopenharmony_ci
16021cb0ef41Sopenharmony_ci  return ret;
16031cb0ef41Sopenharmony_ci}
16041cb0ef41Sopenharmony_ci
16051cb0ef41Sopenharmony_ci
16061cb0ef41Sopenharmony_cistatic int uv__fs_lstat(const char *path, uv_stat_t *buf) {
16071cb0ef41Sopenharmony_ci  struct stat pbuf;
16081cb0ef41Sopenharmony_ci  int ret;
16091cb0ef41Sopenharmony_ci
16101cb0ef41Sopenharmony_ci  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf);
16111cb0ef41Sopenharmony_ci  if (ret != UV_ENOSYS)
16121cb0ef41Sopenharmony_ci    return ret;
16131cb0ef41Sopenharmony_ci
16141cb0ef41Sopenharmony_ci  ret = lstat(path, &pbuf);
16151cb0ef41Sopenharmony_ci  if (ret == 0)
16161cb0ef41Sopenharmony_ci    uv__to_stat(&pbuf, buf);
16171cb0ef41Sopenharmony_ci
16181cb0ef41Sopenharmony_ci  return ret;
16191cb0ef41Sopenharmony_ci}
16201cb0ef41Sopenharmony_ci
16211cb0ef41Sopenharmony_ci
16221cb0ef41Sopenharmony_cistatic int uv__fs_fstat(int fd, uv_stat_t *buf) {
16231cb0ef41Sopenharmony_ci  struct stat pbuf;
16241cb0ef41Sopenharmony_ci  int ret;
16251cb0ef41Sopenharmony_ci
16261cb0ef41Sopenharmony_ci  ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf);
16271cb0ef41Sopenharmony_ci  if (ret != UV_ENOSYS)
16281cb0ef41Sopenharmony_ci    return ret;
16291cb0ef41Sopenharmony_ci
16301cb0ef41Sopenharmony_ci  ret = fstat(fd, &pbuf);
16311cb0ef41Sopenharmony_ci  if (ret == 0)
16321cb0ef41Sopenharmony_ci    uv__to_stat(&pbuf, buf);
16331cb0ef41Sopenharmony_ci
16341cb0ef41Sopenharmony_ci  return ret;
16351cb0ef41Sopenharmony_ci}
16361cb0ef41Sopenharmony_ci
16371cb0ef41Sopenharmony_cistatic size_t uv__fs_buf_offset(uv_buf_t* bufs, size_t size) {
16381cb0ef41Sopenharmony_ci  size_t offset;
16391cb0ef41Sopenharmony_ci  /* Figure out which bufs are done */
16401cb0ef41Sopenharmony_ci  for (offset = 0; size > 0 && bufs[offset].len <= size; ++offset)
16411cb0ef41Sopenharmony_ci    size -= bufs[offset].len;
16421cb0ef41Sopenharmony_ci
16431cb0ef41Sopenharmony_ci  /* Fix a partial read/write */
16441cb0ef41Sopenharmony_ci  if (size > 0) {
16451cb0ef41Sopenharmony_ci    bufs[offset].base += size;
16461cb0ef41Sopenharmony_ci    bufs[offset].len -= size;
16471cb0ef41Sopenharmony_ci  }
16481cb0ef41Sopenharmony_ci  return offset;
16491cb0ef41Sopenharmony_ci}
16501cb0ef41Sopenharmony_ci
16511cb0ef41Sopenharmony_cistatic ssize_t uv__fs_write_all(uv_fs_t* req) {
16521cb0ef41Sopenharmony_ci  unsigned int iovmax;
16531cb0ef41Sopenharmony_ci  unsigned int nbufs;
16541cb0ef41Sopenharmony_ci  uv_buf_t* bufs;
16551cb0ef41Sopenharmony_ci  ssize_t total;
16561cb0ef41Sopenharmony_ci  ssize_t result;
16571cb0ef41Sopenharmony_ci
16581cb0ef41Sopenharmony_ci  iovmax = uv__getiovmax();
16591cb0ef41Sopenharmony_ci  nbufs = req->nbufs;
16601cb0ef41Sopenharmony_ci  bufs = req->bufs;
16611cb0ef41Sopenharmony_ci  total = 0;
16621cb0ef41Sopenharmony_ci
16631cb0ef41Sopenharmony_ci  while (nbufs > 0) {
16641cb0ef41Sopenharmony_ci    req->nbufs = nbufs;
16651cb0ef41Sopenharmony_ci    if (req->nbufs > iovmax)
16661cb0ef41Sopenharmony_ci      req->nbufs = iovmax;
16671cb0ef41Sopenharmony_ci
16681cb0ef41Sopenharmony_ci    do
16691cb0ef41Sopenharmony_ci      result = uv__fs_write(req);
16701cb0ef41Sopenharmony_ci    while (result < 0 && errno == EINTR);
16711cb0ef41Sopenharmony_ci
16721cb0ef41Sopenharmony_ci    if (result <= 0) {
16731cb0ef41Sopenharmony_ci      if (total == 0)
16741cb0ef41Sopenharmony_ci        total = result;
16751cb0ef41Sopenharmony_ci      break;
16761cb0ef41Sopenharmony_ci    }
16771cb0ef41Sopenharmony_ci
16781cb0ef41Sopenharmony_ci    if (req->off >= 0)
16791cb0ef41Sopenharmony_ci      req->off += result;
16801cb0ef41Sopenharmony_ci
16811cb0ef41Sopenharmony_ci    req->nbufs = uv__fs_buf_offset(req->bufs, result);
16821cb0ef41Sopenharmony_ci    req->bufs += req->nbufs;
16831cb0ef41Sopenharmony_ci    nbufs -= req->nbufs;
16841cb0ef41Sopenharmony_ci    total += result;
16851cb0ef41Sopenharmony_ci  }
16861cb0ef41Sopenharmony_ci
16871cb0ef41Sopenharmony_ci  if (bufs != req->bufsml)
16881cb0ef41Sopenharmony_ci    uv__free(bufs);
16891cb0ef41Sopenharmony_ci
16901cb0ef41Sopenharmony_ci  req->bufs = NULL;
16911cb0ef41Sopenharmony_ci  req->nbufs = 0;
16921cb0ef41Sopenharmony_ci
16931cb0ef41Sopenharmony_ci  return total;
16941cb0ef41Sopenharmony_ci}
16951cb0ef41Sopenharmony_ci
16961cb0ef41Sopenharmony_ci
16971cb0ef41Sopenharmony_cistatic void uv__fs_work(struct uv__work* w) {
16981cb0ef41Sopenharmony_ci  int retry_on_eintr;
16991cb0ef41Sopenharmony_ci  uv_fs_t* req;
17001cb0ef41Sopenharmony_ci  ssize_t r;
17011cb0ef41Sopenharmony_ci
17021cb0ef41Sopenharmony_ci  req = container_of(w, uv_fs_t, work_req);
17031cb0ef41Sopenharmony_ci  retry_on_eintr = !(req->fs_type == UV_FS_CLOSE ||
17041cb0ef41Sopenharmony_ci                     req->fs_type == UV_FS_READ);
17051cb0ef41Sopenharmony_ci
17061cb0ef41Sopenharmony_ci  do {
17071cb0ef41Sopenharmony_ci    errno = 0;
17081cb0ef41Sopenharmony_ci
17091cb0ef41Sopenharmony_ci#define X(type, action)                                                       \
17101cb0ef41Sopenharmony_ci  case UV_FS_ ## type:                                                        \
17111cb0ef41Sopenharmony_ci    r = action;                                                               \
17121cb0ef41Sopenharmony_ci    break;
17131cb0ef41Sopenharmony_ci
17141cb0ef41Sopenharmony_ci    switch (req->fs_type) {
17151cb0ef41Sopenharmony_ci    X(ACCESS, access(req->path, req->flags));
17161cb0ef41Sopenharmony_ci    X(CHMOD, chmod(req->path, req->mode));
17171cb0ef41Sopenharmony_ci    X(CHOWN, chown(req->path, req->uid, req->gid));
17181cb0ef41Sopenharmony_ci    X(CLOSE, uv__fs_close(req->file));
17191cb0ef41Sopenharmony_ci    X(COPYFILE, uv__fs_copyfile(req));
17201cb0ef41Sopenharmony_ci    X(FCHMOD, fchmod(req->file, req->mode));
17211cb0ef41Sopenharmony_ci    X(FCHOWN, fchown(req->file, req->uid, req->gid));
17221cb0ef41Sopenharmony_ci    X(LCHOWN, lchown(req->path, req->uid, req->gid));
17231cb0ef41Sopenharmony_ci    X(FDATASYNC, uv__fs_fdatasync(req));
17241cb0ef41Sopenharmony_ci    X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
17251cb0ef41Sopenharmony_ci    X(FSYNC, uv__fs_fsync(req));
17261cb0ef41Sopenharmony_ci    X(FTRUNCATE, ftruncate(req->file, req->off));
17271cb0ef41Sopenharmony_ci    X(FUTIME, uv__fs_futime(req));
17281cb0ef41Sopenharmony_ci    X(LUTIME, uv__fs_lutime(req));
17291cb0ef41Sopenharmony_ci    X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
17301cb0ef41Sopenharmony_ci    X(LINK, link(req->path, req->new_path));
17311cb0ef41Sopenharmony_ci    X(MKDIR, mkdir(req->path, req->mode));
17321cb0ef41Sopenharmony_ci    X(MKDTEMP, uv__fs_mkdtemp(req));
17331cb0ef41Sopenharmony_ci    X(MKSTEMP, uv__fs_mkstemp(req));
17341cb0ef41Sopenharmony_ci    X(OPEN, uv__fs_open(req));
17351cb0ef41Sopenharmony_ci    X(READ, uv__fs_read(req));
17361cb0ef41Sopenharmony_ci    X(SCANDIR, uv__fs_scandir(req));
17371cb0ef41Sopenharmony_ci    X(OPENDIR, uv__fs_opendir(req));
17381cb0ef41Sopenharmony_ci    X(READDIR, uv__fs_readdir(req));
17391cb0ef41Sopenharmony_ci    X(CLOSEDIR, uv__fs_closedir(req));
17401cb0ef41Sopenharmony_ci    X(READLINK, uv__fs_readlink(req));
17411cb0ef41Sopenharmony_ci    X(REALPATH, uv__fs_realpath(req));
17421cb0ef41Sopenharmony_ci    X(RENAME, rename(req->path, req->new_path));
17431cb0ef41Sopenharmony_ci    X(RMDIR, rmdir(req->path));
17441cb0ef41Sopenharmony_ci    X(SENDFILE, uv__fs_sendfile(req));
17451cb0ef41Sopenharmony_ci    X(STAT, uv__fs_stat(req->path, &req->statbuf));
17461cb0ef41Sopenharmony_ci    X(STATFS, uv__fs_statfs(req));
17471cb0ef41Sopenharmony_ci    X(SYMLINK, symlink(req->path, req->new_path));
17481cb0ef41Sopenharmony_ci    X(UNLINK, unlink(req->path));
17491cb0ef41Sopenharmony_ci    X(UTIME, uv__fs_utime(req));
17501cb0ef41Sopenharmony_ci    X(WRITE, uv__fs_write_all(req));
17511cb0ef41Sopenharmony_ci    default: abort();
17521cb0ef41Sopenharmony_ci    }
17531cb0ef41Sopenharmony_ci#undef X
17541cb0ef41Sopenharmony_ci  } while (r == -1 && errno == EINTR && retry_on_eintr);
17551cb0ef41Sopenharmony_ci
17561cb0ef41Sopenharmony_ci  if (r == -1)
17571cb0ef41Sopenharmony_ci    req->result = UV__ERR(errno);
17581cb0ef41Sopenharmony_ci  else
17591cb0ef41Sopenharmony_ci    req->result = r;
17601cb0ef41Sopenharmony_ci
17611cb0ef41Sopenharmony_ci  if (r == 0 && (req->fs_type == UV_FS_STAT ||
17621cb0ef41Sopenharmony_ci                 req->fs_type == UV_FS_FSTAT ||
17631cb0ef41Sopenharmony_ci                 req->fs_type == UV_FS_LSTAT)) {
17641cb0ef41Sopenharmony_ci    req->ptr = &req->statbuf;
17651cb0ef41Sopenharmony_ci  }
17661cb0ef41Sopenharmony_ci}
17671cb0ef41Sopenharmony_ci
17681cb0ef41Sopenharmony_ci
17691cb0ef41Sopenharmony_cistatic void uv__fs_done(struct uv__work* w, int status) {
17701cb0ef41Sopenharmony_ci  uv_fs_t* req;
17711cb0ef41Sopenharmony_ci
17721cb0ef41Sopenharmony_ci  req = container_of(w, uv_fs_t, work_req);
17731cb0ef41Sopenharmony_ci  uv__req_unregister(req->loop, req);
17741cb0ef41Sopenharmony_ci
17751cb0ef41Sopenharmony_ci  if (status == UV_ECANCELED) {
17761cb0ef41Sopenharmony_ci    assert(req->result == 0);
17771cb0ef41Sopenharmony_ci    req->result = UV_ECANCELED;
17781cb0ef41Sopenharmony_ci  }
17791cb0ef41Sopenharmony_ci
17801cb0ef41Sopenharmony_ci  req->cb(req);
17811cb0ef41Sopenharmony_ci}
17821cb0ef41Sopenharmony_ci
17831cb0ef41Sopenharmony_ci
17841cb0ef41Sopenharmony_ciint uv_fs_access(uv_loop_t* loop,
17851cb0ef41Sopenharmony_ci                 uv_fs_t* req,
17861cb0ef41Sopenharmony_ci                 const char* path,
17871cb0ef41Sopenharmony_ci                 int flags,
17881cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
17891cb0ef41Sopenharmony_ci  INIT(ACCESS);
17901cb0ef41Sopenharmony_ci  PATH;
17911cb0ef41Sopenharmony_ci  req->flags = flags;
17921cb0ef41Sopenharmony_ci  POST;
17931cb0ef41Sopenharmony_ci}
17941cb0ef41Sopenharmony_ci
17951cb0ef41Sopenharmony_ci
17961cb0ef41Sopenharmony_ciint uv_fs_chmod(uv_loop_t* loop,
17971cb0ef41Sopenharmony_ci                uv_fs_t* req,
17981cb0ef41Sopenharmony_ci                const char* path,
17991cb0ef41Sopenharmony_ci                int mode,
18001cb0ef41Sopenharmony_ci                uv_fs_cb cb) {
18011cb0ef41Sopenharmony_ci  INIT(CHMOD);
18021cb0ef41Sopenharmony_ci  PATH;
18031cb0ef41Sopenharmony_ci  req->mode = mode;
18041cb0ef41Sopenharmony_ci  POST;
18051cb0ef41Sopenharmony_ci}
18061cb0ef41Sopenharmony_ci
18071cb0ef41Sopenharmony_ci
18081cb0ef41Sopenharmony_ciint uv_fs_chown(uv_loop_t* loop,
18091cb0ef41Sopenharmony_ci                uv_fs_t* req,
18101cb0ef41Sopenharmony_ci                const char* path,
18111cb0ef41Sopenharmony_ci                uv_uid_t uid,
18121cb0ef41Sopenharmony_ci                uv_gid_t gid,
18131cb0ef41Sopenharmony_ci                uv_fs_cb cb) {
18141cb0ef41Sopenharmony_ci  INIT(CHOWN);
18151cb0ef41Sopenharmony_ci  PATH;
18161cb0ef41Sopenharmony_ci  req->uid = uid;
18171cb0ef41Sopenharmony_ci  req->gid = gid;
18181cb0ef41Sopenharmony_ci  POST;
18191cb0ef41Sopenharmony_ci}
18201cb0ef41Sopenharmony_ci
18211cb0ef41Sopenharmony_ci
18221cb0ef41Sopenharmony_ciint uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
18231cb0ef41Sopenharmony_ci  INIT(CLOSE);
18241cb0ef41Sopenharmony_ci  req->file = file;
18251cb0ef41Sopenharmony_ci  POST;
18261cb0ef41Sopenharmony_ci}
18271cb0ef41Sopenharmony_ci
18281cb0ef41Sopenharmony_ci
18291cb0ef41Sopenharmony_ciint uv_fs_fchmod(uv_loop_t* loop,
18301cb0ef41Sopenharmony_ci                 uv_fs_t* req,
18311cb0ef41Sopenharmony_ci                 uv_file file,
18321cb0ef41Sopenharmony_ci                 int mode,
18331cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
18341cb0ef41Sopenharmony_ci  INIT(FCHMOD);
18351cb0ef41Sopenharmony_ci  req->file = file;
18361cb0ef41Sopenharmony_ci  req->mode = mode;
18371cb0ef41Sopenharmony_ci  POST;
18381cb0ef41Sopenharmony_ci}
18391cb0ef41Sopenharmony_ci
18401cb0ef41Sopenharmony_ci
18411cb0ef41Sopenharmony_ciint uv_fs_fchown(uv_loop_t* loop,
18421cb0ef41Sopenharmony_ci                 uv_fs_t* req,
18431cb0ef41Sopenharmony_ci                 uv_file file,
18441cb0ef41Sopenharmony_ci                 uv_uid_t uid,
18451cb0ef41Sopenharmony_ci                 uv_gid_t gid,
18461cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
18471cb0ef41Sopenharmony_ci  INIT(FCHOWN);
18481cb0ef41Sopenharmony_ci  req->file = file;
18491cb0ef41Sopenharmony_ci  req->uid = uid;
18501cb0ef41Sopenharmony_ci  req->gid = gid;
18511cb0ef41Sopenharmony_ci  POST;
18521cb0ef41Sopenharmony_ci}
18531cb0ef41Sopenharmony_ci
18541cb0ef41Sopenharmony_ci
18551cb0ef41Sopenharmony_ciint uv_fs_lchown(uv_loop_t* loop,
18561cb0ef41Sopenharmony_ci                 uv_fs_t* req,
18571cb0ef41Sopenharmony_ci                 const char* path,
18581cb0ef41Sopenharmony_ci                 uv_uid_t uid,
18591cb0ef41Sopenharmony_ci                 uv_gid_t gid,
18601cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
18611cb0ef41Sopenharmony_ci  INIT(LCHOWN);
18621cb0ef41Sopenharmony_ci  PATH;
18631cb0ef41Sopenharmony_ci  req->uid = uid;
18641cb0ef41Sopenharmony_ci  req->gid = gid;
18651cb0ef41Sopenharmony_ci  POST;
18661cb0ef41Sopenharmony_ci}
18671cb0ef41Sopenharmony_ci
18681cb0ef41Sopenharmony_ci
18691cb0ef41Sopenharmony_ciint uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
18701cb0ef41Sopenharmony_ci  INIT(FDATASYNC);
18711cb0ef41Sopenharmony_ci  req->file = file;
18721cb0ef41Sopenharmony_ci  POST;
18731cb0ef41Sopenharmony_ci}
18741cb0ef41Sopenharmony_ci
18751cb0ef41Sopenharmony_ci
18761cb0ef41Sopenharmony_ciint uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
18771cb0ef41Sopenharmony_ci  INIT(FSTAT);
18781cb0ef41Sopenharmony_ci  req->file = file;
18791cb0ef41Sopenharmony_ci  POST;
18801cb0ef41Sopenharmony_ci}
18811cb0ef41Sopenharmony_ci
18821cb0ef41Sopenharmony_ci
18831cb0ef41Sopenharmony_ciint uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
18841cb0ef41Sopenharmony_ci  INIT(FSYNC);
18851cb0ef41Sopenharmony_ci  req->file = file;
18861cb0ef41Sopenharmony_ci  POST;
18871cb0ef41Sopenharmony_ci}
18881cb0ef41Sopenharmony_ci
18891cb0ef41Sopenharmony_ci
18901cb0ef41Sopenharmony_ciint uv_fs_ftruncate(uv_loop_t* loop,
18911cb0ef41Sopenharmony_ci                    uv_fs_t* req,
18921cb0ef41Sopenharmony_ci                    uv_file file,
18931cb0ef41Sopenharmony_ci                    int64_t off,
18941cb0ef41Sopenharmony_ci                    uv_fs_cb cb) {
18951cb0ef41Sopenharmony_ci  INIT(FTRUNCATE);
18961cb0ef41Sopenharmony_ci  req->file = file;
18971cb0ef41Sopenharmony_ci  req->off = off;
18981cb0ef41Sopenharmony_ci  POST;
18991cb0ef41Sopenharmony_ci}
19001cb0ef41Sopenharmony_ci
19011cb0ef41Sopenharmony_ci
19021cb0ef41Sopenharmony_ciint uv_fs_futime(uv_loop_t* loop,
19031cb0ef41Sopenharmony_ci                 uv_fs_t* req,
19041cb0ef41Sopenharmony_ci                 uv_file file,
19051cb0ef41Sopenharmony_ci                 double atime,
19061cb0ef41Sopenharmony_ci                 double mtime,
19071cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
19081cb0ef41Sopenharmony_ci  INIT(FUTIME);
19091cb0ef41Sopenharmony_ci  req->file = file;
19101cb0ef41Sopenharmony_ci  req->atime = atime;
19111cb0ef41Sopenharmony_ci  req->mtime = mtime;
19121cb0ef41Sopenharmony_ci  POST;
19131cb0ef41Sopenharmony_ci}
19141cb0ef41Sopenharmony_ci
19151cb0ef41Sopenharmony_ciint uv_fs_lutime(uv_loop_t* loop,
19161cb0ef41Sopenharmony_ci                 uv_fs_t* req,
19171cb0ef41Sopenharmony_ci                 const char* path,
19181cb0ef41Sopenharmony_ci                 double atime,
19191cb0ef41Sopenharmony_ci                 double mtime,
19201cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
19211cb0ef41Sopenharmony_ci  INIT(LUTIME);
19221cb0ef41Sopenharmony_ci  PATH;
19231cb0ef41Sopenharmony_ci  req->atime = atime;
19241cb0ef41Sopenharmony_ci  req->mtime = mtime;
19251cb0ef41Sopenharmony_ci  POST;
19261cb0ef41Sopenharmony_ci}
19271cb0ef41Sopenharmony_ci
19281cb0ef41Sopenharmony_ci
19291cb0ef41Sopenharmony_ciint uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
19301cb0ef41Sopenharmony_ci  INIT(LSTAT);
19311cb0ef41Sopenharmony_ci  PATH;
19321cb0ef41Sopenharmony_ci  POST;
19331cb0ef41Sopenharmony_ci}
19341cb0ef41Sopenharmony_ci
19351cb0ef41Sopenharmony_ci
19361cb0ef41Sopenharmony_ciint uv_fs_link(uv_loop_t* loop,
19371cb0ef41Sopenharmony_ci               uv_fs_t* req,
19381cb0ef41Sopenharmony_ci               const char* path,
19391cb0ef41Sopenharmony_ci               const char* new_path,
19401cb0ef41Sopenharmony_ci               uv_fs_cb cb) {
19411cb0ef41Sopenharmony_ci  INIT(LINK);
19421cb0ef41Sopenharmony_ci  PATH2;
19431cb0ef41Sopenharmony_ci  POST;
19441cb0ef41Sopenharmony_ci}
19451cb0ef41Sopenharmony_ci
19461cb0ef41Sopenharmony_ci
19471cb0ef41Sopenharmony_ciint uv_fs_mkdir(uv_loop_t* loop,
19481cb0ef41Sopenharmony_ci                uv_fs_t* req,
19491cb0ef41Sopenharmony_ci                const char* path,
19501cb0ef41Sopenharmony_ci                int mode,
19511cb0ef41Sopenharmony_ci                uv_fs_cb cb) {
19521cb0ef41Sopenharmony_ci  INIT(MKDIR);
19531cb0ef41Sopenharmony_ci  PATH;
19541cb0ef41Sopenharmony_ci  req->mode = mode;
19551cb0ef41Sopenharmony_ci  POST;
19561cb0ef41Sopenharmony_ci}
19571cb0ef41Sopenharmony_ci
19581cb0ef41Sopenharmony_ci
19591cb0ef41Sopenharmony_ciint uv_fs_mkdtemp(uv_loop_t* loop,
19601cb0ef41Sopenharmony_ci                  uv_fs_t* req,
19611cb0ef41Sopenharmony_ci                  const char* tpl,
19621cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
19631cb0ef41Sopenharmony_ci  INIT(MKDTEMP);
19641cb0ef41Sopenharmony_ci  req->path = uv__strdup(tpl);
19651cb0ef41Sopenharmony_ci  if (req->path == NULL)
19661cb0ef41Sopenharmony_ci    return UV_ENOMEM;
19671cb0ef41Sopenharmony_ci  POST;
19681cb0ef41Sopenharmony_ci}
19691cb0ef41Sopenharmony_ci
19701cb0ef41Sopenharmony_ci
19711cb0ef41Sopenharmony_ciint uv_fs_mkstemp(uv_loop_t* loop,
19721cb0ef41Sopenharmony_ci                  uv_fs_t* req,
19731cb0ef41Sopenharmony_ci                  const char* tpl,
19741cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
19751cb0ef41Sopenharmony_ci  INIT(MKSTEMP);
19761cb0ef41Sopenharmony_ci  req->path = uv__strdup(tpl);
19771cb0ef41Sopenharmony_ci  if (req->path == NULL)
19781cb0ef41Sopenharmony_ci    return UV_ENOMEM;
19791cb0ef41Sopenharmony_ci  POST;
19801cb0ef41Sopenharmony_ci}
19811cb0ef41Sopenharmony_ci
19821cb0ef41Sopenharmony_ci
19831cb0ef41Sopenharmony_ciint uv_fs_open(uv_loop_t* loop,
19841cb0ef41Sopenharmony_ci               uv_fs_t* req,
19851cb0ef41Sopenharmony_ci               const char* path,
19861cb0ef41Sopenharmony_ci               int flags,
19871cb0ef41Sopenharmony_ci               int mode,
19881cb0ef41Sopenharmony_ci               uv_fs_cb cb) {
19891cb0ef41Sopenharmony_ci  INIT(OPEN);
19901cb0ef41Sopenharmony_ci  PATH;
19911cb0ef41Sopenharmony_ci  req->flags = flags;
19921cb0ef41Sopenharmony_ci  req->mode = mode;
19931cb0ef41Sopenharmony_ci  POST;
19941cb0ef41Sopenharmony_ci}
19951cb0ef41Sopenharmony_ci
19961cb0ef41Sopenharmony_ci
19971cb0ef41Sopenharmony_ciint uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
19981cb0ef41Sopenharmony_ci               uv_file file,
19991cb0ef41Sopenharmony_ci               const uv_buf_t bufs[],
20001cb0ef41Sopenharmony_ci               unsigned int nbufs,
20011cb0ef41Sopenharmony_ci               int64_t off,
20021cb0ef41Sopenharmony_ci               uv_fs_cb cb) {
20031cb0ef41Sopenharmony_ci  INIT(READ);
20041cb0ef41Sopenharmony_ci
20051cb0ef41Sopenharmony_ci  if (bufs == NULL || nbufs == 0)
20061cb0ef41Sopenharmony_ci    return UV_EINVAL;
20071cb0ef41Sopenharmony_ci
20081cb0ef41Sopenharmony_ci  req->file = file;
20091cb0ef41Sopenharmony_ci
20101cb0ef41Sopenharmony_ci  req->nbufs = nbufs;
20111cb0ef41Sopenharmony_ci  req->bufs = req->bufsml;
20121cb0ef41Sopenharmony_ci  if (nbufs > ARRAY_SIZE(req->bufsml))
20131cb0ef41Sopenharmony_ci    req->bufs = uv__malloc(nbufs * sizeof(*bufs));
20141cb0ef41Sopenharmony_ci
20151cb0ef41Sopenharmony_ci  if (req->bufs == NULL)
20161cb0ef41Sopenharmony_ci    return UV_ENOMEM;
20171cb0ef41Sopenharmony_ci
20181cb0ef41Sopenharmony_ci  memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
20191cb0ef41Sopenharmony_ci
20201cb0ef41Sopenharmony_ci  req->off = off;
20211cb0ef41Sopenharmony_ci  POST;
20221cb0ef41Sopenharmony_ci}
20231cb0ef41Sopenharmony_ci
20241cb0ef41Sopenharmony_ci
20251cb0ef41Sopenharmony_ciint uv_fs_scandir(uv_loop_t* loop,
20261cb0ef41Sopenharmony_ci                  uv_fs_t* req,
20271cb0ef41Sopenharmony_ci                  const char* path,
20281cb0ef41Sopenharmony_ci                  int flags,
20291cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
20301cb0ef41Sopenharmony_ci  INIT(SCANDIR);
20311cb0ef41Sopenharmony_ci  PATH;
20321cb0ef41Sopenharmony_ci  req->flags = flags;
20331cb0ef41Sopenharmony_ci  POST;
20341cb0ef41Sopenharmony_ci}
20351cb0ef41Sopenharmony_ci
20361cb0ef41Sopenharmony_ciint uv_fs_opendir(uv_loop_t* loop,
20371cb0ef41Sopenharmony_ci                  uv_fs_t* req,
20381cb0ef41Sopenharmony_ci                  const char* path,
20391cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
20401cb0ef41Sopenharmony_ci  INIT(OPENDIR);
20411cb0ef41Sopenharmony_ci  PATH;
20421cb0ef41Sopenharmony_ci  POST;
20431cb0ef41Sopenharmony_ci}
20441cb0ef41Sopenharmony_ci
20451cb0ef41Sopenharmony_ciint uv_fs_readdir(uv_loop_t* loop,
20461cb0ef41Sopenharmony_ci                  uv_fs_t* req,
20471cb0ef41Sopenharmony_ci                  uv_dir_t* dir,
20481cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
20491cb0ef41Sopenharmony_ci  INIT(READDIR);
20501cb0ef41Sopenharmony_ci
20511cb0ef41Sopenharmony_ci  if (dir == NULL || dir->dir == NULL || dir->dirents == NULL)
20521cb0ef41Sopenharmony_ci    return UV_EINVAL;
20531cb0ef41Sopenharmony_ci
20541cb0ef41Sopenharmony_ci  req->ptr = dir;
20551cb0ef41Sopenharmony_ci  POST;
20561cb0ef41Sopenharmony_ci}
20571cb0ef41Sopenharmony_ci
20581cb0ef41Sopenharmony_ciint uv_fs_closedir(uv_loop_t* loop,
20591cb0ef41Sopenharmony_ci                   uv_fs_t* req,
20601cb0ef41Sopenharmony_ci                   uv_dir_t* dir,
20611cb0ef41Sopenharmony_ci                   uv_fs_cb cb) {
20621cb0ef41Sopenharmony_ci  INIT(CLOSEDIR);
20631cb0ef41Sopenharmony_ci
20641cb0ef41Sopenharmony_ci  if (dir == NULL)
20651cb0ef41Sopenharmony_ci    return UV_EINVAL;
20661cb0ef41Sopenharmony_ci
20671cb0ef41Sopenharmony_ci  req->ptr = dir;
20681cb0ef41Sopenharmony_ci  POST;
20691cb0ef41Sopenharmony_ci}
20701cb0ef41Sopenharmony_ci
20711cb0ef41Sopenharmony_ciint uv_fs_readlink(uv_loop_t* loop,
20721cb0ef41Sopenharmony_ci                   uv_fs_t* req,
20731cb0ef41Sopenharmony_ci                   const char* path,
20741cb0ef41Sopenharmony_ci                   uv_fs_cb cb) {
20751cb0ef41Sopenharmony_ci  INIT(READLINK);
20761cb0ef41Sopenharmony_ci  PATH;
20771cb0ef41Sopenharmony_ci  POST;
20781cb0ef41Sopenharmony_ci}
20791cb0ef41Sopenharmony_ci
20801cb0ef41Sopenharmony_ci
20811cb0ef41Sopenharmony_ciint uv_fs_realpath(uv_loop_t* loop,
20821cb0ef41Sopenharmony_ci                  uv_fs_t* req,
20831cb0ef41Sopenharmony_ci                  const char * path,
20841cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
20851cb0ef41Sopenharmony_ci  INIT(REALPATH);
20861cb0ef41Sopenharmony_ci  PATH;
20871cb0ef41Sopenharmony_ci  POST;
20881cb0ef41Sopenharmony_ci}
20891cb0ef41Sopenharmony_ci
20901cb0ef41Sopenharmony_ci
20911cb0ef41Sopenharmony_ciint uv_fs_rename(uv_loop_t* loop,
20921cb0ef41Sopenharmony_ci                 uv_fs_t* req,
20931cb0ef41Sopenharmony_ci                 const char* path,
20941cb0ef41Sopenharmony_ci                 const char* new_path,
20951cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
20961cb0ef41Sopenharmony_ci  INIT(RENAME);
20971cb0ef41Sopenharmony_ci  PATH2;
20981cb0ef41Sopenharmony_ci  POST;
20991cb0ef41Sopenharmony_ci}
21001cb0ef41Sopenharmony_ci
21011cb0ef41Sopenharmony_ci
21021cb0ef41Sopenharmony_ciint uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
21031cb0ef41Sopenharmony_ci  INIT(RMDIR);
21041cb0ef41Sopenharmony_ci  PATH;
21051cb0ef41Sopenharmony_ci  POST;
21061cb0ef41Sopenharmony_ci}
21071cb0ef41Sopenharmony_ci
21081cb0ef41Sopenharmony_ci
21091cb0ef41Sopenharmony_ciint uv_fs_sendfile(uv_loop_t* loop,
21101cb0ef41Sopenharmony_ci                   uv_fs_t* req,
21111cb0ef41Sopenharmony_ci                   uv_file out_fd,
21121cb0ef41Sopenharmony_ci                   uv_file in_fd,
21131cb0ef41Sopenharmony_ci                   int64_t off,
21141cb0ef41Sopenharmony_ci                   size_t len,
21151cb0ef41Sopenharmony_ci                   uv_fs_cb cb) {
21161cb0ef41Sopenharmony_ci  INIT(SENDFILE);
21171cb0ef41Sopenharmony_ci  req->flags = in_fd; /* hack */
21181cb0ef41Sopenharmony_ci  req->file = out_fd;
21191cb0ef41Sopenharmony_ci  req->off = off;
21201cb0ef41Sopenharmony_ci  req->bufsml[0].len = len;
21211cb0ef41Sopenharmony_ci  POST;
21221cb0ef41Sopenharmony_ci}
21231cb0ef41Sopenharmony_ci
21241cb0ef41Sopenharmony_ci
21251cb0ef41Sopenharmony_ciint uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
21261cb0ef41Sopenharmony_ci  INIT(STAT);
21271cb0ef41Sopenharmony_ci  PATH;
21281cb0ef41Sopenharmony_ci  POST;
21291cb0ef41Sopenharmony_ci}
21301cb0ef41Sopenharmony_ci
21311cb0ef41Sopenharmony_ci
21321cb0ef41Sopenharmony_ciint uv_fs_symlink(uv_loop_t* loop,
21331cb0ef41Sopenharmony_ci                  uv_fs_t* req,
21341cb0ef41Sopenharmony_ci                  const char* path,
21351cb0ef41Sopenharmony_ci                  const char* new_path,
21361cb0ef41Sopenharmony_ci                  int flags,
21371cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
21381cb0ef41Sopenharmony_ci  INIT(SYMLINK);
21391cb0ef41Sopenharmony_ci  PATH2;
21401cb0ef41Sopenharmony_ci  req->flags = flags;
21411cb0ef41Sopenharmony_ci  POST;
21421cb0ef41Sopenharmony_ci}
21431cb0ef41Sopenharmony_ci
21441cb0ef41Sopenharmony_ci
21451cb0ef41Sopenharmony_ciint uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
21461cb0ef41Sopenharmony_ci  INIT(UNLINK);
21471cb0ef41Sopenharmony_ci  PATH;
21481cb0ef41Sopenharmony_ci  POST;
21491cb0ef41Sopenharmony_ci}
21501cb0ef41Sopenharmony_ci
21511cb0ef41Sopenharmony_ci
21521cb0ef41Sopenharmony_ciint uv_fs_utime(uv_loop_t* loop,
21531cb0ef41Sopenharmony_ci                uv_fs_t* req,
21541cb0ef41Sopenharmony_ci                const char* path,
21551cb0ef41Sopenharmony_ci                double atime,
21561cb0ef41Sopenharmony_ci                double mtime,
21571cb0ef41Sopenharmony_ci                uv_fs_cb cb) {
21581cb0ef41Sopenharmony_ci  INIT(UTIME);
21591cb0ef41Sopenharmony_ci  PATH;
21601cb0ef41Sopenharmony_ci  req->atime = atime;
21611cb0ef41Sopenharmony_ci  req->mtime = mtime;
21621cb0ef41Sopenharmony_ci  POST;
21631cb0ef41Sopenharmony_ci}
21641cb0ef41Sopenharmony_ci
21651cb0ef41Sopenharmony_ci
21661cb0ef41Sopenharmony_ciint uv_fs_write(uv_loop_t* loop,
21671cb0ef41Sopenharmony_ci                uv_fs_t* req,
21681cb0ef41Sopenharmony_ci                uv_file file,
21691cb0ef41Sopenharmony_ci                const uv_buf_t bufs[],
21701cb0ef41Sopenharmony_ci                unsigned int nbufs,
21711cb0ef41Sopenharmony_ci                int64_t off,
21721cb0ef41Sopenharmony_ci                uv_fs_cb cb) {
21731cb0ef41Sopenharmony_ci  INIT(WRITE);
21741cb0ef41Sopenharmony_ci
21751cb0ef41Sopenharmony_ci  if (bufs == NULL || nbufs == 0)
21761cb0ef41Sopenharmony_ci    return UV_EINVAL;
21771cb0ef41Sopenharmony_ci
21781cb0ef41Sopenharmony_ci  req->file = file;
21791cb0ef41Sopenharmony_ci
21801cb0ef41Sopenharmony_ci  req->nbufs = nbufs;
21811cb0ef41Sopenharmony_ci  req->bufs = req->bufsml;
21821cb0ef41Sopenharmony_ci  if (nbufs > ARRAY_SIZE(req->bufsml))
21831cb0ef41Sopenharmony_ci    req->bufs = uv__malloc(nbufs * sizeof(*bufs));
21841cb0ef41Sopenharmony_ci
21851cb0ef41Sopenharmony_ci  if (req->bufs == NULL)
21861cb0ef41Sopenharmony_ci    return UV_ENOMEM;
21871cb0ef41Sopenharmony_ci
21881cb0ef41Sopenharmony_ci  memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
21891cb0ef41Sopenharmony_ci
21901cb0ef41Sopenharmony_ci  req->off = off;
21911cb0ef41Sopenharmony_ci  POST;
21921cb0ef41Sopenharmony_ci}
21931cb0ef41Sopenharmony_ci
21941cb0ef41Sopenharmony_ci
21951cb0ef41Sopenharmony_civoid uv_fs_req_cleanup(uv_fs_t* req) {
21961cb0ef41Sopenharmony_ci  if (req == NULL)
21971cb0ef41Sopenharmony_ci    return;
21981cb0ef41Sopenharmony_ci
21991cb0ef41Sopenharmony_ci  /* Only necessary for asychronous requests, i.e., requests with a callback.
22001cb0ef41Sopenharmony_ci   * Synchronous ones don't copy their arguments and have req->path and
22011cb0ef41Sopenharmony_ci   * req->new_path pointing to user-owned memory.  UV_FS_MKDTEMP and
22021cb0ef41Sopenharmony_ci   * UV_FS_MKSTEMP are the exception to the rule, they always allocate memory.
22031cb0ef41Sopenharmony_ci   */
22041cb0ef41Sopenharmony_ci  if (req->path != NULL &&
22051cb0ef41Sopenharmony_ci      (req->cb != NULL ||
22061cb0ef41Sopenharmony_ci        req->fs_type == UV_FS_MKDTEMP || req->fs_type == UV_FS_MKSTEMP))
22071cb0ef41Sopenharmony_ci    uv__free((void*) req->path);  /* Memory is shared with req->new_path. */
22081cb0ef41Sopenharmony_ci
22091cb0ef41Sopenharmony_ci  req->path = NULL;
22101cb0ef41Sopenharmony_ci  req->new_path = NULL;
22111cb0ef41Sopenharmony_ci
22121cb0ef41Sopenharmony_ci  if (req->fs_type == UV_FS_READDIR && req->ptr != NULL)
22131cb0ef41Sopenharmony_ci    uv__fs_readdir_cleanup(req);
22141cb0ef41Sopenharmony_ci
22151cb0ef41Sopenharmony_ci  if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
22161cb0ef41Sopenharmony_ci    uv__fs_scandir_cleanup(req);
22171cb0ef41Sopenharmony_ci
22181cb0ef41Sopenharmony_ci  if (req->bufs != req->bufsml)
22191cb0ef41Sopenharmony_ci    uv__free(req->bufs);
22201cb0ef41Sopenharmony_ci  req->bufs = NULL;
22211cb0ef41Sopenharmony_ci
22221cb0ef41Sopenharmony_ci  if (req->fs_type != UV_FS_OPENDIR && req->ptr != &req->statbuf)
22231cb0ef41Sopenharmony_ci    uv__free(req->ptr);
22241cb0ef41Sopenharmony_ci  req->ptr = NULL;
22251cb0ef41Sopenharmony_ci}
22261cb0ef41Sopenharmony_ci
22271cb0ef41Sopenharmony_ci
22281cb0ef41Sopenharmony_ciint uv_fs_copyfile(uv_loop_t* loop,
22291cb0ef41Sopenharmony_ci                   uv_fs_t* req,
22301cb0ef41Sopenharmony_ci                   const char* path,
22311cb0ef41Sopenharmony_ci                   const char* new_path,
22321cb0ef41Sopenharmony_ci                   int flags,
22331cb0ef41Sopenharmony_ci                   uv_fs_cb cb) {
22341cb0ef41Sopenharmony_ci  INIT(COPYFILE);
22351cb0ef41Sopenharmony_ci
22361cb0ef41Sopenharmony_ci  if (flags & ~(UV_FS_COPYFILE_EXCL |
22371cb0ef41Sopenharmony_ci                UV_FS_COPYFILE_FICLONE |
22381cb0ef41Sopenharmony_ci                UV_FS_COPYFILE_FICLONE_FORCE)) {
22391cb0ef41Sopenharmony_ci    return UV_EINVAL;
22401cb0ef41Sopenharmony_ci  }
22411cb0ef41Sopenharmony_ci
22421cb0ef41Sopenharmony_ci  PATH2;
22431cb0ef41Sopenharmony_ci  req->flags = flags;
22441cb0ef41Sopenharmony_ci  POST;
22451cb0ef41Sopenharmony_ci}
22461cb0ef41Sopenharmony_ci
22471cb0ef41Sopenharmony_ci
22481cb0ef41Sopenharmony_ciint uv_fs_statfs(uv_loop_t* loop,
22491cb0ef41Sopenharmony_ci                 uv_fs_t* req,
22501cb0ef41Sopenharmony_ci                 const char* path,
22511cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
22521cb0ef41Sopenharmony_ci  INIT(STATFS);
22531cb0ef41Sopenharmony_ci  PATH;
22541cb0ef41Sopenharmony_ci  POST;
22551cb0ef41Sopenharmony_ci}
22561cb0ef41Sopenharmony_ci
22571cb0ef41Sopenharmony_ciint uv_fs_get_system_error(const uv_fs_t* req) {
22581cb0ef41Sopenharmony_ci  return -req->result;
22591cb0ef41Sopenharmony_ci}
2260