rktio: most of switch to rktio fd
Doesn't work, yet...
This commit is contained in:
parent
63505d3e16
commit
2b439fc554
|
@ -2141,34 +2141,11 @@ extern Scheme_Extension_Table *scheme_extension_table;
|
|||
/* file descriptors */
|
||||
/*========================================================================*/
|
||||
|
||||
#if defined(DETECT_WIN32_CONSOLE_STDIN) || defined(WINDOWS_PROCESSES)
|
||||
# ifndef NO_STDIO_THREADS
|
||||
# define USE_FAR_MZ_FDCALLS
|
||||
# endif
|
||||
#endif
|
||||
#ifdef USE_DYNAMIC_FDSET_SIZE
|
||||
# define USE_FAR_MZ_FDCALLS
|
||||
#endif
|
||||
#ifdef USE_BEOS_PORT_THREADS
|
||||
# define USE_FAR_MZ_FDCALLS
|
||||
#endif
|
||||
#ifdef HAVE_POLL_SYSCALL
|
||||
# define USE_FAR_MZ_FDCALLS
|
||||
#endif
|
||||
|
||||
#ifdef USE_FAR_MZ_FDCALLS
|
||||
# define MZ_GET_FDSET(p, n) scheme_get_fdset(p, n)
|
||||
# define MZ_FD_ZERO(p) scheme_fdzero(p)
|
||||
# define MZ_FD_SET(n, p) scheme_fdset(p, n)
|
||||
# define MZ_FD_CLR(n, p) scheme_fdclr(p, n)
|
||||
# define MZ_FD_ISSET(n, p) scheme_fdisset(p, n)
|
||||
#else
|
||||
# define MZ_GET_FDSET(p, n) ((void *)(((fd_set *)p) XFORM_OK_PLUS n))
|
||||
# define MZ_FD_ZERO(p) XFORM_HIDE_EXPR(FD_ZERO((fd_set *)(p)))
|
||||
# define MZ_FD_SET(n, p) FD_SET(n, (fd_set *)(p))
|
||||
# define MZ_FD_CLR(n, p) FD_CLR(n, (fd_set *)(p))
|
||||
# define MZ_FD_ISSET(n, p) FD_ISSET(n, (fd_set *)(p))
|
||||
#endif
|
||||
|
||||
/* For scheme_fd_to_semaphore(): */
|
||||
#define MZFD_CREATE_READ 1
|
||||
|
@ -2176,9 +2153,6 @@ extern Scheme_Extension_Table *scheme_extension_table;
|
|||
#define MZFD_CHECK_READ 3
|
||||
#define MZFD_CHECK_WRITE 4
|
||||
#define MZFD_REMOVE 5
|
||||
#define MZFD_CREATE_VNODE 6
|
||||
#define MZFD_CHECK_VNODE 7
|
||||
#define MZFD_REMOVE_VNODE 8
|
||||
|
||||
/*========================================================================*/
|
||||
|
||||
|
|
|
@ -194,21 +194,11 @@ typedef struct Thread_Local_Variables {
|
|||
struct Scheme_Object *scheme_orig_stdout_port_;
|
||||
struct Scheme_Object *scheme_orig_stderr_port_;
|
||||
struct Scheme_Object *scheme_orig_stdin_port_;
|
||||
struct mz_fd_set *scheme_fd_set_;
|
||||
struct mz_fd_set *scheme_semaphore_fd_set_;
|
||||
struct Scheme_Hash_Table *scheme_semaphore_fd_mapping_;
|
||||
int scheme_semaphore_fd_kqueue_;
|
||||
struct rktio_ltps_t *scheme_semaphore_fd_set_;
|
||||
#ifdef USE_FCNTL_AND_FORK_FOR_FILE_LOCKS
|
||||
struct Scheme_Hash_Table *locked_fd_process_map_;
|
||||
#endif
|
||||
struct Scheme_Custodian *new_port_cust_;
|
||||
#if (defined(__WIN32__) || defined(WIN32) || defined(_WIN32))
|
||||
void *scheme_break_semaphore_;
|
||||
void *process_job_object_;
|
||||
#else
|
||||
int external_event_fd_;
|
||||
int put_external_event_fd_;
|
||||
#endif
|
||||
char *read_string_byte_buffer_;
|
||||
struct ITimer_Data *itimerdata_;
|
||||
char *quick_buffer_;
|
||||
|
@ -380,7 +370,6 @@ typedef struct Thread_Local_Variables {
|
|||
void *on_atomic_timeout_data_;
|
||||
int atomic_timeout_auto_suspend_;
|
||||
int atomic_timeout_atomic_level_;
|
||||
void *scheme_inotify_server_;
|
||||
struct Scheme_Object *configuration_callback_cache_[2];
|
||||
struct FFI_Orig_Place_Call *cached_orig_place_todo_;
|
||||
struct Scheme_Hash_Table *ffi_lock_ht_;
|
||||
|
@ -602,16 +591,9 @@ XFORM_GC_VARIABLE_STACK_THROUGH_THREAD_LOCAL;
|
|||
#define scheme_orig_stdout_port XOA (scheme_get_thread_local_variables()->scheme_orig_stdout_port_)
|
||||
#define scheme_orig_stderr_port XOA (scheme_get_thread_local_variables()->scheme_orig_stderr_port_)
|
||||
#define scheme_orig_stdin_port XOA (scheme_get_thread_local_variables()->scheme_orig_stdin_port_)
|
||||
#define scheme_fd_set XOA (scheme_get_thread_local_variables()->scheme_fd_set_)
|
||||
#define scheme_semaphore_fd_set XOA (scheme_get_thread_local_variables()->scheme_semaphore_fd_set_)
|
||||
#define scheme_semaphore_fd_mapping XOA (scheme_get_thread_local_variables()->scheme_semaphore_fd_mapping_)
|
||||
#define scheme_semaphore_fd_kqueue XOA (scheme_get_thread_local_variables()->scheme_semaphore_fd_kqueue_)
|
||||
#define locked_fd_process_map XOA (scheme_get_thread_local_variables()->locked_fd_process_map_)
|
||||
#define new_port_cust XOA (scheme_get_thread_local_variables()->new_port_cust_)
|
||||
#define scheme_break_semaphore XOA (scheme_get_thread_local_variables()->scheme_break_semaphore_)
|
||||
#define process_job_object XOA (scheme_get_thread_local_variables()->process_job_object_)
|
||||
#define external_event_fd XOA (scheme_get_thread_local_variables()->external_event_fd_)
|
||||
#define put_external_event_fd XOA (scheme_get_thread_local_variables()->put_external_event_fd_)
|
||||
#define read_string_byte_buffer XOA (scheme_get_thread_local_variables()->read_string_byte_buffer_)
|
||||
#define itimerdata XOA (scheme_get_thread_local_variables()->itimerdata_)
|
||||
#define quick_buffer XOA (scheme_get_thread_local_variables()->quick_buffer_)
|
||||
|
@ -784,7 +766,6 @@ XFORM_GC_VARIABLE_STACK_THROUGH_THREAD_LOCAL;
|
|||
#define on_atomic_timeout_data XOA (scheme_get_thread_local_variables()->on_atomic_timeout_data_)
|
||||
#define atomic_timeout_auto_suspend XOA (scheme_get_thread_local_variables()->atomic_timeout_auto_suspend_)
|
||||
#define atomic_timeout_atomic_level XOA (scheme_get_thread_local_variables()->atomic_timeout_atomic_level_)
|
||||
#define scheme_inotify_server XOA (scheme_get_thread_local_variables()->scheme_inotify_server_)
|
||||
#define configuration_callback_cache XOA (scheme_get_thread_local_variables()->configuration_callback_cache_)
|
||||
#define cached_orig_place_todo XOA (scheme_get_thread_local_variables()->cached_orig_place_todo_)
|
||||
#define ffi_lock_ht XOA (scheme_get_thread_local_variables()->ffi_lock_ht_)
|
||||
|
|
|
@ -398,7 +398,7 @@ optimize.@LTO@: $(COMMON_HEADERS) \
|
|||
$(srcdir)/stypes.h $(srcdir)/mzmark_optimize.inc
|
||||
place.@LTO@: $(COMMON_HEADERS) \
|
||||
$(srcdir)/stypes.h $(srcdir)/schfd.h $(srcdir)/mzmark_place.inc
|
||||
port.@LTO@: $(COMMON_HEADERS) \
|
||||
port.@LTO@: $(COMMON_HEADERS) $(RKTIO_HEADERS) \
|
||||
$(srcdir)/stypes.h $(srcdir)/schfd.h $(srcdir)/mzmark_port.inc \
|
||||
$(srcdir)/inotify.inc
|
||||
portfun.@LTO@: $(COMMON_HEADERS) $(srcdir)/schvers.h \
|
||||
|
|
|
@ -554,7 +554,7 @@ static Scheme_Env *place_instance_init(void *stack_base, int initial_main_os_thr
|
|||
scheme_init_regexp_places();
|
||||
scheme_init_sema_places();
|
||||
scheme_init_gmp_places();
|
||||
scheme_init_kqueue();
|
||||
scheme_init_fd_semaphores();
|
||||
scheme_alloc_global_fdset();
|
||||
#ifndef DONT_USE_FOREIGN
|
||||
scheme_init_foreign_places();
|
||||
|
@ -629,8 +629,10 @@ Scheme_Env *scheme_place_instance_init(void *stack_base, struct NewGC *parent_gc
|
|||
scheme_rktio = rktio_init();
|
||||
env = place_instance_init(stack_base, 0);
|
||||
# if defined(MZ_PRECISE_GC)
|
||||
if (scheme_rktio) {
|
||||
signal_fd = scheme_get_signal_handle();
|
||||
GC_set_put_external_event_fd(signal_fd);
|
||||
}
|
||||
# endif
|
||||
scheme_set_can_break(1);
|
||||
return env;
|
||||
|
@ -665,6 +667,8 @@ void scheme_place_instance_destroy(int force)
|
|||
scheme_release_process_job_object();
|
||||
#endif
|
||||
|
||||
scheme_release_fd_semaphores();
|
||||
|
||||
scheme_release_file_descriptor();
|
||||
|
||||
scheme_end_futures_per_place();
|
||||
|
@ -677,8 +681,8 @@ void scheme_place_instance_destroy(int force)
|
|||
#endif
|
||||
scheme_free_all_code();
|
||||
scheme_free_ghbn_data();
|
||||
scheme_release_kqueue();
|
||||
scheme_release_inotify();
|
||||
scheme_free_global_fdset();
|
||||
rktio_destroy(scheme_rktio);
|
||||
}
|
||||
|
||||
static void make_kernel_env(void)
|
||||
|
|
|
@ -1,267 +0,0 @@
|
|||
/* #included by "port.c" */
|
||||
|
||||
/* Multiplex multiple filesystem change events onto a single
|
||||
inotify connection. That's almost as easy as using watch
|
||||
descriptors in place of file descriptors, but using the
|
||||
same filesystem path multiple times produces the same
|
||||
watch descriptors, so reference-count it. Also, each watch
|
||||
can be removed as soon as it fires, since filesystem
|
||||
change events are single-shot.
|
||||
|
||||
The values returned by mz_inotify_add() are indices into an array
|
||||
of watch descriptors. There's room for a better data structure if
|
||||
the watch-descriptor-to-index mapping becomes too slow. */
|
||||
|
||||
#ifdef MZ_XFORM
|
||||
START_XFORM_SUSPEND;
|
||||
#endif
|
||||
|
||||
typedef struct mz_wd_t {
|
||||
int wd;
|
||||
int refcount;
|
||||
int val;
|
||||
} mz_wd_t;
|
||||
|
||||
typedef struct mz_inotify_state_t {
|
||||
int ready, errid, fd;
|
||||
mz_wd_t *wds;
|
||||
int size, count;
|
||||
int got;
|
||||
} mz_inotify_state_t;
|
||||
|
||||
static int mzi_find_wd(int wd, mz_wd_t *wds, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (wds[i].wd == wd) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mzi_add_wd(int wd, mz_wd_t *wds, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (wds[i].wd == wd) {
|
||||
wds[i].refcount++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (!wds[i].refcount) {
|
||||
wds[i].wd = wd;
|
||||
wds[i].refcount = 1;
|
||||
wds[i].val = 0;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
abort();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mzi_pull_events(int fd, mz_wd_t *wds, int size)
|
||||
{
|
||||
struct inotify_event _ev, *ev;
|
||||
void *b = NULL;
|
||||
int rc, p, got = 0;
|
||||
int bsize;
|
||||
struct pollfd pfd[1];
|
||||
|
||||
ev = &_ev;
|
||||
bsize = sizeof(_ev);
|
||||
|
||||
pfd[0].fd = fd;
|
||||
pfd[0].events = POLLIN;
|
||||
|
||||
while (poll(pfd, 1, 0)) {
|
||||
rc = read(fd, ev, bsize);
|
||||
if (rc > 0) {
|
||||
p = mzi_find_wd(ev->wd, wds, size);
|
||||
if (p != -1) {
|
||||
got = 1;
|
||||
wds[p].val = 1;
|
||||
wds[p].wd = -1;
|
||||
inotify_rm_watch(fd, ev->wd);
|
||||
}
|
||||
} else if (rc == -1) {
|
||||
if (errno == EAGAIN)
|
||||
break;
|
||||
else if (errno == EINTR) {
|
||||
/* try again */
|
||||
} else if (errno == EINVAL) {
|
||||
bsize *= 2;
|
||||
if (b) free(b);
|
||||
b = malloc(bsize);
|
||||
ev = (struct inotify_event *)b;
|
||||
} else
|
||||
scheme_signal_error("inotify read failed on %d (%e)", fd, errno);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
if (b)
|
||||
free (b);
|
||||
|
||||
return got;
|
||||
}
|
||||
|
||||
static void mz_inotify_start(mz_inotify_state_t *s)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = inotify_init();
|
||||
if (fd == -1) {
|
||||
s->errid = errno;
|
||||
} else {
|
||||
s->errid = 0;
|
||||
s->ready = 1;
|
||||
s->fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
static void mz_inotify_end(mz_inotify_state_t *s)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (s->ready) {
|
||||
do {
|
||||
rc = close(s->fd);
|
||||
} while (rc == -1 && errno == EINTR);
|
||||
}
|
||||
|
||||
if (s->wds) free(s->wds);
|
||||
|
||||
free(s);
|
||||
}
|
||||
|
||||
static void mz_inotify_init()
|
||||
{
|
||||
mz_inotify_state_t *s = scheme_inotify_server;
|
||||
|
||||
if (!s) {
|
||||
s = (mz_inotify_state_t *)malloc(sizeof(mz_inotify_state_t));
|
||||
memset(s, 0, sizeof(mz_inotify_state_t));
|
||||
|
||||
scheme_inotify_server = s;
|
||||
}
|
||||
|
||||
if (!s->ready)
|
||||
mz_inotify_start(s);
|
||||
}
|
||||
|
||||
static int mz_inotify_ready()
|
||||
{
|
||||
mz_inotify_state_t *s = (mz_inotify_state_t *)scheme_inotify_server;
|
||||
|
||||
return s->ready;
|
||||
}
|
||||
|
||||
static int mz_inotify_errid()
|
||||
{
|
||||
mz_inotify_state_t *s = (mz_inotify_state_t *)scheme_inotify_server;
|
||||
|
||||
return s->errid;
|
||||
}
|
||||
|
||||
/* Other functions are called only if mz_inotify_ready() returns 1. */
|
||||
|
||||
static int mz_inotify_add(char *filename)
|
||||
{
|
||||
mz_inotify_state_t *s = (mz_inotify_state_t *)scheme_inotify_server;
|
||||
int wd;
|
||||
|
||||
if (s->count == s->size) {
|
||||
int new_size = (s->size ? (2 * s->size) : 32);
|
||||
mz_wd_t *new_wds;
|
||||
int i;
|
||||
new_wds = (mz_wd_t *)malloc(sizeof(mz_wd_t) * new_size);
|
||||
memcpy(new_wds, s->wds, s->size * sizeof(mz_wd_t));
|
||||
if (s->wds) free(s->wds);
|
||||
s->wds = new_wds;
|
||||
s->size = new_size;
|
||||
for (i = s->count; i < s->size; i++)
|
||||
{
|
||||
s->wds[i].wd = -1;
|
||||
s->wds[i].refcount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
wd = inotify_add_watch(s->fd, filename,
|
||||
(IN_CREATE | IN_DELETE | IN_DELETE_SELF
|
||||
| IN_MODIFY | IN_MOVE_SELF | IN_MOVED_TO
|
||||
| IN_ATTRIB | IN_ONESHOT));
|
||||
|
||||
if (wd == -1)
|
||||
return -1;
|
||||
else {
|
||||
int p;
|
||||
|
||||
p = mzi_add_wd(wd, s->wds, s->size);
|
||||
if (s->wds[p].refcount == 1)
|
||||
s->count++;
|
||||
|
||||
return p+1;
|
||||
}
|
||||
}
|
||||
|
||||
static void mz_inotify_remove(int p2)
|
||||
{
|
||||
mz_inotify_state_t *s = (mz_inotify_state_t *)scheme_inotify_server;
|
||||
int p = p2 - 1;
|
||||
|
||||
if (s->wds[p].refcount == 1) {
|
||||
if (s->wds[p].wd != -1) {
|
||||
inotify_rm_watch(s->fd, s->wds[p].wd);
|
||||
s->wds[p].wd = -1;
|
||||
/* in case the wd gets reused: */
|
||||
if (mzi_pull_events(s->fd, s->wds, s->size))
|
||||
s->got = 1;
|
||||
}
|
||||
--s->count;
|
||||
}
|
||||
s->wds[p].refcount -= 1;
|
||||
}
|
||||
|
||||
static int mz_inotify_poll(int p2)
|
||||
{
|
||||
mz_inotify_state_t *s = (mz_inotify_state_t *)scheme_inotify_server;
|
||||
int p = p2 - 1;
|
||||
|
||||
if (mzi_pull_events(s->fd, s->wds, s->size))
|
||||
s->got = 1;
|
||||
if (s->wds[p].val)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mz_inotify_stop()
|
||||
{
|
||||
mz_inotify_state_t *s = (mz_inotify_state_t *)scheme_inotify_server;
|
||||
|
||||
if (s) {
|
||||
mz_inotify_end(s);
|
||||
scheme_inotify_server = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int mz_inotify_fd()
|
||||
{
|
||||
mz_inotify_state_t *s = (mz_inotify_state_t *)scheme_inotify_server;
|
||||
|
||||
if (s->got) {
|
||||
/* In case we received something for Y in a poll for X */
|
||||
s->got = 0;
|
||||
return -2;
|
||||
}
|
||||
|
||||
return s->fd;
|
||||
}
|
||||
|
||||
#ifdef MZ_XFORM
|
||||
END_XFORM_SUSPEND;
|
||||
#endif
|
|
@ -100,6 +100,7 @@ static int mark_input_fd_MARK(void *p, struct NewGC *gc) {
|
|||
gcMARK2(fd->buffer, gc);
|
||||
gcMARK2(fd->refcount, gc);
|
||||
gcMARK2(fd->flush_handle, gc);
|
||||
gcMARK2(fd->widths, gc);
|
||||
|
||||
# ifdef GC_NO_SIZE_NEEDED_FROM_PROCS
|
||||
return 0;
|
||||
|
@ -117,6 +118,7 @@ static int mark_input_fd_FIXUP(void *p, struct NewGC *gc) {
|
|||
gcFIXUP2(fd->buffer, gc);
|
||||
gcFIXUP2(fd->refcount, gc);
|
||||
gcFIXUP2(fd->flush_handle, gc);
|
||||
gcFIXUP2(fd->widths, gc);
|
||||
|
||||
# ifdef GC_NO_SIZE_NEEDED_FROM_PROCS
|
||||
return 0;
|
||||
|
|
|
@ -1739,6 +1739,7 @@ mark_input_fd {
|
|||
gcMARK2(fd->buffer, gc);
|
||||
gcMARK2(fd->refcount, gc);
|
||||
gcMARK2(fd->flush_handle, gc);
|
||||
gcMARK2(fd->widths, gc);
|
||||
|
||||
size:
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_FD));
|
||||
|
@ -1794,7 +1795,6 @@ mark_read_write_evt {
|
|||
mark_filesystem_change_evt {
|
||||
mark:
|
||||
Scheme_Filesystem_Change_Evt *fc = (Scheme_Filesystem_Change_Evt *)p;
|
||||
gcMARK2(fc->sema, gc);
|
||||
gcMARK2(fc->mref, gc);
|
||||
size:
|
||||
gcBYTES_TO_WORDS(sizeof(Scheme_Filesystem_Change_Evt));
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1055,7 +1055,7 @@ void scheme_wait_resume()
|
|||
{
|
||||
mzrt_mutex_unlock(child_wait_lock);
|
||||
}
|
||||
|
||||
b
|
||||
void scheme_starting_child()
|
||||
{
|
||||
mzrt_mutex_lock(child_wait_lock);
|
||||
|
@ -2785,7 +2785,8 @@ static void *place_start_proc_after_stack(void *data_arg, void *stack_base) {
|
|||
if (!scheme_setjmp(new_error_buf)) {
|
||||
Scheme_Object *dynamic_require;
|
||||
|
||||
scheme_check_place_port_ok();
|
||||
if (!scheme_rktio)
|
||||
scheme_signal_error("place: I/O manager initialization failed");
|
||||
|
||||
dynamic_require = scheme_builtin_value("dynamic-require");
|
||||
place_main = scheme_apply(dynamic_require, 2, a);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2556,7 +2556,7 @@ make_output_port (int argc, Scheme_Object *argv[])
|
|||
static Scheme_Object *
|
||||
open_input_file (int argc, Scheme_Object *argv[])
|
||||
{
|
||||
return scheme_do_open_input_file("open-input-file", 0, argc, argv, 0, NULL, NULL, 0);
|
||||
return scheme_do_open_input_file("open-input-file", 0, argc, argv, 0, 0);
|
||||
}
|
||||
|
||||
static Scheme_Object *
|
||||
|
@ -2602,13 +2602,13 @@ open_input_char_string (int argc, Scheme_Object *argv[])
|
|||
static Scheme_Object *
|
||||
open_output_file (int argc, Scheme_Object *argv[])
|
||||
{
|
||||
return scheme_do_open_output_file("open-output-file", 0, argc, argv, 0, 0, NULL, NULL);
|
||||
return scheme_do_open_output_file("open-output-file", 0, argc, argv, 0, 0);
|
||||
}
|
||||
|
||||
static Scheme_Object *
|
||||
open_input_output_file (int argc, Scheme_Object *argv[])
|
||||
{
|
||||
return scheme_do_open_output_file("open-input-output-file", 0, argc, argv, 1, 0, NULL, NULL);
|
||||
return scheme_do_open_output_file("open-input-output-file", 0, argc, argv, 1, 0);
|
||||
}
|
||||
|
||||
static Scheme_Object *
|
||||
|
@ -2745,7 +2745,7 @@ call_with_output_file (int argc, Scheme_Object *argv[])
|
|||
|
||||
scheme_check_proc_arity("call-with-output-file", 1, 1, argc, argv);
|
||||
|
||||
port = scheme_do_open_output_file("call-with-output-file", 1, argc, argv, 0, 0, NULL, NULL);
|
||||
port = scheme_do_open_output_file("call-with-output-file", 1, argc, argv, 0, 0);
|
||||
|
||||
v = _scheme_apply_multi(argv[1], 1, &port);
|
||||
|
||||
|
@ -2770,7 +2770,7 @@ call_with_input_file(int argc, Scheme_Object *argv[])
|
|||
|
||||
scheme_check_proc_arity("call-with-input-file", 1, 1, argc, argv);
|
||||
|
||||
port = scheme_do_open_input_file("call-with-input-file", 1, argc, argv, 0, NULL, NULL, 0);
|
||||
port = scheme_do_open_input_file("call-with-input-file", 1, argc, argv, 0, 0);
|
||||
|
||||
v = _scheme_apply_multi(argv[1], 1, &port);
|
||||
|
||||
|
@ -2807,7 +2807,7 @@ with_output_to_file (int argc, Scheme_Object *argv[])
|
|||
|
||||
scheme_check_proc_arity("with-output-to-file", 0, 1, argc, argv);
|
||||
|
||||
port = scheme_do_open_output_file("with-output-to-file", 1, argc, argv, 0, 0, NULL, NULL);
|
||||
port = scheme_do_open_output_file("with-output-to-file", 1, argc, argv, 0, 0);
|
||||
|
||||
config = scheme_extend_config(scheme_current_config(),
|
||||
MZCONFIG_OUTPUT_PORT,
|
||||
|
@ -2841,7 +2841,7 @@ with_input_from_file(int argc, Scheme_Object *argv[])
|
|||
|
||||
scheme_check_proc_arity("with-input-from-file", 0, 1, argc, argv);
|
||||
|
||||
port = scheme_do_open_input_file("with-input-from-file", 1, argc, argv, 0, NULL, NULL, 0);
|
||||
port = scheme_do_open_input_file("with-input-from-file", 1, argc, argv, 0, 0);
|
||||
|
||||
config = scheme_extend_config(scheme_current_config(),
|
||||
MZCONFIG_INPUT_PORT,
|
||||
|
@ -4899,7 +4899,7 @@ static Scheme_Object *default_load(int argc, Scheme_Object *argv[])
|
|||
"(or/c #f symbol? (cons/c (or/c #f symbol?) (non-empty-listof symbol?)))",
|
||||
1, argc, argv);
|
||||
|
||||
port = scheme_do_open_input_file("default-load-handler", 0, 1, argv, 0, NULL, NULL, SCHEME_TRUEP(expected_module));
|
||||
port = scheme_do_open_input_file("default-load-handler", 0, 1, argv, 0, SCHEME_TRUEP(expected_module));
|
||||
|
||||
/* Turn on line/column counting, unless it's a .zo file: */
|
||||
if (SCHEME_PATHP(argv[0])) {
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
|
||||
#ifdef USE_FAR_MZ_FDCALLS
|
||||
THREAD_LOCAL_DECL(extern struct mz_fd_set *scheme_fd_set);
|
||||
# ifdef HAVE_POLL_SYSCALL
|
||||
struct mz_fd_set {
|
||||
struct mz_fd_set_data *data;
|
||||
struct mz_fd_set *w;
|
||||
struct mz_fd_set *e;
|
||||
Scheme_Object *flags;
|
||||
};
|
||||
struct mz_fd_set_data {
|
||||
struct pollfd *pfd;
|
||||
Scheme_Object *size, *count;
|
||||
};
|
||||
# else
|
||||
struct mz_fd_set { fd_set data; };
|
||||
# endif
|
||||
#define DECL_FDSET(n, c) fd_set *n
|
||||
#define INIT_DECL_FDSET(r, w, e) { \
|
||||
r = MZ_GET_FDSET(&scheme_fd_set->data, 0 ); \
|
||||
w = MZ_GET_FDSET(&scheme_fd_set->data, 1 ); \
|
||||
e = MZ_GET_FDSET(&scheme_fd_set->data, 2 ); \
|
||||
}
|
||||
# define INIT_DECL_RD_FDSET(r) r = MZ_GET_FDSET(&scheme_fd_set->data, 0 )
|
||||
# define INIT_DECL_WR_FDSET(r) r = MZ_GET_FDSET(&scheme_fd_set->data, 1 )
|
||||
# define INIT_DECL_ER_FDSET(r) r = MZ_GET_FDSET(&scheme_fd_set->data, 2 )
|
||||
#else
|
||||
# define DECL_FDSET(n, c) fd_set n[c]
|
||||
# define INIT_DECL_FDSET(r, w, e) /* empty */
|
||||
# define INIT_DECL_RD_FDSET(r) /* empty */
|
||||
# define INIT_DECL_WR_FDSET(r) /* empty */
|
||||
# define INIT_DECL_ER_FDSET(r) /* empty */
|
||||
#endif
|
||||
|
||||
void *scheme_merge_fd_sets(void *fds, void *src_fds);
|
||||
void scheme_clean_fd_set(void *fds);
|
||||
int scheme_get_fd_limit(void *fds);
|
|
@ -436,6 +436,7 @@ void scheme_register_network_evts();
|
|||
void scheme_free_dynamic_extensions(void);
|
||||
void scheme_free_all_code(void);
|
||||
void scheme_free_ghbn_data(void);
|
||||
void scheme_free_global_fdset(void);
|
||||
|
||||
XFORM_NONGCING int scheme_is_multithreaded(int now);
|
||||
|
||||
|
@ -4351,7 +4352,7 @@ void scheme_flush_if_output_fds(Scheme_Object *o);
|
|||
Scheme_Object *scheme_file_stream_port_p(int, Scheme_Object *[]);
|
||||
Scheme_Object *scheme_terminal_port_p(int, Scheme_Object *[]);
|
||||
Scheme_Object *scheme_do_open_input_file(char *name, int offset, int argc, Scheme_Object *argv[],
|
||||
int internal, char **err, int *eerrno, int for_module);
|
||||
int internal, int for_module);
|
||||
Scheme_Object *scheme_do_open_output_file(char *name, int offset, int argc, Scheme_Object *argv[], int and_read,
|
||||
int internal, char **err, int *eerrno);
|
||||
Scheme_Object *scheme_file_position(int argc, Scheme_Object *argv[]);
|
||||
|
@ -4365,9 +4366,7 @@ Scheme_Object *scheme_file_unlock(int argc, Scheme_Object **argv);
|
|||
void scheme_reserve_file_descriptor(void);
|
||||
void scheme_release_file_descriptor(void);
|
||||
|
||||
void scheme_init_kqueue(void);
|
||||
void scheme_release_kqueue(void);
|
||||
void scheme_release_inotify(void);
|
||||
int scheme_get_port_rktio_file_descriptor(Scheme_Object *p, struct rktio_fd_t *_fd);
|
||||
|
||||
void scheme_fs_change_properties(int *_supported, int *_scalable, int *_low_latency, int *_file_level);
|
||||
|
||||
|
@ -4428,8 +4427,13 @@ intptr_t scheme_redirect_get_or_peek_bytes(Scheme_Input_Port *orig_port,
|
|||
Scheme_Object *scheme_filesystem_change_evt(Scheme_Object *path, int flags, int report_errs);
|
||||
void scheme_filesystem_change_evt_cancel(Scheme_Object *evt, void *ignored_data);
|
||||
|
||||
int scheme_fd_regular_file(intptr_t fd, int dir_ok);
|
||||
void scheme_init_fd_semaphores(void);
|
||||
void scheme_release_fd_semaphores(void);
|
||||
|
||||
void scheme_check_fd_semaphores(void);
|
||||
Scheme_Object *scheme_rktio_fd_to_semaphore(struct rktio_fd_t *fd, int mode);
|
||||
|
||||
rktio_envvars_t *scheme_environment_variables_to_envvars(Scheme_Object *ev);
|
||||
|
||||
/*========================================================================*/
|
||||
/* memory debugging */
|
||||
|
@ -4743,7 +4747,6 @@ Scheme_Object *scheme_make_place_object();
|
|||
void scheme_place_instance_destroy(int force);
|
||||
void scheme_kill_green_thread_timer();
|
||||
void scheme_place_check_for_interruption();
|
||||
void scheme_check_place_port_ok();
|
||||
void scheme_place_set_memory_use(intptr_t amt);
|
||||
void scheme_place_check_memory_use();
|
||||
void scheme_clear_place_ifs_stack();
|
||||
|
|
|
@ -2485,35 +2485,15 @@ static Scheme_Object *sch_getenv_names(int argc, Scheme_Object *argv[])
|
|||
return r;
|
||||
}
|
||||
|
||||
/* Temporarily use internal function: */
|
||||
extern void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars);
|
||||
|
||||
/* This will go away when we use rktio processes: */
|
||||
void *scheme_environment_variables_to_block(Scheme_Object *ev, int *_need_free)
|
||||
rktio_envvars_t *scheme_environment_variables_to_envvars(Scheme_Object *ev)
|
||||
{
|
||||
|
||||
Scheme_Hash_Tree *ht;
|
||||
Scheme_Object *key, *val;
|
||||
void *p;
|
||||
|
||||
*_need_free = 1;
|
||||
|
||||
ht = SCHEME_ENVVARS_TABLE(ev);
|
||||
if (!ht) {
|
||||
rktio_envvars_t *envvars;
|
||||
envvars = rktio_envvars(scheme_rktio);
|
||||
|
||||
p = rktio_envvars_to_block(scheme_rktio, envvars);
|
||||
|
||||
rktio_envvars_free(scheme_rktio, envvars);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
{
|
||||
Scheme_Hash_Tree *ht = SCHEME_ENVVARS_TABLE(ev);
|
||||
rktio_envvars_t *envvars;
|
||||
mzlonglong i;
|
||||
|
||||
if (!ht)
|
||||
return NULL;
|
||||
|
||||
envvars = rktio_empty_envvars(scheme_rktio);
|
||||
|
||||
for (i = scheme_hash_tree_next(ht, -1); i != -1; i = scheme_hash_tree_next(ht, i)) {
|
||||
|
@ -2525,12 +2505,7 @@ void *scheme_environment_variables_to_block(Scheme_Object *ev, int *_need_free)
|
|||
SCHEME_BYTE_STR_VAL(val));
|
||||
}
|
||||
|
||||
p = rktio_envvars_to_block(scheme_rktio, envvars);
|
||||
|
||||
rktio_envvars_free(scheme_rktio, envvars);
|
||||
|
||||
return p;
|
||||
}
|
||||
return envvars;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
|
|
@ -41,42 +41,10 @@
|
|||
#include "schpriv.h"
|
||||
#include "schmach.h"
|
||||
#include "schgc.h"
|
||||
#include "schrktio.h"
|
||||
#ifdef MZ_USE_FUTURES
|
||||
# include "future.h"
|
||||
#endif
|
||||
#ifndef PALMOS_STUFF
|
||||
# include <time.h>
|
||||
#endif
|
||||
#ifdef FILES_HAVE_FDS
|
||||
# include <sys/types.h>
|
||||
# include <sys/time.h>
|
||||
# ifdef SELECT_INCLUDE
|
||||
# include <sys/select.h>
|
||||
# endif
|
||||
# ifdef USE_BEOS_SOCKET_INCLUDE
|
||||
# include <be/net/socket.h>
|
||||
# endif
|
||||
# ifdef HAVE_POLL_SYSCALL
|
||||
# include <poll.h>
|
||||
# endif
|
||||
# ifdef HAVE_EPOLL_SYSCALL
|
||||
# include <sys/epoll.h>
|
||||
# endif
|
||||
# ifdef HAVE_KQUEUE_SYSCALL
|
||||
# include <sys/types.h>
|
||||
# include <sys/event.h>
|
||||
# include <sys/time.h>
|
||||
# endif
|
||||
# include <errno.h>
|
||||
#endif
|
||||
#ifdef USE_WINSOCK_TCP
|
||||
# ifdef USE_TCP
|
||||
# include <winsock.h>
|
||||
# endif
|
||||
#endif
|
||||
#ifdef USE_BEOS_PORT_THREADS
|
||||
# include <be/net/socket.h>
|
||||
#endif
|
||||
#ifdef USE_STACKAVAIL
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
@ -88,11 +56,6 @@
|
|||
# define SIGMZTHREAD SIGUSR2
|
||||
#endif
|
||||
|
||||
#if defined(WINDOWS_PROCESSES) || defined(WINDOWS_FILE_HANDLES)
|
||||
# include <windows.h>
|
||||
THREAD_LOCAL_DECL(extern void *scheme_break_semaphore;)
|
||||
#endif
|
||||
|
||||
#if defined(FILES_HAVE_FDS) \
|
||||
|| defined(USE_BEOS_PORT_THREADS) \
|
||||
|| (defined(USE_WINSOCK_TCP) && defined(USE_TCP)) \
|
||||
|
@ -103,8 +66,6 @@ THREAD_LOCAL_DECL(extern void *scheme_break_semaphore;)
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#include "schfd.h"
|
||||
|
||||
#define DEFAULT_INIT_STACK_SIZE 1000
|
||||
#define MAX_INIT_STACK_SIZE 100000
|
||||
|
||||
|
@ -193,7 +154,7 @@ THREAD_LOCAL_DECL(MZ_MARK_STACK_TYPE scheme_current_cont_mark_stack);
|
|||
THREAD_LOCAL_DECL(MZ_MARK_POS_TYPE scheme_current_cont_mark_pos);
|
||||
#endif
|
||||
|
||||
THREAD_LOCAL_DECL(int scheme_semaphore_fd_kqueue);
|
||||
THREAD_LOCAL_DECL(struct rktio_ltps_t *scheme_semaphore_fd_set);
|
||||
|
||||
THREAD_LOCAL_DECL(static Scheme_Custodian *main_custodian);
|
||||
THREAD_LOCAL_DECL(static Scheme_Hash_Table *limited_custodians = NULL);
|
||||
|
@ -3853,471 +3814,122 @@ static Scheme_Object *call_as_nested_thread(int argc, Scheme_Object *argv[])
|
|||
/* thread scheduling and termination */
|
||||
/*========================================================================*/
|
||||
|
||||
void scheme_init_kqueue(void)
|
||||
void scheme_init_fd_semaphores(void)
|
||||
{
|
||||
#if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL)
|
||||
scheme_semaphore_fd_kqueue = -1;
|
||||
#endif
|
||||
scheme_semaphore_fd_set = rktio_open_ltps(scheme_rktio);
|
||||
}
|
||||
|
||||
void scheme_release_kqueue(void)
|
||||
void scheme_release_fd_semaphores(void)
|
||||
{
|
||||
#if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL)
|
||||
if (scheme_semaphore_fd_kqueue >= 0) {
|
||||
intptr_t rc;
|
||||
do {
|
||||
rc = close(scheme_semaphore_fd_kqueue);
|
||||
} while ((rc == -1) && (errno == EINTR));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL)
|
||||
static void log_kqueue_error(const char *action, int kr)
|
||||
{
|
||||
if (kr < 0) {
|
||||
Scheme_Logger *logger;
|
||||
logger = scheme_get_main_logger();
|
||||
scheme_log(logger, SCHEME_LOG_WARNING, 0,
|
||||
#ifdef HAVE_KQUEUE_SYSCALL
|
||||
"kqueue"
|
||||
#else
|
||||
"epoll"
|
||||
#endif
|
||||
" error at %s: %E",
|
||||
action, errno);
|
||||
if (scheme_semaphore_fd_set) {
|
||||
rktio_ltps_remove_all(scheme_rktio, scheme_semaphore_fd_set);
|
||||
(void)check_fd_semaphores();
|
||||
rktio_ltps_close(scheme_semaphore_fd_set);
|
||||
}
|
||||
}
|
||||
|
||||
static void log_kqueue_fd(int fd, int flags)
|
||||
static void log_fd_semaphore_error()
|
||||
{
|
||||
{
|
||||
Scheme_Logger *logger;
|
||||
logger = scheme_get_main_logger();
|
||||
scheme_log(logger, SCHEME_LOG_WARNING, 0,
|
||||
#ifdef HAVE_KQUEUE_SYSCALL
|
||||
"kqueue"
|
||||
#else
|
||||
"epoll"
|
||||
#endif
|
||||
" expected event %d %d",
|
||||
fd, flags);
|
||||
"error for long-term poll set: %R");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket)
|
||||
{
|
||||
#ifdef USE_WINSOCK_TCP
|
||||
return NULL;
|
||||
#else
|
||||
Scheme_Object *key, *v, *s = NULL;
|
||||
#if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL)
|
||||
# else
|
||||
void *r, *w, *e;
|
||||
# endif
|
||||
rktio_fd_t *rfd;
|
||||
|
||||
if (!scheme_semaphore_fd_mapping)
|
||||
return NULL;
|
||||
|
||||
# ifdef HAVE_KQUEUE_SYSCALL
|
||||
if (!is_socket) {
|
||||
/* kqueue() might not work on devices, such as ttys; also, while
|
||||
Mac OS X kqueue() claims to work on FIFOs, there are problems:
|
||||
watching for reads on a FIFO sometimes disables watching for
|
||||
writes on the same FIFO with a different file descriptor */
|
||||
if (!scheme_fd_regular_file(fd, 1))
|
||||
return NULL;
|
||||
}
|
||||
if (scheme_semaphore_fd_kqueue < 0) {
|
||||
scheme_semaphore_fd_kqueue = kqueue();
|
||||
if (scheme_semaphore_fd_kqueue < 0) {
|
||||
log_kqueue_error("create", scheme_semaphore_fd_kqueue);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
# ifdef HAVE_EPOLL_SYSCALL
|
||||
if (scheme_semaphore_fd_kqueue < 0) {
|
||||
scheme_semaphore_fd_kqueue = epoll_create(5);
|
||||
if (scheme_semaphore_fd_kqueue < 0) {
|
||||
log_kqueue_error("create", scheme_semaphore_fd_kqueue);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
rfd = rktio_system_fd(fd, (RKTIO_OPEN_READ
|
||||
| RKTIO_OPEN_WRITE
|
||||
| (is_socket ? RKTIO_OPEN_SOCKET : 0)));
|
||||
|
||||
key = scheme_make_integer_value(fd);
|
||||
v = scheme_hash_get(scheme_semaphore_fd_mapping, key);
|
||||
if (!v && ((mode == MZFD_CHECK_READ)
|
||||
|| (mode == MZFD_CHECK_WRITE)
|
||||
|| (mode == MZFD_CHECK_VNODE)
|
||||
|| (mode == MZFD_REMOVE)
|
||||
|| (mode == MZFD_REMOVE_VNODE)))
|
||||
sema = scheme_rktio_fd_to_semaphore(rfd, mode);
|
||||
|
||||
rktio_forget(rfd);
|
||||
|
||||
return sema;
|
||||
}
|
||||
|
||||
Scheme_Object *scheme_rktio_fd_to_semaphore(rktio_fd_t *fd, int mode)
|
||||
{
|
||||
rktio_handle_t *h;
|
||||
void **ib;
|
||||
|
||||
if (!scheme_semaphore_fd_mapping)
|
||||
return NULL;
|
||||
|
||||
if (!v) {
|
||||
v = scheme_make_vector(2, scheme_false);
|
||||
scheme_hash_set(scheme_semaphore_fd_mapping, key, v);
|
||||
switch(mode) {
|
||||
case MZFD_CREATE_READ:
|
||||
mode = RKTIO_LTPS_CREATE_READ;
|
||||
break;
|
||||
case MZFD_CREATE_WRITE:
|
||||
mode = RKTIO_LTPS_CREATE_WRITE;
|
||||
break;
|
||||
case MZFD_CHECK_READ:
|
||||
mode = RKTIO_LTPS_CHECK_READ;
|
||||
break;
|
||||
case MZFD_CHECK_WRITE:
|
||||
mode = RKTIO_LTPS_CHECK_WRITE;
|
||||
break;
|
||||
case MZFD_REMOVE:
|
||||
mode = RKTIO_LTPS_REMOVE;
|
||||
break;
|
||||
}
|
||||
|
||||
# if !defined(HAVE_KQUEUE_SYSCALL) && !defined(HAVE_EPOLL_SYSCALL)
|
||||
r = MZ_GET_FDSET(scheme_semaphore_fd_set, 0);
|
||||
w = MZ_GET_FDSET(scheme_semaphore_fd_set, 1);
|
||||
e = MZ_GET_FDSET(scheme_semaphore_fd_set, 2);
|
||||
# endif
|
||||
h = rktio_ltps_add(scheme_rktio, scheme_semaphore_fd_mapping, fd, mode);
|
||||
|
||||
if ((mode == MZFD_REMOVE) || (mode == MZFD_REMOVE_VNODE)) {
|
||||
s = SCHEME_VEC_ELS(v)[0];
|
||||
if (!SCHEME_FALSEP(s))
|
||||
scheme_post_sema_all(s);
|
||||
s = SCHEME_VEC_ELS(v)[1];
|
||||
if (!SCHEME_FALSEP(s))
|
||||
scheme_post_sema_all(s);
|
||||
s = NULL;
|
||||
scheme_hash_set(scheme_semaphore_fd_mapping, key, NULL);
|
||||
# ifdef HAVE_KQUEUE_SYSCALL
|
||||
{
|
||||
GC_CAN_IGNORE struct kevent kev[2];
|
||||
struct timespec timeout = {0, 0};
|
||||
int kr, pos = 0;
|
||||
if (mode == MZFD_REMOVE_VNODE) {
|
||||
EV_SET(&kev[pos], fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
|
||||
pos++;
|
||||
} else {
|
||||
if (SCHEME_TRUEP(SCHEME_VEC_ELS(v)[0])) {
|
||||
EV_SET(&kev[pos], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
||||
pos++;
|
||||
if (!h) {
|
||||
if (scheme_last_error_is_racket(RKTIO_ERROR_LTPS_REMOVED)
|
||||
|| scheme_last_error_is_racket(RKTIO_ERROR_LTPS_NOT_FOUND)) {
|
||||
/* That's a kind of success, not failure. */
|
||||
return NULL;
|
||||
}
|
||||
if (SCHEME_TRUEP(SCHEME_VEC_ELS(v)[1])) {
|
||||
EV_SET(&kev[pos], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
do {
|
||||
kr = kevent(scheme_semaphore_fd_kqueue, kev, pos, NULL, 0, &timeout);
|
||||
} while ((kr == -1) && (errno == EINTR));
|
||||
log_kqueue_error("remove", kr);
|
||||
}
|
||||
# elif defined(HAVE_EPOLL_SYSCALL)
|
||||
{
|
||||
int kr;
|
||||
kr = epoll_ctl(scheme_semaphore_fd_kqueue, EPOLL_CTL_DEL, fd, NULL);
|
||||
log_kqueue_error("remove", kr);
|
||||
}
|
||||
# else
|
||||
MZ_FD_CLR(fd, r);
|
||||
MZ_FD_CLR(fd, w);
|
||||
MZ_FD_CLR(fd, e);
|
||||
# endif
|
||||
s = NULL;
|
||||
} else if ((mode == MZFD_CHECK_READ)
|
||||
|| (mode == MZFD_CREATE_READ)
|
||||
|| (mode == MZFD_CHECK_VNODE)
|
||||
|| (mode == MZFD_CREATE_VNODE)) {
|
||||
s = SCHEME_VEC_ELS(v)[0];
|
||||
if (SCHEME_FALSEP(s)) {
|
||||
if ((mode == MZFD_CREATE_READ)
|
||||
|| (mode == MZFD_CREATE_VNODE)) {
|
||||
s = scheme_make_sema(0);
|
||||
SCHEME_VEC_ELS(v)[0] = s;
|
||||
# ifdef HAVE_KQUEUE_SYSCALL
|
||||
{
|
||||
GC_CAN_IGNORE struct kevent kev;
|
||||
struct timespec timeout = {0, 0};
|
||||
int kr;
|
||||
if (mode == MZFD_CREATE_READ)
|
||||
EV_SET(&kev, fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL);
|
||||
else
|
||||
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT,
|
||||
(NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND
|
||||
| NOTE_RENAME | NOTE_ATTRIB),
|
||||
0, NULL);
|
||||
do {
|
||||
kr = kevent(scheme_semaphore_fd_kqueue, &kev, 1, NULL, 0, &timeout);
|
||||
} while ((kr == -1) && (errno == EINTR));
|
||||
log_kqueue_error("read", kr);
|
||||
}
|
||||
# elif defined(HAVE_EPOLL_SYSCALL)
|
||||
{
|
||||
GC_CAN_IGNORE struct epoll_event ev;
|
||||
int already = !SCHEME_FALSEP(SCHEME_VEC_ELS(v)[1]), kr;
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.data.fd = fd;
|
||||
ev.events = EPOLLIN | (already ? EPOLLOUT : 0);
|
||||
kr = epoll_ctl(scheme_semaphore_fd_kqueue,
|
||||
(already ? EPOLL_CTL_MOD : EPOLL_CTL_ADD), fd, &ev);
|
||||
log_kqueue_error("read", kr);
|
||||
}
|
||||
# else
|
||||
MZ_FD_SET(fd, r);
|
||||
MZ_FD_SET(fd, e);
|
||||
#endif
|
||||
} else
|
||||
s = NULL;
|
||||
}
|
||||
} else if ((mode == MZFD_CHECK_WRITE)
|
||||
|| (mode == MZFD_CREATE_WRITE)) {
|
||||
s = SCHEME_VEC_ELS(v)[1];
|
||||
if (SCHEME_FALSEP(s)) {
|
||||
if (mode == MZFD_CREATE_WRITE) {
|
||||
s = scheme_make_sema(0);
|
||||
SCHEME_VEC_ELS(v)[1] = s;
|
||||
# ifdef HAVE_KQUEUE_SYSCALL
|
||||
{
|
||||
GC_CAN_IGNORE struct kevent kev;
|
||||
struct timespec timeout = {0, 0};
|
||||
int kr;
|
||||
EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, NULL);
|
||||
do {
|
||||
kr = kevent(scheme_semaphore_fd_kqueue, &kev, 1, NULL, 0, &timeout);
|
||||
} while ((kr == -1) && (errno == EINTR));
|
||||
log_kqueue_error("write", kr);
|
||||
log_fd_semaphore_error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
# elif defined(HAVE_EPOLL_SYSCALL)
|
||||
{
|
||||
GC_CAN_IGNORE struct epoll_event ev;
|
||||
int already = !SCHEME_FALSEP(SCHEME_VEC_ELS(v)[0]), kr;
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.data.fd = fd;
|
||||
ev.events = EPOLLOUT | (already ? EPOLLIN : 0);
|
||||
kr = epoll_ctl(scheme_semaphore_fd_kqueue,
|
||||
(already ? EPOLL_CTL_MOD : EPOLL_CTL_ADD), fd, &ev);
|
||||
log_kqueue_error("write", kr);
|
||||
}
|
||||
# else
|
||||
MZ_FD_SET(fd, w);
|
||||
MZ_FD_SET(fd, e);
|
||||
#endif
|
||||
} else
|
||||
s = NULL;
|
||||
}
|
||||
ib = rktio_ltps_handle_get_data(scheme_rktio, h);
|
||||
if (!ib) {
|
||||
ib = scheme_malloc_immobile_box(scheme_make_sema(0));
|
||||
rktio_ltps_handle_set_data(scheme_rktio, ib);
|
||||
}
|
||||
|
||||
return s;
|
||||
#endif
|
||||
return *(Scheme_Object **)p;
|
||||
}
|
||||
|
||||
static int check_fd_semaphores()
|
||||
{
|
||||
#ifdef USE_WINSOCK_TCP
|
||||
return 0;
|
||||
#elif defined(HAVE_KQUEUE_SYSCALL)
|
||||
Scheme_Object *v, *s, *key;
|
||||
GC_CAN_IGNORE struct kevent kev;
|
||||
struct timespec timeout = {0, 0};
|
||||
int kr, hit = 0;
|
||||
rktio_ltps_handle_t *h;
|
||||
int did = 0;
|
||||
|
||||
if (!scheme_semaphore_fd_mapping || (scheme_semaphore_fd_kqueue < 0))
|
||||
if (!scheme_semaphore_fd_set)
|
||||
return 0;
|
||||
|
||||
while (1) {
|
||||
do {
|
||||
kr = kevent(scheme_semaphore_fd_kqueue, NULL, 0, &kev, 1, &timeout);
|
||||
} while ((kr == -1) && (errno == EINTR));
|
||||
log_kqueue_error("wait", kr);
|
||||
h = rktio_ltps_get_signaled_handle(scheme_rktio, scheme_semaphore_fd_set);
|
||||
if (h) {
|
||||
void *p;
|
||||
p = rktio_ltps_handle_get_data(scheme_rktio, h);
|
||||
free(h);
|
||||
|
||||
if (kr > 0) {
|
||||
key = scheme_make_integer_value(kev.ident);
|
||||
v = scheme_hash_get(scheme_semaphore_fd_mapping, key);
|
||||
if (v) {
|
||||
if ((kev.filter == EVFILT_READ) || (kev.filter == EVFILT_VNODE)) {
|
||||
s = SCHEME_VEC_ELS(v)[0];
|
||||
if (!SCHEME_FALSEP(s)) {
|
||||
scheme_post_sema_all(s);
|
||||
hit = 1;
|
||||
SCHEME_VEC_ELS(v)[0] = scheme_false;
|
||||
}
|
||||
} else if (kev.filter == EVFILT_WRITE) {
|
||||
s = SCHEME_VEC_ELS(v)[1];
|
||||
if (!SCHEME_FALSEP(s)) {
|
||||
scheme_post_sema_all(s);
|
||||
hit = 1;
|
||||
SCHEME_VEC_ELS(v)[1] = scheme_false;
|
||||
}
|
||||
}
|
||||
if (SCHEME_FALSEP(SCHEME_VEC_ELS(v)[0])
|
||||
&& SCHEME_FALSEP(SCHEME_VEC_ELS(v)[1]))
|
||||
scheme_hash_set(scheme_semaphore_fd_mapping, key, NULL);
|
||||
} else {
|
||||
log_kqueue_fd(kev.ident, kev.filter);
|
||||
}
|
||||
sema = *(Scheme_Object **)p;
|
||||
scheme_free_immobile_box(p);
|
||||
|
||||
scheme_post_sema_all(sema);
|
||||
|
||||
did = 1;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
return hit;
|
||||
#elif defined(HAVE_EPOLL_SYSCALL)
|
||||
Scheme_Object *v, *s, *key;
|
||||
int kr, hit = 0;
|
||||
GC_CAN_IGNORE struct epoll_event ev;
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
|
||||
if (!scheme_semaphore_fd_mapping || (scheme_semaphore_fd_kqueue < 0))
|
||||
return 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
do {
|
||||
kr = epoll_wait(scheme_semaphore_fd_kqueue, &ev, 1, 0);
|
||||
} while ((kr == -1) && (errno == EINTR));
|
||||
log_kqueue_error("wait", kr);
|
||||
|
||||
if (kr > 0) {
|
||||
key = scheme_make_integer_value(ev.data.fd);
|
||||
v = scheme_hash_get(scheme_semaphore_fd_mapping, key);
|
||||
if (v) {
|
||||
if (ev.events & (POLLIN | POLLHUP | POLLERR)) {
|
||||
s = SCHEME_VEC_ELS(v)[0];
|
||||
if (!SCHEME_FALSEP(s)) {
|
||||
scheme_post_sema_all(s);
|
||||
hit = 1;
|
||||
SCHEME_VEC_ELS(v)[0] = scheme_false;
|
||||
}
|
||||
}
|
||||
if (ev.events & (POLLOUT | POLLHUP | POLLERR)) {
|
||||
s = SCHEME_VEC_ELS(v)[1];
|
||||
if (!SCHEME_FALSEP(s)) {
|
||||
scheme_post_sema_all(s);
|
||||
hit = 1;
|
||||
SCHEME_VEC_ELS(v)[1] = scheme_false;
|
||||
}
|
||||
}
|
||||
if (SCHEME_FALSEP(SCHEME_VEC_ELS(v)[0])
|
||||
&& SCHEME_FALSEP(SCHEME_VEC_ELS(v)[1])) {
|
||||
scheme_hash_set(scheme_semaphore_fd_mapping, key, NULL);
|
||||
kr = epoll_ctl(scheme_semaphore_fd_kqueue, EPOLL_CTL_DEL, ev.data.fd, NULL);
|
||||
log_kqueue_error("remove*", kr);
|
||||
} else {
|
||||
ev.events = ((SCHEME_FALSEP(SCHEME_VEC_ELS(v)[0]) ? 0 : POLLIN)
|
||||
| (SCHEME_FALSEP(SCHEME_VEC_ELS(v)[1]) ? 0 : POLLOUT));
|
||||
kr = epoll_ctl(scheme_semaphore_fd_kqueue, EPOLL_CTL_MOD, ev.data.fd, &ev);
|
||||
log_kqueue_error("update", kr);
|
||||
}
|
||||
} else {
|
||||
log_kqueue_fd(ev.data.fd, ev.events);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
return hit;
|
||||
#elif defined(HAVE_POLL_SYSCALL)
|
||||
struct pollfd *pfd;
|
||||
intptr_t i, c;
|
||||
Scheme_Object *v, *s, *key;
|
||||
int sr, hit = 0;
|
||||
|
||||
if (!scheme_semaphore_fd_mapping || !scheme_semaphore_fd_mapping->count)
|
||||
return 0;
|
||||
|
||||
scheme_clean_fd_set(scheme_semaphore_fd_set);
|
||||
c = SCHEME_INT_VAL(scheme_semaphore_fd_set->data->count);
|
||||
pfd = scheme_semaphore_fd_set->data->pfd;
|
||||
|
||||
do {
|
||||
sr = poll(pfd, c, 0);
|
||||
} while ((sr == -1) && (errno == EINTR));
|
||||
|
||||
if (sr > 0) {
|
||||
for (i = 0; i < c; i++) {
|
||||
if (pfd[i].revents) {
|
||||
key = scheme_make_integer_value(pfd[i].fd);
|
||||
v = scheme_hash_get(scheme_semaphore_fd_mapping, key);
|
||||
if (v) {
|
||||
if (pfd[i].revents & (POLLIN | POLLHUP | POLLERR)) {
|
||||
s = SCHEME_VEC_ELS(v)[0];
|
||||
if (!SCHEME_FALSEP(s)) {
|
||||
scheme_post_sema_all(s);
|
||||
hit = 1;
|
||||
SCHEME_VEC_ELS(v)[0] = scheme_false;
|
||||
}
|
||||
pfd[i].events -= (pfd[i].events & POLLIN);
|
||||
}
|
||||
if (pfd[i].revents & (POLLOUT | POLLHUP | POLLERR)) {
|
||||
s = SCHEME_VEC_ELS(v)[1];
|
||||
if (!SCHEME_FALSEP(s)) {
|
||||
scheme_post_sema_all(s);
|
||||
hit = 1;
|
||||
SCHEME_VEC_ELS(v)[1] = scheme_false;
|
||||
}
|
||||
pfd[i].events -= (pfd[i].events & POLLOUT);
|
||||
}
|
||||
if (SCHEME_FALSEP(SCHEME_VEC_ELS(v)[0])
|
||||
&& SCHEME_FALSEP(SCHEME_VEC_ELS(v)[1]))
|
||||
scheme_hash_set(scheme_semaphore_fd_mapping, key, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit;
|
||||
#else
|
||||
void *fds;
|
||||
struct timeval time = {0, 0};
|
||||
int i, actual_limit, r, w, e, sr, hit = 0;
|
||||
Scheme_Object *key, *v, *s;
|
||||
DECL_FDSET(set, 3);
|
||||
fd_set *set1, *set2;
|
||||
|
||||
if (!scheme_semaphore_fd_mapping || !scheme_semaphore_fd_mapping->count)
|
||||
return 0;
|
||||
|
||||
INIT_DECL_FDSET(set, set1, set2);
|
||||
set1 = (fd_set *) MZ_GET_FDSET(set, 1);
|
||||
set2 = (fd_set *) MZ_GET_FDSET(set, 2);
|
||||
|
||||
fds = (void *)set;
|
||||
MZ_FD_ZERO(set);
|
||||
MZ_FD_ZERO(set1);
|
||||
MZ_FD_ZERO(set2);
|
||||
|
||||
scheme_merge_fd_sets(fds, scheme_semaphore_fd_set);
|
||||
|
||||
actual_limit = scheme_get_fd_limit(fds);
|
||||
|
||||
do {
|
||||
sr = select(actual_limit, set, set1, set2, &time);
|
||||
} while ((sr == -1) && (errno == EINTR));
|
||||
|
||||
if (sr > 0) {
|
||||
for (i = 0; i < actual_limit; i++) {
|
||||
r = MZ_FD_ISSET(i, set);
|
||||
w = MZ_FD_ISSET(i, set1);
|
||||
e = MZ_FD_ISSET(i, set2);
|
||||
if (r || w || e) {
|
||||
key = scheme_make_integer_value(i);
|
||||
v = scheme_hash_get(scheme_semaphore_fd_mapping, key);
|
||||
if (v) {
|
||||
if (r || e) {
|
||||
s = SCHEME_VEC_ELS(v)[0];
|
||||
if (!SCHEME_FALSEP(s)) {
|
||||
scheme_post_sema_all(s);
|
||||
hit = 1;
|
||||
SCHEME_VEC_ELS(v)[0] = scheme_false;
|
||||
}
|
||||
MZ_FD_CLR(i, MZ_GET_FDSET(scheme_semaphore_fd_set, 0));
|
||||
}
|
||||
if (w || e) {
|
||||
s = SCHEME_VEC_ELS(v)[1];
|
||||
if (!SCHEME_FALSEP(s)) {
|
||||
scheme_post_sema_all(s);
|
||||
hit = 1;
|
||||
SCHEME_VEC_ELS(v)[1] = scheme_false;
|
||||
}
|
||||
MZ_FD_CLR(i, MZ_GET_FDSET(scheme_semaphore_fd_set, 1));
|
||||
}
|
||||
if (SCHEME_FALSEP(SCHEME_VEC_ELS(v)[0])
|
||||
&& SCHEME_FALSEP(SCHEME_VEC_ELS(v)[1])) {
|
||||
MZ_FD_CLR(i, MZ_GET_FDSET(scheme_semaphore_fd_set, 2));
|
||||
scheme_hash_set(scheme_semaphore_fd_mapping, key, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit;
|
||||
#endif
|
||||
return did;
|
||||
}
|
||||
|
||||
void scheme_check_fd_semaphores(void)
|
||||
|
@ -4435,18 +4047,7 @@ static int check_sleep(int need_activity, int sleep_now)
|
|||
if (have_activity && scheme_notify_multithread)
|
||||
scheme_notify_multithread(0);
|
||||
|
||||
#if defined(USING_FDS)
|
||||
INIT_DECL_FDSET(set, set1, set2);
|
||||
set1 = (fd_set *) MZ_GET_FDSET(set, 1);
|
||||
set2 = (fd_set *) MZ_GET_FDSET(set, 2);
|
||||
|
||||
fds = (void *)set;
|
||||
MZ_FD_ZERO(set);
|
||||
MZ_FD_ZERO(set1);
|
||||
MZ_FD_ZERO(set2);
|
||||
#else
|
||||
fds = NULL;
|
||||
#endif
|
||||
fds = rktio_make_poll_set(scheme_rktio);
|
||||
|
||||
needs_sleep_cancelled = 0;
|
||||
|
||||
|
@ -4497,24 +4098,16 @@ static int check_sleep(int need_activity, int sleep_now)
|
|||
p = p->next;
|
||||
}
|
||||
|
||||
if (needs_sleep_cancelled)
|
||||
if (needs_sleep_cancelled) {
|
||||
rktio_poll_set_close(scheme_rktio, fds);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (post_system_idle()) {
|
||||
rktio_poll_set_close(scheme_rktio, fds);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL)
|
||||
if (scheme_semaphore_fd_mapping && (scheme_semaphore_fd_kqueue >= 0)) {
|
||||
MZ_FD_SET(scheme_semaphore_fd_kqueue, set);
|
||||
MZ_FD_SET(scheme_semaphore_fd_kqueue, set2);
|
||||
}
|
||||
# else
|
||||
fds = scheme_merge_fd_sets(fds, scheme_semaphore_fd_set);
|
||||
# endif
|
||||
|
||||
scheme_clean_fd_set(fds);
|
||||
|
||||
if (sleep_now) {
|
||||
float mst = (float)max_sleep_time;
|
||||
|
||||
|
@ -4535,6 +4128,8 @@ static int check_sleep(int need_activity, int sleep_now)
|
|||
} else if (scheme_wakeup_on_input)
|
||||
scheme_wakeup_on_input(fds);
|
||||
|
||||
rktio_poll_set_forget(scheme_rktio, fds);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -4897,10 +4492,6 @@ void scheme_break_kind_thread(Scheme_Thread *p, int kind)
|
|||
}
|
||||
}
|
||||
scheme_weak_resume_thread(p);
|
||||
# if defined(WINDOWS_PROCESSES) || defined(WINDOWS_FILE_HANDLES)
|
||||
if (SAME_OBJ(p, scheme_main_thread))
|
||||
ReleaseSemaphore((HANDLE)scheme_break_semaphore, 1, NULL);
|
||||
# endif
|
||||
}
|
||||
|
||||
void scheme_break_thread(Scheme_Thread *p)
|
||||
|
|
|
@ -189,7 +189,7 @@ static void wait_read(rktio_t *rktio, rktio_fd_t *fd)
|
|||
check_valid(ps);
|
||||
rktio_poll_add(rktio, fd, ps, RKTIO_POLL_READ);
|
||||
rktio_sleep(rktio, 0, ps, NULL);
|
||||
rktio_poll_set_close(rktio, ps);
|
||||
rktio_poll_set_forget(rktio, ps);
|
||||
}
|
||||
|
||||
static void check_read_write_pair(rktio_t *rktio, rktio_fd_t *fd, rktio_fd_t *fd2, int immediate_available)
|
||||
|
@ -337,7 +337,7 @@ void check_many_lookup(rktio_t *rktio)
|
|||
}
|
||||
|
||||
rktio_sleep(rktio, 0, ps, NULL);
|
||||
rktio_poll_set_close(rktio, ps);
|
||||
rktio_poll_set_forget(rktio, ps);
|
||||
|
||||
for (i = 0; i < LOOKUPS_N; i++) {
|
||||
if (lookup[i] && (rktio_poll_addrinfo_lookup_ready(rktio, lookup[i]) == RKTIO_POLL_READY)) {
|
||||
|
@ -346,7 +346,7 @@ void check_many_lookup(rktio_t *rktio)
|
|||
else {
|
||||
addr = rktio_addrinfo_lookup_get(rktio, lookup[i]);
|
||||
check_valid(addr);
|
||||
rktio_free_addrinfo(rktio, addr);
|
||||
rktio_addrinfo_free(rktio, addr);
|
||||
}
|
||||
lookup[i] = NULL;
|
||||
break;
|
||||
|
@ -371,7 +371,7 @@ rktio_addrinfo_t *lookup_loop(rktio_t *rktio,
|
|||
|
||||
rktio_poll_add_addrinfo_lookup(rktio, lookup, ps);
|
||||
rktio_sleep(rktio, 0, ps, NULL);
|
||||
rktio_poll_set_close(rktio, ps);
|
||||
rktio_poll_set_forget(rktio, ps);
|
||||
check_valid(rktio_poll_addrinfo_lookup_ready(rktio, lookup) == RKTIO_POLL_READY);
|
||||
|
||||
addr = rktio_addrinfo_lookup_get(rktio, lookup);
|
||||
|
@ -396,7 +396,7 @@ static void pause_for_process(rktio_t *rktio, rktio_process_t *process, int dont
|
|||
} else {
|
||||
rktio_sleep(rktio, 0, ps, NULL);
|
||||
}
|
||||
rktio_poll_set_close(rktio, ps);
|
||||
rktio_poll_set_forget(rktio, ps);
|
||||
done = rktio_poll_process_done(rktio, process);
|
||||
check_valid(done != RKTIO_PROCESS_ERROR);
|
||||
} while (!done);
|
||||
|
@ -417,7 +417,7 @@ static rktio_fd_t *connect_loop(rktio_t *rktio, rktio_addrinfo_t *addr, rktio_ad
|
|||
|
||||
rktio_poll_add_connect(rktio, conn, ps);
|
||||
rktio_sleep(rktio, 0, ps, NULL);
|
||||
rktio_poll_set_close(rktio, ps);
|
||||
rktio_poll_set_forget(rktio, ps);
|
||||
check_valid(rktio_poll_connect_ready(rktio, conn) == RKTIO_POLL_READY);
|
||||
|
||||
fd = rktio_connect_finish(rktio, conn);
|
||||
|
@ -452,7 +452,7 @@ static char *week_day_name(rktio_t *rktio, int dow)
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
rktio_t *rktio;
|
||||
rktio_size_t *sz;
|
||||
rktio_filesize_t *sz;
|
||||
rktio_fd_t *fd, *fd2;
|
||||
intptr_t amt, i, saw_file;
|
||||
int perms;
|
||||
|
@ -506,8 +506,7 @@ int main(int argc, char **argv)
|
|||
|
||||
sz = rktio_file_size(rktio, "test1");
|
||||
check_valid(sz);
|
||||
check_valid(sz->lo == 5);
|
||||
check_valid(sz->hi == 0);
|
||||
check_valid(*sz == 5);
|
||||
free(sz);
|
||||
|
||||
fd = rktio_open(rktio, "test2", RKTIO_OPEN_WRITE | RKTIO_OPEN_MUST_EXIST);
|
||||
|
@ -655,7 +654,7 @@ int main(int argc, char **argv)
|
|||
|
||||
lnr = rktio_listen(rktio, addr, 5, 1);
|
||||
check_valid(lnr);
|
||||
rktio_free_addrinfo(rktio, addr);
|
||||
rktio_addrinfo_free(rktio, addr);
|
||||
|
||||
check_valid(!rktio_poll_accept_ready(rktio, lnr));
|
||||
|
||||
|
@ -704,7 +703,7 @@ int main(int argc, char **argv)
|
|||
check_read_write_pair(rktio, fd, fd2, 0);
|
||||
|
||||
fd = connect_loop(rktio, addr, NULL);
|
||||
rktio_free_addrinfo(rktio, addr);
|
||||
rktio_addrinfo_free(rktio, addr);
|
||||
|
||||
fd2 = rktio_accept(rktio, lnr);
|
||||
|
||||
|
@ -734,7 +733,7 @@ int main(int argc, char **argv)
|
|||
addr = lookup_loop(rktio, NULL, 4536, -1, 1, 0);
|
||||
check_valid(addr);
|
||||
check_valid(rktio_udp_bind(rktio, fd, addr));
|
||||
rktio_free_addrinfo(rktio, addr);
|
||||
rktio_addrinfo_free(rktio, addr);
|
||||
|
||||
fd2 = rktio_udp_open(rktio, intf_addr);
|
||||
check_valid(fd2);
|
||||
|
@ -742,7 +741,7 @@ int main(int argc, char **argv)
|
|||
addr = lookup_loop(rktio, "localhost", 4536, -1, 0, 0);
|
||||
check_valid(addr);
|
||||
check_valid(rktio_udp_connect(rktio, fd2, addr));
|
||||
rktio_free_addrinfo(rktio, addr);
|
||||
rktio_addrinfo_free(rktio, addr);
|
||||
|
||||
check_read_write_pair(rktio, fd, fd2, 0);
|
||||
|
||||
|
@ -755,7 +754,7 @@ int main(int argc, char **argv)
|
|||
addr = lookup_loop(rktio, NULL, 4536, -1, 1, 0);
|
||||
check_valid(addr);
|
||||
check_valid(rktio_udp_bind(rktio, fd, addr));
|
||||
rktio_free_addrinfo(rktio, addr);
|
||||
rktio_addrinfo_free(rktio, addr);
|
||||
|
||||
addr = lookup_loop(rktio, "localhost", 4536, -1, 0, 0);
|
||||
check_valid(addr);
|
||||
|
@ -763,8 +762,8 @@ int main(int argc, char **argv)
|
|||
check_fill_write(rktio, fd2, addr, AMOUNT_FOR_UDP);
|
||||
check_drain_read(rktio, fd, AMOUNT_FOR_UDP+1);
|
||||
|
||||
rktio_free_addrinfo(rktio, addr);
|
||||
rktio_free_addrinfo(rktio, intf_addr);
|
||||
rktio_addrinfo_free(rktio, addr);
|
||||
rktio_addrinfo_free(rktio, intf_addr);
|
||||
|
||||
check_valid(rktio_close(rktio, fd));
|
||||
check_valid(rktio_close(rktio, fd2));
|
||||
|
@ -927,7 +926,7 @@ int main(int argc, char **argv)
|
|||
|
||||
start = rktio_get_inexact_milliseconds();
|
||||
rktio_sleep(rktio, 0.1, ps, NULL);
|
||||
rktio_poll_set_close(rktio, ps);
|
||||
rktio_poll_set_forget(rktio, ps);
|
||||
check_valid(rktio_get_inexact_milliseconds() - start > 0.1);
|
||||
|
||||
ps = rktio_make_poll_set(rktio);
|
||||
|
@ -944,7 +943,7 @@ int main(int argc, char **argv)
|
|||
check_valid(rktio_poll_fs_change_ready(rktio, fc) == RKTIO_POLL_READY);
|
||||
|
||||
check_valid(rktio_close(rktio, fd2));
|
||||
rktio_poll_set_close(rktio, ps);
|
||||
rktio_poll_set_forget(rktio, ps);
|
||||
|
||||
rktio_fs_change_forget(rktio, fc);
|
||||
}
|
||||
|
|
|
@ -7,87 +7,184 @@
|
|||
# define RKTIO_EXTERN extern
|
||||
#endif
|
||||
|
||||
typedef struct rktio_t rktio_t;
|
||||
/* A rktio_t value represents an instance of the Racket I/O system.
|
||||
Almost every rktio_...() function takes it as the first argument. */
|
||||
typedef struct rktio_t rktio_t;
|
||||
|
||||
RKTIO_EXTERN rktio_t *rktio_init(void);
|
||||
/* Call rktio_init() before anything else. The first call to
|
||||
rktio_init() must return before any additional calls (in other
|
||||
threads), but there's no ordering requirement after that. */
|
||||
RKTIO_EXTERN rktio_t *rktio_init(void);
|
||||
|
||||
RKTIO_EXTERN void rktio_destroy(rktio_t *);
|
||||
/* Call rktio_destroy() as the last thing. Everything else must be
|
||||
explicitly deallocated/closed/forgotten before calling
|
||||
rktio_destroy(). */
|
||||
RKTIO_EXTERN void rktio_destroy(rktio_t *);
|
||||
|
||||
RKTIO_EXTERN void rktio_free(void *p);
|
||||
/* Normally equivalent to free(), but ensures the same malloc()/free()
|
||||
that rktio function use: */
|
||||
RKTIO_EXTERN void rktio_free(void *p);
|
||||
|
||||
typedef int rktio_ok_t;
|
||||
/* A result of this type is 0 for failure (in which case an error is
|
||||
available from `rktio_get_last_error`) and 1 for success. */
|
||||
|
||||
typedef int rktio_tri_t;
|
||||
/* A result of this type is a boolean, but a `...ERROR` value means
|
||||
that an error value is available from `rktio_get_last_error`. */
|
||||
|
||||
typedef int rktio_bool_t;
|
||||
/* 0 or 1. */
|
||||
|
||||
/*************************************************/
|
||||
/* Reading and writing files */
|
||||
|
||||
typedef struct rktio_fd_t rktio_fd_t;
|
||||
|
||||
/* Mode flags shared in part by `rktio_open` and `rktio_system_fd`. */
|
||||
|
||||
/* Accepted by both, but `RKTIO_OPEN_READ` and `RKTIO_OPEN_WRITE` are
|
||||
merely advisory for `rktio_system_fd` */
|
||||
#define RKTIO_OPEN_READ (1<<0)
|
||||
#define RKTIO_OPEN_WRITE (1<<1)
|
||||
#define RKTIO_OPEN_TRUNCATE (1<<2)
|
||||
#define RKTIO_OPEN_APPEND (1<<3)
|
||||
#define RKTIO_OPEN_REPLACE (1<<4)
|
||||
#define RKTIO_OPEN_MUST_EXIST (1<<5)
|
||||
#define RKTIO_OPEN_CAN_EXIST (1<<6)
|
||||
#define RKTIO_OPEN_SOCKET (1<<7)
|
||||
#define RKTIO_OPEN_UDP (1<<8)
|
||||
#define RKTIO_OPEN_TEXT (1<<2)
|
||||
|
||||
/* Used for `rktio_open` with `RKTIO_OPEN_WRITE`: */
|
||||
#define RKTIO_OPEN_TRUNCATE (1<<3)
|
||||
#define RKTIO_OPEN_APPEND (1<<4)
|
||||
#define RKTIO_OPEN_REPLACE (1<<5)
|
||||
#define RKTIO_OPEN_MUST_EXIST (1<<6)
|
||||
#define RKTIO_OPEN_CAN_EXIST (1<<7)
|
||||
|
||||
/* Used for `rktio_system_fd`: */
|
||||
#define RKTIO_OPEN_SOCKET (1<<8)
|
||||
#define RKTIO_OPEN_UDP (1<<9)
|
||||
#define RKTIO_OPEN_REGFILE (1<<10)
|
||||
#define RKTIO_OPEN_NOT_REGFILE (1<<11)
|
||||
|
||||
/* If neither RKTIO_OPEN_REGILE nor RKTIO_OPEN_NOT_REGILE
|
||||
are specified, then the value is inferred */
|
||||
are specified, then the value is inferred by `rtkio_system_fd`. */
|
||||
#define RKTIO_OPEN_INIT (1 << 12)
|
||||
/* Make `rtkio_system_fd` set a socket as nonblocking, etc. */
|
||||
#define RKTIO_OPEN_OWN (1 << 13)
|
||||
/* Make `rtkio_system_fd` record a socket for reliable clean up on pre-NT Windows. */
|
||||
|
||||
/* A socket registered this way should be non-blocking: */
|
||||
RKTIO_EXTERN rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes);
|
||||
RKTIO_EXTERN intptr_t rktio_fd_system_fd(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
/* A socket (as opposed to other file descriptors) registered this way
|
||||
should include include `RKTIO_OPEN_SOCKET` and be non-blocking or
|
||||
use `RKTIO_OPEN_INIT`. */
|
||||
|
||||
RKTIO_EXTERN int rktio_fd_is_regular_file(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN int rktio_fd_is_socket(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN int rktio_fd_is_udp(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN int rktio_fd_is_terminal(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN intptr_t rktio_fd_system_fd(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
/* Extracts a native file descriptor or socket. */
|
||||
|
||||
RKTIO_EXTERN rktio_bool_t rktio_fd_is_regular_file(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN rktio_bool_t rktio_fd_is_socket(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN rktio_bool_t rktio_fd_is_udp(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN rktio_bool_t rktio_fd_is_terminal(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN rktio_bool_t rktio_fd_is_text_converted(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
/* The functions mostly report values of recorded mode flags. */
|
||||
|
||||
RKTIO_EXTERN int rktio_fd_modes(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
/* Returns all of the recorded mode flags. */
|
||||
|
||||
RKTIO_EXTERN rktio_fd_t *rktio_open(rktio_t *rktio, char *src, int modes);
|
||||
/* Can report `RKTIO_ERROR_DOES_NOT_EXIST` in place of system error,
|
||||
and can report `RKTIO_ERROR_UNSUPPORTED_TEXT_MODE` on Windows:=. */
|
||||
|
||||
RKTIO_EXTERN rktio_ok_t rktio_close(rktio_t *rktio, rktio_fd_t *fd);
|
||||
/* Can report `RKTIO_ERROR_EXISTS` in place of system error,
|
||||
and can report `RKTIO_ERROR_UNSUPPORTED_TEXT_MODE` on Windows.
|
||||
See also `rktio_write` and `rktio_poll_write_flushed. */
|
||||
|
||||
RKTIO_EXTERN rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
/* Copies a file descriptor, where each must be closed or forgotten
|
||||
independenty. */
|
||||
|
||||
RKTIO_EXTERN void rktio_forget(rktio_t *rktio, rktio_fd_t *fd);
|
||||
/* Deallocates a `rktio_fd_t` without closing the file descriptor,
|
||||
but the descriptor is no longer recorded if it was opened with
|
||||
`RKTIO_OPEN_OWN`. */
|
||||
|
||||
RKTIO_EXTERN rktio_fd_t *rktio_std_fd(rktio_t *rktio, int which);
|
||||
/* Gets stdin/stdout/stderr.
|
||||
`which` values: */
|
||||
#define RKTIO_STDIN 0
|
||||
#define RKTIO_STDOUT 1
|
||||
#define RKTIO_STDERR 2
|
||||
|
||||
RKTIO_EXTERN intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
/* Returns the number of bytes read, possibly 0, in non-blocking mode.
|
||||
Alternatively, the result can be `RKTIO_READ_EOF` for end-of-file
|
||||
or `RKTIO_READ_ERROR` for an error. Although rktio_read is intended
|
||||
to have no buffering, text-mode conversion (on Windows) and certain
|
||||
uncooperative OS corners can buffer 1 byte. */
|
||||
|
||||
#define RKTIO_READ_EOF (-1)
|
||||
#define RKTIO_READ_ERROR (-2)
|
||||
|
||||
RKTIO_EXTERN intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
/* Returns the number of bytes written, possibly 0, in non-blocking
|
||||
mode. Alternatively, the result can be `RKTIO_WRITE_ERROR` for an
|
||||
error. Although rktio_write() is intended to write only bytes that
|
||||
can be fully delivered to the OS, there may be OS limitations that
|
||||
require buffering (e.g., on Windows). Use
|
||||
rktio_poll_write_flushed() to make sure it's completely flushed
|
||||
before closing. */
|
||||
|
||||
#define RKTIO_WRITE_ERROR (-2)
|
||||
|
||||
/* The read and write functions return the number of bytes read/write
|
||||
in non-blocking mode, possibly 0. A read can produce `RKTIO_READ_EOF`
|
||||
for end-of-file or `RKTIO_READ_ERROR` for an error. Similarly, write
|
||||
can produce `RKTIO_WRITE_ERROR`. */
|
||||
RKTIO_EXTERN intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
RKTIO_EXTERN intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
RKTIO_EXTERN intptr_t rktio_read_converted(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len,
|
||||
char *is_converted);
|
||||
/* Like rktio_read(), but also reports whether each character was
|
||||
original two characters that were converted to a single newline for
|
||||
text mode. */
|
||||
|
||||
#define RKTIO_POLL_ERROR (-2)
|
||||
#define RKTIO_POLL_READY 1
|
||||
RKTIO_EXTERN intptr_t rktio_buffered_byte_count(rktio_t *rktio, rktio_fd_t *fd);
|
||||
/* Reports the number of bytes that are buffered kfrom the file descriptor.
|
||||
The result is normally zero, but text-mode conversion and the rare
|
||||
uncooperative corner of an OS can make the result 1 byte. */
|
||||
|
||||
RKTIO_EXTERN rktio_tri_t rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN rktio_tri_t rktio_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
/* Each polling function returns one of the following: */
|
||||
#define RKTIO_POLL_NOT_READY 0
|
||||
#define RKTIO_POLL_READY 1
|
||||
#define RKTIO_POLL_ERROR (-2)
|
||||
|
||||
RKTIO_EXTERN rktio_tri_t rktio_poll_write_flushed(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
/* See `rktio_write` above. */
|
||||
|
||||
RKTIO_EXTERN rktio_tri_t rktio_file_lock_try(rktio_t *rktio, rktio_fd_t *rfd, int excl);
|
||||
RKTIO_EXTERN rktio_ok_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
/* Advisory file locks, where `excl` attempts to claim an exclusive
|
||||
lock. Whether these work in various situations depend on many OS
|
||||
details, where the differences involve promoting from non-exlcusive
|
||||
to exclusive, taking a lock that is already held, getting an
|
||||
exclusive lock for a file descriptor in read mode, getting a
|
||||
non-exclusive lock in write mode, and whether a lock prevents
|
||||
opening or using another file descriptor. */
|
||||
|
||||
#define RKTIO_LOCK_ERROR (-2)
|
||||
#define RKTIO_LOCK_ACQUIRED 1
|
||||
#define RKTIO_LOCK_NOT_ACQUIRED 0
|
||||
|
||||
RKTIO_EXTERN rktio_tri_t rktio_file_lock_try(rktio_t *rktio, rktio_fd_t *rfd, int excl);
|
||||
RKTIO_EXTERN rktio_tri_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
typedef rktio_int64_t rktio_filesize_t;
|
||||
|
||||
rktio_ok_t rktio_set_file_position(rktio_t *rktio, rktio_fd_t *rfd, rktio_filesize_t pos, int whence);
|
||||
/* Can report `RKTIO_ERROR_CANNOT_SET_FILE_POSITION` on Windows. */
|
||||
/* For `whence`: */
|
||||
enum {
|
||||
RKTIO_POSITION_FROM_START,
|
||||
RKTIO_POSITION_FROM_END
|
||||
};
|
||||
|
||||
rktio_filesize_t *rktio_get_file_position(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
/* Returns the file position, not taking into account rare input
|
||||
buffering (see `rktio_read`). On Windows, can report
|
||||
`RKTIO_ERROR_CANNOT_SET_FILE_POSITION`, which doesn't have a
|
||||
corresponding Windows error code. */
|
||||
|
||||
rktio_ok_t rktio_set_file_size(rktio_t *rktio, rktio_fd_t *rfd, rktio_filesize_t sz);
|
||||
/* Can report `RKTIO_ERROR_CANNOT_SET_FILE_POSITION` on Windows. */
|
||||
|
||||
/*************************************************/
|
||||
/* Network */
|
||||
|
@ -95,37 +192,64 @@ RKTIO_EXTERN rktio_tri_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd);
|
|||
typedef struct rktio_addrinfo_lookup_t rktio_addrinfo_lookup_t;
|
||||
typedef struct rktio_addrinfo_t rktio_addrinfo_t;
|
||||
|
||||
RKTIO_EXTERN int rktio_get_ipv4_family(rktio_t *rktio);
|
||||
|
||||
RKTIO_EXTERN rktio_addrinfo_lookup_t *rktio_start_addrinfo_lookup(rktio_t *rktio,
|
||||
const char *hostname, int portno,
|
||||
int family, int passive, int tcp);
|
||||
RKTIO_EXTERN int rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup);
|
||||
RKTIO_EXTERN rktio_addrinfo_t *rktio_addrinfo_lookup_get(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup);
|
||||
RKTIO_EXTERN void rktio_addrinfo_lookup_stop(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup);
|
||||
int family, rktio_bool_t passive, rktio_bool_t tcp);
|
||||
/* The `family` argument should be one of the following: */
|
||||
#define RKTIO_FAMILY_ANY (-1)
|
||||
RKTIO_EXTERN int rktio_get_ipv4_family(rktio_t *rktio);
|
||||
|
||||
RKTIO_EXTERN void rktio_free_addrinfo(rktio_t *rktio, struct rktio_addrinfo_t *a);
|
||||
RKTIO_EXTERN rktio_tri_t rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup);
|
||||
/* Check whether an address is available for a lookup request. */
|
||||
|
||||
RKTIO_EXTERN rktio_addrinfo_t *rktio_addrinfo_lookup_get(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup);
|
||||
/* Deallocates `lookup`. */
|
||||
|
||||
RKTIO_EXTERN void rktio_addrinfo_lookup_stop(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup);
|
||||
/* Abandons a lookup whose result (or error) is not yet received. */
|
||||
|
||||
RKTIO_EXTERN void rktio_addrinfo_free(rktio_t *rktio, struct rktio_addrinfo_t *a);
|
||||
/* Frees the result of a lookup. */
|
||||
|
||||
typedef struct rktio_listener_t rktio_listener_t;
|
||||
typedef struct rktio_connect_t rktio_connect_t;
|
||||
|
||||
#define RKTIO_SHUTDOWN_READ RKTIO_OPEN_READ
|
||||
#define RKTIO_SHUTDOWN_WRITE RKTIO_OPEN_WRITE
|
||||
RKTIO_EXTERN rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *local, int backlog, rktio_bool_t reuse);
|
||||
/* Can fail with `RKTIO_ERROR_TRY_AGAIN_WITH_IPV4`, which suggests
|
||||
trying an address using the family reported by
|
||||
`rktio_get_ipv4_family` instead of `RKTIO_FAMILY_ANY`. */
|
||||
|
||||
RKTIO_EXTERN rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *local, int backlog, int reuse);
|
||||
RKTIO_EXTERN void rktio_listen_stop(rktio_t *rktio, rktio_listener_t *l);
|
||||
RKTIO_EXTERN int rktio_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener);
|
||||
RKTIO_EXTERN rktio_fd_t *rktio_accept(rktio_t *rktio, rktio_listener_t *listener);
|
||||
/* Stops a listener. */
|
||||
|
||||
RKTIO_EXTERN rktio_tri_t rktio_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener);
|
||||
/* Returns one of `RKTIO_POLL_READY`, etc. */
|
||||
|
||||
RKTIO_EXTERN rktio_fd_t *rktio_accept(rktio_t *rktio, rktio_listener_t *listener);
|
||||
/* Accepts one connection on a listener. */
|
||||
|
||||
/* Addreses must not be freed until the connection is complete or stopped: */
|
||||
RKTIO_EXTERN rktio_connect_t *rktio_start_connect(rktio_t *rktio, rktio_addrinfo_t *remote, rktio_addrinfo_t *local);
|
||||
/* A `RKTIO_ERROR_CONNECT_TRYING_NEXT` error effectively means "try again",
|
||||
and the connection object is still valid: */
|
||||
/* Starts a connection request. Addreses must not be freed until the
|
||||
connection is complete, errored, or stopped. */
|
||||
|
||||
RKTIO_EXTERN rktio_fd_t *rktio_connect_finish(rktio_t *rktio, rktio_connect_t *conn);
|
||||
/* A `RKTIO_ERROR_CONNECT_TRYING_NEXT` error effectively means "try
|
||||
again", and the connection object is still valid. On any other
|
||||
error, or if the connection completes successfully, `conn` is
|
||||
deallocated */
|
||||
|
||||
RKTIO_EXTERN void rktio_connect_stop(rktio_t *rktio, rktio_connect_t *conn);
|
||||
RKTIO_EXTERN int rktio_poll_connect_ready(rktio_t *rktio, rktio_connect_t *conn);
|
||||
/* Stops a connection whose result or error has not been received. */
|
||||
|
||||
RKTIO_EXTERN rktio_tri_t rktio_poll_connect_ready(rktio_t *rktio, rktio_connect_t *conn);
|
||||
/* Returns one of `RKTIO_POLL_READY`, etc. */
|
||||
|
||||
RKTIO_EXTERN int rktio_socket_shutdown(rktio_t *rktio, rktio_fd_t *rfd, int mode);
|
||||
/* Useful for TCP to report an EOF to the other end. Does not close the socket,
|
||||
but may make it ineligible for forther use.
|
||||
`mode` values: */
|
||||
#define RKTIO_SHUTDOWN_READ 0
|
||||
#define RKTIO_SHUTDOWN_WRITE 1
|
||||
|
||||
RKTIO_EXTERN rktio_fd_t *rktio_udp_open(rktio_t *rktio, rktio_addrinfo_t *addr);
|
||||
RKTIO_EXTERN int rktio_udp_disconnect(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
|
@ -142,80 +266,81 @@ typedef struct rktio_length_and_addrinfo_t {
|
|||
|
||||
RKTIO_EXTERN rktio_length_and_addrinfo_t *rktio_udp_recvfrom(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len);
|
||||
|
||||
#define RKTIO_PROP_ERROR (-2)
|
||||
|
||||
/* The following accessors return RKTIO_PROP_ERROR on failure */
|
||||
/* The following accessors return `RKTIO_PROP_ERROR` on failure */
|
||||
RKTIO_EXTERN int rktio_udp_get_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN int rktio_udp_set_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd, int on);
|
||||
RKTIO_EXTERN int rktio_udp_get_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN int rktio_udp_set_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd, int ttl_val);
|
||||
|
||||
#define RKTIO_PROP_ERROR (-2)
|
||||
|
||||
RKTIO_EXTERN char **rktio_socket_address(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN char **rktio_socket_peer_address(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN char **rktio_listener_address(rktio_t *rktio, rktio_listener_t *lnr);
|
||||
/* These return two strings in an array (where the array itself should
|
||||
be deallocated), address and service. */
|
||||
|
||||
RKTIO_EXTERN char *rktio_udp_multicast_interface(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
RKTIO_EXTERN int rktio_udp_set_multicast_interface(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr);
|
||||
|
||||
enum {
|
||||
RKTIO_ADD_MEMBERSHIP,
|
||||
RKTIO_DROP_MEMBERSHIP
|
||||
};
|
||||
|
||||
RKTIO_EXTERN int rktio_udp_change_multicast_group(rktio_t *rktio, rktio_fd_t *rfd,
|
||||
rktio_addrinfo_t *group_addr,
|
||||
rktio_addrinfo_t *intf_addr,
|
||||
int action);
|
||||
/* `action` values: */
|
||||
enum {
|
||||
RKTIO_ADD_MEMBERSHIP,
|
||||
RKTIO_DROP_MEMBERSHIP
|
||||
};
|
||||
|
||||
/*************************************************/
|
||||
/* Environment variables */
|
||||
|
||||
/* Check whether a string is valid as a new (e.g., no "=") */
|
||||
RKTIO_EXTERN int rktio_is_ok_envvar_name(rktio_t *rktio, const char *name);
|
||||
RKTIO_EXTERN rktio_bool_t rktio_is_ok_envvar_name(rktio_t *rktio, const char *name);
|
||||
/* Checks whether a string is valid as a new (e.g., no "="). */
|
||||
|
||||
RKTIO_EXTERN rktio_bool_t rktio_are_envvar_names_case_insensitive(rktio_t *rktio);
|
||||
/* Checks whether environment variables are case-folded by the OS.
|
||||
That doesn't mean that clients need to case-fold names, but clients
|
||||
may want to immitate the OS. */
|
||||
RKTIO_EXTERN int rktio_are_envvar_names_case_insensitive(rktio_t *rktio);
|
||||
|
||||
RKTIO_EXTERN char *rktio_getenv(rktio_t *rktio, const char *name);
|
||||
/* Gets an environment variable value, or reports
|
||||
`RKTIO_ERROR_NO_SUCH_ENVVAR` when returning NULL; the result must
|
||||
be freed. */
|
||||
RKTIO_EXTERN char *rktio_getenv(rktio_t *rktio, const char *name);
|
||||
|
||||
RKTIO_EXTERN rktio_ok_t rktio_setenv(rktio_t *rktio, const char *name, const char *val);
|
||||
/* Set an environment variable's value, where a NULL value for `val`
|
||||
unsets it. */
|
||||
RKTIO_EXTERN rktio_ok_t rktio_setenv(rktio_t *rktio, const char *name, const char *val);
|
||||
|
||||
typedef struct rktio_envvars_t rktio_envvars_t;
|
||||
|
||||
/* Extracts all environment variables into a record */
|
||||
RKTIO_EXTERN rktio_envvars_t *rktio_envvars(rktio_t *rktio);
|
||||
/* Create an empty environment-variables record: */
|
||||
RKTIO_EXTERN rktio_envvars_t *rktio_empty_envvars(rktio_t *rktio);
|
||||
/* Clones an environment-variable record: */
|
||||
RKTIO_EXTERN rktio_envvars_t *rktio_envvars_copy(rktio_t *rktio, rktio_envvars_t *envvars);
|
||||
/* Deallocates an environment-variables record: */
|
||||
RKTIO_EXTERN void rktio_envvars_free(rktio_t *rktio, rktio_envvars_t *envvars);
|
||||
/* Extracts all environment variables into a record */
|
||||
|
||||
RKTIO_EXTERN rktio_envvars_t *rktio_empty_envvars(rktio_t *rktio);
|
||||
/* Create an empty environment-variables record. */
|
||||
|
||||
RKTIO_EXTERN rktio_envvars_t *rktio_envvars_copy(rktio_t *rktio, rktio_envvars_t *envvars);
|
||||
/* Clones an environment-variable record. */
|
||||
|
||||
RKTIO_EXTERN void rktio_envvars_free(rktio_t *rktio, rktio_envvars_t *envvars);
|
||||
/* Deallocates an environment-variables record: */
|
||||
|
||||
/* Access/update environment-variables record by name: */
|
||||
RKTIO_EXTERN char *rktio_envvars_get(rktio_t *rktio, rktio_envvars_t *envvars, char *name);
|
||||
RKTIO_EXTERN void rktio_envvars_set(rktio_t *rktio, rktio_envvars_t *envvars, char *name, char *value);
|
||||
/* Access/update environment-variables record by name. */
|
||||
|
||||
/* Access/update environment-variables record by index: */
|
||||
RKTIO_EXTERN intptr_t rktio_envvars_count(rktio_t *rktio, rktio_envvars_t *envvars);
|
||||
RKTIO_EXTERN char *rktio_envvars_name_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i);
|
||||
RKTIO_EXTERN char *rktio_envvars_value_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i);
|
||||
/* Access/update environment-variables record by index. */
|
||||
|
||||
/*************************************************/
|
||||
/* Processes */
|
||||
|
||||
typedef struct rktio_process_t rktio_process_t;
|
||||
|
||||
#define RKTIO_PROCESS_NEW_GROUP (1<<0)
|
||||
#define RKTIO_PROCESS_STDOUT_AS_STDERR (1<<1)
|
||||
#define RKTIO_PROCESS_WINDOWS_EXACT_CMDLINE (1<<2)
|
||||
#define RKTIO_PROCESS_WINDOWS_CHAIN_TERMINATION (1<<3)
|
||||
|
||||
typedef struct rktio_process_result_t {
|
||||
rktio_process_t *process;
|
||||
rktio_fd_t *stdin_fd, *stdout_fd, *stderr_fd;
|
||||
|
@ -227,67 +352,101 @@ RKTIO_EXTERN rktio_process_result_t *rktio_process(rktio_t *rktio,
|
|||
const char *current_directory, rktio_envvars_t *envvars,
|
||||
int flags,
|
||||
void (*unix_child_process_callback)());
|
||||
/* `flags` flags: */
|
||||
#define RKTIO_PROCESS_NEW_GROUP (1<<0)
|
||||
#define RKTIO_PROCESS_STDOUT_AS_STDERR (1<<1)
|
||||
#define RKTIO_PROCESS_WINDOWS_EXACT_CMDLINE (1<<2)
|
||||
#define RKTIO_PROCESS_WINDOWS_CHAIN_TERMINATION (1<<3)
|
||||
|
||||
RKTIO_EXTERN int rktio_process_allowed_flags(rktio_t *rktio);
|
||||
/* Reports the flags that are accepted by `rktio_process` on the
|
||||
current OS. */
|
||||
|
||||
RKTIO_EXTERN int rktio_process_pid(rktio_t *rktio, rktio_process_t *sp);
|
||||
/* Always succeeds, whether or not the process is still running. */
|
||||
|
||||
RKTIO_EXTERN rktio_ok_t rktio_process_kill(rktio_t *rktio, rktio_process_t *sp);
|
||||
RKTIO_EXTERN rktio_ok_t rktio_process_interrupt(rktio_t *rktio, rktio_process_t *sp);
|
||||
/* Interrupts or kills a process; does not deallocate the process record. */
|
||||
|
||||
RKTIO_EXTERN int rktio_process_kill(rktio_t *rktio, rktio_process_t *sp);
|
||||
RKTIO_EXTERN int rktio_process_interrupt(rktio_t *rktio, rktio_process_t *sp);
|
||||
RKTIO_EXTERN void rktio_process_forget(rktio_t *rktio, rktio_process_t *sp);
|
||||
/* Deallocates a process record, whether or not the process has
|
||||
stopped. */
|
||||
|
||||
RKTIO_EXTERN rktio_ok_t rktio_poll_process_done(rktio_t *rktio, rktio_process_t *sp);
|
||||
/* Check whether a process has completed: */
|
||||
#define RKTIO_PROCESS_ERROR (-2)
|
||||
#define RKTIO_PROCESS_DONE 1
|
||||
|
||||
RKTIO_EXTERN int rktio_poll_process_done(rktio_t *rktio, rktio_process_t *sp);
|
||||
#define RKTIO_PROCESS_RUNNING 0
|
||||
|
||||
typedef struct rktio_status_t {
|
||||
int running;
|
||||
rktio_bool_t running;
|
||||
int result;
|
||||
} rktio_status_t;
|
||||
|
||||
RKTIO_EXTERN rktio_status_t *rktio_process_status(rktio_t *rktio, rktio_process_t *sp);
|
||||
/* The `result` value is only value if `running` is 0. */
|
||||
|
||||
RKTIO_EXTERN void rktio_block_child_signals(rktio_t*rktio, int block);
|
||||
|
||||
|
||||
/*************************************************/
|
||||
/* Filesystem-change events */
|
||||
|
||||
RKTIO_EXTERN int rktio_fs_change_properties(rktio_t *rktio);
|
||||
/* Reports properties of the filesystem-change event implementation: */
|
||||
#define RKTIO_FS_CHANGE_SUPPORTED (1 << 0)
|
||||
#define RKTIO_FS_CHANGE_SCALABLE (1 << 1)
|
||||
#define RKTIO_FS_CHANGE_LOW_LATENCY (1 << 2)
|
||||
#define RKTIO_FS_CHANGE_FILE_LEVEL (1 << 3)
|
||||
|
||||
RKTIO_EXTERN int rktio_fs_change_properties(rktio_t *rktio);
|
||||
|
||||
typedef struct rktio_fs_change_t rktio_fs_change_t;
|
||||
|
||||
RKTIO_EXTERN rktio_fs_change_t *rktio_fs_change(rktio_t *rktio, char *path);
|
||||
|
||||
RKTIO_EXTERN void rktio_fs_change_forget(rktio_t *rktio, rktio_fs_change_t *fc);
|
||||
RKTIO_EXTERN int rktio_poll_fs_change_ready(rktio_t *rktio, rktio_fs_change_t *fc);
|
||||
|
||||
RKTIO_EXTERN rktio_tri_t rktio_poll_fs_change_ready(rktio_t *rktio, rktio_fs_change_t *fc);
|
||||
/* Returns one of `RKTIO_POLL_READY`, etc. */
|
||||
|
||||
/*************************************************/
|
||||
/* File-descriptor sets for polling */
|
||||
|
||||
/* A poll set works for a single use via rktio_sleep(), as opposed to
|
||||
"long-term" poll sets that can be used multiple times. */
|
||||
"long-term" poll sets that can be used multiple times. The
|
||||
`rktio_sleep` function accepts one of each and combines them. */
|
||||
|
||||
typedef struct rktio_poll_set_t rktio_poll_set_t;
|
||||
|
||||
#define RKTIO_POLL_READ RKTIO_OPEN_READ
|
||||
#define RKTIO_POLL_WRITE RKTIO_OPEN_WRITE
|
||||
|
||||
RKTIO_EXTERN rktio_poll_set_t *rktio_make_poll_set(rktio_t *rktio);
|
||||
RKTIO_EXTERN void rktio_poll_set_close(rktio_t *rktio, rktio_poll_set_t *fds);
|
||||
RKTIO_EXTERN void rktio_poll_set_forget(rktio_t *rktio, rktio_poll_set_t *fds);
|
||||
/* Don't reuse a poll set after calling `rktio_sleep`, but do
|
||||
explicitly forget it afterward. */
|
||||
|
||||
RKTIO_EXTERN void rktio_poll_add(rktio_t *rktio, rktio_fd_t *rfd, rktio_poll_set_t *fds, int modes);
|
||||
RKTIO_EXTERN void rktio_poll_add_receive(rktio_t *rktio, rktio_listener_t *listener, rktio_poll_set_t *fds);
|
||||
/* Registers a wait on a file descriptor in read and/or write mode or
|
||||
flush mode. The flush mode corresponds to
|
||||
`rktio_poll_write_flushed`.
|
||||
`modes` values: */
|
||||
#define RKTIO_POLL_READ RKTIO_OPEN_READ
|
||||
#define RKTIO_POLL_WRITE RKTIO_OPEN_WRITE
|
||||
#define RKTIO_POLL_FLUSH (RKTIO_OPEN_WRITE << 2)
|
||||
|
||||
RKTIO_EXTERN void rktio_poll_add_accept(rktio_t *rktio, rktio_listener_t *listener, rktio_poll_set_t *fds);
|
||||
RKTIO_EXTERN void rktio_poll_add_connect(rktio_t *rktio, rktio_connect_t *conn, rktio_poll_set_t *fds);
|
||||
RKTIO_EXTERN void rktio_poll_add_addrinfo_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup, rktio_poll_set_t *fds);
|
||||
RKTIO_EXTERN void rktio_poll_add_process(rktio_t *rktio, rktio_process_t *sp, rktio_poll_set_t *fds);
|
||||
RKTIO_EXTERN void rktio_poll_add_fs_change(rktio_t *rktio, rktio_fs_change_t *fc, rktio_poll_set_t *fds);
|
||||
/* Registers various other waits. */
|
||||
|
||||
RKTIO_EXTERN void rktio_poll_set_add_nosleep(rktio_t *rktio, rktio_poll_set_t *fds);
|
||||
/* Causes a sleep given `fds` to return immediately. */
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
RKTIO_EXTERN void rktio_poll_set_add_handle(rktio_t *rktio, intptr_t h, rktio_poll_set_t *fds, int repost);
|
||||
RKTIO_EXTERN void rktio_poll_set_add_eventmask(rktio_t *rktio, rktio_poll_set_t *fds, int mask);
|
||||
/* When sleeping on Windows, extra handles or eventmasks can be added
|
||||
to trigger a wake up */
|
||||
#endif
|
||||
|
||||
/*************************************************/
|
||||
|
@ -300,6 +459,23 @@ RKTIO_EXTERN void rktio_poll_set_add_eventmask(rktio_t *rktio, rktio_poll_set_t
|
|||
typedef struct rktio_ltps_t rktio_ltps_t;
|
||||
typedef struct rktio_ltps_handle_t rktio_ltps_handle_t;
|
||||
|
||||
RKTIO_EXTERN rktio_ltps_t *rktio_open_ltps(rktio_t *rktio);
|
||||
|
||||
RKTIO_EXTERN int rktio_ltps_close(rktio_t *rktio, rktio_ltps_t *lt);
|
||||
/* Closing will signal all remianing handles and free all signaled
|
||||
handles, but use `rktio_ltps_remove_all` and
|
||||
`rktio_ltps_get_signaled_handle` is you need to clean up any
|
||||
per-handle data: */
|
||||
|
||||
RKTIO_EXTERN rktio_ltps_handle_t *rktio_ltps_add(rktio_t *rktio, rktio_ltps_t *lt, rktio_fd_t *rfd, int mode);
|
||||
/* Don't free the returned handle; use it with `rktio_ltps_handle_set_data`
|
||||
and `rktio_ltps_handle_get_data`, and free it only when the same handle
|
||||
is returned by `rktio_ltps_get_signaled_handle`. Using the `RKTIO_LTPS_REMOVE`
|
||||
mode causes a previous created handle to be signaled. A successful remove
|
||||
reports `RKTIO_ERROR_LTPS_REMOVED` while returning NULL. A `...CHECK...`
|
||||
or `...REMOVE...` mode that doesn't find the handle reports
|
||||
`RKTIO_ERROR_LTPS_NOT_FOUND`.
|
||||
`mode` values: */
|
||||
enum {
|
||||
RKTIO_LTPS_CREATE_READ = 1,
|
||||
RKTIO_LTPS_CREATE_WRITE,
|
||||
|
@ -312,17 +488,21 @@ enum {
|
|||
RKTIO_LTPS_REMOVE_VNODE
|
||||
};
|
||||
|
||||
RKTIO_EXTERN rktio_ltps_t *rktio_open_ltps(rktio_t *rktio);
|
||||
RKTIO_EXTERN int rktio_ltps_close(rktio_t *rktio, rktio_ltps_t *lt);
|
||||
RKTIO_EXTERN void rktio_ltps_handle_set_data(rktio_t *rktio, rktio_ltps_handle_t *s, void *data);
|
||||
RKTIO_EXTERN void *rktio_ltps_handle_get_data(rktio_t *rktio, rktio_ltps_handle_t *s);
|
||||
|
||||
RKTIO_EXTERN rktio_ltps_handle_t *rktio_ltps_add(rktio_t *rktio, rktio_ltps_t *lt, rktio_fd_t *rfd, int mode);
|
||||
RKTIO_EXTERN void rktio_ltps_handle_set_data(rktio_ltps_t *lt, rktio_ltps_handle_t *s, void *data);
|
||||
RKTIO_EXTERN void *rktio_ltps_handle_get_data(rktio_ltps_t *lt, rktio_ltps_handle_t *s);
|
||||
void rktio_ltps_remove_all(rktio_t *rktio, rktio_ltps_t *lt);
|
||||
/* Removes all additions, signaling all handles. */
|
||||
|
||||
RKTIO_EXTERN rktio_ok_t rktio_ltps_poll(rktio_t *rktio, rktio_ltps_t *lt);
|
||||
/* Enqueues signaled handles for retreival via `rktio_ltps_get_signaled_handle`. */
|
||||
|
||||
RKTIO_EXTERN int rktio_ltps_poll(rktio_t *rktio, rktio_ltps_t *lt);
|
||||
RKTIO_EXTERN rktio_ltps_handle_t *rktio_ltps_get_signaled_handle(rktio_t *rktio, rktio_ltps_t *lt);
|
||||
/* Free the returned handle when you're done with it. */
|
||||
|
||||
RKTIO_EXTERN void rktio_sleep(rktio_t *rktio, float nsecs, rktio_poll_set_t *fds, rktio_ltps_t *lt);
|
||||
/* Waits up to `nsecs` seconds (or forever if `nsecs` is 0) or until
|
||||
something registered with `fds` or `lt` is ready. */
|
||||
|
||||
/*************************************************/
|
||||
/* Files, directories, and links */
|
||||
|
@ -334,34 +514,33 @@ RKTIO_EXTERN int rktio_is_regular_file(rktio_t *rktio, char *filename);
|
|||
|
||||
RKTIO_EXTERN rktio_ok_t rktio_delete_file(rktio_t *rktio, char *fn, int enable_write_on_fail);
|
||||
|
||||
/* Can report `RKTIO_ERROR_EXISTS`: */
|
||||
RKTIO_EXTERN rktio_ok_t rktio_rename_file(rktio_t *rktio, char *dest, char *src, int exists_ok);
|
||||
/* Can report `RKTIO_ERROR_EXISTS`. */
|
||||
|
||||
RKTIO_EXTERN char *rktio_get_current_directory(rktio_t *rktio);
|
||||
RKTIO_EXTERN rktio_ok_t rktio_set_current_directory(rktio_t *rktio, const char *path);
|
||||
|
||||
/* Can report `RKTIO_ERROR_EXISTS`: */
|
||||
RKTIO_EXTERN rktio_ok_t rktio_make_directory(rktio_t *rktio, char *filename);
|
||||
/* Can report `RKTIO_ERROR_EXISTS`. */
|
||||
|
||||
RKTIO_EXTERN rktio_ok_t rktio_delete_directory(rktio_t *rktio, char *filename, char *current_directory,
|
||||
int enable_write_on_fail);
|
||||
/* The `current_directory` argument is used on Windows to avoid being
|
||||
in `filename` (instead) as a directory while trying to delete it.
|
||||
The `enable_write_on_fail` argument also applied to Windows. */
|
||||
RKTIO_EXTERN rktio_ok_t rktio_delete_directory(rktio_t *rktio, char *filename, char *current_directory,
|
||||
int enable_write_on_fail);
|
||||
|
||||
RKTIO_EXTERN char *rktio_readlink(rktio_t *rktio, char *fullfilename);
|
||||
/* Argument should not have a trailing separator. Can report
|
||||
`RKTIO_ERROR_NOT_A_LINK`. */
|
||||
RKTIO_EXTERN char *rktio_readlink(rktio_t *rktio, char *fullfilename);
|
||||
|
||||
/* The `dest_is_directory` argument is used only
|
||||
on Windows. Can report `RKTIO_ERROR_EXISTS`. */
|
||||
RKTIO_EXTERN rktio_ok_t rktio_make_link(rktio_t *rktio, char *src, char *dest,
|
||||
int dest_is_directory);
|
||||
/* The `dest_is_directory` argument is used only
|
||||
on Windows. Can report `RKTIO_ERROR_EXISTS`. */
|
||||
|
||||
/*************************************************/
|
||||
/* File attributes */
|
||||
|
||||
typedef rktio_int64_t rktio_filesize_t;
|
||||
typedef intptr_t rktio_timestamp_t;
|
||||
|
||||
RKTIO_EXTERN rktio_filesize_t *rktio_file_size(rktio_t *rktio, char *filename);
|
||||
|
@ -387,43 +566,44 @@ RKTIO_EXTERN rktio_identity_t *rktio_path_identity(rktio_t *rktio, char *path, i
|
|||
|
||||
#define RKTIO_PERMISSION_ERROR (-1)
|
||||
|
||||
RKTIO_EXTERN int rktio_get_file_or_directory_permissions(rktio_t *rktio, char *filename, int all_bits);
|
||||
/* Result is `RKTIO_PERMISSION_ERROR` for error, otherwise a combination of
|
||||
bits. If not `all_bits`, then use constants above. */
|
||||
RKTIO_EXTERN int rktio_get_file_or_directory_permissions(rktio_t *rktio, char *filename, int all_bits);
|
||||
|
||||
RKTIO_EXTERN rktio_ok_t rktio_set_file_or_directory_permissions(rktio_t *rktio, char *filename, int new_bits);
|
||||
/* The `new_bits` format corresponds to `all_bits` for getting permissions.
|
||||
Can report `RKTIO_ERROR_BAD_PERMISSION` for bits that make no sense. */
|
||||
RKTIO_EXTERN rktio_ok_t rktio_set_file_or_directory_permissions(rktio_t *rktio, char *filename, int new_bits);
|
||||
|
||||
/*************************************************/
|
||||
/* Directory listing */
|
||||
|
||||
typedef struct rktio_directory_list_t rktio_directory_list_t;
|
||||
|
||||
RKTIO_EXTERN rktio_directory_list_t *rktio_directory_list_start(rktio_t *rktio, char *filename);
|
||||
/* On Windows, the given `filename` must be normalized and not have
|
||||
`.` or `..`: */
|
||||
RKTIO_EXTERN rktio_directory_list_t *rktio_directory_list_start(rktio_t *rktio, char *filename);
|
||||
|
||||
RKTIO_EXTERN char *rktio_directory_list_step(rktio_t *rktio, rktio_directory_list_t *dl);
|
||||
/* Returns an unallocated "" and deallocates `dl` when the iteration
|
||||
is complete. A NULL result would mean an error without deallocating
|
||||
`dl`, but that doesn't currently happen. */
|
||||
RKTIO_EXTERN char *rktio_directory_list_step(rktio_t *rktio, rktio_directory_list_t *dl);
|
||||
|
||||
RKTIO_EXTERN void rktio_directory_list_stop(rktio_t *rktio, rktio_directory_list_t *dl);
|
||||
/* Interrupt a directory list in progress, not needed after
|
||||
rktio_directory_list_step() returns "": */
|
||||
RKTIO_EXTERN void rktio_directory_list_stop(rktio_t *rktio, rktio_directory_list_t *dl);
|
||||
|
||||
RKTIO_EXTERN char **rktio_filesystem_root_list(rktio_t *rktio);
|
||||
/* Returns a NULL-terminated array. Free each string. Currently never
|
||||
errors. */
|
||||
RKTIO_EXTERN char **rktio_filesystem_root_list(rktio_t *rktio);
|
||||
|
||||
/*************************************************/
|
||||
/* File copying */
|
||||
|
||||
typedef struct rktio_file_copy_t rktio_file_copy_t;
|
||||
|
||||
/* Can report `RKTIO_ERROR_EXISTS`: */
|
||||
RKTIO_EXTERN rktio_file_copy_t *rktio_copy_file_start(rktio_t *rktio, char *dest, char *src, int exists_ok);
|
||||
RKTIO_EXTERN rktio_file_copy_t *rktio_copy_file_start(rktio_t *rktio, char *dest, char *src,
|
||||
rktio_bool_t exists_ok);
|
||||
/* Can report `RKTIO_ERROR_EXISTS`. */
|
||||
|
||||
RKTIO_EXTERN int rktio_copy_file_is_done(rktio_t *rktio, rktio_file_copy_t *fc);
|
||||
RKTIO_EXTERN rktio_ok_t rktio_copy_file_step(rktio_t *rktio, rktio_file_copy_t *fc);
|
||||
|
@ -432,6 +612,8 @@ RKTIO_EXTERN void rktio_copy_file_stop(rktio_t *rktio, rktio_file_copy_t *fc);
|
|||
/*************************************************/
|
||||
/* System paths */
|
||||
|
||||
RKTIO_EXTERN char *rktio_system_path(rktio_t *rktio, int which);
|
||||
/* `which` values: */
|
||||
enum {
|
||||
RKTIO_PATH_SYS_DIR,
|
||||
RKTIO_PATH_TEMP_DIR,
|
||||
|
@ -445,12 +627,10 @@ enum {
|
|||
RKTIO_PATH_INIT_FILE
|
||||
};
|
||||
|
||||
RKTIO_EXTERN char *rktio_system_path(rktio_t *rktio, int which);
|
||||
|
||||
RKTIO_EXTERN char *rktio_expand_user_tilde(rktio_t *rktio, char *filename);
|
||||
/* Path must start with tilde, otherwise `RKTIO_ERROR_NO_TILDE`.
|
||||
Other possible errors are `RKTIO_ERROR_ILL_FORMED_USER` and
|
||||
`RKTIO_ERROR_UNKNOWN_USER`. */
|
||||
RKTIO_EXTERN char *rktio_expand_user_tilde(rktio_t *rktio, char *filename);
|
||||
|
||||
/*************************************************/
|
||||
/* Sleep and signals */
|
||||
|
@ -461,6 +641,12 @@ RKTIO_EXTERN rktio_signal_handle_t *rktio_get_signal_handle(rktio_t *rktio);
|
|||
RKTIO_EXTERN void rktio_signal_received_at(rktio_signal_handle_t *h);
|
||||
RKTIO_EXTERN void rktio_signal_received(rktio_t *rktio);
|
||||
|
||||
RKTIO_EXTERN void rktio_wait_until_signal_received(rktio_t *rktio);
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
RKTIO_EXTERN int rktio_signal_handle_to_fd();
|
||||
#endif
|
||||
|
||||
/*************************************************/
|
||||
/* Time and date */
|
||||
|
||||
|
@ -471,7 +657,7 @@ typedef struct rktio_date_t {
|
|||
int day_of_year;
|
||||
int is_dst;
|
||||
int zone_offset;
|
||||
char *zone_name; /* can be NULL */
|
||||
char *zone_name; /* can be NULL; otherwise, free it */
|
||||
} rktio_date_t;
|
||||
|
||||
RKTIO_EXTERN intptr_t rktio_get_milliseconds(void);
|
||||
|
@ -486,23 +672,30 @@ RKTIO_EXTERN rktio_date_t *rktio_seconds_to_date(rktio_t *rktio, rktio_timestamp
|
|||
/*************************************************/
|
||||
/* Errors */
|
||||
|
||||
RKTIO_EXTERN int rktio_get_last_error_kind(rktio_t *rktio);
|
||||
|
||||
/* Kinds of error values: */
|
||||
enum {
|
||||
RKTIO_ERROR_KIND_POSIX,
|
||||
RKTIO_ERROR_KIND_WINDOWS,
|
||||
RKTIO_ERROR_KIND_GAI, /* => error sub-code available */
|
||||
RKTIO_ERROR_KIND_GAI,
|
||||
RKTIO_ERROR_KIND_RACKET
|
||||
};
|
||||
|
||||
RKTIO_EXTERN int rktio_get_last_error(rktio_t *rktio);
|
||||
|
||||
/* Error IDs of kind RKTIO_ERROR_KIND_RACKET */
|
||||
enum {
|
||||
RKTIO_ERROR_UNSUPPORTED = 1,
|
||||
RKTIO_ERROR_DOES_NOT_EXIST,
|
||||
RKTIO_ERROR_EXISTS,
|
||||
RKTIO_ERROR_LINK_FAILED,
|
||||
RKTIO_ERROR_NOT_A_LINK,
|
||||
RKTIO_ERROR_BAD_PERMISSION,
|
||||
RKTIO_ERROR_IS_A_DIRECTORY,
|
||||
RKTIO_ERROR_NOT_A_DIRECTORY,
|
||||
RKTIO_ERROR_UNSUPPORTED_TEXT_MODE,
|
||||
RKTIO_ERROR_CANNOT_FILE_POSITION,
|
||||
RKTIO_ERROR_NO_TILDE,
|
||||
RKTIO_ERROR_ILL_FORMED_USER,
|
||||
RKTIO_ERROR_UNKNOWN_USER,
|
||||
|
@ -519,20 +712,11 @@ enum {
|
|||
RKTIO_ERROR_NO_SUCH_ENVVAR,
|
||||
};
|
||||
|
||||
/* GAI error sub-codes */
|
||||
enum {
|
||||
RKTIO_ERROR_REMOTE_HOST_NOT_FOUND,
|
||||
RKTIO_ERROR_LOCAL_HOST_NOT_FOUND,
|
||||
};
|
||||
|
||||
RKTIO_EXTERN int rktio_get_last_error(rktio_t *rktio);
|
||||
RKTIO_EXTERN int rktio_get_last_error_kind(rktio_t *rktio);
|
||||
|
||||
RKTIO_EXTERN const char *rktio_get_last_error_string(rktio_t *rktio);
|
||||
RKTIO_EXTERN const char *rktio_get_error_string(rktio_t *rktio, int kind, int errid);
|
||||
/* The returned strings for `rktio_...error_string()` should not be
|
||||
deallocated, but it only lasts reliably until the next call to
|
||||
either of the functions. */
|
||||
RKTIO_EXTERN const char *rktio_get_last_error_string(rktio_t *rktio);
|
||||
RKTIO_EXTERN const char *rktio_get_error_string(rktio_t *rktio, int kind, int errid);
|
||||
|
||||
/*************************************************/
|
||||
|
||||
|
|
|
@ -19,6 +19,12 @@ extern char **environ;
|
|||
# define GET_ENVIRON_ARRAY environ
|
||||
#endif
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
char **rktio_get_environ_array(void)
|
||||
{
|
||||
return GET_ENVIRON_ARRAY;
|
||||
}
|
||||
#endif
|
||||
|
||||
int rktio_is_ok_envvar_name(rktio_t *rktio, const char *s)
|
||||
{
|
||||
|
|
|
@ -13,12 +13,15 @@ typedef struct err_str_t {
|
|||
|
||||
err_str_t err_strs[] = {
|
||||
{ RKTIO_ERROR_UNSUPPORTED, "unsupported" },
|
||||
{ RKTIO_ERROR_EXISTS, "file or directory already exists"},
|
||||
{ RKTIO_ERROR_DOES_NOT_EXIST, "no such file or directory" },
|
||||
{ RKTIO_ERROR_EXISTS, "file or directory already exists" },
|
||||
{ RKTIO_ERROR_LINK_FAILED, "link creation failed" },
|
||||
{ RKTIO_ERROR_NOT_A_LINK, "not a link" },
|
||||
{ RKTIO_ERROR_BAD_PERMISSION, "unsupported permission value" },
|
||||
{ RKTIO_ERROR_IS_A_DIRECTORY, "path refers to a directory" },
|
||||
{ RKTIO_ERROR_NOT_A_DIRECTORY, "path does not refer to a directory" },
|
||||
{ RKTIO_ERROR_UNSUPPORTED_TEXT_MODE, "cannot use text mode on a non-file device" },
|
||||
{ RKTIO_ERROR_CANNOT_FILE_POSITION, "cannot get/set position/size on device" },
|
||||
{ RKTIO_ERROR_NO_TILDE, "path does not start with a tilde" },
|
||||
{ RKTIO_ERROR_ILL_FORMED_USER, "ill-formed username in path" },
|
||||
{ RKTIO_ERROR_UNKNOWN_USER, "unknown username in path" },
|
||||
|
|
|
@ -39,6 +39,7 @@ struct rktio_fd_t {
|
|||
struct Win_FD_Output_Thread *oth; /* output mode */
|
||||
int unblocked; /* whether non-blocking mode is installed */
|
||||
char *buffer; /* shared with reading thread */
|
||||
int pending_cr; /* for text-mode input, may be dropped by a following lf */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -112,6 +113,10 @@ static CSI_proc get_csi(void)
|
|||
return csi;
|
||||
}
|
||||
|
||||
static intptr_t rktio_adjust_input_text(rktio_fd_t *rfd, char *buffer, intptr_t got);
|
||||
static char *rktio_adjust_output_text(char *buffer, intptr_t *towrite);
|
||||
static intptr_t rktio_recount_output_text(char *orig_buffer, char *buffer, intptr_t wrote);
|
||||
|
||||
#endif
|
||||
|
||||
/*========================================================================*/
|
||||
|
@ -173,7 +178,7 @@ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes)
|
|||
{
|
||||
rktio_fd_t *rfd;
|
||||
|
||||
rfd = malloc(sizeof(rktio_fd_t));
|
||||
rfd = calloc(1, sizeof(rktio_fd_t));
|
||||
rfd->modes = modes;
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
|
@ -203,6 +208,12 @@ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes)
|
|||
if (modes & RKTIO_OPEN_READ)
|
||||
init_read_fd(rktio, rfd);
|
||||
|
||||
if ((modes & RKTIO_OPEN_SOCKET) && (modes & RKTIO_OPEN_INIT))
|
||||
rktio_socket_init(rktio, rfd);
|
||||
|
||||
if ((modes & RKTIO_OPEN_SOCKET) && (modes & RKTIO_OPEN_OWN))
|
||||
rktio_socket_own(rktio, rfd);
|
||||
|
||||
return rfd;
|
||||
}
|
||||
|
||||
|
@ -219,6 +230,30 @@ intptr_t rktio_fd_system_fd(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
#endif
|
||||
}
|
||||
|
||||
rktio_fd_t *rktio_std_fd(rktio_t *rktio, int which)
|
||||
{
|
||||
int mode = ((which == RKTIO_STDIN)
|
||||
? RKTIO_OPEN_READ
|
||||
: RKTIO_OPEN_WRITE);
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
return rktio_system_fd(rktio, which, mode);
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
switch (which) {
|
||||
case RKTIO_STDIN:
|
||||
which = STD_INPUT_HANDLE;
|
||||
break;
|
||||
case RKTIO_STDOUT:
|
||||
which = STD_OUTPUT_HANDLE;
|
||||
break;
|
||||
case RKTIO_STDERR:
|
||||
which = STD_ERROR_HANDLE;
|
||||
break;
|
||||
}
|
||||
return rktio_system_fd(rktio, (intptr_t)GetStdHandle(which), mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
int rktio_fd_is_regular_file(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
return ((rfd->modes & RKTIO_OPEN_REGFILE) ? 1 : 0);
|
||||
|
@ -261,6 +296,15 @@ int rktio_fd_is_terminal(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
return rktio_system_fd_is_terminal(rktio, (intptr_t)rfd->fd);
|
||||
}
|
||||
|
||||
int rktio_fd_is_text_converted(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (rfd->modes & RKTIO_OPEN_TEXT)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
|
@ -382,12 +426,6 @@ int rktio_close(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
|
||||
void rktio_forget(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (rfd->modes & RKTIO_OPEN_SOCKET) {
|
||||
rktio_socket_forget(rktio, rfd);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
free(rfd);
|
||||
}
|
||||
|
||||
|
@ -661,6 +699,13 @@ void rktio_poll_add(rktio_t *rktio, rktio_fd_t *rfd, rktio_poll_set_t *fds, int
|
|||
else
|
||||
rktio_poll_set_add_nosleep(rktio, fds);
|
||||
}
|
||||
|
||||
if (modes & RKTIO_POLL_FLUSH) {
|
||||
if (rfd->oth && !rktio_poll_flush_ready(rktio, rfd))
|
||||
rktio_poll_set_add_handle(rktio, (intptr_t)rfd->oth->ready_sema, fds, 1);
|
||||
else
|
||||
rktio_poll_set_add_nosleep(rktio, fds);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -677,6 +722,14 @@ intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
|||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||
return rktio_socket_read(rktio, rfd, buffer, len);
|
||||
|
||||
# ifdef SOME_FDS_ARE_NOT_SELECTABLE
|
||||
if (rfd->bufcount && len) {
|
||||
buffer[0] = rfd->buffer[0];
|
||||
rfd->bufcount = 0;
|
||||
return 1;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (rktio_fd_is_regular_file(rktio, rfd)) {
|
||||
/* Reading regular file never blocks */
|
||||
do {
|
||||
|
@ -730,6 +783,11 @@ intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
|||
reading never blocks. */
|
||||
DWORD rgot;
|
||||
|
||||
if (rfd->pending_cr && len) {
|
||||
/* just in case we need to add the cr */
|
||||
len--;
|
||||
}
|
||||
|
||||
if (!ReadFile((HANDLE)rfd->fd, buffer, len, &rgot, NULL)) {
|
||||
get_windows_error();
|
||||
return RKTIO_READ_ERROR;
|
||||
|
@ -737,6 +795,8 @@ intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
|||
|
||||
if (!rgot)
|
||||
return RKTIO_READ_EOF;
|
||||
else if (rfd->modes & RKTIO_OPEN_TEXT)
|
||||
return rktio_adjust_input_text(rfd, buffer, rgot);
|
||||
else
|
||||
return rgot;
|
||||
} else {
|
||||
|
@ -764,7 +824,46 @@ intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
|||
#endif
|
||||
}
|
||||
|
||||
RKTIO_EXTERN intptr_t rktio_buffered_byte_count(rktio_t *rktio, rktio_fd_t *fd)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
# ifdef SOME_FDS_ARE_NOT_SELECTABLE
|
||||
return rfd->bufcount;
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
return (fd-?pending_cr : 1 : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
|
||||
static intptr_t rktio_adjust_input_text(rktio_fd_t *rfd, char *buffer, intptr_t got)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (rfd->pending_cr) {
|
||||
MSC_IZE(memmove)(buffer+1, buffer, got);
|
||||
buffer[0] = '\r';
|
||||
rfd->pending_cr = 0;
|
||||
got++;
|
||||
}
|
||||
if (got && (buffer[got-1] == '\r')) {
|
||||
rfd->pending_cr = 1;
|
||||
--got;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < got-1; i++) {
|
||||
if ((buffer[i] == '\r') && (buffer[i+1] == '\n'))
|
||||
buffer[j++] = '\n';
|
||||
else
|
||||
buffer[j++] = buffer[i++];
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
static long WINAPI WindowsFDReader(Win_FD_Input_Thread *th)
|
||||
{
|
||||
|
@ -887,17 +986,21 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len
|
|||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||
return rktio_socket_write(rktio, rfd, buffer, len);
|
||||
|
||||
if (rktio_fd_is_regular_file(rktio, rfd)) {
|
||||
if (rktio_fd_is_regular_file(rktio, rfd)
|
||||
|| rktio_fd_is_terminal(rktio, rfd)) {
|
||||
/* Regular files never block, so this code looks like the Unix
|
||||
code. We've cheated in the make_fd proc and called
|
||||
consoles regular files, because they cannot block, either. */
|
||||
code. */
|
||||
|
||||
/* If we try to write too much at once, the result
|
||||
is ERROR_NOT_ENOUGH_MEMORY (as opposed to a partial write). */
|
||||
int ok;
|
||||
intptr_t towrite = len;
|
||||
char *orig_buffer = buffer;
|
||||
int err;
|
||||
|
||||
if (rfd->modes & RKTIO_OPEN_TEXT)
|
||||
buffer = rktio_adjust_output_text(buffer, &towrite);
|
||||
|
||||
while (1) {
|
||||
ok = WriteFile((HANDLE)rfd->fd, buffer, towrite, &winwrote, NULL);
|
||||
if (!ok)
|
||||
|
@ -905,6 +1008,11 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len
|
|||
|
||||
if (!ok && (err == ERROR_NOT_ENOUGH_MEMORY)) {
|
||||
towrite = towrite >> 1;
|
||||
if (towrite && (buffer != orig_buffer)) {
|
||||
/* don't write half of a CRLF: */
|
||||
if ((buffer[towrite-1] == '\r') && (buffer[towrite-1] == '\n'))
|
||||
--towrite;
|
||||
}
|
||||
if (!towrite)
|
||||
break;
|
||||
} else
|
||||
|
@ -916,6 +1024,11 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len
|
|||
return RKTIO_WRITE_ERROR;
|
||||
}
|
||||
|
||||
if (buffer != orig_buffer) {
|
||||
/* Convert converted count back to original count: */
|
||||
winwrote = rktio_recount_output_text(orig_buffer, buffer, winwrote);
|
||||
}
|
||||
|
||||
return winwrote;
|
||||
} else {
|
||||
/* If we don't have a thread yet, we'll need to start it. If
|
||||
|
@ -1152,6 +1265,54 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len
|
|||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
|
||||
static char *rktio_adjust_output_text(char *buffer, intptr_t *towrite)
|
||||
{
|
||||
intptr_t len = *towrite, i, j, newlines = 0;
|
||||
char *new_buffer;
|
||||
|
||||
/* Limit work done here to avoid O(N^2) work if a client tried
|
||||
repeatedly to write a O(N)-sized buffer and only part goes out
|
||||
each time. */
|
||||
if (len > 4096)
|
||||
len = 4096;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buffer[i] == '\n')
|
||||
newlines++;
|
||||
}
|
||||
|
||||
if (!newlines)
|
||||
return buffer;
|
||||
|
||||
new_buffer = malloc(len + newlines);
|
||||
*towrite = len + newlines;
|
||||
|
||||
for (i = 0, j = 0; i < len; i++) {
|
||||
if (buffer[i] == '\n') {
|
||||
new_buffer[j++] = '\r';
|
||||
new_buffer[j++] = '\n';
|
||||
} else
|
||||
new_buffer[j++] = buffer[i];
|
||||
}
|
||||
|
||||
return new_buffer;
|
||||
}
|
||||
|
||||
static intptr_t rktio_recount_output_text(char *orig_buffer, char *buffer, intptr_t wrote)
|
||||
{
|
||||
intptr_t i = 0, j = 0;
|
||||
|
||||
while (j < wrote) {
|
||||
if (buffer[i] == '\n')
|
||||
j += 2;
|
||||
or
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth)
|
||||
{
|
||||
DWORD towrite, wrote, start;
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
/*************************************************************/
|
||||
/* opening a file fd */
|
||||
/*************************************************************/
|
||||
/*========================================================================*/
|
||||
/* Opening a file */
|
||||
/*========================================================================*/
|
||||
|
||||
static rktio_fd_t *open_read(rktio_t *rktio, char *filename)
|
||||
{
|
||||
|
@ -27,6 +27,9 @@ static rktio_fd_t *open_read(rktio_t *rktio, char *filename)
|
|||
} while ((fd == -1) && (errno == EINTR));
|
||||
|
||||
if (fd == -1) {
|
||||
if (errno == ENOENT) {
|
||||
set_racket_error(RKTIO_ERROR_DOES_NOT_EXIST);
|
||||
} else
|
||||
get_posix_error();
|
||||
return NULL;
|
||||
} else {
|
||||
|
@ -60,6 +63,7 @@ static rktio_fd_t *open_read(rktio_t *rktio, char *filename)
|
|||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
HANDLE fd;
|
||||
rktio_fd_t *rfd;
|
||||
|
||||
fd = CreateFileW(WIDE_PATH_temp(filename),
|
||||
GENERIC_READ,
|
||||
|
@ -70,11 +74,24 @@ static rktio_fd_t *open_read(rktio_t *rktio, char *filename)
|
|||
NULL);
|
||||
|
||||
if (fd == INVALID_HANDLE_VALUE) {
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||
set_racket_error(RKTIO_ERROR_DOES_NOT_EXIST);
|
||||
} else
|
||||
get_windows_error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rktio_system_fd(rktio, (intptr_t)fd, RKTIO_OPEN_READ);
|
||||
rfd = rktio_system_fd(rktio, (intptr_t)fd, RKTIO_OPEN_READ);
|
||||
|
||||
if (modes & RKTIO_MODE_TEXT) {
|
||||
if (!rktio_fd_is_regular_file(rfd)) {
|
||||
rktio_fd_forget(rfd);
|
||||
set_racket_error(RKTIO_ERROR_UNSUPPORTED_TEXT_MODE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return rfd;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -222,6 +239,14 @@ static rktio_fd_t *open_write(rktio_t *rktio, char *filename, int modes)
|
|||
|
||||
rfd = rktio_system_fd(rktio, (intptr_t)fd, modes);
|
||||
|
||||
if (modes & RKTIO_MODE_TEXT) {
|
||||
if (!rktio_fd_is_regular_file(rfd)) {
|
||||
rktio_fd_forget(rfd);
|
||||
set_racket_error(RKTIO_ERROR_UNSUPPORTED_TEXT_MODE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((modes & RKTIO_OPEN_APPEND) && rktio_fd_is_regular_file(rktio, rfd)) {
|
||||
SetFilePointer(fd, 0, NULL, FILE_END);
|
||||
}
|
||||
|
@ -238,3 +263,131 @@ rktio_fd_t *rktio_open(rktio_t *rktio, char *filename, int modes)
|
|||
return open_read(rktio, filename);
|
||||
}
|
||||
|
||||
/*========================================================================*/
|
||||
/* File positions */
|
||||
/*========================================================================*/
|
||||
|
||||
#ifdef WINDOWS_FILE_HANDLES
|
||||
static int win_seekable(intptr_t fd)
|
||||
{
|
||||
/* SetFilePointer() requires " a file stored on a seeking device".
|
||||
I'm not sure how to test that, so we approximate as "regular
|
||||
file". */
|
||||
return GetFileType((HANDLE)fd) == FILE_TYPE_DISK;
|
||||
}
|
||||
#endif
|
||||
|
||||
rktio_ok_t rktio_set_file_position(rktio_t *rktio, rktio_fd_t *rfd, rktio_filesize_t pos, int whence)
|
||||
{
|
||||
intptr_t fd = rktio_fd_system_fd(rktio, rfd);
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
if (whence == RKTIO_POSITION_FROM_START)
|
||||
whence = SEEK_SET;
|
||||
else
|
||||
whence = SEEK_END;
|
||||
if (BIG_OFF_T_IZE(lseek)(fd, pos, whence) < 0) {
|
||||
get_posix_error();
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (win_seekable(fd)) {
|
||||
DWORD r;
|
||||
LONG lo_w, hi_w;
|
||||
lo_w = (LONG)(pos & 0xFFFFFFFF);
|
||||
hi_w = (LONG)(pos >> 32);
|
||||
r = SetFilePointer((HANDLE)fd, lo_w, &hi_w,
|
||||
((whence == RKTIO_POSITION_FROM_START) ? FILE_BEGIN : FILE_END));
|
||||
if ((r == INVALID_SET_FILE_POINTER)
|
||||
&& GetLastError() != NO_ERROR) {
|
||||
get_windows_error();
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
} else {
|
||||
set_racket_error(RKTIO_ERROR_CANNOT_SET_FILE_POSITION);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
rktio_filesize_t *rktio_get_file_position(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
intptr_t fd = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_filesize_t pll, *r;
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
pll = BIG_OFF_T_IZE(lseek)(fd, 0, 1);
|
||||
if (pll < 0) {
|
||||
get_posix_error();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (win_seekable(fd)) {
|
||||
DWORD lo_w, hi_w;
|
||||
hi_w = 0;
|
||||
lo_w = SetFilePointer((HANDLE)fd, 0, &hi_w, FILE_CURRENT);
|
||||
if ((lo_w == INVALID_SET_FILE_POINTER)
|
||||
&& GetLastError() != NO_ERROR) {
|
||||
get_windows_error();
|
||||
return NULL;
|
||||
} else
|
||||
pll = ((mzlonglong)hi_w << 32) | lo_w;
|
||||
} else {
|
||||
set_racket_error(RKTIO_ERROR_CANNOT_SET_FILE_POSITION);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
r = malloc(sizeof(rktio_filesize_t));
|
||||
*r = pll;
|
||||
return r;
|
||||
}
|
||||
|
||||
rktio_ok_t rktio_set_file_size(rktio_t *rktio, rktio_fd_t *rfd, rktio_filesize_t sz)
|
||||
{
|
||||
intptr_t fd = rktio_fd_system_fd(rktio, rfd);
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
if (!BIG_OFF_T_IZE(ftruncate)(fd, sz))
|
||||
return 1;
|
||||
get_posix_error();
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (win_seekable(fd)) {
|
||||
DWORD r;
|
||||
LONG lo_w, hi_w, old_lo_w, old_hi_w;
|
||||
old_hi_w = 0;
|
||||
old_lo_w = SetFilePointer((HANDLE)fd, 0, &old_hi_w, FILE_CURRENT);
|
||||
if ((old_lo_w == INVALID_SET_FILE_POINTER)
|
||||
&& GetLastError() != NO_ERROR) {
|
||||
get_windows_error();
|
||||
return 0;
|
||||
} else {
|
||||
lo_w = (LONG)(sz & 0xFFFFFFFF);
|
||||
hi_w = (LONG)(sz >> 32);
|
||||
r = SetFilePointer((HANDLE)fd, lo_w, &hi_w, FILE_BEGIN);
|
||||
if ((r == INVALID_SET_FILE_POINTER)
|
||||
&& GetLastError() != NO_ERROR) {
|
||||
get_windows_error();
|
||||
return 0;
|
||||
} else {
|
||||
if (SetEndOfFile((HANDLE)fd)) {
|
||||
/* we assume that this works: */
|
||||
(void)SetFilePointer((HANDLE)fd, lo_w, &hi_w, FILE_BEGIN);
|
||||
return 1;
|
||||
}
|
||||
get_windows_error();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
set_racket_error(RKTIO_ERROR_CANNOT_SET_FILE_POSITION);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ void rktio_release_lockf(rktio_t *rktio, int fd)
|
|||
}
|
||||
#endif
|
||||
|
||||
int rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
rktio_ok_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
intptr_t fd = rktio_fd_system_fd(rktio, rfd);
|
||||
int ok;
|
||||
|
@ -240,5 +240,6 @@ int rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
if (!ok)
|
||||
get_windows_error();
|
||||
#endif
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -46,12 +46,6 @@
|
|||
#endif
|
||||
#define IS_A_SEP(c) ((c) == A_PATH_SEP)
|
||||
|
||||
#ifdef USE_TRANSITIONAL_64_FILE_OPS
|
||||
# define BIG_OFF_T_IZE(n) n ## 64
|
||||
#else
|
||||
# define BIG_OFF_T_IZE(n) n
|
||||
#endif
|
||||
|
||||
#if defined(RKTIO_SYSTEM_UNIX) && !defined(NO_UNIX_USERS)
|
||||
static int have_user_ids = 0;
|
||||
static uid_t uid;
|
||||
|
|
|
@ -10,7 +10,6 @@ struct rktio_hash_t {
|
|||
typedef struct bucket_t {
|
||||
/* v is non-NULL => bucket is filled */
|
||||
/* v is NULL and fd is -1 => was removed */
|
||||
int used;
|
||||
intptr_t key;
|
||||
void *v;
|
||||
} bucket_t;
|
||||
|
@ -41,6 +40,19 @@ int rktio_hash_is_empty(rktio_hash_t *ht)
|
|||
return (ht->count == 0);
|
||||
}
|
||||
|
||||
intptr_t rktio_hash_size(rktio_hash_t *ht)
|
||||
{
|
||||
return ht->size;
|
||||
}
|
||||
|
||||
intptr_t rktio_hash_get_key(rktio_hash_t *ht, intptr_t i)
|
||||
{
|
||||
if (ht->buckets[i].v)
|
||||
return ht->buckets[i].key;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void do_rehash(rktio_hash_t *ht, intptr_t new_size)
|
||||
{
|
||||
if (new_size >= 16) {
|
||||
|
@ -81,7 +93,7 @@ void *rktio_hash_get(rktio_hash_t *ht, intptr_t key)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void rktio_hash_remove(rktio_hash_t *ht, intptr_t key)
|
||||
void rktio_hash_remove(rktio_hash_t *ht, intptr_t key, int dont_rehash)
|
||||
{
|
||||
if (ht->buckets) {
|
||||
intptr_t mask = (ht->size - 1);
|
||||
|
@ -93,8 +105,10 @@ void rktio_hash_remove(rktio_hash_t *ht, intptr_t key)
|
|||
ht->buckets[hc].key = -1;
|
||||
ht->buckets[hc].v = NULL;
|
||||
--ht->count;
|
||||
if (!dont_rehash) {
|
||||
if (4 * ht->count <= ht->size)
|
||||
do_rehash(ht, ht->size >> 1);
|
||||
}
|
||||
} else if (ht->buckets[hc].v
|
||||
|| (ht->buckets[hc].key == -1)) {
|
||||
/* keep looking */
|
||||
|
|
|
@ -82,12 +82,12 @@ void ltps_signal_handle(rktio_ltps_t *lt, rktio_ltps_handle_t *s)
|
|||
lt->signaled = s;
|
||||
}
|
||||
|
||||
void rktio_ltps_handle_set_data(rktio_ltps_t *lt, rktio_ltps_handle_t *s, void *data)
|
||||
void rktio_ltps_handle_set_data(rktio_t *rktio, rktio_ltps_handle_t *s, void *data)
|
||||
{
|
||||
s->data = data;
|
||||
}
|
||||
|
||||
void *rktio_ltps_handle_get_data(rktio_ltps_t *lt, rktio_ltps_handle_t *s)
|
||||
void *rktio_ltps_handle_get_data(rktio_t *rktio, rktio_ltps_handle_t *s)
|
||||
{
|
||||
return s->data;
|
||||
}
|
||||
|
@ -131,6 +131,8 @@ int rktio_ltps_close(rktio_t *rktio, rktio_ltps_t *lt)
|
|||
{
|
||||
rktio_ltps_handle_t *s;
|
||||
|
||||
rktio_ltps_remove_all(rktio, lt);
|
||||
|
||||
while ((s = rktio_ltps_get_signaled_handle(rktio, lt)))
|
||||
free(s);
|
||||
|
||||
|
@ -167,19 +169,17 @@ rktio_ltps_handle_t *rktio_ltps_get_signaled_handle(rktio_t *rktio, rktio_ltps_t
|
|||
#if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL)
|
||||
static void log_kqueue_error(const char *action, int kr)
|
||||
{
|
||||
#if 0
|
||||
if (kr < 0) {
|
||||
fprintf(stderr, "%s error at %s: %d\n",
|
||||
#ifdef HAVE_KQUEUE_SYSCALL
|
||||
"kqueue",
|
||||
#else
|
||||
"epoll",
|
||||
#endif
|
||||
fprintf(stderr, "ltps error at %s: %d\n",
|
||||
action, errno);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void log_kqueue_fd(int fd, int flags)
|
||||
{
|
||||
/* ... "expected event %d %d" ... */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -254,6 +254,7 @@ rktio_ltps_handle_t *rktio_ltps_add(rktio_t *rktio, rktio_ltps_t *lt, rktio_fd_t
|
|||
s = v->write_handle;
|
||||
if (s) ltps_signal_handle(lt, s);
|
||||
ltps_hash_remove(lt, fd);
|
||||
/* `v` is freed below */
|
||||
s = NULL;
|
||||
# ifdef HAVE_KQUEUE_SYSCALL
|
||||
{
|
||||
|
@ -630,7 +631,7 @@ static void ltps_hash_set(rktio_ltps_t *lt, intptr_t fd, rktio_ltps_handle_pair_
|
|||
|
||||
static void ltps_hash_remove(rktio_ltps_t *lt, intptr_t fd)
|
||||
{
|
||||
rktio_hash_remove(lt->fd_handles, fd);
|
||||
rktio_hash_remove(lt->fd_handles, fd, 0);
|
||||
}
|
||||
|
||||
static void ltps_hash_init(rktio_ltps_t *lt)
|
||||
|
@ -644,3 +645,29 @@ static void ltps_hash_free(rktio_ltps_t *lt)
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
void rktio_ltps_remove_all(rktio_t *rktio, rktio_ltps_t *lt)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
intptr_t sz, i;
|
||||
|
||||
sz = rktio_hash_size(lt->fd_handles);
|
||||
for (i = 0; i < sz; i++) {
|
||||
intptr_t fd;
|
||||
fd = rktio_hash_get_key(lt->fd_handles, i);
|
||||
if (fd != -1) {
|
||||
rktio_ltps_handle_pair_t *v;
|
||||
rktio_ltps_handle_t *s;
|
||||
v = ltps_hash_get(lt, fd);
|
||||
if (v) {
|
||||
s = v->read_handle;
|
||||
if (s) ltps_signal_handle(lt, s);
|
||||
s = v->write_handle;
|
||||
if (s) ltps_signal_handle(lt, s);
|
||||
rktio_hash_remove(lt->fd_handles, fd, 1);
|
||||
free(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -726,7 +726,7 @@ rktio_addrinfo_lookup_t *rktio_start_addrinfo_lookup(rktio_t *rktio,
|
|||
return start_lookup(rktio, lookup);
|
||||
}
|
||||
|
||||
void rktio_free_addrinfo(rktio_t *rktio, rktio_addrinfo_t *a)
|
||||
void rktio_addrinfo_free(rktio_t *rktio, rktio_addrinfo_t *a)
|
||||
{
|
||||
do_freeaddrinfo(RKTIO_AS_ADDRINFO(a));
|
||||
}
|
||||
|
@ -852,6 +852,38 @@ void rktio_winsock_done(rktio_t *rktio)
|
|||
/* TCP sockets */
|
||||
/*========================================================================*/
|
||||
|
||||
void rktio_socket_init(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
fcntl(s, F_SETFL, RKTIO_NONBLOCKING);
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
{
|
||||
unsigned long ioarg = 1;
|
||||
ioctlsocket(s, FIONBIO, &ioarg);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rktio_fd_is_udp(rktio, rfd)) {
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
# ifdef SO_BROADCAST
|
||||
{
|
||||
int bc = 1;
|
||||
setsockopt(s, SOL_SOCKET, SO_BROADCAST, &bc, sizeof(bc));
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
{
|
||||
BOOL bc = 1;
|
||||
setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)(&bc), sizeof(BOOL));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
|
@ -867,15 +899,19 @@ int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
#endif
|
||||
}
|
||||
|
||||
void rktio_socket_forget(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
void rktio_socket_own(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
rktio_forget(rktio, rfd);
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
REGISTER_SOCKET(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rktio_socket_forget_owned(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
UNREGISTER_SOCKET(s);
|
||||
closesocket(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -947,19 +983,6 @@ int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void init_socket(rktio_socket_t s)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
fcntl(s, F_SETFL, RKTIO_NONBLOCKING);
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
{
|
||||
unsigned long ioarg = 1;
|
||||
ioctlsocket(s, FIONBIO, &ioarg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
|
@ -980,8 +1003,7 @@ rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
get_socket_error();
|
||||
return NULL;
|
||||
}
|
||||
REGISTER_SOCKET(nsocket);
|
||||
return rktio_system_fd(rktio, nsocket, rktio_fd_modes(rktio, rfd));
|
||||
return rktio_system_fd(rktio, nsocket, rktio_fd_modes(rktio, rfd) | RKTIO_OPEN_OWN);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1137,9 +1159,7 @@ static rktio_connect_t *try_connect(rktio_t *rktio, rktio_connect_t *conn)
|
|||
errno = status;
|
||||
#endif
|
||||
|
||||
REGISTER_SOCKET(s);
|
||||
|
||||
conn->trying_fd = rktio_system_fd(rktio, s, RKTIO_OPEN_SOCKET | RKTIO_OPEN_READ | RKTIO_OPEN_WRITE);
|
||||
conn->trying_fd = rktio_system_fd(rktio, s, RKTIO_OPEN_SOCKET | RKTIO_OPEN_READ | RKTIO_OPEN_WRITE | RKTIO_OPEN_OWN);
|
||||
conn->inprogress = inprogress;
|
||||
|
||||
return conn;
|
||||
|
@ -1212,8 +1232,6 @@ rktio_fd_t *rktio_connect_finish(rktio_t *rktio, rktio_connect_t *conn)
|
|||
}
|
||||
}
|
||||
|
||||
init_socket(rktio_fd_system_fd(rktio, rfd));
|
||||
|
||||
conn_free(conn);
|
||||
|
||||
return rfd;
|
||||
|
@ -1519,7 +1537,7 @@ int rktio_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener)
|
|||
return do_poll_accept_ready(rktio, listener, 0);
|
||||
}
|
||||
|
||||
void rktio_poll_add_receive(rktio_t *rktio, rktio_listener_t *listener, rktio_poll_set_t *fds)
|
||||
void rktio_poll_add_accept(rktio_t *rktio, rktio_listener_t *listener, rktio_poll_set_t *fds)
|
||||
{
|
||||
int i;
|
||||
rktio_socket_t s;
|
||||
|
@ -1562,10 +1580,7 @@ rktio_fd_t *rktio_accept(rktio_t *rktio, rktio_listener_t *listener)
|
|||
RKTIO_WHEN_SET_SOCKBUF_SIZE(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(int)));
|
||||
# endif
|
||||
|
||||
init_socket(s);
|
||||
REGISTER_SOCKET(s);
|
||||
|
||||
return rktio_system_fd(rktio, s, RKTIO_OPEN_SOCKET | RKTIO_OPEN_READ | RKTIO_OPEN_WRITE);
|
||||
return rktio_system_fd(rktio, s, RKTIO_OPEN_SOCKET | RKTIO_OPEN_READ | RKTIO_OPEN_WRITE | RKTIO_OPEN_OWN);
|
||||
} else {
|
||||
get_socket_error();
|
||||
return NULL;
|
||||
|
@ -1635,6 +1650,20 @@ char **rktio_socket_peer_address(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
return get_numeric_strings(rktio, name, name_len);
|
||||
}
|
||||
|
||||
char **rktio_listener_address(rktio_t *rktio, rktio_listener_t *lnr)
|
||||
{
|
||||
char name[RKTIO_SOCK_NAME_MAX_LEN];
|
||||
rktio_sockopt_len_t name_len;
|
||||
|
||||
name_len = sizeof(name);
|
||||
if (getsockname(lnr->s[0], (struct sockaddr *)name, &name_len)) {
|
||||
get_socket_error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return get_numeric_strings(rktio, name, name_len);
|
||||
}
|
||||
|
||||
/*========================================================================*/
|
||||
/* UDP */
|
||||
/*========================================================================*/
|
||||
|
|
|
@ -898,7 +898,7 @@ rktio_poll_set_t *rktio_make_poll_set(rktio_t *rktio)
|
|||
return fds;
|
||||
}
|
||||
|
||||
void rktio_poll_set_close(rktio_t *rktio, rktio_poll_set_t *fds)
|
||||
void rktio_poll_set_forget(rktio_t *rktio, rktio_poll_set_t *fds)
|
||||
{
|
||||
free_fdset_arrays(fds);
|
||||
}
|
||||
|
|
|
@ -175,8 +175,11 @@ struct pollfd *rktio_get_poll_fd_array(rktio_poll_set_t *fds);
|
|||
/* Network */
|
||||
/*========================================================================*/
|
||||
|
||||
void rktio_socket_init(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
|
||||
int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
void rktio_socket_forget(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
void rktio_socket_own(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
void rktio_socket_forget_owned(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
|
||||
int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
|
@ -235,9 +238,12 @@ rktio_hash_t *rktio_hash_new(void);
|
|||
void rktio_hash_free(rktio_hash_t *ht, int free_values);
|
||||
int rktio_hash_is_empty(rktio_hash_t *ht);
|
||||
void *rktio_hash_get(rktio_hash_t *ht, intptr_t key);
|
||||
void rktio_hash_remove(rktio_hash_t *ht, intptr_t key);
|
||||
void rktio_hash_remove(rktio_hash_t *ht, intptr_t key, int dont_rehash);
|
||||
void rktio_hash_set(rktio_hash_t *ht, intptr_t key, void *v);
|
||||
|
||||
intptr_t rktio_hash_size(rktio_hash_t *ht);
|
||||
intptr_t rktio_hash_get_key(rktio_hash_t *ht, intptr_t i);
|
||||
|
||||
/*========================================================================*/
|
||||
/* Misc */
|
||||
/*========================================================================*/
|
||||
|
@ -289,3 +295,13 @@ void rktio_init_wide(rktio_t *rktio);
|
|||
#ifdef RKTIO_USE_FCNTL_AND_FORK_FOR_FILE_LOCKS
|
||||
void rktio_release_lockf(rktio_t *rktio, int fd);
|
||||
#endif
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
char **rktio_get_environ_array(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_TRANSITIONAL_64_FILE_OPS
|
||||
# define BIG_OFF_T_IZE(n) n ## 64
|
||||
#else
|
||||
# define BIG_OFF_T_IZE(n) n
|
||||
#endif
|
||||
|
|
|
@ -1225,6 +1225,16 @@ static void CloseFileHandleForSubprocess(intptr_t *hs, int pos)
|
|||
|
||||
#endif
|
||||
|
||||
int rktio_process_allowed_flags(rktio_t *rktio)
|
||||
{
|
||||
int flags = (RKTIO_PROCESS_NEW_GROUP
|
||||
| RKTIO_PROCESS_STDOUT_AS_STDERR);
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
flags |= (RKTIO_PROCESS_WINDOWS_EXACT_CMDLINE
|
||||
| RKTIO_PROCESS_WINDOWS_CHAIN_TERMINATION)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*========================================================================*/
|
||||
/* Main process-creation function */
|
||||
/*========================================================================*/
|
||||
|
@ -1298,7 +1308,10 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (envvars)
|
||||
env = rktio_envvars_to_block(rktio, envvars);
|
||||
else
|
||||
env = NULL;
|
||||
|
||||
#if defined(RKTIO_SYSTEM_WINDOWS)
|
||||
|
||||
|
@ -1504,10 +1517,14 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
|
|||
}
|
||||
new_argv[i] = NULL;
|
||||
|
||||
if (!env)
|
||||
env = rktio_get_environ_array();
|
||||
|
||||
err = MSC_IZE(execve)(command, new_argv, (char **)env);
|
||||
if (err)
|
||||
err = errno;
|
||||
|
||||
if (envvars)
|
||||
free(env);
|
||||
|
||||
/* If we get here it failed; give up */
|
||||
|
@ -1583,6 +1600,11 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
|
|||
return result;
|
||||
}
|
||||
|
||||
int rktio_process_pid(rktio_t *rktio, rktio_process_t *sp)
|
||||
{
|
||||
return sp->pid;
|
||||
}
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
void rktio_close_fds_after_fork(int skip1, int skip2, int skip3)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user