mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-09 15:20:56 -06:00
Merge branch 'upstream-libuv' into update-libuv
* upstream-libuv: libuv 2020-04-29 (e7ebae26)
This commit is contained in:
@@ -269,6 +269,8 @@ typedef void* (*uv_realloc_func)(void* ptr, size_t size);
|
||||
typedef void* (*uv_calloc_func)(size_t count, size_t size);
|
||||
typedef void (*uv_free_func)(void* ptr);
|
||||
|
||||
UV_EXTERN void uv_library_shutdown(void);
|
||||
|
||||
UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func,
|
||||
uv_realloc_func realloc_func,
|
||||
uv_calloc_func calloc_func,
|
||||
@@ -614,7 +616,12 @@ enum uv_udp_flags {
|
||||
* Indicates that the message was received by recvmmsg, so the buffer provided
|
||||
* must not be freed by the recv_cb callback.
|
||||
*/
|
||||
UV_UDP_MMSG_CHUNK = 8
|
||||
UV_UDP_MMSG_CHUNK = 8,
|
||||
|
||||
/*
|
||||
* Indicates that recvmmsg should be used, if available.
|
||||
*/
|
||||
UV_UDP_RECVMMSG = 256
|
||||
};
|
||||
|
||||
typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
|
||||
@@ -1081,11 +1088,11 @@ UV_EXTERN int uv_cancel(uv_req_t* req);
|
||||
|
||||
|
||||
struct uv_cpu_times_s {
|
||||
uint64_t user;
|
||||
uint64_t nice;
|
||||
uint64_t sys;
|
||||
uint64_t idle;
|
||||
uint64_t irq;
|
||||
uint64_t user; /* milliseconds */
|
||||
uint64_t nice; /* milliseconds */
|
||||
uint64_t sys; /* milliseconds */
|
||||
uint64_t idle; /* milliseconds */
|
||||
uint64_t irq; /* milliseconds */
|
||||
};
|
||||
|
||||
struct uv_cpu_info_s {
|
||||
@@ -1292,7 +1299,8 @@ typedef enum {
|
||||
UV_FS_READDIR,
|
||||
UV_FS_CLOSEDIR,
|
||||
UV_FS_STATFS,
|
||||
UV_FS_MKSTEMP
|
||||
UV_FS_MKSTEMP,
|
||||
UV_FS_LUTIME
|
||||
} uv_fs_type;
|
||||
|
||||
struct uv_dir_s {
|
||||
@@ -1317,6 +1325,7 @@ struct uv_fs_s {
|
||||
|
||||
UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*);
|
||||
UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*);
|
||||
UV_EXTERN int uv_fs_get_system_error(const uv_fs_t*);
|
||||
UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*);
|
||||
UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*);
|
||||
UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*);
|
||||
@@ -1465,6 +1474,12 @@ UV_EXTERN int uv_fs_futime(uv_loop_t* loop,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_lutime(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_lstat(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
* Versions with the same major number are ABI stable. API is allowed to
|
||||
* evolve between minor releases, but only in a backwards compatible way.
|
||||
* Make sure you update the -soname directives in configure.ac
|
||||
* and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
|
||||
* whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
|
||||
* not UV_VERSION_PATCH.)
|
||||
*/
|
||||
|
||||
#define UV_VERSION_MAJOR 1
|
||||
#define UV_VERSION_MINOR 35
|
||||
#define UV_VERSION_MINOR 37
|
||||
#define UV_VERSION_PATCH 1
|
||||
#define UV_VERSION_IS_RELEASE 0
|
||||
#define UV_VERSION_SUFFIX "dev"
|
||||
|
||||
@@ -160,8 +160,8 @@ static void post(QUEUE* q, enum uv__work_kind kind) {
|
||||
}
|
||||
|
||||
|
||||
void uv__threadpool_cleanup(void) {
|
||||
#ifndef _WIN32
|
||||
UV_DESTRUCTOR(static void cleanup(void)) {
|
||||
unsigned int i;
|
||||
|
||||
if (nthreads == 0)
|
||||
@@ -181,8 +181,8 @@ UV_DESTRUCTOR(static void cleanup(void)) {
|
||||
|
||||
threads = NULL;
|
||||
nthreads = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void init_threads(void) {
|
||||
|
||||
@@ -51,12 +51,7 @@ static int timer_less_than(const struct heap_node* ha,
|
||||
/* Compare start_id when both have the same timeout. start_id is
|
||||
* allocated with loop->timer_counter in uv_timer_start().
|
||||
*/
|
||||
if (a->start_id < b->start_id)
|
||||
return 1;
|
||||
if (b->start_id < a->start_id)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
return a->start_id < b->start_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -926,7 +926,7 @@ int uv_get_process_title(char* buffer, size_t size) {
|
||||
}
|
||||
|
||||
|
||||
UV_DESTRUCTOR(static void free_args_mem(void)) {
|
||||
void uv__process_title_cleanup(void) {
|
||||
uv__free(args_mem); /* Keep valgrind happy. */
|
||||
args_mem = NULL;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h> /* sched_yield() */
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/eventfd.h>
|
||||
@@ -81,20 +82,32 @@ int uv_async_send(uv_async_t* handle) {
|
||||
|
||||
/* Only call this from the event loop thread. */
|
||||
static int uv__async_spin(uv_async_t* handle) {
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
for (;;) {
|
||||
/* rc=0 -- handle is not pending.
|
||||
* rc=1 -- handle is pending, other thread is still working with it.
|
||||
* rc=2 -- handle is pending, other thread is done.
|
||||
/* 997 is not completely chosen at random. It's a prime number, acyclical
|
||||
* by nature, and should therefore hopefully dampen sympathetic resonance.
|
||||
*/
|
||||
rc = cmpxchgi(&handle->pending, 2, 0);
|
||||
for (i = 0; i < 997; i++) {
|
||||
/* rc=0 -- handle is not pending.
|
||||
* rc=1 -- handle is pending, other thread is still working with it.
|
||||
* rc=2 -- handle is pending, other thread is done.
|
||||
*/
|
||||
rc = cmpxchgi(&handle->pending, 2, 0);
|
||||
|
||||
if (rc != 1)
|
||||
return rc;
|
||||
if (rc != 1)
|
||||
return rc;
|
||||
|
||||
/* Other thread is busy with this handle, spin until it's done. */
|
||||
cpu_relax();
|
||||
/* Other thread is busy with this handle, spin until it's done. */
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
/* Yield the CPU. We may have preempted the other thread while it's
|
||||
* inside the critical section and if it's running on the same CPU
|
||||
* as us, we'll just burn CPU cycles until the end of our time slice.
|
||||
*/
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
|
||||
UV_UNUSED(static void cpu_relax(void)) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
__asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */
|
||||
#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
|
||||
__asm__ volatile("yield");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,13 @@ static void init_process_title_mutex_once(void) {
|
||||
}
|
||||
|
||||
|
||||
void uv__process_title_cleanup(void) {
|
||||
/* TODO(bnoordhuis) uv_mutex_destroy(&process_title_mutex)
|
||||
* and reset process_title_mutex_once?
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
process_title = argc > 0 ? uv__strdup(argv[0]) : NULL;
|
||||
return argv;
|
||||
|
||||
@@ -74,7 +74,7 @@ extern char** environ;
|
||||
# include <sys/wait.h>
|
||||
# include <sys/param.h>
|
||||
# include <sys/cpuset.h>
|
||||
# if defined(__FreeBSD__) || defined(__linux__)
|
||||
# if defined(__FreeBSD__)
|
||||
# define uv__accept4 accept4
|
||||
# endif
|
||||
# if defined(__NetBSD__)
|
||||
@@ -91,7 +91,8 @@ extern char** environ;
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/syscall.h>
|
||||
# include <sys/syscall.h>
|
||||
# define uv__accept4 accept4
|
||||
#endif
|
||||
|
||||
static int uv__run_pending(uv_loop_t* loop);
|
||||
@@ -1260,7 +1261,7 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) {
|
||||
|
||||
*envitems = uv__calloc(i, sizeof(**envitems));
|
||||
|
||||
if (envitems == NULL)
|
||||
if (*envitems == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
for (j = 0, cnt = 0; j < i; j++) {
|
||||
|
||||
@@ -30,8 +30,7 @@
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
# include <CoreFoundation/CoreFoundation.h>
|
||||
# include <ApplicationServices/ApplicationServices.h>
|
||||
#include "darwin-stub.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
97
Utilities/cmlibuv/src/unix/darwin-stub.h
Normal file
97
Utilities/cmlibuv/src/unix/darwin-stub.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_DARWIN_STUB_H_
|
||||
#define UV_DARWIN_STUB_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct CFArrayCallBacks;
|
||||
struct CFRunLoopSourceContext;
|
||||
struct FSEventStreamContext;
|
||||
|
||||
typedef double CFAbsoluteTime;
|
||||
typedef double CFTimeInterval;
|
||||
typedef int FSEventStreamEventFlags;
|
||||
typedef int OSStatus;
|
||||
typedef long CFIndex;
|
||||
typedef struct CFArrayCallBacks CFArrayCallBacks;
|
||||
typedef struct CFRunLoopSourceContext CFRunLoopSourceContext;
|
||||
typedef struct FSEventStreamContext FSEventStreamContext;
|
||||
typedef uint32_t FSEventStreamCreateFlags;
|
||||
typedef uint64_t FSEventStreamEventId;
|
||||
typedef unsigned CFStringEncoding;
|
||||
typedef void* CFAllocatorRef;
|
||||
typedef void* CFArrayRef;
|
||||
typedef void* CFBundleRef;
|
||||
typedef void* CFDictionaryRef;
|
||||
typedef void* CFRunLoopRef;
|
||||
typedef void* CFRunLoopSourceRef;
|
||||
typedef void* CFStringRef;
|
||||
typedef void* CFTypeRef;
|
||||
typedef void* FSEventStreamRef;
|
||||
|
||||
typedef void (*FSEventStreamCallback)(const FSEventStreamRef,
|
||||
void*,
|
||||
size_t,
|
||||
void*,
|
||||
const FSEventStreamEventFlags*,
|
||||
const FSEventStreamEventId*);
|
||||
|
||||
struct CFRunLoopSourceContext {
|
||||
CFIndex version;
|
||||
void* info;
|
||||
void* pad[7];
|
||||
void (*perform)(void*);
|
||||
};
|
||||
|
||||
struct FSEventStreamContext {
|
||||
CFIndex version;
|
||||
void* info;
|
||||
void* pad[3];
|
||||
};
|
||||
|
||||
static const CFStringEncoding kCFStringEncodingUTF8 = 0x8000100;
|
||||
static const OSStatus noErr = 0;
|
||||
|
||||
static const FSEventStreamEventId kFSEventStreamEventIdSinceNow = -1;
|
||||
|
||||
static const int kFSEventStreamCreateFlagNoDefer = 2;
|
||||
static const int kFSEventStreamCreateFlagFileEvents = 16;
|
||||
|
||||
static const int kFSEventStreamEventFlagEventIdsWrapped = 8;
|
||||
static const int kFSEventStreamEventFlagHistoryDone = 16;
|
||||
static const int kFSEventStreamEventFlagItemChangeOwner = 0x4000;
|
||||
static const int kFSEventStreamEventFlagItemCreated = 0x100;
|
||||
static const int kFSEventStreamEventFlagItemFinderInfoMod = 0x2000;
|
||||
static const int kFSEventStreamEventFlagItemInodeMetaMod = 0x400;
|
||||
static const int kFSEventStreamEventFlagItemIsDir = 0x20000;
|
||||
static const int kFSEventStreamEventFlagItemModified = 0x1000;
|
||||
static const int kFSEventStreamEventFlagItemRemoved = 0x200;
|
||||
static const int kFSEventStreamEventFlagItemRenamed = 0x800;
|
||||
static const int kFSEventStreamEventFlagItemXattrMod = 0x8000;
|
||||
static const int kFSEventStreamEventFlagKernelDropped = 4;
|
||||
static const int kFSEventStreamEventFlagMount = 64;
|
||||
static const int kFSEventStreamEventFlagRootChanged = 32;
|
||||
static const int kFSEventStreamEventFlagUnmount = 128;
|
||||
static const int kFSEventStreamEventFlagUserDropped = 2;
|
||||
|
||||
#endif /* UV_DARWIN_STUB_H_ */
|
||||
@@ -205,6 +205,20 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
|
||||
UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = time;
|
||||
ts.tv_nsec = (uint64_t)(time * 1000000) % 1000000 * 1000;
|
||||
return ts;
|
||||
}
|
||||
|
||||
UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = time;
|
||||
tv.tv_usec = (uint64_t)(time * 1000000) % 1000000;
|
||||
return tv;
|
||||
}
|
||||
|
||||
static ssize_t uv__fs_futime(uv_fs_t* req) {
|
||||
#if defined(__linux__) \
|
||||
|| defined(_AIX71) \
|
||||
@@ -213,10 +227,8 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
|
||||
* for the sake of consistency with other platforms.
|
||||
*/
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = req->atime;
|
||||
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
||||
ts[1].tv_sec = req->mtime;
|
||||
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
|
||||
return utimensat(req->file, NULL, ts, 0);
|
||||
#else
|
||||
@@ -230,10 +242,8 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__sun)
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = req->atime;
|
||||
tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
|
||||
tv[1].tv_sec = req->mtime;
|
||||
tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||
# if defined(__sun)
|
||||
return futimesat(req->file, NULL, tv);
|
||||
# else
|
||||
@@ -982,10 +992,8 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
* for the sake of consistency with other platforms.
|
||||
*/
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = req->atime;
|
||||
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
||||
ts[1].tv_sec = req->mtime;
|
||||
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
return utimensat(AT_FDCWD, req->path, ts, 0);
|
||||
#elif defined(__APPLE__) \
|
||||
|| defined(__DragonFly__) \
|
||||
@@ -994,10 +1002,8 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__)
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = req->atime;
|
||||
tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
|
||||
tv[1].tv_sec = req->mtime;
|
||||
tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||
return utimes(req->path, tv);
|
||||
#elif defined(_AIX) \
|
||||
&& !defined(_AIX71)
|
||||
@@ -1020,6 +1026,31 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uv__fs_lutime(uv_fs_t* req) {
|
||||
#if defined(__linux__) || \
|
||||
defined(_AIX71) || \
|
||||
defined(__sun) || \
|
||||
defined(__HAIKU__)
|
||||
struct timespec ts[2];
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW);
|
||||
#elif defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__)
|
||||
struct timeval tv[2];
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||
return lutimes(req->path, tv);
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uv__fs_write(uv_fs_t* req) {
|
||||
#if defined(__linux__)
|
||||
static int no_pwritev;
|
||||
@@ -1089,9 +1120,10 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
int dst_flags;
|
||||
int result;
|
||||
int err;
|
||||
size_t bytes_to_send;
|
||||
int64_t in_offset;
|
||||
ssize_t bytes_written;
|
||||
off_t bytes_to_send;
|
||||
off_t in_offset;
|
||||
off_t bytes_written;
|
||||
size_t bytes_chunk;
|
||||
|
||||
dstfd = -1;
|
||||
err = 0;
|
||||
@@ -1190,7 +1222,10 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
bytes_to_send = src_statsbuf.st_size;
|
||||
in_offset = 0;
|
||||
while (bytes_to_send != 0) {
|
||||
uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_to_send, NULL);
|
||||
bytes_chunk = SSIZE_MAX;
|
||||
if (bytes_to_send < (off_t) bytes_chunk)
|
||||
bytes_chunk = bytes_to_send;
|
||||
uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_chunk, NULL);
|
||||
bytes_written = fs_req.result;
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
@@ -1533,6 +1568,7 @@ static void uv__fs_work(struct uv__work* w) {
|
||||
X(FSYNC, uv__fs_fsync(req));
|
||||
X(FTRUNCATE, ftruncate(req->file, req->off));
|
||||
X(FUTIME, uv__fs_futime(req));
|
||||
X(LUTIME, uv__fs_lutime(req));
|
||||
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
|
||||
X(LINK, link(req->path, req->new_path));
|
||||
X(MKDIR, mkdir(req->path, req->mode));
|
||||
@@ -1719,6 +1755,19 @@ int uv_fs_futime(uv_loop_t* loop,
|
||||
POST;
|
||||
}
|
||||
|
||||
int uv_fs_lutime(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb) {
|
||||
INIT(LUTIME);
|
||||
PATH;
|
||||
req->atime = atime;
|
||||
req->mtime = mtime;
|
||||
POST;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
INIT(LSTAT);
|
||||
@@ -2047,3 +2096,7 @@ int uv_fs_statfs(uv_loop_t* loop,
|
||||
PATH;
|
||||
POST;
|
||||
}
|
||||
|
||||
int uv_fs_get_system_error(const uv_fs_t* req) {
|
||||
return -req->result;
|
||||
}
|
||||
|
||||
@@ -41,34 +41,33 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) {
|
||||
|
||||
#else /* TARGET_OS_IPHONE */
|
||||
|
||||
#include "darwin-stub.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <CoreFoundation/CFRunLoop.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
static const int kFSEventsModified =
|
||||
kFSEventStreamEventFlagItemChangeOwner |
|
||||
kFSEventStreamEventFlagItemFinderInfoMod |
|
||||
kFSEventStreamEventFlagItemInodeMetaMod |
|
||||
kFSEventStreamEventFlagItemModified |
|
||||
kFSEventStreamEventFlagItemXattrMod;
|
||||
|
||||
/* These are macros to avoid "initializer element is not constant" errors
|
||||
* with old versions of gcc.
|
||||
*/
|
||||
#define kFSEventsModified (kFSEventStreamEventFlagItemFinderInfoMod | \
|
||||
kFSEventStreamEventFlagItemModified | \
|
||||
kFSEventStreamEventFlagItemInodeMetaMod | \
|
||||
kFSEventStreamEventFlagItemChangeOwner | \
|
||||
kFSEventStreamEventFlagItemXattrMod)
|
||||
static const int kFSEventsRenamed =
|
||||
kFSEventStreamEventFlagItemCreated |
|
||||
kFSEventStreamEventFlagItemRemoved |
|
||||
kFSEventStreamEventFlagItemRenamed;
|
||||
|
||||
#define kFSEventsRenamed (kFSEventStreamEventFlagItemCreated | \
|
||||
kFSEventStreamEventFlagItemRemoved | \
|
||||
kFSEventStreamEventFlagItemRenamed)
|
||||
|
||||
#define kFSEventsSystem (kFSEventStreamEventFlagUserDropped | \
|
||||
kFSEventStreamEventFlagKernelDropped | \
|
||||
kFSEventStreamEventFlagEventIdsWrapped | \
|
||||
kFSEventStreamEventFlagHistoryDone | \
|
||||
kFSEventStreamEventFlagMount | \
|
||||
kFSEventStreamEventFlagUnmount | \
|
||||
kFSEventStreamEventFlagRootChanged)
|
||||
static const int kFSEventsSystem =
|
||||
kFSEventStreamEventFlagUserDropped |
|
||||
kFSEventStreamEventFlagKernelDropped |
|
||||
kFSEventStreamEventFlagEventIdsWrapped |
|
||||
kFSEventStreamEventFlagHistoryDone |
|
||||
kFSEventStreamEventFlagMount |
|
||||
kFSEventStreamEventFlagUnmount |
|
||||
kFSEventStreamEventFlagRootChanged;
|
||||
|
||||
typedef struct uv__fsevents_event_s uv__fsevents_event_t;
|
||||
typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t;
|
||||
@@ -148,7 +147,7 @@ static void (*pFSEventStreamRelease)(FSEventStreamRef);
|
||||
static void (*pFSEventStreamScheduleWithRunLoop)(FSEventStreamRef,
|
||||
CFRunLoopRef,
|
||||
CFStringRef);
|
||||
static Boolean (*pFSEventStreamStart)(FSEventStreamRef);
|
||||
static int (*pFSEventStreamStart)(FSEventStreamRef);
|
||||
static void (*pFSEventStreamStop)(FSEventStreamRef);
|
||||
|
||||
#define UV__FSEVENTS_PROCESS(handle, block) \
|
||||
@@ -215,7 +214,7 @@ static void uv__fsevents_push_event(uv_fs_event_t* handle,
|
||||
|
||||
|
||||
/* Runs in CF thread, when there're events in FSEventStream */
|
||||
static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
|
||||
static void uv__fsevents_event_cb(const FSEventStreamRef streamRef,
|
||||
void* info,
|
||||
size_t numEvents,
|
||||
void* eventPaths,
|
||||
@@ -340,11 +339,8 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) {
|
||||
FSEventStreamCreateFlags flags;
|
||||
|
||||
/* Initialize context */
|
||||
ctx.version = 0;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.info = loop;
|
||||
ctx.retain = NULL;
|
||||
ctx.release = NULL;
|
||||
ctx.copyDescription = NULL;
|
||||
|
||||
latency = 0.05;
|
||||
|
||||
|
||||
@@ -116,10 +116,8 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
|
||||
#if defined(__clang__) || \
|
||||
defined(__GNUC__) || \
|
||||
defined(__INTEL_COMPILER)
|
||||
# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
|
||||
# define UV_UNUSED(declaration) __attribute__((unused)) declaration
|
||||
#else
|
||||
# define UV_DESTRUCTOR(declaration) declaration
|
||||
# define UV_UNUSED(declaration) declaration
|
||||
#endif
|
||||
|
||||
|
||||
@@ -768,7 +768,8 @@ static int read_times(FILE* statfile_fp,
|
||||
unsigned int numcpus,
|
||||
uv_cpu_info_t* ci) {
|
||||
struct uv_cpu_times_s ts;
|
||||
uint64_t clock_ticks;
|
||||
unsigned int ticks;
|
||||
unsigned int multiplier;
|
||||
uint64_t user;
|
||||
uint64_t nice;
|
||||
uint64_t sys;
|
||||
@@ -779,9 +780,10 @@ static int read_times(FILE* statfile_fp,
|
||||
uint64_t len;
|
||||
char buf[1024];
|
||||
|
||||
clock_ticks = sysconf(_SC_CLK_TCK);
|
||||
assert(clock_ticks != (uint64_t) -1);
|
||||
assert(clock_ticks != 0);
|
||||
ticks = (unsigned int)sysconf(_SC_CLK_TCK);
|
||||
multiplier = ((uint64_t)1000L / ticks);
|
||||
assert(ticks != (unsigned int) -1);
|
||||
assert(ticks != 0);
|
||||
|
||||
rewind(statfile_fp);
|
||||
|
||||
@@ -823,11 +825,11 @@ static int read_times(FILE* statfile_fp,
|
||||
&irq))
|
||||
abort();
|
||||
|
||||
ts.user = clock_ticks * user;
|
||||
ts.nice = clock_ticks * nice;
|
||||
ts.sys = clock_ticks * sys;
|
||||
ts.idle = clock_ticks * idle;
|
||||
ts.irq = clock_ticks * irq;
|
||||
ts.user = user * multiplier;
|
||||
ts.nice = nice * multiplier;
|
||||
ts.sys = sys * multiplier;
|
||||
ts.idle = idle * multiplier;
|
||||
ts.irq = irq * multiplier;
|
||||
ci[num++].cpu_times = ts;
|
||||
}
|
||||
assert(num == numcpus);
|
||||
|
||||
@@ -29,6 +29,9 @@ char** uv_setup_args(int argc, char** argv) {
|
||||
return argv;
|
||||
}
|
||||
|
||||
void uv__process_title_cleanup(void) {
|
||||
}
|
||||
|
||||
int uv_set_process_title(const char* title) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ int uv_get_process_title(char* buffer, size_t size) {
|
||||
}
|
||||
|
||||
|
||||
UV_DESTRUCTOR(static void free_args_mem(void)) {
|
||||
void uv__process_title_cleanup(void) {
|
||||
uv__free(args_mem); /* Keep valgrind happy. */
|
||||
args_mem = NULL;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ static void uv__signal_global_init(void) {
|
||||
}
|
||||
|
||||
|
||||
UV_DESTRUCTOR(static void uv__signal_global_fini(void)) {
|
||||
void uv__signal_cleanup(void) {
|
||||
/* We can only use signal-safe functions here.
|
||||
* That includes read/write and close, fortunately.
|
||||
* We do all of this directly here instead of resetting
|
||||
@@ -98,7 +98,7 @@ UV_DESTRUCTOR(static void uv__signal_global_fini(void)) {
|
||||
|
||||
|
||||
static void uv__signal_global_reinit(void) {
|
||||
uv__signal_global_fini();
|
||||
uv__signal_cleanup();
|
||||
|
||||
if (uv__make_pipe(uv__signal_lock_pipefd, 0))
|
||||
abort();
|
||||
|
||||
@@ -202,6 +202,9 @@ static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) {
|
||||
msgs[k].msg_hdr.msg_iovlen = 1;
|
||||
msgs[k].msg_hdr.msg_name = peers + k;
|
||||
msgs[k].msg_hdr.msg_namelen = sizeof(peers[0]);
|
||||
msgs[k].msg_hdr.msg_control = NULL;
|
||||
msgs[k].msg_hdr.msg_controllen = 0;
|
||||
msgs[k].msg_hdr.msg_flags = 0;
|
||||
}
|
||||
|
||||
do
|
||||
@@ -262,11 +265,9 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
|
||||
assert(buf.base != NULL);
|
||||
|
||||
#if HAVE_MMSG
|
||||
uv_once(&once, uv__udp_mmsg_init);
|
||||
if (uv__recvmmsg_avail) {
|
||||
/* Returned space for more than 1 datagram, use it to receive
|
||||
* multiple datagrams. */
|
||||
if (buf.len >= 2 * UV__UDP_DGRAM_MAXSIZE) {
|
||||
if (handle->flags & UV_HANDLE_UDP_RECVMMSG) {
|
||||
uv_once(&once, uv__udp_mmsg_init);
|
||||
if (uv__recvmmsg_avail) {
|
||||
nread = uv__udp_recvmmsg(handle, &buf);
|
||||
if (nread > 0)
|
||||
count -= nread;
|
||||
@@ -946,26 +947,17 @@ static int uv__udp_set_source_membership6(uv_udp_t* handle,
|
||||
#endif
|
||||
|
||||
|
||||
int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
|
||||
int domain;
|
||||
int err;
|
||||
int uv__udp_init_ex(uv_loop_t* loop,
|
||||
uv_udp_t* handle,
|
||||
unsigned flags,
|
||||
int domain) {
|
||||
int fd;
|
||||
|
||||
/* Use the lower 8 bits for the domain */
|
||||
domain = flags & 0xFF;
|
||||
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (flags & ~0xFF)
|
||||
return UV_EINVAL;
|
||||
|
||||
fd = -1;
|
||||
if (domain != AF_UNSPEC) {
|
||||
err = uv__socket(domain, SOCK_DGRAM, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
fd = err;
|
||||
} else {
|
||||
fd = -1;
|
||||
fd = uv__socket(domain, SOCK_DGRAM, 0);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
}
|
||||
|
||||
uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP);
|
||||
@@ -981,11 +973,6 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
return uv_udp_init_ex(loop, handle, AF_UNSPEC);
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
int err;
|
||||
|
||||
|
||||
@@ -294,6 +294,36 @@ int uv_tcp_bind(uv_tcp_t* handle,
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned flags) {
|
||||
unsigned extra_flags;
|
||||
int domain;
|
||||
int rc;
|
||||
|
||||
/* Use the lower 8 bits for the domain. */
|
||||
domain = flags & 0xFF;
|
||||
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
|
||||
return UV_EINVAL;
|
||||
|
||||
/* Use the higher bits for extra flags. */
|
||||
extra_flags = flags & ~0xFF;
|
||||
if (extra_flags & ~UV_UDP_RECVMMSG)
|
||||
return UV_EINVAL;
|
||||
|
||||
rc = uv__udp_init_ex(loop, handle, flags, domain);
|
||||
|
||||
if (rc == 0)
|
||||
if (extra_flags & UV_UDP_RECVMMSG)
|
||||
handle->flags |= UV_HANDLE_UDP_RECVMMSG;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
return uv_udp_init_ex(loop, handle, AF_UNSPEC);
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_bind(uv_udp_t* handle,
|
||||
const struct sockaddr* addr,
|
||||
unsigned int flags) {
|
||||
@@ -823,3 +853,19 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
|
||||
uv__free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __GNUC__ /* Also covers __clang__ and __INTEL_COMPILER. */
|
||||
__attribute__((destructor))
|
||||
#endif
|
||||
void uv_library_shutdown(void) {
|
||||
static int was_shutdown;
|
||||
|
||||
if (was_shutdown)
|
||||
return;
|
||||
|
||||
uv__process_title_cleanup();
|
||||
uv__signal_cleanup();
|
||||
uv__threadpool_cleanup();
|
||||
was_shutdown = 1;
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ enum {
|
||||
/* Only used by uv_udp_t handles. */
|
||||
UV_HANDLE_UDP_PROCESSING = 0x01000000,
|
||||
UV_HANDLE_UDP_CONNECTED = 0x02000000,
|
||||
UV_HANDLE_UDP_RECVMMSG = 0x04000000,
|
||||
|
||||
/* Only used by uv_pipe_t handles. */
|
||||
UV_HANDLE_NON_OVERLAPPED_PIPE = 0x01000000,
|
||||
@@ -138,6 +139,11 @@ int uv__tcp_connect(uv_connect_t* req,
|
||||
unsigned int addrlen,
|
||||
uv_connect_cb cb);
|
||||
|
||||
int uv__udp_init_ex(uv_loop_t* loop,
|
||||
uv_udp_t* handle,
|
||||
unsigned flags,
|
||||
int domain);
|
||||
|
||||
int uv__udp_bind(uv_udp_t* handle,
|
||||
const struct sockaddr* addr,
|
||||
unsigned int addrlen,
|
||||
@@ -200,6 +206,10 @@ int uv__next_timeout(const uv_loop_t* loop);
|
||||
void uv__run_timers(uv_loop_t* loop);
|
||||
void uv__timer_close(uv_timer_t* handle);
|
||||
|
||||
void uv__process_title_cleanup(void);
|
||||
void uv__signal_cleanup(void);
|
||||
void uv__threadpool_cleanup(void);
|
||||
|
||||
#define uv__has_active_reqs(loop) \
|
||||
((loop)->active_reqs.count > 0)
|
||||
|
||||
|
||||
@@ -449,12 +449,12 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) {
|
||||
timeout_time = loop->time + timeout;
|
||||
|
||||
for (repeat = 0; ; repeat++) {
|
||||
success = GetQueuedCompletionStatusEx(loop->iocp,
|
||||
overlappeds,
|
||||
ARRAY_SIZE(overlappeds),
|
||||
&count,
|
||||
timeout,
|
||||
FALSE);
|
||||
success = pGetQueuedCompletionStatusEx(loop->iocp,
|
||||
overlappeds,
|
||||
ARRAY_SIZE(overlappeds),
|
||||
&count,
|
||||
timeout,
|
||||
FALSE);
|
||||
|
||||
if (success) {
|
||||
for (i = 0; i < count; i++) {
|
||||
|
||||
@@ -72,6 +72,7 @@ int uv_translate_sys_error(int sys_errno) {
|
||||
case ERROR_NOACCESS: return UV_EACCES;
|
||||
case WSAEACCES: return UV_EACCES;
|
||||
case ERROR_ELEVATION_REQUIRED: return UV_EACCES;
|
||||
case ERROR_CANT_ACCESS_FILE: return UV_EACCES;
|
||||
case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE;
|
||||
case WSAEADDRINUSE: return UV_EADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
|
||||
|
||||
@@ -83,6 +83,7 @@ static void uv_relative_path(const WCHAR* filename,
|
||||
static int uv_split_path(const WCHAR* filename, WCHAR** dir,
|
||||
WCHAR** file) {
|
||||
size_t len, i;
|
||||
DWORD dir_len;
|
||||
|
||||
if (filename == NULL) {
|
||||
if (dir != NULL)
|
||||
@@ -97,12 +98,16 @@ static int uv_split_path(const WCHAR* filename, WCHAR** dir,
|
||||
|
||||
if (i == 0) {
|
||||
if (dir) {
|
||||
*dir = (WCHAR*)uv__malloc((MAX_PATH + 1) * sizeof(WCHAR));
|
||||
dir_len = GetCurrentDirectoryW(0, NULL);
|
||||
if (dir_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
*dir = (WCHAR*)uv__malloc(dir_len * sizeof(WCHAR));
|
||||
if (!*dir) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
|
||||
}
|
||||
|
||||
if (!GetCurrentDirectoryW(MAX_PATH, *dir)) {
|
||||
if (!GetCurrentDirectoryW(dir_len, *dir)) {
|
||||
uv__free(*dir);
|
||||
*dir = NULL;
|
||||
return -1;
|
||||
@@ -155,9 +160,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
||||
int name_size, is_path_dir, size;
|
||||
DWORD attr, last_error;
|
||||
WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
|
||||
WCHAR short_path_buffer[MAX_PATH];
|
||||
DWORD short_path_buffer_len;
|
||||
WCHAR *short_path_buffer;
|
||||
WCHAR* short_path, *long_path;
|
||||
|
||||
short_path = NULL;
|
||||
if (uv__is_active(handle))
|
||||
return UV_EINVAL;
|
||||
|
||||
@@ -230,13 +237,23 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
||||
*/
|
||||
|
||||
/* Convert to short path. */
|
||||
short_path_buffer = NULL;
|
||||
short_path_buffer_len = GetShortPathNameW(pathw, NULL, 0);
|
||||
if (short_path_buffer_len == 0) {
|
||||
goto short_path_done;
|
||||
}
|
||||
short_path_buffer = uv__malloc(short_path_buffer_len * sizeof(WCHAR));
|
||||
if (short_path_buffer == NULL) {
|
||||
goto short_path_done;
|
||||
}
|
||||
if (GetShortPathNameW(pathw,
|
||||
short_path_buffer,
|
||||
ARRAY_SIZE(short_path_buffer))) {
|
||||
short_path = short_path_buffer;
|
||||
} else {
|
||||
short_path = NULL;
|
||||
short_path_buffer_len) == 0) {
|
||||
uv__free(short_path_buffer);
|
||||
short_path_buffer = NULL;
|
||||
}
|
||||
short_path_done:
|
||||
short_path = short_path_buffer;
|
||||
|
||||
if (uv_split_path(pathw, &dir, &handle->filew) != 0) {
|
||||
last_error = GetLastError();
|
||||
@@ -346,6 +363,8 @@ error:
|
||||
if (uv__is_active(handle))
|
||||
uv__handle_stop(handle);
|
||||
|
||||
uv__free(short_path);
|
||||
|
||||
return uv_translate_sys_error(last_error);
|
||||
}
|
||||
|
||||
|
||||
@@ -257,6 +257,7 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
|
||||
req->loop = loop;
|
||||
req->flags = 0;
|
||||
req->fs_type = fs_type;
|
||||
req->sys_errno_ = 0;
|
||||
req->result = 0;
|
||||
req->ptr = NULL;
|
||||
req->path = NULL;
|
||||
@@ -321,6 +322,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
||||
WCHAR* w_target;
|
||||
DWORD w_target_len;
|
||||
DWORD bytes;
|
||||
size_t i;
|
||||
size_t len;
|
||||
|
||||
if (!DeviceIoControl(handle,
|
||||
FSCTL_GET_REPARSE_POINT,
|
||||
@@ -405,6 +408,38 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
||||
w_target += 4;
|
||||
w_target_len -= 4;
|
||||
|
||||
} else if (reparse_data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) {
|
||||
/* String #3 in the list has the target filename. */
|
||||
if (reparse_data->AppExecLinkReparseBuffer.StringCount < 3) {
|
||||
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
w_target = reparse_data->AppExecLinkReparseBuffer.StringList;
|
||||
/* The StringList buffer contains a list of strings separated by "\0", */
|
||||
/* with "\0\0" terminating the list. Move to the 3rd string in the list: */
|
||||
for (i = 0; i < 2; ++i) {
|
||||
len = wcslen(w_target);
|
||||
if (len == 0) {
|
||||
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
w_target += len + 1;
|
||||
}
|
||||
w_target_len = wcslen(w_target);
|
||||
if (w_target_len == 0) {
|
||||
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
/* Make sure it is an absolute path. */
|
||||
if (!(w_target_len >= 3 &&
|
||||
((w_target[0] >= L'a' && w_target[0] <= L'z') ||
|
||||
(w_target[0] >= L'A' && w_target[0] <= L'Z')) &&
|
||||
w_target[1] == L':' &&
|
||||
w_target[2] == L'\\')) {
|
||||
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Reparse tag does not indicate a symlink. */
|
||||
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
|
||||
@@ -2225,34 +2260,68 @@ INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void fs__utime(uv_fs_t* req) {
|
||||
INLINE static DWORD fs__utime_impl_from_path(WCHAR* path,
|
||||
double atime,
|
||||
double mtime,
|
||||
int do_lutime) {
|
||||
HANDLE handle;
|
||||
DWORD flags;
|
||||
DWORD ret;
|
||||
|
||||
handle = CreateFileW(req->file.pathw,
|
||||
flags = FILE_FLAG_BACKUP_SEMANTICS;
|
||||
if (do_lutime) {
|
||||
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
}
|
||||
|
||||
handle = CreateFileW(path,
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
flags,
|
||||
NULL);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
CloseHandle(handle);
|
||||
return;
|
||||
ret = GetLastError();
|
||||
} else if (fs__utime_handle(handle, atime, mtime) != 0) {
|
||||
ret = GetLastError();
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
INLINE static void fs__utime_impl(uv_fs_t* req, int do_lutime) {
|
||||
DWORD error;
|
||||
|
||||
error = fs__utime_impl_from_path(req->file.pathw,
|
||||
req->fs.time.atime,
|
||||
req->fs.time.mtime,
|
||||
do_lutime);
|
||||
|
||||
if (error != 0) {
|
||||
if (do_lutime &&
|
||||
(error == ERROR_SYMLINK_NOT_SUPPORTED ||
|
||||
error == ERROR_NOT_A_REPARSE_POINT)) {
|
||||
/* Opened file is a reparse point but not a symlink. Try again. */
|
||||
fs__utime_impl(req, 0);
|
||||
} else {
|
||||
/* utime failed. */
|
||||
SET_REQ_WIN32_ERROR(req, error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
req->result = 0;
|
||||
}
|
||||
|
||||
static void fs__utime(uv_fs_t* req) {
|
||||
fs__utime_impl(req, /* do_lutime */ 0);
|
||||
}
|
||||
|
||||
|
||||
static void fs__futime(uv_fs_t* req) {
|
||||
int fd = req->file.fd;
|
||||
@@ -2274,6 +2343,10 @@ static void fs__futime(uv_fs_t* req) {
|
||||
req->result = 0;
|
||||
}
|
||||
|
||||
static void fs__lutime(uv_fs_t* req) {
|
||||
fs__utime_impl(req, /* do_lutime */ 1);
|
||||
}
|
||||
|
||||
|
||||
static void fs__link(uv_fs_t* req) {
|
||||
DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);
|
||||
@@ -2621,14 +2694,62 @@ static void fs__statfs(uv_fs_t* req) {
|
||||
DWORD bytes_per_sector;
|
||||
DWORD free_clusters;
|
||||
DWORD total_clusters;
|
||||
WCHAR* pathw;
|
||||
|
||||
if (0 == GetDiskFreeSpaceW(req->file.pathw,
|
||||
pathw = req->file.pathw;
|
||||
retry_get_disk_free_space:
|
||||
if (0 == GetDiskFreeSpaceW(pathw,
|
||||
§ors_per_cluster,
|
||||
&bytes_per_sector,
|
||||
&free_clusters,
|
||||
&total_clusters)) {
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
return;
|
||||
DWORD err;
|
||||
WCHAR* fpart;
|
||||
size_t len;
|
||||
DWORD ret;
|
||||
BOOL is_second;
|
||||
|
||||
err = GetLastError();
|
||||
is_second = pathw != req->file.pathw;
|
||||
if (err != ERROR_DIRECTORY || is_second) {
|
||||
if (is_second)
|
||||
uv__free(pathw);
|
||||
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return;
|
||||
}
|
||||
|
||||
len = MAX_PATH + 1;
|
||||
pathw = uv__malloc(len * sizeof(*pathw));
|
||||
if (pathw == NULL) {
|
||||
SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
|
||||
return;
|
||||
}
|
||||
retry_get_full_path_name:
|
||||
ret = GetFullPathNameW(req->file.pathw,
|
||||
len,
|
||||
pathw,
|
||||
&fpart);
|
||||
if (ret == 0) {
|
||||
uv__free(pathw);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return;
|
||||
} else if (ret > len) {
|
||||
len = ret;
|
||||
pathw = uv__reallocf(pathw, len * sizeof(*pathw));
|
||||
if (pathw == NULL) {
|
||||
SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
|
||||
return;
|
||||
}
|
||||
goto retry_get_full_path_name;
|
||||
}
|
||||
if (fpart != 0)
|
||||
*fpart = L'\0';
|
||||
|
||||
goto retry_get_disk_free_space;
|
||||
}
|
||||
if (pathw != req->file.pathw) {
|
||||
uv__free(pathw);
|
||||
}
|
||||
|
||||
stat_fs = uv__malloc(sizeof(*stat_fs));
|
||||
@@ -2670,6 +2791,7 @@ static void uv__fs_work(struct uv__work* w) {
|
||||
XX(FTRUNCATE, ftruncate)
|
||||
XX(UTIME, utime)
|
||||
XX(FUTIME, futime)
|
||||
XX(LUTIME, lutime)
|
||||
XX(ACCESS, access)
|
||||
XX(CHMOD, chmod)
|
||||
XX(FCHMOD, fchmod)
|
||||
@@ -2753,7 +2875,8 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
|
||||
INIT(UV_FS_OPEN);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
req->fs.info.file_flags = flags;
|
||||
@@ -2778,8 +2901,10 @@ int uv_fs_read(uv_loop_t* loop,
|
||||
uv_fs_cb cb) {
|
||||
INIT(UV_FS_READ);
|
||||
|
||||
if (bufs == NULL || nbufs == 0)
|
||||
if (bufs == NULL || nbufs == 0) {
|
||||
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
req->file.fd = fd;
|
||||
|
||||
@@ -2788,8 +2913,10 @@ int uv_fs_read(uv_loop_t* loop,
|
||||
if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
|
||||
req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
|
||||
|
||||
if (req->fs.info.bufs == NULL)
|
||||
if (req->fs.info.bufs == NULL) {
|
||||
SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
|
||||
|
||||
@@ -2807,8 +2934,10 @@ int uv_fs_write(uv_loop_t* loop,
|
||||
uv_fs_cb cb) {
|
||||
INIT(UV_FS_WRITE);
|
||||
|
||||
if (bufs == NULL || nbufs == 0)
|
||||
if (bufs == NULL || nbufs == 0) {
|
||||
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
req->file.fd = fd;
|
||||
|
||||
@@ -2817,8 +2946,10 @@ int uv_fs_write(uv_loop_t* loop,
|
||||
if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
|
||||
req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
|
||||
|
||||
if (req->fs.info.bufs == NULL)
|
||||
if (req->fs.info.bufs == NULL) {
|
||||
SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
|
||||
|
||||
@@ -2834,7 +2965,8 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
INIT(UV_FS_UNLINK);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
@@ -2848,7 +2980,8 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
|
||||
INIT(UV_FS_MKDIR);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
req->fs.info.mode = mode;
|
||||
@@ -2864,8 +2997,10 @@ int uv_fs_mkdtemp(uv_loop_t* loop,
|
||||
|
||||
INIT(UV_FS_MKDTEMP);
|
||||
err = fs__capture_path(req, tpl, NULL, TRUE);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
if (err) {
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
}
|
||||
@@ -2879,8 +3014,10 @@ int uv_fs_mkstemp(uv_loop_t* loop,
|
||||
|
||||
INIT(UV_FS_MKSTEMP);
|
||||
err = fs__capture_path(req, tpl, NULL, TRUE);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
if (err) {
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
}
|
||||
@@ -2892,7 +3029,8 @@ int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
INIT(UV_FS_RMDIR);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
@@ -2906,7 +3044,8 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
|
||||
INIT(UV_FS_SCANDIR);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
req->fs.info.file_flags = flags;
|
||||
@@ -2921,8 +3060,10 @@ int uv_fs_opendir(uv_loop_t* loop,
|
||||
|
||||
INIT(UV_FS_OPENDIR);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
if (err) {
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
POST;
|
||||
}
|
||||
|
||||
@@ -2935,6 +3076,7 @@ int uv_fs_readdir(uv_loop_t* loop,
|
||||
if (dir == NULL ||
|
||||
dir->dirents == NULL ||
|
||||
dir->dir_handle == INVALID_HANDLE_VALUE) {
|
||||
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
@@ -2947,8 +3089,10 @@ int uv_fs_closedir(uv_loop_t* loop,
|
||||
uv_dir_t* dir,
|
||||
uv_fs_cb cb) {
|
||||
INIT(UV_FS_CLOSEDIR);
|
||||
if (dir == NULL)
|
||||
if (dir == NULL) {
|
||||
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
|
||||
return UV_EINVAL;
|
||||
}
|
||||
req->ptr = dir;
|
||||
POST;
|
||||
}
|
||||
@@ -2960,7 +3104,8 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
INIT(UV_FS_LINK);
|
||||
err = fs__capture_path(req, path, new_path, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
@@ -2974,7 +3119,8 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
INIT(UV_FS_SYMLINK);
|
||||
err = fs__capture_path(req, path, new_path, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
req->fs.info.file_flags = flags;
|
||||
@@ -2989,7 +3135,8 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
INIT(UV_FS_READLINK);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
@@ -3003,12 +3150,14 @@ int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
INIT(UV_FS_REALPATH);
|
||||
|
||||
if (!path) {
|
||||
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
@@ -3022,7 +3171,8 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
|
||||
INIT(UV_FS_CHOWN);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
@@ -3043,8 +3193,10 @@ int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
|
||||
INIT(UV_FS_LCHOWN);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
}
|
||||
|
||||
@@ -3055,7 +3207,8 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
INIT(UV_FS_STAT);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
@@ -3068,7 +3221,8 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
INIT(UV_FS_LSTAT);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
@@ -3089,7 +3243,8 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
INIT(UV_FS_RENAME);
|
||||
err = fs__capture_path(req, path, new_path, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
@@ -3132,13 +3287,15 @@ int uv_fs_copyfile(uv_loop_t* loop,
|
||||
if (flags & ~(UV_FS_COPYFILE_EXCL |
|
||||
UV_FS_COPYFILE_FICLONE |
|
||||
UV_FS_COPYFILE_FICLONE_FORCE)) {
|
||||
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
err = fs__capture_path(req, path, new_path, cb != NULL);
|
||||
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
if (err) {
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
req->fs.info.file_flags = flags;
|
||||
POST;
|
||||
@@ -3165,8 +3322,10 @@ int uv_fs_access(uv_loop_t* loop,
|
||||
|
||||
INIT(UV_FS_ACCESS);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
if (err) {
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
req->fs.info.mode = flags;
|
||||
POST;
|
||||
@@ -3180,7 +3339,8 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
|
||||
INIT(UV_FS_CHMOD);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
req->fs.info.mode = mode;
|
||||
@@ -3204,7 +3364,8 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
|
||||
INIT(UV_FS_UTIME);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
req->fs.time.atime = atime;
|
||||
@@ -3222,6 +3383,22 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,
|
||||
POST;
|
||||
}
|
||||
|
||||
int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
|
||||
double mtime, uv_fs_cb cb) {
|
||||
int err;
|
||||
|
||||
INIT(UV_FS_LUTIME);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
req->fs.time.atime = atime;
|
||||
req->fs.time.mtime = mtime;
|
||||
POST;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_statfs(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
@@ -3231,8 +3408,14 @@ int uv_fs_statfs(uv_loop_t* loop,
|
||||
|
||||
INIT(UV_FS_STATFS);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
if (err) {
|
||||
SET_REQ_WIN32_ERROR(req, err);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
POST;
|
||||
}
|
||||
|
||||
int uv_fs_get_system_error(const uv_fs_t* req) {
|
||||
return req->sys_errno_;
|
||||
}
|
||||
|
||||
@@ -134,32 +134,6 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
}
|
||||
|
||||
|
||||
static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
AFD_POLL_INFO afd_poll_info;
|
||||
int result;
|
||||
|
||||
afd_poll_info.Exclusive = TRUE;
|
||||
afd_poll_info.NumberOfHandles = 1;
|
||||
afd_poll_info.Timeout.QuadPart = INT64_MAX;
|
||||
afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;
|
||||
afd_poll_info.Handles[0].Status = 0;
|
||||
afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
|
||||
|
||||
result = uv_msafd_poll(handle->socket,
|
||||
&afd_poll_info,
|
||||
uv__get_afd_poll_info_dummy(),
|
||||
uv__get_overlapped_dummy());
|
||||
|
||||
if (result == SOCKET_ERROR) {
|
||||
DWORD error = WSAGetLastError();
|
||||
if (error != WSA_IO_PENDING)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
||||
uv_req_t* req) {
|
||||
unsigned char mask_events;
|
||||
@@ -226,44 +200,6 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
||||
}
|
||||
|
||||
|
||||
static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
|
||||
assert(handle->type == UV_POLL);
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
||||
assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
|
||||
|
||||
handle->events = events;
|
||||
|
||||
if (handle->events != 0) {
|
||||
uv__handle_start(handle);
|
||||
} else {
|
||||
uv__handle_stop(handle);
|
||||
}
|
||||
|
||||
if ((handle->events & ~(handle->submitted_events_1 |
|
||||
handle->submitted_events_2)) != 0) {
|
||||
uv__fast_poll_submit_poll_req(handle->loop, handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
handle->events = 0;
|
||||
uv__handle_closing(handle);
|
||||
|
||||
if (handle->submitted_events_1 == 0 &&
|
||||
handle->submitted_events_2 == 0) {
|
||||
uv_want_endgame(loop, (uv_handle_t*) handle);
|
||||
return 0;
|
||||
} else {
|
||||
/* Cancel outstanding poll requests by executing another, unique poll
|
||||
* request that forces the outstanding ones to return. */
|
||||
return uv__fast_poll_cancel_poll_req(loop, handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static SOCKET uv__fast_poll_create_peer_socket(HANDLE iocp,
|
||||
WSAPROTOCOL_INFOW* protocol_info) {
|
||||
SOCKET sock = 0;
|
||||
@@ -469,41 +405,6 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
||||
}
|
||||
|
||||
|
||||
static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
|
||||
assert(handle->type == UV_POLL);
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
||||
assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
|
||||
|
||||
handle->events = events;
|
||||
|
||||
if (handle->events != 0) {
|
||||
uv__handle_start(handle);
|
||||
} else {
|
||||
uv__handle_stop(handle);
|
||||
}
|
||||
|
||||
if ((handle->events &
|
||||
~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) {
|
||||
uv__slow_poll_submit_poll_req(handle->loop, handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uv__slow_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
handle->events = 0;
|
||||
uv__handle_closing(handle);
|
||||
|
||||
if (handle->submitted_events_1 == 0 &&
|
||||
handle->submitted_events_2 == 0) {
|
||||
uv_want_endgame(loop, (uv_handle_t*) handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
|
||||
return uv_poll_init_socket(loop, handle, (SOCKET) uv__get_osfhandle(fd));
|
||||
}
|
||||
@@ -582,35 +483,43 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
|
||||
}
|
||||
|
||||
|
||||
int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) {
|
||||
int err;
|
||||
static int uv__poll_set(uv_poll_t* handle, int events, uv_poll_cb cb) {
|
||||
int submitted_events;
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
|
||||
err = uv__fast_poll_set(handle->loop, handle, events);
|
||||
} else {
|
||||
err = uv__slow_poll_set(handle->loop, handle, events);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
assert(handle->type == UV_POLL);
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
||||
assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
|
||||
|
||||
handle->events = events;
|
||||
handle->poll_cb = cb;
|
||||
|
||||
if (handle->events == 0) {
|
||||
uv__handle_stop(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uv__handle_start(handle);
|
||||
submitted_events = handle->submitted_events_1 | handle->submitted_events_2;
|
||||
|
||||
if (handle->events & ~submitted_events) {
|
||||
if (handle->flags & UV_HANDLE_POLL_SLOW) {
|
||||
uv__slow_poll_submit_poll_req(handle->loop, handle);
|
||||
} else {
|
||||
uv__fast_poll_submit_poll_req(handle->loop, handle);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) {
|
||||
return uv__poll_set(handle, events, cb);
|
||||
}
|
||||
|
||||
|
||||
int uv_poll_stop(uv_poll_t* handle) {
|
||||
int err;
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
|
||||
err = uv__fast_poll_set(handle->loop, handle, 0);
|
||||
} else {
|
||||
err = uv__slow_poll_set(handle->loop, handle, 0);
|
||||
}
|
||||
|
||||
return uv_translate_sys_error(err);
|
||||
return uv__poll_set(handle, 0, handle->poll_cb);
|
||||
}
|
||||
|
||||
|
||||
@@ -624,11 +533,43 @@ void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) {
|
||||
|
||||
|
||||
int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
|
||||
if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
|
||||
return uv__fast_poll_close(loop, handle);
|
||||
} else {
|
||||
return uv__slow_poll_close(loop, handle);
|
||||
AFD_POLL_INFO afd_poll_info;
|
||||
DWORD error;
|
||||
int result;
|
||||
|
||||
handle->events = 0;
|
||||
uv__handle_closing(handle);
|
||||
|
||||
if (handle->submitted_events_1 == 0 &&
|
||||
handle->submitted_events_2 == 0) {
|
||||
uv_want_endgame(loop, (uv_handle_t*) handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_POLL_SLOW)
|
||||
return 0;
|
||||
|
||||
/* Cancel outstanding poll requests by executing another, unique poll
|
||||
* request that forces the outstanding ones to return. */
|
||||
afd_poll_info.Exclusive = TRUE;
|
||||
afd_poll_info.NumberOfHandles = 1;
|
||||
afd_poll_info.Timeout.QuadPart = INT64_MAX;
|
||||
afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;
|
||||
afd_poll_info.Handles[0].Status = 0;
|
||||
afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
|
||||
|
||||
result = uv_msafd_poll(handle->socket,
|
||||
&afd_poll_info,
|
||||
uv__get_afd_poll_info_dummy(),
|
||||
uv__get_overlapped_dummy());
|
||||
|
||||
if (result == SOCKET_ERROR) {
|
||||
error = WSAGetLastError();
|
||||
if (error != WSA_IO_PENDING)
|
||||
return uv_translate_sys_error(error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ static const env_var_t required_vars[] = { /* keep me sorted */
|
||||
E_V("USERPROFILE"),
|
||||
E_V("WINDIR"),
|
||||
};
|
||||
static size_t n_required_vars = ARRAY_SIZE(required_vars);
|
||||
|
||||
|
||||
static HANDLE uv_global_job_handle_;
|
||||
@@ -692,7 +691,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
|
||||
WCHAR* dst_copy;
|
||||
WCHAR** ptr_copy;
|
||||
WCHAR** env_copy;
|
||||
DWORD* required_vars_value_len = alloca(n_required_vars * sizeof(DWORD*));
|
||||
DWORD required_vars_value_len[ARRAY_SIZE(required_vars)];
|
||||
|
||||
/* first pass: determine size in UTF-16 */
|
||||
for (env = env_block; *env; env++) {
|
||||
@@ -745,7 +744,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
|
||||
qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp);
|
||||
|
||||
/* third pass: check for required variables */
|
||||
for (ptr_copy = env_copy, i = 0; i < n_required_vars; ) {
|
||||
for (ptr_copy = env_copy, i = 0; i < ARRAY_SIZE(required_vars); ) {
|
||||
int cmp;
|
||||
if (!*ptr_copy) {
|
||||
cmp = -1;
|
||||
@@ -778,10 +777,10 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
|
||||
}
|
||||
|
||||
for (ptr = dst, ptr_copy = env_copy, i = 0;
|
||||
*ptr_copy || i < n_required_vars;
|
||||
*ptr_copy || i < ARRAY_SIZE(required_vars);
|
||||
ptr += len) {
|
||||
int cmp;
|
||||
if (i >= n_required_vars) {
|
||||
if (i >= ARRAY_SIZE(required_vars)) {
|
||||
cmp = 1;
|
||||
} else if (!*ptr_copy) {
|
||||
cmp = -1;
|
||||
|
||||
@@ -46,6 +46,11 @@ void uv_signals_init(void) {
|
||||
}
|
||||
|
||||
|
||||
void uv__signal_cleanup(void) {
|
||||
/* TODO(bnoordhuis) Undo effects of uv_signal_init()? */
|
||||
}
|
||||
|
||||
|
||||
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
|
||||
/* Compare signums first so all watchers with the same signnum end up
|
||||
* adjacent. */
|
||||
|
||||
@@ -125,17 +125,10 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
|
||||
int domain;
|
||||
|
||||
/* Use the lower 8 bits for the domain */
|
||||
domain = flags & 0xFF;
|
||||
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (flags & ~0xFF)
|
||||
return UV_EINVAL;
|
||||
|
||||
int uv__udp_init_ex(uv_loop_t* loop,
|
||||
uv_udp_t* handle,
|
||||
unsigned flags,
|
||||
int domain) {
|
||||
uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP);
|
||||
handle->socket = INVALID_SOCKET;
|
||||
handle->reqs_pending = 0;
|
||||
@@ -174,11 +167,6 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
return uv_udp_init_ex(loop, handle, AF_UNSPEC);
|
||||
}
|
||||
|
||||
|
||||
void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
uv_udp_recv_stop(handle);
|
||||
closesocket(handle->socket);
|
||||
|
||||
@@ -60,9 +60,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Maximum environment variable size, including the terminating null */
|
||||
#define MAX_ENV_VAR_LENGTH 32767
|
||||
|
||||
/* A RtlGenRandom() by any other name... */
|
||||
extern BOOLEAN NTAPI SystemFunction036(PVOID Buffer, ULONG BufferLength);
|
||||
|
||||
@@ -154,20 +151,26 @@ int uv_exepath(char* buffer, size_t* size_ptr) {
|
||||
|
||||
int uv_cwd(char* buffer, size_t* size) {
|
||||
DWORD utf16_len;
|
||||
WCHAR utf16_buffer[MAX_PATH];
|
||||
WCHAR *utf16_buffer;
|
||||
int r;
|
||||
|
||||
if (buffer == NULL || size == NULL) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
|
||||
utf16_len = GetCurrentDirectoryW(0, NULL);
|
||||
if (utf16_len == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
} else if (utf16_len > MAX_PATH) {
|
||||
/* This should be impossible; however the CRT has a code path to deal with
|
||||
* this scenario, so I added a check anyway. */
|
||||
return UV_EIO;
|
||||
}
|
||||
utf16_buffer = uv__malloc(utf16_len * sizeof(WCHAR));
|
||||
if (utf16_buffer == NULL) {
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
utf16_len = GetCurrentDirectoryW(utf16_len, utf16_buffer);
|
||||
if (utf16_len == 0) {
|
||||
uv__free(utf16_buffer);
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
/* utf16_len contains the length, *not* including the terminating null. */
|
||||
@@ -191,8 +194,10 @@ int uv_cwd(char* buffer, size_t* size) {
|
||||
NULL,
|
||||
NULL);
|
||||
if (r == 0) {
|
||||
uv__free(utf16_buffer);
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
} else if (r > (int) *size) {
|
||||
uv__free(utf16_buffer);
|
||||
*size = r;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
@@ -206,6 +211,8 @@ int uv_cwd(char* buffer, size_t* size) {
|
||||
*size > INT_MAX ? INT_MAX : (int) *size,
|
||||
NULL,
|
||||
NULL);
|
||||
uv__free(utf16_buffer);
|
||||
|
||||
if (r == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
@@ -216,43 +223,61 @@ int uv_cwd(char* buffer, size_t* size) {
|
||||
|
||||
|
||||
int uv_chdir(const char* dir) {
|
||||
WCHAR utf16_buffer[MAX_PATH];
|
||||
size_t utf16_len;
|
||||
WCHAR *utf16_buffer;
|
||||
size_t utf16_len, new_utf16_len;
|
||||
WCHAR drive_letter, env_var[4];
|
||||
|
||||
if (dir == NULL) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
utf16_len = MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
dir,
|
||||
-1,
|
||||
NULL,
|
||||
0);
|
||||
if (utf16_len == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
utf16_buffer = uv__malloc(utf16_len * sizeof(WCHAR));
|
||||
if (utf16_buffer == NULL) {
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
if (MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
dir,
|
||||
-1,
|
||||
utf16_buffer,
|
||||
MAX_PATH) == 0) {
|
||||
DWORD error = GetLastError();
|
||||
/* The maximum length of the current working directory is 260 chars,
|
||||
* including terminating null. If it doesn't fit, the path name must be too
|
||||
* long. */
|
||||
if (error == ERROR_INSUFFICIENT_BUFFER) {
|
||||
return UV_ENAMETOOLONG;
|
||||
} else {
|
||||
return uv_translate_sys_error(error);
|
||||
}
|
||||
utf16_len) == 0) {
|
||||
uv__free(utf16_buffer);
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
if (!SetCurrentDirectoryW(utf16_buffer)) {
|
||||
uv__free(utf16_buffer);
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
/* Windows stores the drive-local path in an "hidden" environment variable,
|
||||
* which has the form "=C:=C:\Windows". SetCurrentDirectory does not update
|
||||
* this, so we'll have to do it. */
|
||||
utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
|
||||
new_utf16_len = GetCurrentDirectoryW(utf16_len, utf16_buffer);
|
||||
if (new_utf16_len > utf16_len ) {
|
||||
uv__free(utf16_buffer);
|
||||
utf16_buffer = uv__malloc(new_utf16_len * sizeof(WCHAR));
|
||||
if (utf16_buffer == NULL) {
|
||||
/* When updating the environment variable fails, return UV_OK anyway.
|
||||
* We did successfully change current working directory, only updating
|
||||
* hidden env variable failed. */
|
||||
return 0;
|
||||
}
|
||||
new_utf16_len = GetCurrentDirectoryW(new_utf16_len, utf16_buffer);
|
||||
}
|
||||
if (utf16_len == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
} else if (utf16_len > MAX_PATH) {
|
||||
return UV_EIO;
|
||||
uv__free(utf16_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The returned directory should not have a trailing slash, unless it points
|
||||
@@ -284,11 +309,10 @@ int uv_chdir(const char* dir) {
|
||||
env_var[2] = L':';
|
||||
env_var[3] = L'\0';
|
||||
|
||||
if (!SetEnvironmentVariableW(env_var, utf16_buffer)) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
SetEnvironmentVariableW(env_var, utf16_buffer);
|
||||
}
|
||||
|
||||
uv__free(utf16_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -361,6 +385,10 @@ char** uv_setup_args(int argc, char** argv) {
|
||||
}
|
||||
|
||||
|
||||
void uv__process_title_cleanup(void) {
|
||||
}
|
||||
|
||||
|
||||
int uv_set_process_title(const char* title) {
|
||||
int err;
|
||||
int length;
|
||||
@@ -1163,20 +1191,29 @@ int uv_os_homedir(char* buffer, size_t* size) {
|
||||
|
||||
|
||||
int uv_os_tmpdir(char* buffer, size_t* size) {
|
||||
wchar_t path[MAX_PATH + 2];
|
||||
wchar_t *path;
|
||||
DWORD bufsize;
|
||||
size_t len;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
len = GetTempPathW(ARRAY_SIZE(path), path);
|
||||
|
||||
len = 0;
|
||||
len = GetTempPathW(0, NULL);
|
||||
if (len == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
} else if (len > ARRAY_SIZE(path)) {
|
||||
/* This should not be possible */
|
||||
return UV_EIO;
|
||||
}
|
||||
/* Include space for terminating null char. */
|
||||
len += 1;
|
||||
path = uv__malloc(len * sizeof(wchar_t));
|
||||
if (path == NULL) {
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
len = GetTempPathW(len, path);
|
||||
|
||||
if (len == 0) {
|
||||
uv__free(path);
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
/* The returned directory should not have a trailing slash, unless it points
|
||||
@@ -1191,8 +1228,10 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
|
||||
bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (bufsize == 0) {
|
||||
uv__free(path);
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
} else if (bufsize > *size) {
|
||||
uv__free(path);
|
||||
*size = bufsize;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
@@ -1206,6 +1245,7 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
|
||||
*size,
|
||||
NULL,
|
||||
NULL);
|
||||
uv__free(path);
|
||||
|
||||
if (bufsize == 0)
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
@@ -1325,7 +1365,7 @@ int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) {
|
||||
int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
HANDLE token;
|
||||
wchar_t username[UNLEN + 1];
|
||||
wchar_t path[MAX_PATH];
|
||||
wchar_t *path;
|
||||
DWORD bufsize;
|
||||
int r;
|
||||
|
||||
@@ -1336,15 +1376,24 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
|
||||
bufsize = ARRAY_SIZE(path);
|
||||
bufsize = 0;
|
||||
GetUserProfileDirectoryW(token, NULL, &bufsize);
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
r = GetLastError();
|
||||
CloseHandle(token);
|
||||
return uv_translate_sys_error(r);
|
||||
}
|
||||
|
||||
path = uv__malloc(bufsize * sizeof(wchar_t));
|
||||
if (path == NULL) {
|
||||
CloseHandle(token);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
|
||||
r = GetLastError();
|
||||
CloseHandle(token);
|
||||
|
||||
/* This should not be possible */
|
||||
if (r == ERROR_INSUFFICIENT_BUFFER)
|
||||
return UV_ENOMEM;
|
||||
|
||||
uv__free(path);
|
||||
return uv_translate_sys_error(r);
|
||||
}
|
||||
|
||||
@@ -1354,6 +1403,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
bufsize = ARRAY_SIZE(username);
|
||||
if (!GetUserNameW(username, &bufsize)) {
|
||||
r = GetLastError();
|
||||
uv__free(path);
|
||||
|
||||
/* This should not be possible */
|
||||
if (r == ERROR_INSUFFICIENT_BUFFER)
|
||||
@@ -1364,6 +1414,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
|
||||
pwd->homedir = NULL;
|
||||
r = uv__convert_utf16_to_utf8(path, -1, &pwd->homedir);
|
||||
uv__free(path);
|
||||
|
||||
if (r != 0)
|
||||
return r;
|
||||
@@ -1405,7 +1456,7 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) {
|
||||
for (penv = env, i = 0; *penv != L'\0'; penv += wcslen(penv) + 1, i++);
|
||||
|
||||
*envitems = uv__calloc(i, sizeof(**envitems));
|
||||
if (envitems == NULL) {
|
||||
if (*envitems == NULL) {
|
||||
FreeEnvironmentStringsW(env);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
@@ -1461,7 +1512,9 @@ fail:
|
||||
|
||||
|
||||
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
||||
wchar_t var[MAX_ENV_VAR_LENGTH];
|
||||
wchar_t fastvar[512];
|
||||
wchar_t* var;
|
||||
DWORD varlen;
|
||||
wchar_t* name_w;
|
||||
DWORD bufsize;
|
||||
size_t len;
|
||||
@@ -1475,25 +1528,52 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH);
|
||||
var = fastvar;
|
||||
varlen = ARRAY_SIZE(fastvar);
|
||||
|
||||
for (;;) {
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
len = GetEnvironmentVariableW(name_w, var, varlen);
|
||||
|
||||
if (len < varlen)
|
||||
break;
|
||||
|
||||
/* Try repeatedly because we might have been preempted by another thread
|
||||
* modifying the environment variable just as we're trying to read it.
|
||||
*/
|
||||
if (var != fastvar)
|
||||
uv__free(var);
|
||||
|
||||
varlen = 1 + len;
|
||||
var = uv__malloc(varlen * sizeof(*var));
|
||||
|
||||
if (var == NULL) {
|
||||
r = UV_ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
uv__free(name_w);
|
||||
assert(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */
|
||||
name_w = NULL;
|
||||
|
||||
if (len == 0) {
|
||||
r = GetLastError();
|
||||
if (r != ERROR_SUCCESS)
|
||||
return uv_translate_sys_error(r);
|
||||
if (r != ERROR_SUCCESS) {
|
||||
r = uv_translate_sys_error(r);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check how much space we need */
|
||||
bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (bufsize == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
r = uv_translate_sys_error(GetLastError());
|
||||
goto fail;
|
||||
} else if (bufsize > *size) {
|
||||
*size = bufsize;
|
||||
return UV_ENOBUFS;
|
||||
r = UV_ENOBUFS;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Convert to UTF-8 */
|
||||
@@ -1506,11 +1586,23 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (bufsize == 0)
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
if (bufsize == 0) {
|
||||
r = uv_translate_sys_error(GetLastError());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*size = bufsize - 1;
|
||||
return 0;
|
||||
r = 0;
|
||||
|
||||
fail:
|
||||
|
||||
if (name_w != NULL)
|
||||
uv__free(name_w);
|
||||
|
||||
if (var != fastvar)
|
||||
uv__free(var);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4160,6 +4160,10 @@ typedef const UNICODE_STRING *PCUNICODE_STRING;
|
||||
struct {
|
||||
UCHAR DataBuffer[1];
|
||||
} GenericReparseBuffer;
|
||||
struct {
|
||||
ULONG StringCount;
|
||||
WCHAR StringList[1];
|
||||
} AppExecLinkReparseBuffer;
|
||||
};
|
||||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||
#endif
|
||||
@@ -4525,6 +4529,9 @@ typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
|
||||
#ifndef IO_REPARSE_TAG_SYMLINK
|
||||
# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_APPEXECLINK
|
||||
# define IO_REPARSE_TAG_APPEXECLINK (0x8000001BL)
|
||||
#endif
|
||||
|
||||
typedef VOID (NTAPI *PIO_APC_ROUTINE)
|
||||
(PVOID ApcContext,
|
||||
|
||||
Reference in New Issue
Block a user