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