diff --git a/cmd/CMakeLists.txt b/cmd/CMakeLists.txt index 813522b16478..8ce472d663c2 100644 --- a/cmd/CMakeLists.txt +++ b/cmd/CMakeLists.txt @@ -12,3 +12,4 @@ add_subdirectory(os/windows/kstat) add_subdirectory(os/windows/zfsinstaller) add_subdirectory(raidz_test) add_subdirectory(zinject) +add_subdirectory(zed) diff --git a/cmd/zed/CMakeLists.txt b/cmd/zed/CMakeLists.txt new file mode 100644 index 000000000000..39d883ad020b --- /dev/null +++ b/cmd/zed/CMakeLists.txt @@ -0,0 +1,35 @@ + +use_clang() + +um_add_executable(zed + zed.c + zed_conf.c + zed_disk_event.c + zed_event.c + zed_file.c + zed_log.c + zed_strings.c + agents/fmd_api.c + agents/fmd_serd.c + agents/zfs_agents.c + agents/zfs_diagnosis.c + agents/zfs_mod.c + agents/zfs_retire.c + os/windows/zed_exec.c + os/windows/resource.rc +) +target_link_libraries(zed PRIVATE +# libnvpair +# libuutil + libzfs +# libzfs_core + libzpool +) + +target_include_directories(zed PRIVATE "${CMAKE_SOURCE_DIR}/cmd/zed" "${CMAKE_SOURCE_DIR}/include") + +install(TARGETS zed RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") +install(FILES $ + DESTINATION "${CMAKE_INSTALL_BINDIR}" + OPTIONAL +) diff --git a/cmd/zed/agents/fmd_api.c b/cmd/zed/agents/fmd_api.c index fe43e2ab971e..394e5f3eef47 100644 --- a/cmd/zed/agents/fmd_api.c +++ b/cmd/zed/agents/fmd_api.c @@ -564,7 +564,7 @@ fmd_serd_gc(fmd_hdl_t *hdl) } /* FMD Timers */ - +#if 0 static void _timer_notify(union sigval sv) { @@ -584,7 +584,7 @@ _timer_notify(union sigval sv) if (ops->fmdo_timeout != NULL) ops->fmdo_timeout(hdl, ftp, ftp->ft_arg); } - +#endif /* * Install a new timer which will fire at least delta nanoseconds after the * current time. After the timeout has expired, the module's fmdo_timeout @@ -608,9 +608,9 @@ fmd_timer_install(fmd_hdl_t *hdl, void *arg, fmd_event_t *ep, hrtime_t delta) its.it_interval.tv_nsec = its.it_value.tv_nsec; sev.sigev_notify = SIGEV_THREAD; - sev.sigev_notify_function = _timer_notify; - sev.sigev_notify_attributes = NULL; - sev.sigev_value.sival_ptr = ftp; +// sev.sigev_notify_function = _timer_notify; +// sev.sigev_notify_attributes = NULL; +// sev.sigev_value.sival_ptr = ftp; sev.sigev_signo = 0; timer_create(CLOCK_REALTIME, &sev, &ftp->ft_tid); diff --git a/cmd/zed/os/windows/resource.h b/cmd/zed/os/windows/resource.h new file mode 100644 index 000000000000..8a09cc650089 --- /dev/null +++ b/cmd/zed/os/windows/resource.h @@ -0,0 +1,15 @@ +// {{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by resource.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/cmd/zed/os/windows/resource.rc b/cmd/zed/os/windows/resource.rc new file mode 100644 index 000000000000..7d3a6879ae23 --- /dev/null +++ b/cmd/zed/os/windows/resource.rc @@ -0,0 +1,110 @@ +// Microsoft Visual C++ generated resource script. +// +#include +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (India) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENN) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_INDIA +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "400904b0" + BEGIN + VALUE "CompanyName", "TODO: " + VALUE "FileDescription", "zed.exe" + VALUE "FileVersion", "1.0.0.1" + VALUE "LegalCopyright", "Copyright (C) 2021" + VALUE "OriginalFilename", "resource.rc" + VALUE "ProductName", "zed.exe" + VALUE "ProductVersion", "1.0.0.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x4009, 1200 + END +END + +#endif // English (India) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/cmd/zed/os/windows/zed_exec.c b/cmd/zed/os/windows/zed_exec.c new file mode 100644 index 000000000000..0c3d8701041c --- /dev/null +++ b/cmd/zed/os/windows/zed_exec.c @@ -0,0 +1,378 @@ +/* + * This file is part of the ZFS Event Daemon (ZED). + * + * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). + * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. + * Refer to the OpenZFS git commit log for authoritative copyright attribution. + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License Version 1.0 (CDDL-1.0). + * You can obtain a copy of the license from the top-level file + * "OPENSOLARIS.LICENSE" or at . + * You may not use this file except in compliance with the license. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zed_exec.h" +#include "zed_log.h" +#include "zed_strings.h" + +#define ZEVENT_FILENO 3 + +struct launched_process_node { + avl_node_t node; + pid_t pid; + uint64_t eid; + char *name; +}; + +static int +_launched_process_node_compare(const void *x1, const void *x2) +{ + pid_t p1; + pid_t p2; + + assert(x1 != NULL); + assert(x2 != NULL); + + p1 = ((const struct launched_process_node *) x1)->pid; + p2 = ((const struct launched_process_node *) x2)->pid; + + if (p1 < p2) + return (-1); + else if (p1 == p2) + return (0); + else + return (1); +} + +static pthread_t _reap_children_tid = (pthread_t)-1; +static volatile boolean_t _reap_children_stop; +static avl_tree_t _launched_processes; +static pthread_mutex_t _launched_processes_lock = PTHREAD_MUTEX_INITIALIZER; +static int16_t _launched_processes_limit; + +/* + * Create an environment string array for passing to execve() using the + * NAME=VALUE strings in container [zsp]. + * Return a newly-allocated environment, or NULL on error. + */ +static char ** +_zed_exec_create_env(zed_strings_t *zsp) +{ + int num_ptrs; + int buflen; + char *buf; + char **pp; + char *p; + const char *q; + int i; + int len; + + num_ptrs = zed_strings_count(zsp) + 1; + buflen = num_ptrs * sizeof (char *); + for (q = zed_strings_first(zsp); q; q = zed_strings_next(zsp)) + buflen += strlen(q) + 1; + + buf = calloc(1, buflen); + if (!buf) + return (NULL); + + pp = (char **)buf; + p = buf + (num_ptrs * sizeof (char *)); + i = 0; + for (q = zed_strings_first(zsp); q; q = zed_strings_next(zsp)) { + pp[i] = p; + len = strlen(q) + 1; + memcpy(p, q, len); + p += len; + i++; + } + pp[i] = NULL; + assert(buf + buflen == p); + return ((char **)buf); +} + +/* + * Fork a child process to handle event [eid]. The program [prog] + * in directory [dir] is executed with the environment [env]. + * + * The file descriptor [zfd] is the zevent_fd used to track the + * current cursor location within the zevent nvlist. + */ +static void +_zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog, + char *env[], int zfd, boolean_t in_foreground) +{ + char path[PATH_MAX]; + int n; + pid_t pid; + int fd; + struct launched_process_node *node; + sigset_t mask; + struct timespec launch_timeout = + { .tv_sec = 0, .tv_nsec = 200 * 1000 * 1000, }; + + assert(dir != NULL); + assert(prog != NULL); + assert(env != NULL); + assert(zfd >= 0); + + while (__atomic_load_n(&_launched_processes_limit, + __ATOMIC_SEQ_CST) <= 0) + (void) nanosleep(&launch_timeout, NULL); + + n = snprintf(path, sizeof (path), "%s/%s", dir, prog); + if ((n < 0) || (n >= sizeof (path))) { + zed_log_msg(LOG_WARNING, + "Failed to fork \"%s\" for eid=%llu: %s", + prog, eid, strerror(ENAMETOOLONG)); + return; + } + (void) pthread_mutex_lock(&_launched_processes_lock); + pid = fork(); + if (pid < 0) { + (void) pthread_mutex_unlock(&_launched_processes_lock); + zed_log_msg(LOG_WARNING, + "Failed to fork \"%s\" for eid=%llu: %s", + prog, eid, strerror(errno)); + return; + } else if (pid == 0) { + (void) sigemptyset(&mask); + (void) sigprocmask(SIG_SETMASK, &mask, NULL); + + (void) umask(022); + if (in_foreground && /* we're already devnulled if daemonised */ + (fd = open("/dev/null", O_RDWR | O_CLOEXEC)) != -1) { + (void) dup2(fd, STDIN_FILENO); + (void) dup2(fd, STDOUT_FILENO); + (void) dup2(fd, STDERR_FILENO); + } + (void) dup2(zfd, ZEVENT_FILENO); + execle(path, prog, NULL, env); + _exit(127); + } + + /* parent process */ + + node = calloc(1, sizeof (*node)); + if (node) { + node->pid = pid; + node->eid = eid; + node->name = strdup(prog); + if (node->name == NULL) { + perror("strdup"); + exit(EXIT_FAILURE); + } + + avl_add(&_launched_processes, node); + } + (void) pthread_mutex_unlock(&_launched_processes_lock); + + __atomic_sub_fetch(&_launched_processes_limit, 1, __ATOMIC_SEQ_CST); + zed_log_msg(LOG_INFO, "Invoking \"%s\" eid=%llu pid=%d", + prog, eid, pid); +} + +static void +_nop(int sig) +{ + (void) sig; +} + +static void * +_reap_children(void *arg) +{ + (void) arg; +#if 0 + struct launched_process_node node, *pnode; + pid_t pid; + int status; + struct rusage usage; + struct sigaction sa = {}; + + (void) sigfillset(&sa.sa_mask); + (void) sigdelset(&sa.sa_mask, SIGCHLD); + (void) pthread_sigmask(SIG_SETMASK, &sa.sa_mask, NULL); + + (void) sigemptyset(&sa.sa_mask); + sa.sa_handler = _nop; + sa.sa_flags = SA_NOCLDSTOP; + (void) sigaction(SIGCHLD, &sa, NULL); + + for (_reap_children_stop = B_FALSE; !_reap_children_stop; ) { + (void) pthread_mutex_lock(&_launched_processes_lock); + pid = wait4(0, &status, WNOHANG, &usage); + + if (pid == 0 || pid == (pid_t)-1) { + (void) pthread_mutex_unlock(&_launched_processes_lock); + if (pid == 0 || errno == ECHILD) + pause(); + else if (errno != EINTR) + zed_log_msg(LOG_WARNING, + "Failed to wait for children: %s", + strerror(errno)); + } else { + memset(&node, 0, sizeof (node)); + node.pid = pid; + pnode = avl_find(&_launched_processes, &node, NULL); + if (pnode) { + memcpy(&node, pnode, sizeof (node)); + + avl_remove(&_launched_processes, pnode); + free(pnode); + } + (void) pthread_mutex_unlock(&_launched_processes_lock); + __atomic_add_fetch(&_launched_processes_limit, 1, + __ATOMIC_SEQ_CST); + + usage.ru_utime.tv_sec += usage.ru_stime.tv_sec; + usage.ru_utime.tv_usec += usage.ru_stime.tv_usec; + usage.ru_utime.tv_sec += + usage.ru_utime.tv_usec / (1000 * 1000); + usage.ru_utime.tv_usec %= 1000 * 1000; + + if (WIFEXITED(status)) { + zed_log_msg(LOG_INFO, + "Finished \"%s\" eid=%llu pid=%d " + "time=%llu.%06us exit=%d", + node.name, node.eid, pid, + (unsigned long long) usage.ru_utime.tv_sec, + (unsigned int) usage.ru_utime.tv_usec, + WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + zed_log_msg(LOG_INFO, + "Finished \"%s\" eid=%llu pid=%d " + "time=%llu.%06us sig=%d/%s", + node.name, node.eid, pid, + (unsigned long long) usage.ru_utime.tv_sec, + (unsigned int) usage.ru_utime.tv_usec, + WTERMSIG(status), + strsignal(WTERMSIG(status))); + } else { + zed_log_msg(LOG_INFO, + "Finished \"%s\" eid=%llu pid=%d " + "time=%llu.%06us status=0x%X", + node.name, node.eid, pid, + (unsigned long long) usage.ru_utime.tv_sec, + (unsigned int) usage.ru_utime.tv_usec, + (unsigned int) status); + } + + free(node.name); + } + } +#endif + return (NULL); +} + +void +zed_exec_fini(void) +{ + struct launched_process_node *node; + void *ck = NULL; + + if (_reap_children_tid == (pthread_t)-1) + return; + + _reap_children_stop = B_TRUE; + (void) pthread_kill(_reap_children_tid, SIGCHLD); + (void) pthread_join(_reap_children_tid, NULL); + + while ((node = avl_destroy_nodes(&_launched_processes, &ck)) != NULL) { + free(node->name); + free(node); + } + avl_destroy(&_launched_processes); + + (void) pthread_mutex_destroy(&_launched_processes_lock); + (void) pthread_mutex_init(&_launched_processes_lock, NULL); + + _reap_children_tid = (pthread_t)-1; +} + +/* + * Process the event [eid] by synchronously invoking all zedlets with a + * matching class prefix. + * + * Each executable in [zcp->zedlets] from the directory [zcp->zedlet_dir] + * is matched against the event's [class], [subclass], and the "all" class + * (which matches all events). + * Every zedlet with a matching class prefix is invoked. + * The NAME=VALUE strings in [envs] will be passed to the zedlet as + * environment variables. + * + * The file descriptor [zcp->zevent_fd] is the zevent_fd used to track the + * current cursor location within the zevent nvlist. + * + * Return 0 on success, -1 on error. + */ +int +zed_exec_process(uint64_t eid, const char *class, const char *subclass, + struct zed_conf *zcp, zed_strings_t *envs) +{ + const char *class_strings[4]; + const char *allclass = "all"; + const char **csp; + const char *z; + char **e; + int n; + + if (!zcp->zedlet_dir || !zcp->zedlets || !envs || zcp->zevent_fd < 0) + return (-1); + + if (_reap_children_tid == (pthread_t)-1) { + _launched_processes_limit = zcp->max_jobs; + + if (pthread_create(&_reap_children_tid, NULL, + _reap_children, NULL) != 0) + return (-1); + pthread_setname_np(_reap_children_tid, "reap ZEDLETs"); + + avl_create(&_launched_processes, _launched_process_node_compare, + sizeof (struct launched_process_node), + offsetof(struct launched_process_node, node)); + } + + csp = class_strings; + + if (class) + *csp++ = class; + + if (subclass) + *csp++ = subclass; + + if (allclass) + *csp++ = allclass; + + *csp = NULL; + + e = _zed_exec_create_env(envs); + + for (z = zed_strings_first(zcp->zedlets); z; + z = zed_strings_next(zcp->zedlets)) { + for (csp = class_strings; *csp; csp++) { + n = strlen(*csp); + if ((strncmp(z, *csp, n) == 0) && !isalpha(z[n])) + _zed_exec_fork_child(eid, zcp->zedlet_dir, + z, e, zcp->zevent_fd, zcp->do_foreground); + } + } + free(e); + return (0); +} diff --git a/cmd/zed/zed_log.c b/cmd/zed/zed_log.c index 0c4ab6f47db7..47341d72f215 100644 --- a/cmd/zed/zed_log.c +++ b/cmd/zed/zed_log.c @@ -218,9 +218,15 @@ _zed_log_aux(int priority, const char *fmt, va_list vargs) if (_ctx.do_syslog) syslog(priority, "%s", buf); - +#ifdef _WIN32 + if (_ctx.do_stderr && (priority <= _ctx.priority)) { + fprintf(stderr, "%s\r\n", buf); + fflush(stderr); + } +#else if (_ctx.do_stderr && (priority <= _ctx.priority)) fprintf(stderr, "%s\n", buf); +#endif } /* diff --git a/include/os/windows/spl/sys/uio.h b/include/os/windows/spl/sys/uio.h index 5f00902da98a..4172755cb0b0 100644 --- a/include/os/windows/spl/sys/uio.h +++ b/include/os/windows/spl/sys/uio.h @@ -185,7 +185,8 @@ extern int zfs_uio_prefaultpages(ssize_t, zfs_uio_t *); #define zfs_uio_fault_disable(uio, set) #define zfs_uio_fault_move(p, n, rw, u) zfs_uiomove((p), (n), (rw), (u)) -static ssize_t writev(int fd, struct iovec *iov, unsigned iov_cnt); +extern ssize_t readv(int, const struct iovec *, int); +extern ssize_t writev(int fd, struct iovec *iov, unsigned iov_cnt); #ifdef __cplusplus } diff --git a/include/os/windows/zfs/zfs_config.h b/include/os/windows/zfs/zfs_config.h index 43458c522832..9478b0e13c3e 100644 --- a/include/os/windows/zfs/zfs_config.h +++ b/include/os/windows/zfs/zfs_config.h @@ -54,7 +54,7 @@ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mlockall' function. */ -#define HAVE_MLOCKALL 1 +/* #undef HAVE_MLOCKALL 1 */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 @@ -153,3 +153,8 @@ #define ZFS_META_ALIAS ZFS_META_GITREV #define ZFSEXECDIR "C:/Program Files/OpenZFS on Windows" + +#define RUNSTATEDIR ZFSEXECDIR "/zed" +#define _PATH_STDPATH "" +#define SBINDIR ZFSEXECDIR + diff --git a/include/sys/sysevent/dev.h b/include/sys/sysevent/dev.h index 0783d0073162..5700fe180dc1 100644 --- a/include/sys/sysevent/dev.h +++ b/include/sys/sysevent/dev.h @@ -239,7 +239,7 @@ extern "C" { #define DEV_INSTANCE "instance" #define DEV_PROP_PREFIX "prop-" -#ifdef __linux__ +#if defined(__linux__) || defined(_WIN32) #define DEV_IDENTIFIER "devid" #define DEV_PATH "path" #define DEV_IS_PART "is_slice" diff --git a/lib/libspl/include/os/windows/fcntl.h b/lib/libspl/include/os/windows/fcntl.h index b8dee281657f..f17ab4108bcc 100644 --- a/lib/libspl/include/os/windows/fcntl.h +++ b/lib/libspl/include/os/windows/fcntl.h @@ -45,6 +45,29 @@ */ #define AT_FDCWD -100 +/* regular version, for both small and large file compilation environment */ +typedef struct flock { + short l_type; + short l_whence; + unsigned long long l_start; + unsigned long long l_len; /* len == 0 means until end of file */ + int l_sysid; + unsigned int l_pid; + long l_pad[4]; /* reserve area */ +} flock_t; + +/* + * File segment locking types. + */ +#define F_RDLCK 01 /* Read lock */ +#define F_WRLCK 02 /* Write lock */ +#define F_UNLCK 03 /* Remove lock(s) */ +#define F_UNLKSYS 04 /* remove remote locks for a given system */ + +#define F_SETLK 6 /* Set file lock */ +#define F_SETLKW 7 /* Set file lock and wait */ +#define F_GETLK 14 /* Get file lock */ + extern int fcntl(int fildes, int cmd, /* arg */ ...); #endif /* _LIBSPL_SYS_FCNTL_H */ diff --git a/lib/libspl/include/os/windows/inttypes.h b/lib/libspl/include/os/windows/inttypes.h new file mode 100644 index 000000000000..209ee55090b5 --- /dev/null +++ b/lib/libspl/include/os/windows/inttypes.h @@ -0,0 +1,38 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#ifndef _LIBSPL_INTTYPES_H +#define _LIBSPL_INTTYPES_H + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 "lli" +#define PRId32 "i" +#define PRIu64 "llu" +#define PRIx64 "llx" +#define PRIi64 "lli" +#define PRId64 "lli" + +#define strtoimax strtoull + + +#endif /* SPL_INTTYPES_H */ diff --git a/lib/libspl/include/os/windows/paths.h b/lib/libspl/include/os/windows/paths.h new file mode 100644 index 000000000000..286589203255 --- /dev/null +++ b/lib/libspl/include/os/windows/paths.h @@ -0,0 +1,20 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ diff --git a/lib/libspl/include/os/windows/signal.h b/lib/libspl/include/os/windows/signal.h index 8bc15e3dd8c9..234a254307fd 100644 --- a/lib/libspl/include/os/windows/signal.h +++ b/lib/libspl/include/os/windows/signal.h @@ -35,7 +35,9 @@ #define SIGEV_SIGNAL 1 /* Generate a queued signal. */ #define SIGEV_THREAD 2 /* Call back from another pthread. */ +#define SIGHUP 1 #define SIGPIPE 13 +#define SIGCHLD 18 #define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR2 31 /* user defined signal 2 */ @@ -45,8 +47,11 @@ struct proc; // extern int // thread_issignal(struct proc *, thread_t, sigset_t); +#define SA_RESTART 0x00000004 #define SA_SIGINFO 0x00000008 +#define SIG_SETMASK 3 + typedef struct __siginfo { /* Windows version goes here */ void *si_addr; diff --git a/lib/libspl/include/os/windows/sys/uio.h b/lib/libspl/include/os/windows/sys/uio.h index 1d23a05880c7..7d38fc9971e8 100644 --- a/lib/libspl/include/os/windows/sys/uio.h +++ b/lib/libspl/include/os/windows/sys/uio.h @@ -49,4 +49,7 @@ typedef struct iovec iovec_t; #include_next +extern ssize_t readv(int, const struct iovec *, int); +extern ssize_t writev(int fd, struct iovec *iov, unsigned iov_cnt); + #endif /* _WINDOWS_SYS_UIO_H */ diff --git a/lib/libspl/include/os/windows/syslog.h b/lib/libspl/include/os/windows/syslog.h new file mode 100644 index 000000000000..1e230b93a7ab --- /dev/null +++ b/lib/libspl/include/os/windows/syslog.h @@ -0,0 +1,78 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#ifndef _SPL_SYSLOG_H +#define _SPL_SYSLOG_H + +#include + +/* + * Facility codes + */ +#define LOG_KERN (0<<3) /* kernel messages */ +#define LOG_USER (1<<3) /* random user-level messages */ +#define LOG_MAIL (2<<3) /* mail system */ +#define LOG_DAEMON (3<<3) /* system daemons */ +#define LOG_AUTH (4<<3) /* security/authorization messages */ +#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ +#define LOG_LPR (6<<3) /* line printer subsystem */ +#define LOG_NEWS (7<<3) /* netnews subsystem */ +#define LOG_UUCP (8<<3) /* uucp subsystem */ +#define LOG_ALTCRON (9<<3) /* BSD cron/at subsystem */ +#define LOG_AUTHPRIV (10<<3) /* BSD security/authorization messages */ +#define LOG_FTP (11<<3) /* file transfer subsystem */ +#define LOG_NTP (12<<3) /* network time subsystem */ +#define LOG_AUDIT (13<<3) /* audit subsystem */ +#define LOG_CONSOLE (14<<3) /* BSD console messages */ +#define LOG_CRON (15<<3) /* cron/at subsystem */ +#define LOG_LOCAL0 (16<<3) /* reserved for local use */ +#define LOG_LOCAL1 (17<<3) /* reserved for local use */ +#define LOG_LOCAL2 (18<<3) /* reserved for local use */ +#define LOG_LOCAL3 (19<<3) /* reserved for local use */ +#define LOG_LOCAL4 (20<<3) /* reserved for local use */ +#define LOG_LOCAL5 (21<<3) /* reserved for local use */ +#define LOG_LOCAL6 (22<<3) /* reserved for local use */ +#define LOG_LOCAL7 (23<<3) /* reserved for local use */ + +/* + * Priorities (these are ordered) + */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but signification condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ + +#define LOG_PID 0x01 /* log the pid with each message */ +// #define LOG_CONS 0x02 /* log on the console if errors in sending */ +// #define LOG_ODELAY 0x04 /* delay open until syslog() is called */ +#define LOG_NDELAY 0x08 /* don't delay open */ +// #define LOG_NOWAIT 0x10 /* if forking to log on console, don't wait() */ + +void openlog(const char *, int, int); +// void syslog(int, const char *, ...); +// void closelog(void); +// int setlogmask(int); + +#endif diff --git a/lib/libspl/include/os/windows/unistd.h b/lib/libspl/include/os/windows/unistd.h index 4e96d0b5c3ad..6f52c67fca33 100644 --- a/lib/libspl/include/os/windows/unistd.h +++ b/lib/libspl/include/os/windows/unistd.h @@ -48,6 +48,7 @@ extern char *optarg; #include #include +#define _SC_OPEN_MAX 5 #define _SC_PAGESIZE 11 #define _SC_PAGE_SIZE _SC_PAGESIZE #define _SC_NPROCESSORS_ONLN 15 @@ -99,6 +100,8 @@ extern void closelog(void); extern int unmount(const char *dir, int flags); +extern pid_t setsid(void); + static inline pid_t fork(void) { return (0); diff --git a/lib/libspl/include/os/windows/wosix.h b/lib/libspl/include/os/windows/wosix.h index d1d74c0c907f..432996e5dfc6 100644 --- a/lib/libspl/include/os/windows/wosix.h +++ b/lib/libspl/include/os/windows/wosix.h @@ -162,6 +162,8 @@ extern int wosix_access(const char *name, int mode); #define ftruncate wosix_ftruncate #undef socketpair #define socketpair wosix_socketpair +#undef dup2 +#define dup2 wosix_dup2 #undef fdopen #define fdopen wosix_fdopen #undef freopen diff --git a/lib/libspl/os/windows/posix.c b/lib/libspl/os/windows/posix.c index 6c1e25c52ebd..5b6508b3c72a 100644 --- a/lib/libspl/os/windows/posix.c +++ b/lib/libspl/os/windows/posix.c @@ -1011,6 +1011,12 @@ wosix_open(const char *inpath, int oflag, ...) path = otherpath; } + if (strncmp(path, "\\dev\\null", 9) == 0) { + snprintf(otherpath, MAXPATHLEN, "NUL:"); + path = otherpath; + } + + // Try to open verbatim, but if that fail, check if it is the // "#offset#length#name" style, and try again. We let it fail first // just in case someone names their file with a starting '#'. @@ -1232,6 +1238,35 @@ writev(int fd, struct iovec *iov, unsigned iov_cnt) return (ret); } +ssize_t +readv(int fd, const struct iovec *iov, int iov_cnt) +{ + unsigned int i = 0; + ssize_t ret = 0; + while (i < iov_cnt) { + ssize_t r = wosix_read(fd, iov[i].iov_base, iov[i].iov_len); + + if (r > 0) { + ret += r; + } else if (!r) { + break; + } else if (errno == EINTR) { + continue; + } else { + /* + * else it is some "other" error, + * only return if there was no data processed. + */ + if (ret == 0) { + ret = -1; + } + break; + } + +i++; + } + return (ret); +} + #define is_wprefix(s, prefix) \ (wcsncmp((s), (prefix), sizeof (prefix) / sizeof (WCHAR) - 1) == 0) @@ -1663,7 +1698,7 @@ wosix_socketpair(int domain, int type, int protocol, int sv[2]) int wosix_dup2(int fildes, int fildes2) { - return (-1); + return (0); } void * @@ -2041,3 +2076,8 @@ getgrnam_r(const char *name, struct group *grp, *result = NULL; return (0); } + +extern pid_t setsid(void) +{ + return (0); +}