rktio: put "globals" in an rktio_t
Avoid thread-local state by threading a `rktio_t` record through everything.
This commit is contained in:
parent
68352ef86a
commit
09703b94f7
|
@ -9,13 +9,17 @@ RKTIO_HEADERS = $(srcdir)/rktio.h $(srcdir)/rktio_private.h rktio_config.h
|
|||
OBJS = rktio_filesystem.o \
|
||||
rktio_read_write.o \
|
||||
rktio_poll_set.o \
|
||||
rktio_error.o
|
||||
rktio_error.o \
|
||||
rktio_main.o
|
||||
|
||||
all: $(OBJS)
|
||||
|
||||
demo: $(OBJS) main.o
|
||||
demo: $(OBJS) main.o demo_fifo
|
||||
$(CC) -o demo $(CFLAGS) $(LDFLAGS) main.o $(OBJS)
|
||||
|
||||
demo_fifo:
|
||||
mkfifo demo_fifo
|
||||
|
||||
rktio_filesystem.o: $(srcdir)/rktio_filesystem.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_filesystem.o -c $(srcdir)/rktio_filesystem.c
|
||||
|
||||
|
@ -28,5 +32,8 @@ rktio_poll_set.o: $(srcdir)/rktio_poll_set.c $(RKTIO_HEADERS)
|
|||
rktio_error.o: $(srcdir)/rktio_error.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_error.o -c $(srcdir)/rktio_error.c
|
||||
|
||||
rktio_main.o: $(srcdir)/rktio_main.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_main.o -c $(srcdir)/rktio_main.c
|
||||
|
||||
main.o: $(srcdir)/main.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o main.o -c $(srcdir)/main.c
|
||||
|
|
|
@ -3,19 +3,20 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void do_check_valid(int ok, int where)
|
||||
static void do_check_valid(rktio_t *rktio, int ok, int where)
|
||||
{
|
||||
if (!ok) {
|
||||
printf("error at %d: %d@%d = %s\n",
|
||||
where,
|
||||
rktio_get_last_error(),
|
||||
rktio_get_last_error_kind(),
|
||||
rktio_get_error_string(rktio_get_last_error(),
|
||||
rktio_get_last_error_kind()));
|
||||
rktio_get_last_error(rktio),
|
||||
rktio_get_last_error_kind(rktio),
|
||||
rktio_get_error_string(rktio,
|
||||
rktio_get_last_error_kind(rktio),
|
||||
rktio_get_last_error(rktio)));
|
||||
}
|
||||
}
|
||||
|
||||
static void do_check_expected_error(int err, int where)
|
||||
static void do_check_expected_error(rktio_t *rktio, int err, int where)
|
||||
{
|
||||
if (!err) {
|
||||
printf("error expected at %d\n",
|
||||
|
@ -23,121 +24,165 @@ static void do_check_expected_error(int err, int where)
|
|||
}
|
||||
}
|
||||
|
||||
static void do_check_expected_racket_error(int err, int what, int where)
|
||||
static void do_check_expected_racket_error(rktio_t *rktio, int err, int what, int where)
|
||||
{
|
||||
if (!err) {
|
||||
printf("error expected at %d\n",
|
||||
where);
|
||||
} else if ((what != rktio_get_last_error())
|
||||
|| (RKTIO_ERROR_KIND_RACKET != rktio_get_last_error_kind())) {
|
||||
} else if ((what != rktio_get_last_error(rktio))
|
||||
|| (RKTIO_ERROR_KIND_RACKET != rktio_get_last_error_kind(rktio))) {
|
||||
printf("wrong error at %d: %d@%d = %s\n",
|
||||
where,
|
||||
rktio_get_last_error(),
|
||||
rktio_get_last_error_kind(),
|
||||
rktio_get_error_string(rktio_get_last_error(),
|
||||
rktio_get_last_error_kind()));
|
||||
rktio_get_last_error(rktio),
|
||||
rktio_get_last_error_kind(rktio),
|
||||
rktio_get_error_string(rktio,
|
||||
rktio_get_last_error_kind(rktio),
|
||||
rktio_get_last_error(rktio)));
|
||||
}
|
||||
}
|
||||
|
||||
#define check_valid(e) do_check_valid(e, __LINE__)
|
||||
#define check_expected_error(e) do_check_expected_error(e, __LINE__)
|
||||
#define check_expected_racket_error(e, what) do_check_expected_racket_error(e, what, __LINE__)
|
||||
#define check_valid(e) do_check_valid(rktio, e, __LINE__)
|
||||
#define check_expected_error(e) do_check_expected_error(rktio, e, __LINE__)
|
||||
#define check_expected_racket_error(e, what) do_check_expected_racket_error(rktio, e, what, __LINE__)
|
||||
|
||||
static void check_hello_content(char *fn)
|
||||
static void check_hello_content(rktio_t *rktio, char *fn)
|
||||
{
|
||||
rktio_fd_t *fd;
|
||||
intptr_t amt;
|
||||
char buffer[256], *s;
|
||||
|
||||
fd = rktio_open(fn, RKTIO_OPEN_READ);
|
||||
fd = rktio_open(rktio, fn, RKTIO_OPEN_READ);
|
||||
check_valid(!!fd);
|
||||
check_valid(rktio_poll_read_ready(fd) != RKTIO_POLL_ERROR);
|
||||
amt = rktio_read(fd, buffer, sizeof(buffer));
|
||||
check_valid(rktio_poll_read_ready(rktio, fd) != RKTIO_POLL_ERROR);
|
||||
amt = rktio_read(rktio, fd, buffer, sizeof(buffer));
|
||||
check_valid(amt == 5);
|
||||
check_valid(!strncmp(buffer, "hello", 5));
|
||||
check_valid(rktio_close(fd));
|
||||
amt = rktio_read(rktio, fd, buffer, sizeof(buffer));
|
||||
check_valid(amt == RKTIO_READ_EOF);
|
||||
check_valid(rktio_close(rktio, fd));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
rktio_t *rktio;
|
||||
rktio_size_t *sz;
|
||||
rktio_fd_t *fd;
|
||||
intptr_t amt, i,saw_file;
|
||||
char *s, *pwd;
|
||||
rktio_fd_t *fd, *fd2;
|
||||
intptr_t amt, i, saw_file;
|
||||
int perms;
|
||||
char buffer[256], *s, *pwd;
|
||||
rktio_directory_list_t *ls;
|
||||
rktio_file_copy_t *cp;
|
||||
rktio_timestamp_t *ts1, *ts1a;
|
||||
|
||||
fd = rktio_open("test1", RKTIO_OPEN_WRITE | RKTIO_OPEN_CAN_EXIST);
|
||||
rktio = rktio_init();
|
||||
|
||||
/* Basic file I/O */
|
||||
|
||||
fd = rktio_open(rktio, "test1", RKTIO_OPEN_WRITE | RKTIO_OPEN_CAN_EXIST);
|
||||
check_valid(!!fd);
|
||||
check_valid(rktio_poll_write_ready(fd) != RKTIO_POLL_ERROR);
|
||||
amt = rktio_write(fd, "hello", 5);
|
||||
check_valid(rktio_poll_write_ready(rktio, fd) != RKTIO_POLL_ERROR);
|
||||
amt = rktio_write(rktio, fd, "hello", 5);
|
||||
check_valid(amt == 5);
|
||||
check_valid(rktio_close(fd));
|
||||
check_valid(rktio_close(rktio, fd));
|
||||
|
||||
check_valid(rktio_file_exists("test1"));
|
||||
check_valid(!rktio_directory_exists("test1"));
|
||||
check_valid(rktio_is_regular_file("test1"));
|
||||
check_valid(rktio_file_exists(rktio, "test1"));
|
||||
check_valid(!rktio_directory_exists(rktio, "test1"));
|
||||
check_valid(rktio_is_regular_file(rktio, "test1"));
|
||||
|
||||
s = rktio_get_current_directory();
|
||||
s = rktio_get_current_directory(rktio);
|
||||
check_valid(!!s);
|
||||
check_valid(rktio_directory_exists(s));
|
||||
check_valid(!rktio_file_exists(s));
|
||||
check_valid(!rktio_is_regular_file(s));
|
||||
check_expected_racket_error(!rktio_open(s, RKTIO_OPEN_WRITE | RKTIO_OPEN_CAN_EXIST),
|
||||
check_valid(rktio_directory_exists(rktio, s));
|
||||
check_valid(!rktio_file_exists(rktio, s));
|
||||
check_valid(!rktio_is_regular_file(rktio, s));
|
||||
check_expected_racket_error(!rktio_open(rktio, s, RKTIO_OPEN_WRITE | RKTIO_OPEN_CAN_EXIST),
|
||||
RKTIO_ERROR_IS_A_DIRECTORY);
|
||||
pwd = s;
|
||||
|
||||
sz = rktio_file_size("test1");
|
||||
sz = rktio_file_size(rktio, "test1");
|
||||
check_valid(!!sz);
|
||||
check_valid(sz->lo == 5);
|
||||
check_valid(sz->hi == 0);
|
||||
free(sz);
|
||||
|
||||
fd = rktio_open("test2", RKTIO_OPEN_WRITE | RKTIO_OPEN_MUST_EXIST);
|
||||
fd = rktio_open(rktio, "test2", RKTIO_OPEN_WRITE | RKTIO_OPEN_MUST_EXIST);
|
||||
check_expected_error(!fd);
|
||||
|
||||
fd = rktio_open("test1", RKTIO_OPEN_WRITE);
|
||||
fd = rktio_open(rktio, "test1", RKTIO_OPEN_WRITE);
|
||||
check_expected_racket_error(!fd, RKTIO_ERROR_EXISTS);
|
||||
|
||||
check_hello_content("test1");
|
||||
check_hello_content(rktio, "test1");
|
||||
|
||||
if (rktio_file_exists("test1a"))
|
||||
check_valid(rktio_delete_file("test1a", 1));
|
||||
if (rktio_file_exists("test1b"))
|
||||
check_valid(rktio_delete_file("test1b", 1));
|
||||
/* Copying, renaming, and deleting files */
|
||||
|
||||
cp = rktio_copy_file_start("test1a", "test1", 0);
|
||||
if (rktio_file_exists(rktio, "test1a"))
|
||||
check_valid(rktio_delete_file(rktio, "test1a", 1));
|
||||
if (rktio_file_exists(rktio, "test1b"))
|
||||
check_valid(rktio_delete_file(rktio, "test1b", 1));
|
||||
|
||||
ts1 = rktio_get_file_modify_seconds(rktio, "test1a");
|
||||
check_expected_error(!ts1);
|
||||
perms = rktio_get_file_or_directory_permissions(rktio, "test1a", 1);
|
||||
check_expected_error(perms == -1);
|
||||
check_expected_error(!rktio_set_file_or_directory_permissions(rktio, "test1a", 511));
|
||||
|
||||
ts1 = rktio_get_file_modify_seconds(rktio, "test1");
|
||||
perms = rktio_get_file_or_directory_permissions(rktio, "test1", 0);
|
||||
check_valid(perms != -1);
|
||||
check_valid(perms & (RKTIO_PERMISSION_READ << 6));
|
||||
check_valid(perms & (RKTIO_PERMISSION_WRITE << 6));
|
||||
perms = rktio_get_file_or_directory_permissions(rktio, "test1", 1);
|
||||
check_valid(perms != -1);
|
||||
check_valid(perms & (RKTIO_PERMISSION_READ << 6));
|
||||
check_valid(perms & (RKTIO_PERMISSION_WRITE << 6));
|
||||
check_valid(rktio_set_file_or_directory_permissions(rktio, "test1", perms & (0x7 << 6)));
|
||||
check_valid((perms & (0x7 << 6)) == rktio_get_file_or_directory_permissions(rktio, "test1", 1));
|
||||
rktio_set_file_or_directory_permissions(rktio, "test1", perms);
|
||||
|
||||
cp = rktio_copy_file_start(rktio, "test1a", "test1", 0);
|
||||
check_valid(!!cp);
|
||||
while (!rktio_copy_file_is_done(cp)) {
|
||||
check_valid(rktio_copy_file_step(cp));
|
||||
while (!rktio_copy_file_is_done(rktio, cp)) {
|
||||
check_valid(rktio_copy_file_step(rktio, cp));
|
||||
}
|
||||
rktio_copy_file_stop(cp);
|
||||
check_hello_content("test1a");
|
||||
rktio_copy_file_stop(rktio, cp);
|
||||
check_hello_content(rktio, "test1a");
|
||||
|
||||
check_valid(rktio_file_exists("test1a"));
|
||||
cp = rktio_copy_file_start("test1a", "test1", 0);
|
||||
ts1a = rktio_get_file_modify_seconds(rktio, "test1a");
|
||||
check_valid(*ts1a >= *ts1);
|
||||
|
||||
rktio_set_file_modify_seconds(rktio, "test1a", *ts1 - 10);
|
||||
free(ts1a);
|
||||
ts1a = rktio_get_file_modify_seconds(rktio, "test1a");
|
||||
check_valid(*ts1a == (*ts1 - 10));
|
||||
|
||||
free(ts1);
|
||||
free(ts1a);
|
||||
|
||||
check_valid(rktio_file_exists(rktio, "test1a"));
|
||||
cp = rktio_copy_file_start(rktio, "test1a", "test1", 0);
|
||||
check_expected_racket_error(!cp, RKTIO_ERROR_EXISTS);
|
||||
|
||||
cp = rktio_copy_file_start("test1a", "test1", 1);
|
||||
cp = rktio_copy_file_start(rktio, "test1a", "test1", 1);
|
||||
check_valid(!!cp);
|
||||
rktio_copy_file_stop(cp);
|
||||
rktio_copy_file_stop(rktio, cp);
|
||||
|
||||
check_valid(rktio_rename_file("test1b", "test1a", 0));
|
||||
check_valid(rktio_file_exists("test1b"));
|
||||
check_expected_racket_error(!rktio_rename_file("test1b", "test1", 0),
|
||||
check_valid(rktio_rename_file(rktio, "test1b", "test1a", 0));
|
||||
check_valid(rktio_file_exists(rktio, "test1b"));
|
||||
check_expected_racket_error(!rktio_rename_file(rktio, "test1b", "test1", 0),
|
||||
RKTIO_ERROR_EXISTS);
|
||||
check_valid(rktio_file_exists("test1"));
|
||||
check_valid(rktio_file_exists("test1b"));
|
||||
check_valid(!rktio_file_exists("test1a"));
|
||||
check_valid(rktio_file_exists(rktio, "test1"));
|
||||
check_valid(rktio_file_exists(rktio, "test1b"));
|
||||
check_valid(!rktio_file_exists(rktio, "test1a"));
|
||||
|
||||
check_valid(rktio_delete_file("test1b", 0));
|
||||
check_valid(!rktio_file_exists("test1b"));
|
||||
check_valid(rktio_delete_file(rktio, "test1b", 0));
|
||||
check_valid(!rktio_file_exists(rktio, "test1b"));
|
||||
|
||||
ls = rktio_directory_list_start(pwd, 0);
|
||||
/* Listing directory content */
|
||||
|
||||
ls = rktio_directory_list_start(rktio, pwd, 0);
|
||||
check_valid(!!ls);
|
||||
saw_file = 0;
|
||||
while (1) {
|
||||
s = rktio_directory_list_step(ls);
|
||||
s = rktio_directory_list_step(rktio, ls);
|
||||
check_valid(!!s);
|
||||
if (!*s) break;
|
||||
if (!strcmp(s, "test1"))
|
||||
|
@ -145,6 +190,54 @@ int main()
|
|||
check_valid(strcmp(s, "test1b"));
|
||||
}
|
||||
check_valid(saw_file);
|
||||
|
||||
|
||||
/* Pipes and non-blocking operations */
|
||||
|
||||
fd = rktio_open(rktio, "demo_fifo", RKTIO_OPEN_READ);
|
||||
check_valid(!!fd);
|
||||
check_valid(!rktio_poll_read_ready(rktio, fd));
|
||||
fd2 = rktio_open(rktio, "demo_fifo", RKTIO_OPEN_WRITE | RKTIO_OPEN_CAN_EXIST);
|
||||
check_valid(!!fd2);
|
||||
check_valid(!rktio_poll_read_ready(rktio, fd));
|
||||
|
||||
amt = rktio_write(rktio, fd2, "hello", 5);
|
||||
check_valid(amt == 5);
|
||||
check_valid(rktio_poll_read_ready(rktio, fd));
|
||||
amt = rktio_read(rktio, fd, buffer, sizeof(buffer));
|
||||
check_valid(amt == 5);
|
||||
check_valid(!strncmp(buffer, "hello", 5));
|
||||
check_valid(!rktio_poll_read_ready(rktio, fd));
|
||||
|
||||
check_valid(rktio_close(rktio, fd2));
|
||||
amt = rktio_read(rktio, fd, buffer, sizeof(buffer));
|
||||
check_valid(amt == RKTIO_READ_EOF);
|
||||
check_valid(rktio_close(rktio, fd));
|
||||
|
||||
fd2 = rktio_open(rktio, "demo_fifo", RKTIO_OPEN_WRITE | RKTIO_OPEN_CAN_EXIST);
|
||||
check_valid(!!fd2);
|
||||
/* should eventually block: */
|
||||
for (i = 0; i < 100000; i++) {
|
||||
amt = rktio_write(rktio, fd2, "hello", 5);
|
||||
check_valid(amt != RKTIO_WRITE_ERROR);
|
||||
if (!amt)
|
||||
break;
|
||||
}
|
||||
check_valid(i < 100000);
|
||||
|
||||
fd = rktio_open(rktio, "demo_fifo", RKTIO_OPEN_READ);
|
||||
check_valid(!!fd);
|
||||
/* should eventually block: */
|
||||
for (i = 0; i < 100000; i++) {
|
||||
amt = rktio_read(rktio, fd2, buffer, sizeof(buffer));
|
||||
check_valid(amt != RKTIO_READ_ERROR);
|
||||
check_valid(amt != RKTIO_READ_EOF);
|
||||
if (!amt)
|
||||
break;
|
||||
}
|
||||
check_valid(i < 100000);
|
||||
|
||||
check_valid(rktio_close(rktio, fd));
|
||||
check_valid(rktio_close(rktio, fd2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,18 @@
|
|||
|
||||
#include "rktio_config.h"
|
||||
|
||||
/* A rktio_t value represents an instance of the Racket I/O system.
|
||||
Every rktio_...() function takes it as the first argument, except
|
||||
for rktio_init(), rktio_signal_received_at(), and rktio_free(). */
|
||||
typedef struct rktio_t rktio_t;
|
||||
|
||||
rktio_t *rktio_init(void);
|
||||
void rktio_destroy(rktio_t *);
|
||||
|
||||
/* Normally equivalent to free(), but ensures the same malloc()/free()
|
||||
that rktio function use: */
|
||||
void rktio_free(void *p);
|
||||
|
||||
/*************************************************/
|
||||
/* Reading and writing files */
|
||||
|
||||
|
@ -16,23 +28,23 @@ typedef struct rktio_fd_t rktio_fd_t;
|
|||
#define RKTIO_OPEN_MUST_EXIST (1<<5)
|
||||
#define RKTIO_OPEN_CAN_EXIST (1<<6)
|
||||
|
||||
rktio_fd_t *rktio_system_fd(intptr_t system_fd, int modes);
|
||||
intptr_t rktio_fd_system_fd(rktio_fd_t *rfd);
|
||||
rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes);
|
||||
intptr_t rktio_fd_system_fd(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
|
||||
rktio_fd_t *rktio_open(char *src, int modes);
|
||||
int rktio_close(rktio_fd_t *fd);
|
||||
rktio_fd_t *rktio_open(rktio_t *rktio, char *src, int modes);
|
||||
int rktio_close(rktio_t *rktio, rktio_fd_t *fd);
|
||||
|
||||
#define RKTIO_READ_EOF (-1)
|
||||
#define RKTIO_READ_ERROR (-2)
|
||||
#define RKTIO_WRITE_ERROR (-2)
|
||||
#define RKTIO_POLL_ERROR (-2)
|
||||
|
||||
intptr_t rktio_read(rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
intptr_t rktio_write(rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
|
||||
int rktio_poll_read_ready(rktio_fd_t *rfd);
|
||||
int rktio_poll_write_ready(rktio_fd_t *rfd);
|
||||
int rktio_poll_write_flushed(rktio_fd_t *rfd);
|
||||
int rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
int rktio_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
int rktio_poll_write_flushed(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
|
||||
/*************************************************/
|
||||
/* File-descriptor sets */
|
||||
|
@ -42,26 +54,26 @@ typedef struct rktio_poll_set_t rktio_poll_set_t;
|
|||
#define RKTIO_POLL_READ RKTIO_OPEN_READ
|
||||
#define RKTIO_POLL_WRITE RKTIO_OPEN_WRITE
|
||||
|
||||
void rktio_poll_add(rktio_fd_t *rfd, rktio_poll_set_t *fds, int modes);
|
||||
void rktio_poll_add(rktio_t *rktio, rktio_fd_t *rfd, rktio_poll_set_t *fds, int modes);
|
||||
|
||||
/*************************************************/
|
||||
/* Files, directories, and links */
|
||||
|
||||
int rktio_file_exists(char *filename);
|
||||
int rktio_directory_exists(char *dirname);
|
||||
int rktio_link_exists(char *filename);
|
||||
int rktio_is_regular_file(char *filename);
|
||||
int rktio_file_exists(rktio_t *rktio, char *filename);
|
||||
int rktio_directory_exists(rktio_t *rktio, char *dirname);
|
||||
int rktio_link_exists(rktio_t *rktio, char *filename);
|
||||
int rktio_is_regular_file(rktio_t *rktio, char *filename);
|
||||
|
||||
int rktio_delete_file(char *fn, int enable_write_on_fail);
|
||||
int rktio_rename_file(char *dest, char *src, int exists_ok);
|
||||
int rktio_delete_file(rktio_t *rktio, char *fn, int enable_write_on_fail);
|
||||
int rktio_rename_file(rktio_t *rktio, char *dest, char *src, int exists_ok);
|
||||
|
||||
char *rktio_get_current_directory();
|
||||
int rktio_set_current_directory(char *expanded);
|
||||
int rktio_make_directory(char *filename);
|
||||
int rktio_delete_directory(char *filename, char *current_directory, int enable_write_on_fail);
|
||||
char *rktio_get_current_directory(rktio_t *rktio);
|
||||
int rktio_set_current_directory(rktio_t *rktio, char *expanded);
|
||||
int rktio_make_directory(rktio_t *rktio, char *filename);
|
||||
int rktio_delete_directory(rktio_t *rktio, char *filename, char *current_directory, int enable_write_on_fail);
|
||||
|
||||
char *rktio_readlink(char *fullfilename);
|
||||
int rktio_make_link(char *src, char *dest, int dest_is_directory);
|
||||
char *rktio_readlink(rktio_t *rktio, char *fullfilename);
|
||||
int rktio_make_link(rktio_t *rktio, char *src, char *dest, int dest_is_directory);
|
||||
|
||||
/*************************************************/
|
||||
/* File attributes */
|
||||
|
@ -76,43 +88,44 @@ typedef struct {
|
|||
uintptr_t a, b, c;
|
||||
} rktio_identity_t;
|
||||
|
||||
rktio_size_t *rktio_file_size(char *filename);
|
||||
rktio_size_t *rktio_file_size(rktio_t *rktio, char *filename);
|
||||
|
||||
rktio_timestamp_t *rktio_get_file_modify_seconds(char *file);
|
||||
int rktio_set_file_modify_seconds(char *file, rktio_timestamp_t secs);
|
||||
rktio_timestamp_t *rktio_get_file_modify_seconds(rktio_t *rktio, char *file);
|
||||
int rktio_set_file_modify_seconds(rktio_t *rktio, char *file, rktio_timestamp_t secs);
|
||||
|
||||
rktio_identity_t *rktio_get_fd_identity(intptr_t fd, char *path);
|
||||
rktio_identity_t *rktio_fd_identity(rktio_t *rktio, rktio_fd_t *fd);
|
||||
rktio_identity_t *rktio_path_identity(rktio_t *rktio, char *path, int follow_links);
|
||||
|
||||
/*************************************************/
|
||||
/* Permissions */
|
||||
|
||||
/* Must match OS bits: */
|
||||
#define RKTIO_PERMISSION_READ 0x1
|
||||
#define RKTIO_PERMISSION_READ 0x4
|
||||
#define RKTIO_PERMISSION_WRITE 0x2
|
||||
#define RKTIO_PERMISSION_EXEC 0x4
|
||||
#define RKTIO_PERMISSION_EXEC 0x1
|
||||
|
||||
int rktio_get_file_or_directory_permissions(char *filename, int all_bits);
|
||||
int rktio_set_file_or_directory_permissions(char *filename, int new_bits);
|
||||
int rktio_get_file_or_directory_permissions(rktio_t *rktio, char *filename, int all_bits);
|
||||
int 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_directory_list_t *rktio_directory_list_start(char *filename, int is_drive);
|
||||
char *rktio_directory_list_step(rktio_directory_list_t *dl);
|
||||
rktio_directory_list_t *rktio_directory_list_start(rktio_t *rktio, char *filename, int is_drive);
|
||||
char *rktio_directory_list_step(rktio_t *rktio, rktio_directory_list_t *dl);
|
||||
|
||||
char **rktio_filesystem_root_list();
|
||||
char **rktio_filesystem_root_list(rktio_t *rktio);
|
||||
|
||||
/*************************************************/
|
||||
/* File copying */
|
||||
|
||||
typedef struct rktio_file_copy_t rktio_file_copy_t;
|
||||
|
||||
rktio_file_copy_t *rktio_copy_file_start(char *dest, char *src, int exists_ok);
|
||||
int rktio_copy_file_is_done(rktio_file_copy_t *fc);
|
||||
int rktio_copy_file_step(rktio_file_copy_t *fc);
|
||||
void rktio_copy_file_stop(rktio_file_copy_t *fc);
|
||||
rktio_file_copy_t *rktio_copy_file_start(rktio_t *rktio, char *dest, char *src, int exists_ok);
|
||||
int rktio_copy_file_is_done(rktio_t *rktio, rktio_file_copy_t *fc);
|
||||
int rktio_copy_file_step(rktio_t *rktio, rktio_file_copy_t *fc);
|
||||
void rktio_copy_file_stop(rktio_t *rktio, rktio_file_copy_t *fc);
|
||||
|
||||
/*************************************************/
|
||||
/* System paths */
|
||||
|
@ -130,8 +143,17 @@ enum {
|
|||
RKTIO_PATH_INIT_FILE
|
||||
};
|
||||
|
||||
char *rktio_system_path(int which);
|
||||
char *rktio_expand_user_tilde(char *filename);
|
||||
char *rktio_system_path(rktio_t *rktio, int which);
|
||||
char *rktio_expand_user_tilde(rktio_t *rktio, char *filename);
|
||||
|
||||
/*************************************************/
|
||||
/* Sleep and signals */
|
||||
|
||||
typedef struct rktio_signal_handle_t rktio_signal_handle_t;
|
||||
|
||||
rktio_signal_handle_t *rktio_get_signal_handle(rktio_t *rktio);
|
||||
void rktio_signal_received_at(rktio_signal_handle_t *h);
|
||||
void rktio_signal_received(rktio_t *rktio);
|
||||
|
||||
/*************************************************/
|
||||
/* Errors */
|
||||
|
@ -155,13 +177,14 @@ enum {
|
|||
RKTIO_ERROR_NOT_A_DIRECTORY,
|
||||
RKTIO_ERROR_NO_TILDE,
|
||||
RKTIO_ERROR_ILL_FORMED_USER,
|
||||
RKTIO_ERROR_UNKNOWN_USER
|
||||
RKTIO_ERROR_UNKNOWN_USER,
|
||||
RKTIO_ERROR_INIT_FAILED
|
||||
};
|
||||
|
||||
int rktio_get_last_error(void);
|
||||
int rktio_get_last_error_kind(void);
|
||||
int rktio_get_last_error(rktio_t *rktio);
|
||||
int rktio_get_last_error_kind(rktio_t *rktio);
|
||||
|
||||
char *rktio_get_error_string(int kind, int errid);
|
||||
char *rktio_get_error_string(rktio_t *rktio, int kind, int errid);
|
||||
|
||||
/*************************************************/
|
||||
|
||||
|
|
|
@ -4,41 +4,43 @@
|
|||
# include <windows.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
THREAD_LOCAL_DECL(static intptr_t errid);
|
||||
THREAD_LOCAL_DECL(static int errkind);
|
||||
|
||||
void rktio_get_posix_error(void)
|
||||
void rktio_get_posix_error(rktio_t *rktio)
|
||||
{
|
||||
errid = errno;
|
||||
errkind = RKTIO_ERROR_KIND_POSIX;
|
||||
rktio->errid = errno;
|
||||
rktio->errkind = RKTIO_ERROR_KIND_POSIX;
|
||||
}
|
||||
|
||||
void rktio_set_racket_error(int new_errid)
|
||||
void rktio_set_racket_error(rktio_t *rktio, int new_errid)
|
||||
{
|
||||
errid = new_errid;
|
||||
errkind = RKTIO_ERROR_KIND_RACKET;
|
||||
rktio->errid = new_errid;
|
||||
rktio->errkind = RKTIO_ERROR_KIND_RACKET;
|
||||
}
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
void rktio_get_windows_error(void)
|
||||
void rktio_get_windows_error(rktio_t *rktio)
|
||||
{
|
||||
errid = GetLastError();
|
||||
errkind = RKTIO_ERROR_KIND_WINDOWS;
|
||||
rktio->errid = GetLastError();
|
||||
rktio->errkind = RKTIO_ERROR_KIND_WINDOWS;
|
||||
}
|
||||
#endif
|
||||
|
||||
int rktio_get_last_error(void)
|
||||
int rktio_get_last_error(rktio_t *rktio)
|
||||
{
|
||||
return errid;
|
||||
return rktio->errid;
|
||||
}
|
||||
|
||||
int rktio_get_last_error_kind(void)
|
||||
int rktio_get_last_error_kind(rktio_t *rktio)
|
||||
{
|
||||
return errkind;
|
||||
return rktio->errkind;
|
||||
}
|
||||
|
||||
char *rktio_get_error_string(int kind, int errid)
|
||||
char *rktio_get_error_string(rktio_t *rktio, int kind, int errid)
|
||||
{
|
||||
char *s = NULL;
|
||||
if (kind == RKTIO_ERROR_KIND_POSIX)
|
||||
s = strerror(errid);
|
||||
if (s) return s;
|
||||
return "???";
|
||||
}
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
#include <uuid/uuid.h>
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
# define A_PATH_SEP '/'
|
||||
|
@ -43,12 +40,11 @@ static gid_t egid;
|
|||
#define GROUP_MEMBER_CACHE_STATE_UNUSED 0
|
||||
#define GROUP_MEMBER_CACHE_STATE_IN 1
|
||||
#define GROUP_MEMBER_CACHE_STATE_NOT_IN 2
|
||||
typedef struct {
|
||||
typedef struct group_member_cache_entry_t {
|
||||
int state;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
} group_member_cache_entry_t;
|
||||
THREAD_LOCAL_DECL(static group_member_cache_entry_t *group_member_cache);
|
||||
# define GROUP_CACHE_SIZE 10
|
||||
#endif
|
||||
|
||||
|
@ -307,7 +303,7 @@ static char *UNC_readlink(const char *fn)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
static int UNC_stat(const char *dirname, int *flags, int *isdir, int *islink,
|
||||
static int UNC_stat(rktio_t *rktio, const char *dirname, int *flags, int *isdir, int *islink,
|
||||
rktio_timestamp_t **date, rktio_file_size_t *filesize,
|
||||
const char **resolved_path, int set_flags)
|
||||
/* dirname must be absolute */
|
||||
|
@ -337,7 +333,7 @@ static int UNC_stat(const char *dirname, int *flags, int *isdir, int *islink,
|
|||
copy = malloc(len+1);
|
||||
memcpy(copy, dirname, len+1);
|
||||
|
||||
if (!rktio_windows_nt_or_later()
|
||||
if (!rktio->windows_nt_or_later
|
||||
|| ((len >= 4)
|
||||
&& (copy[0] == '\\')
|
||||
&& (copy[1] == '\\')
|
||||
|
@ -478,7 +474,7 @@ static int UNC_stat(const char *dirname, int *flags, int *isdir, int *islink,
|
|||
}
|
||||
#endif
|
||||
|
||||
int rktio_file_exists(char *filename)
|
||||
int rktio_file_exists(rktio_t *rktio, char *filename)
|
||||
/* Windows: check for special filenames before calling */
|
||||
{
|
||||
# ifdef NO_STAT_PROC
|
||||
|
@ -494,7 +490,7 @@ int rktio_file_exists(char *filename)
|
|||
# ifdef RKTIO_SYSTEM_WINDOWS
|
||||
{
|
||||
int isdir;
|
||||
return (UNC_stat(filename, NULL, &isdir, NULL, NULL, NULL, NULL, -1)
|
||||
return (UNC_stat(rktio, filename, NULL, &isdir, NULL, NULL, NULL, NULL, -1)
|
||||
&& !isdir);
|
||||
}
|
||||
# else
|
||||
|
@ -510,7 +506,7 @@ int rktio_file_exists(char *filename)
|
|||
# endif
|
||||
}
|
||||
|
||||
int rktio_directory_exists(char *dirname)
|
||||
int rktio_directory_exists(rktio_t *rktio, char *dirname)
|
||||
{
|
||||
# ifdef NO_STAT_PROC
|
||||
return 0;
|
||||
|
@ -518,7 +514,7 @@ int rktio_directory_exists(char *dirname)
|
|||
# ifdef RKTIO_SYSTEM_WINDOWS
|
||||
int isdir;
|
||||
|
||||
return (UNC_stat(dirname, NULL, &isdir, NULL, NULL, NULL, NULL, -1)
|
||||
return (UNC_stat(rktio, dirname, NULL, &isdir, NULL, NULL, NULL, NULL, -1)
|
||||
&& isdir);
|
||||
# else
|
||||
struct MSC_IZE(stat) buf;
|
||||
|
@ -535,7 +531,7 @@ int rktio_directory_exists(char *dirname)
|
|||
# endif
|
||||
}
|
||||
|
||||
int rktio_is_regular_file(char *filename)
|
||||
int rktio_is_regular_file(rktio_t *rktio, char *filename)
|
||||
/* Windows: check for special filenames before calling */
|
||||
{
|
||||
# ifdef NO_STAT_PROC
|
||||
|
@ -554,12 +550,12 @@ int rktio_is_regular_file(char *filename)
|
|||
# endif
|
||||
}
|
||||
|
||||
int rktio_link_exists(char *filename)
|
||||
int rktio_link_exists(rktio_t *rktio, char *filename)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
{
|
||||
int islink;
|
||||
if (UNC_stat(filename, NULL, NULL, &islink, NULL, NULL, NULL, -1)
|
||||
if (UNC_stat(rktio, filename, NULL, NULL, &islink, NULL, NULL, NULL, -1)
|
||||
&& islink)
|
||||
return 1;
|
||||
else
|
||||
|
@ -583,7 +579,7 @@ int rktio_link_exists(char *filename)
|
|||
#endif
|
||||
}
|
||||
|
||||
char *rktio_get_current_directory()
|
||||
char *rktio_get_current_directory(rktio_t *rktio)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
int need_l, bl = 256;
|
||||
|
@ -631,7 +627,7 @@ char *rktio_get_current_directory()
|
|||
#endif
|
||||
}
|
||||
|
||||
int rktio_set_current_directory(char *expanded)
|
||||
int rktio_set_current_directory(rktio_t *rktio, char *expanded)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -646,8 +642,7 @@ int rktio_set_current_directory(char *expanded)
|
|||
return !err;
|
||||
}
|
||||
|
||||
rktio_identity_t *rktio_get_fd_identity(intptr_t fd, char *path)
|
||||
/* If path is supplied, then fd is 0 for stat, 1 for lstat */
|
||||
static rktio_identity_t *get_identity(rktio_t *rktio, rktio_fd_t *fd, char *path, int follow_links)
|
||||
{
|
||||
uintptr_t devi = 0, inoi = 0, inoi2 = 0;
|
||||
|
||||
|
@ -656,11 +651,11 @@ rktio_identity_t *rktio_get_fd_identity(intptr_t fd, char *path)
|
|||
struct MSC_IZE(stat) buf;
|
||||
|
||||
while (1) {
|
||||
if (!path && !MSC_IZE(fstat)(fd, &buf))
|
||||
if (!path && !MSC_IZE(fstat)(rktio_fd_system_fd(rktio, fd), &buf))
|
||||
break;
|
||||
else if (path && !fd && !MSC_IZE(stat)(path, &buf))
|
||||
else if (path && follow_links && !MSC_IZE(stat)(path, &buf))
|
||||
break;
|
||||
else if (path && fd && !MSC_IZE(lstat)(path, &buf))
|
||||
else if (path && !follow_links && !MSC_IZE(lstat)(path, &buf))
|
||||
break;
|
||||
else if (errno != EINTR) {
|
||||
errid = errno;
|
||||
|
@ -679,7 +674,7 @@ rktio_identity_t *rktio_get_fd_identity(intptr_t fd, char *path)
|
|||
#endif
|
||||
#ifdef WINDOWS_FILE_HANDLES
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
HANDLE fdh = (HANDLE)fd;
|
||||
HANDLE fdh;
|
||||
|
||||
init_procs();
|
||||
|
||||
|
@ -698,7 +693,8 @@ rktio_identity_t *rktio_get_fd_identity(intptr_t fd, char *path)
|
|||
get_windows_error();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
} else
|
||||
fdh = (HANDLE)rktio_fd_system_fd(rktio, fd);
|
||||
|
||||
if (!GetFileInformationByHandle(fdh, &info)) {
|
||||
get_windows_error();
|
||||
|
@ -726,16 +722,26 @@ rktio_identity_t *rktio_get_fd_identity(intptr_t fd, char *path)
|
|||
}
|
||||
}
|
||||
|
||||
rktio_identity_t *rktio_fd_identity(rktio_t *rktio, rktio_fd_t *fd)
|
||||
{
|
||||
return get_identity(rktio, fd, NULL, 0);
|
||||
}
|
||||
|
||||
rktio_identity_t *rktio_path_identity(rktio_t *rktio, char *path, int follow_links)
|
||||
{
|
||||
return get_identity(rktio, NULL, path, follow_links);
|
||||
}
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
static int enable_write_permission(const char *fn)
|
||||
{
|
||||
int flags;
|
||||
|
||||
return UNC_stat(fn, &flags, NULL, NULL, NULL, NULL, NULL, MZ_UNC_WRITE);
|
||||
return UNC_stat(rktio, fn, &flags, NULL, NULL, NULL, NULL, NULL, MZ_UNC_WRITE);
|
||||
}
|
||||
#endif
|
||||
|
||||
int rktio_delete_file(char *fn, int enable_write_on_fail)
|
||||
int rktio_delete_file(rktio_t *rktio, char *fn, int enable_write_on_fail)
|
||||
{
|
||||
int errid;
|
||||
|
||||
|
@ -767,7 +773,7 @@ int rktio_delete_file(char *fn, int enable_write_on_fail)
|
|||
#endif
|
||||
}
|
||||
|
||||
int rktio_rename_file(char *dest, char *src, int exists_ok)
|
||||
int rktio_rename_file(rktio_t *rktio, char *dest, char *src, int exists_ok)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
int errid;
|
||||
|
@ -798,7 +804,7 @@ int rktio_rename_file(char *dest, char *src, int exists_ok)
|
|||
free(src_w);
|
||||
return 0;
|
||||
#else
|
||||
if (!exists_ok && (rktio_file_exists(dest) || rktio_directory_exists(dest))) {
|
||||
if (!exists_ok && (rktio_file_exists(rktio, dest) || rktio_directory_exists(rktio, dest))) {
|
||||
/* We use a specialized error here, because it's not
|
||||
a system error (e.g., setting `errval` to `EEXIST` would
|
||||
be a lie). */
|
||||
|
@ -818,10 +824,10 @@ int rktio_rename_file(char *dest, char *src, int exists_ok)
|
|||
#endif
|
||||
}
|
||||
|
||||
char *rktio_readlink(char *fullfilename)
|
||||
char *rktio_readlink(rktio_t *rktio, char *fullfilename)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (UNC_stat(fullfilename, NULL, NULL, &is_link, NULL, NULL, NULL, -1)
|
||||
if (UNC_stat(rktio, fullfilename, NULL, NULL, &is_link, NULL, NULL, NULL, -1)
|
||||
&& is_link) {
|
||||
return UNC_readlink(fullfilename);
|
||||
} else {
|
||||
|
@ -852,7 +858,7 @@ char *rktio_readlink(char *fullfilename)
|
|||
#endif
|
||||
}
|
||||
|
||||
int rktio_make_directory(char *filename)
|
||||
int rktio_make_directory(rktio_t *rktio, char *filename)
|
||||
{
|
||||
#ifdef NO_MKDIR
|
||||
set_racket_error(RKTIO_ERROR_UNSUPPORTED);
|
||||
|
@ -893,7 +899,7 @@ int rktio_make_directory(char *filename)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int rktio_delete_directory(char *filename, char *current_directory, int enable_write_on_fail)
|
||||
int rktio_delete_directory(rktio_t *rktio, char *filename, char *current_directory, int enable_write_on_fail)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
int tried_cwd = 0, tried_perm = 0;
|
||||
|
@ -922,7 +928,7 @@ int rktio_delete_directory(char *filename, char *current_directory, int enable_w
|
|||
#endif
|
||||
}
|
||||
|
||||
int rktio_make_link(char *src, char *dest, int dest_is_directory)
|
||||
int rktio_make_link(rktio_t *rktio, char *src, char *dest, int dest_is_directory)
|
||||
/* `src` is the file that is written, and `dest` is written to that
|
||||
file */
|
||||
{
|
||||
|
@ -960,12 +966,12 @@ int rktio_make_link(char *src, char *dest, int dest_is_directory)
|
|||
#endif
|
||||
}
|
||||
|
||||
rktio_timestamp_t *rktio_get_file_modify_seconds(char *file)
|
||||
rktio_timestamp_t *rktio_get_file_modify_seconds(rktio_t *rktio, char *file)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
rktio_timestamp_t *secs;
|
||||
|
||||
if (UNC_stat(file, NULL, NULL, NULL, &secs, NULL, NULL, -1))
|
||||
if (UNC_stat(rktio, file, NULL, NULL, NULL, &secs, NULL, NULL, -1))
|
||||
return secs;
|
||||
return NULL;
|
||||
#else
|
||||
|
@ -986,7 +992,7 @@ rktio_timestamp_t *rktio_get_file_modify_seconds(char *file)
|
|||
#endif
|
||||
}
|
||||
|
||||
int rktio_set_file_modify_seconds(char *file, rktio_timestamp_t secs)
|
||||
int rktio_set_file_modify_seconds(rktio_t *rktio, char *file, rktio_timestamp_t secs)
|
||||
{
|
||||
while (1) {
|
||||
struct MSC_IZE(utimbuf) ut;
|
||||
|
@ -1003,20 +1009,20 @@ int rktio_set_file_modify_seconds(char *file, rktio_timestamp_t secs)
|
|||
}
|
||||
|
||||
#if defined(RKTIO_SYSTEM_UNIX) && !defined(NO_UNIX_USERS)
|
||||
static int user_in_group(uid_t uid, gid_t gid)
|
||||
static int user_in_group(rktio_t *rktio, uid_t uid, gid_t gid)
|
||||
{
|
||||
struct group *g;
|
||||
struct passwd *pw;
|
||||
int i, in;
|
||||
|
||||
if (!group_member_cache)
|
||||
group_member_cache = calloc(GROUP_CACHE_SIZE, sizeof(group_member_cache_entry_t));
|
||||
if (!rktio->group_member_cache)
|
||||
rktio->group_member_cache = calloc(GROUP_CACHE_SIZE, sizeof(group_member_cache_entry_t));
|
||||
|
||||
for (i = 0; i < GROUP_CACHE_SIZE; i++) {
|
||||
if ((group_member_cache[i].state != GROUP_MEMBER_CACHE_STATE_UNUSED)
|
||||
&& (group_member_cache[i].gid == gid)
|
||||
&& (group_member_cache[i].uid == uid))
|
||||
return (group_member_cache[i].state == GROUP_MEMBER_CACHE_STATE_IN);
|
||||
if ((rktio->group_member_cache[i].state != GROUP_MEMBER_CACHE_STATE_UNUSED)
|
||||
&& (rktio->group_member_cache[i].gid == gid)
|
||||
&& (rktio->group_member_cache[i].uid == uid))
|
||||
return (rktio->group_member_cache[i].state == GROUP_MEMBER_CACHE_STATE_IN);
|
||||
}
|
||||
|
||||
pw = getpwuid(uid);
|
||||
|
@ -1035,10 +1041,10 @@ static int user_in_group(uid_t uid, gid_t gid)
|
|||
in = !!(g->gr_mem[i]);
|
||||
|
||||
for (i = 0; i < GROUP_CACHE_SIZE; i++) {
|
||||
if (group_member_cache[i].state == GROUP_MEMBER_CACHE_STATE_UNUSED) {
|
||||
group_member_cache[i].gid = gid;
|
||||
group_member_cache[i].uid = uid;
|
||||
group_member_cache[i].state = (in
|
||||
if (rktio->group_member_cache[i].state == GROUP_MEMBER_CACHE_STATE_UNUSED) {
|
||||
rktio->group_member_cache[i].gid = gid;
|
||||
rktio->group_member_cache[i].uid = uid;
|
||||
rktio->group_member_cache[i].state = (in
|
||||
? GROUP_MEMBER_CACHE_STATE_IN
|
||||
: GROUP_MEMBER_CACHE_STATE_NOT_IN);
|
||||
break;
|
||||
|
@ -1049,7 +1055,7 @@ static int user_in_group(uid_t uid, gid_t gid)
|
|||
}
|
||||
#endif
|
||||
|
||||
int rktio_get_file_or_directory_permissions(char *filename, int all_bits)
|
||||
int rktio_get_file_or_directory_permissions(rktio_t *rktio, char *filename, int all_bits)
|
||||
/* -1 result indicates an error */
|
||||
{
|
||||
# ifdef NO_STAT_PROC
|
||||
|
@ -1117,13 +1123,13 @@ int rktio_get_file_or_directory_permissions(char *filename, int all_bits)
|
|||
{
|
||||
/* Use stat, because setuid, or because or no user info available */
|
||||
struct stat buf;
|
||||
int ok, read, write, execute;
|
||||
int cr, read, write, execute;
|
||||
|
||||
do {
|
||||
ok = stat(filename, &buf);
|
||||
} while ((ok == -1) && (errno == EINTR));
|
||||
cr = stat(filename, &buf);
|
||||
} while ((cr == -1) && (errno == EINTR));
|
||||
|
||||
if (ok) {
|
||||
if (cr) {
|
||||
get_posix_error();
|
||||
return -1;
|
||||
} else {
|
||||
|
@ -1145,7 +1151,7 @@ int rktio_get_file_or_directory_permissions(char *filename, int all_bits)
|
|||
read = !!(buf.st_mode & S_IRUSR);
|
||||
write = !!(buf.st_mode & S_IWUSR);
|
||||
execute = !!(buf.st_mode & S_IXUSR);
|
||||
} else if ((egid == buf.st_gid) || user_in_group(euid, buf.st_gid)) {
|
||||
} else if ((egid == buf.st_gid) || user_in_group(rktio, euid, buf.st_gid)) {
|
||||
read = !!(buf.st_mode & S_IRGRP);
|
||||
write = !!(buf.st_mode & S_IWGRP);
|
||||
execute = !!(buf.st_mode & S_IXGRP);
|
||||
|
@ -1171,7 +1177,7 @@ int rktio_get_file_or_directory_permissions(char *filename, int all_bits)
|
|||
{
|
||||
int flags;
|
||||
|
||||
if (UNC_stat(filename, &flags, NULL, NULL, NULL, NULL, NULL, -1)) {
|
||||
if (UNC_stat(rktio, filename, &flags, NULL, NULL, NULL, NULL, NULL, -1)) {
|
||||
if (as_bits)
|
||||
return (flags | (flags << 3) | (flags << 6));
|
||||
else {
|
||||
|
@ -1187,7 +1193,7 @@ int rktio_get_file_or_directory_permissions(char *filename, int all_bits)
|
|||
# endif
|
||||
}
|
||||
|
||||
int rktio_set_file_or_directory_permissions(char *filename, int new_bits)
|
||||
int rktio_set_file_or_directory_permissions(rktio_t *rktio, char *filename, int new_bits)
|
||||
{
|
||||
# ifdef NO_STAT_PROC
|
||||
set_racket_error(RKTIO_ERROR_UNSUPPORTED);
|
||||
|
@ -1221,7 +1227,7 @@ int rktio_set_file_or_directory_permissions(char *filename, int new_bits)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (UNC_stat(filename, NULL, NULL, NULL, NULL, NULL, NULL, new_bits))
|
||||
if (UNC_stat(rktio, filename, NULL, NULL, NULL, NULL, NULL, NULL, new_bits))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -1230,12 +1236,12 @@ int rktio_set_file_or_directory_permissions(char *filename, int new_bits)
|
|||
# endif
|
||||
}
|
||||
|
||||
rktio_size_t *rktio_file_size(char *filename)
|
||||
rktio_size_t *rktio_file_size(rktio_t *rktio, char *filename)
|
||||
{
|
||||
rktio_size_t *sz = NULL;
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
{
|
||||
if (UNC_stat(filename, NULL, NULL, NULL, NULL, &sz, NULL, -1)) {
|
||||
if (UNC_stat(rktio, filename, NULL, NULL, NULL, NULL, &sz, NULL, -1)) {
|
||||
return sz;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -1281,7 +1287,7 @@ struct rktio_directory_list_t {
|
|||
FF_TYPE info;
|
||||
};
|
||||
|
||||
rktio_directory_list_t *rktio_directory_list_start(char *filename, int is_drive)
|
||||
rktio_directory_list_t *rktio_directory_list_start(rktio_t *rktio, char *filename, int is_drive)
|
||||
/* path must be normalized */
|
||||
{
|
||||
char *pattern;
|
||||
|
@ -1340,7 +1346,7 @@ rktio_directory_list_t *rktio_directory_list_start(char *filename, int is_drive)
|
|||
if ((err_val == ERROR_DIRECTORY) && CreateSymbolicLinkProc) {
|
||||
/* check for symbolic link */
|
||||
const char *resolved;
|
||||
if (UNC_stat(filename, NULL, NULL, NULL, NULL, NULL, &resolved, -1)) {
|
||||
if (UNC_stat(rktio, filename, NULL, NULL, NULL, NULL, NULL, &resolved, -1)) {
|
||||
if (resolved) {
|
||||
filename = (char *)resolved;
|
||||
goto retry;
|
||||
|
@ -1358,7 +1364,7 @@ rktio_directory_list_t *rktio_directory_list_start(char *filename, int is_drive)
|
|||
return dl;
|
||||
}
|
||||
|
||||
char *rktio_directory_list_step(rktio_directory_list_t *dl)
|
||||
char *rktio_directory_list_step(rktio_t *rktio, rktio_directory_list_t *dl)
|
||||
/* empty-strng result (don't deallocate) means done */
|
||||
{
|
||||
while (dl->first_ready || FIND_NEXT(dl->hfile, &dl->info)) {
|
||||
|
@ -1385,7 +1391,7 @@ struct rktio_directory_list_t {
|
|||
DIR *dir;
|
||||
};
|
||||
|
||||
rktio_directory_list_t *rktio_directory_list_start(char *filename, int is_drive)
|
||||
rktio_directory_list_t *rktio_directory_list_start(rktio_t *rktio, char *filename, int is_drive)
|
||||
{
|
||||
rktio_directory_list_t *dl;
|
||||
DIR *dir;
|
||||
|
@ -1403,7 +1409,7 @@ rktio_directory_list_t *rktio_directory_list_start(char *filename, int is_drive)
|
|||
return dl;
|
||||
}
|
||||
|
||||
char *rktio_directory_list_step(rktio_directory_list_t *dl)
|
||||
char *rktio_directory_list_step(rktio_t *rktio, rktio_directory_list_t *dl)
|
||||
/* empty-strng result (don't deallocate) means done */
|
||||
{
|
||||
struct dirent *e;
|
||||
|
@ -1437,13 +1443,13 @@ char *rktio_directory_list_step(rktio_directory_list_t *dl)
|
|||
|
||||
#else
|
||||
|
||||
rktio_directory_list_t *rktio_directory_list_start(char *filename, int is_drive)
|
||||
rktio_directory_list_t *rktio_directory_list_start(rktio_t *rktio, char *filename, int is_drive)
|
||||
{
|
||||
set_racket_error(RKTIO_ERROR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *rktio_directory_list_step(rktio_directory_list_t *dl)
|
||||
char *rktio_directory_list_step(rktio_t *rktio, rktio_directory_list_t *dl)
|
||||
{
|
||||
set_racket_error(RKTIO_ERROR_UNSUPPORTED);
|
||||
return NULL;
|
||||
|
@ -1460,7 +1466,7 @@ struct rktio_file_copy_t {
|
|||
rktio_fd_t *src_fd, *dest_fd;
|
||||
};
|
||||
|
||||
rktio_file_copy_t *rktio_copy_file_start(char *dest, char *src, int exists_ok)
|
||||
rktio_file_copy_t *rktio_copy_file_start(rktio_t *rktio, char *dest, char *src, int exists_ok)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
{
|
||||
|
@ -1469,12 +1475,12 @@ rktio_file_copy_t *rktio_copy_file_start(char *dest, char *src, int exists_ok)
|
|||
struct stat buf;
|
||||
rktio_fd_t *src_fd, *dest_fd;
|
||||
|
||||
src_fd = rktio_open(src, RKTIO_OPEN_READ);
|
||||
src_fd = rktio_open(rktio, src, RKTIO_OPEN_READ);
|
||||
if (!src_fd)
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
ok = fstat(rktio_fd_system_fd(src_fd), &buf);
|
||||
ok = fstat(rktio_fd_system_fd(rktio, src_fd), &buf);
|
||||
} while ((ok == -1) && (errno == EINTR));
|
||||
|
||||
if (ok || S_ISDIR(buf.st_mode)) {
|
||||
|
@ -1482,14 +1488,14 @@ rktio_file_copy_t *rktio_copy_file_start(char *dest, char *src, int exists_ok)
|
|||
get_posix_error();
|
||||
else
|
||||
set_racket_error(RKTIO_ERROR_IS_A_DIRECTORY);
|
||||
rktio_close(src_fd);
|
||||
rktio_close(rktio, src_fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dest_fd = rktio_open(dest, (RKTIO_OPEN_WRITE
|
||||
| (exists_ok ? RKTIO_OPEN_TRUNCATE : 0)));
|
||||
dest_fd = rktio_open(rktio, dest, (RKTIO_OPEN_WRITE
|
||||
| (exists_ok ? RKTIO_OPEN_TRUNCATE : 0)));
|
||||
if (!dest_fd) {
|
||||
rktio_close(src_fd);
|
||||
rktio_close(rktio, src_fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1532,12 +1538,12 @@ rktio_file_copy_t *rktio_copy_file_start(char *dest, char *src, int exists_ok)
|
|||
#endif
|
||||
}
|
||||
|
||||
int rktio_copy_file_is_done(rktio_file_copy_t *fc)
|
||||
int rktio_copy_file_is_done(rktio_t *rktio, rktio_file_copy_t *fc)
|
||||
{
|
||||
return fc->done;
|
||||
}
|
||||
|
||||
int rktio_copy_file_step(rktio_file_copy_t *fc)
|
||||
int rktio_copy_file_step(rktio_t *rktio, rktio_file_copy_t *fc)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
char buffer[4096];
|
||||
|
@ -1546,7 +1552,7 @@ int rktio_copy_file_step(rktio_file_copy_t *fc)
|
|||
if (fc->done)
|
||||
return 1;
|
||||
|
||||
len = rktio_read(fc->src_fd, buffer, sizeof(buffer));
|
||||
len = rktio_read(rktio, fc->src_fd, buffer, sizeof(buffer));
|
||||
if (len == RKTIO_READ_EOF) {
|
||||
fc->done = 1;
|
||||
return 1;
|
||||
|
@ -1556,7 +1562,7 @@ int rktio_copy_file_step(rktio_file_copy_t *fc)
|
|||
intptr_t done = 0, amt;
|
||||
|
||||
while (done < len) {
|
||||
amt = rktio_write(fc->dest_fd, buffer + done, len - done);
|
||||
amt = rktio_write(rktio, fc->dest_fd, buffer + done, len - done);
|
||||
if (amt < 0)
|
||||
return 0;
|
||||
done += amt;
|
||||
|
@ -1569,11 +1575,11 @@ int rktio_copy_file_step(rktio_file_copy_t *fc)
|
|||
#endif
|
||||
}
|
||||
|
||||
void rktio_copy_file_stop(rktio_file_copy_t *fc)
|
||||
void rktio_copy_file_stop(rktio_t *rktio, rktio_file_copy_t *fc)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
rktio_close(fc->src_fd);
|
||||
rktio_close(fc->dest_fd);
|
||||
rktio_close(rktio, fc->src_fd);
|
||||
rktio_close(rktio, fc->dest_fd);
|
||||
#endif
|
||||
free(fc);
|
||||
}
|
||||
|
@ -1582,7 +1588,7 @@ void rktio_copy_file_stop(rktio_file_copy_t *fc)
|
|||
/* filesystem root list */
|
||||
/*************************************************************/
|
||||
|
||||
char **rktio_filesystem_root_list(void)
|
||||
char **rktio_filesystem_root_list(rktio_t *rktio)
|
||||
/* returns a NULL-terminated array of strings */
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
|
@ -1645,7 +1651,7 @@ char **rktio_filesystem_root_list(void)
|
|||
/* expand user tilde & system paths */
|
||||
/*************************************************************/
|
||||
|
||||
char *rktio_expand_user_tilde(char *filename) {
|
||||
char *rktio_expand_user_tilde(rktio_t *rktio, char *filename) {
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
set_racket_error(RKTIO_ERROR_UNSUPPORTED);
|
||||
return NULL;
|
||||
|
@ -1737,7 +1743,7 @@ static char *append_paths(char *a, char *b, int free_a, int free_b)
|
|||
return s;
|
||||
}
|
||||
|
||||
char *rktio_system_path(int which)
|
||||
char *rktio_system_path(rktio_t *rktio, int which)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
if (which == RKTIO_PATH_SYS_DIR) {
|
||||
|
@ -1748,20 +1754,20 @@ char *rktio_system_path(int which)
|
|||
char *p;
|
||||
|
||||
if ((p = getenv("TMPDIR"))) {
|
||||
if (rktio_directory_exists(p))
|
||||
if (rktio_directory_exists(rktio, p))
|
||||
return strdup(p);
|
||||
}
|
||||
|
||||
if (rktio_directory_exists("/var/tmp"))
|
||||
if (rktio_directory_exists(rktio, "/var/tmp"))
|
||||
return strdup("/var/tmp");
|
||||
|
||||
if (rktio_directory_exists("/usr/tmp"))
|
||||
if (rktio_directory_exists(rktio, "/usr/tmp"))
|
||||
return strdup("/usr/tmp");
|
||||
|
||||
if (rktio_directory_exists("/tmp"))
|
||||
if (rktio_directory_exists(rktio, "/tmp"))
|
||||
return strdup("/tmp");
|
||||
|
||||
return rktio_get_current_directory();
|
||||
return rktio_get_current_directory(rktio);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1797,7 +1803,7 @@ char *rktio_system_path(int which)
|
|||
if (alt_home)
|
||||
home = append_paths(alt_home, home_str + 2, 0, 0);
|
||||
else {
|
||||
home = rktio_expand_user_tilde(home_str);
|
||||
home = rktio_expand_user_tilde(rktio, home_str);
|
||||
|
||||
if (!home) {
|
||||
/* Something went wrong with the user lookup. Just drop "~'. */
|
||||
|
|
33
racket/src/rktio/rktio_main.c
Normal file
33
racket/src/rktio/rktio_main.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "rktio.h"
|
||||
#include "rktio_private.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
rktio_t *rktio_init(void)
|
||||
{
|
||||
rktio_t *rktio;
|
||||
|
||||
rktio = malloc(sizeof(rktio_t));
|
||||
memset(rktio, 0, sizeof(rktio_t));
|
||||
|
||||
rktio_alloc_global_poll_set(rktio);
|
||||
if (!rktio_initialize_signal(rktio)) {
|
||||
rktio_destroy(rktio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rktio;
|
||||
}
|
||||
|
||||
void rktio_destroy(rktio_t *rktio)
|
||||
{
|
||||
free(rktio);
|
||||
}
|
||||
|
||||
/* Useful on Windows to make sure everyone is using the same malloc()
|
||||
and fre(): */
|
||||
void rktio_free(void *p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
|
@ -3,6 +3,9 @@
|
|||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
# include <sys/select.h>
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
# include <errno.h>
|
||||
# include <math.h>
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
# include <windows.h>
|
||||
|
@ -13,13 +16,9 @@
|
|||
special hooks for Windows "descriptors" like even queues and
|
||||
semaphores, etc. */
|
||||
|
||||
void rktio_alloc_global_poll_set(rktio_t *rktio) {
|
||||
#ifdef USE_FAR_RKTIO_FDCALLS
|
||||
THREAD_LOCAL_DECL(rktio_poll_set_t *rktio_global_poll_set);
|
||||
#endif
|
||||
|
||||
void rktio_alloc_global_poll_set() {
|
||||
#ifdef USE_FAR_RKTIO_FDCALLS
|
||||
rktio_global_poll_set = rktio_alloc_fdset_array(3);
|
||||
rktio->rktio_global_poll_set = rktio_alloc_fdset_array(3);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -777,3 +776,362 @@ int rktio_get_fd_limit(rktio_poll_set_t *fds)
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
/************************************************************/
|
||||
/* Sleeping as a generalized select() */
|
||||
/************************************************************/
|
||||
|
||||
int rktio_initialize_signal(rktio_t *rktio)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
/* Set up a pipe for signaling external events: */
|
||||
int fds[2];
|
||||
if (!pipe(fds)) {
|
||||
rktio->external_event_fd = fds[0];
|
||||
rktio->put_external_event_fd = fds[1];
|
||||
fcntl(rktio->external_event_fd, F_SETFL, RKTIO_NONBLOCKING);
|
||||
fcntl(rktio->put_external_event_fd, F_SETFL, RKTIO_NONBLOCKING);
|
||||
return 1;
|
||||
} else {
|
||||
set_racket_error(RKTIO_ERROR_INIT_FAILED);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32_FD_HANDLES
|
||||
break_semaphore = (void*)CreateSemaphore(NULL, 0, 1, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
rktio_signal_handle_t *rktio_get_signal_handle(rktio_t *rktio)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
return (rktio_signal_handle_t *)&rktio->put_external_event_fd;
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
return (rktio_signal_handle_t *)rktio->break_semaphore;
|
||||
#endif
|
||||
}
|
||||
|
||||
void rktio_signal_received(rktio_t *rktio)
|
||||
{
|
||||
rktio_signal_received_at(rktio_get_signal_handle(rktio));
|
||||
}
|
||||
|
||||
void rktio_signal_received_at(rktio_signal_handle_t *h)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
int put_ext_event_fd = *(int *)h;
|
||||
int saved_errno = errno;
|
||||
if (put_ext_event_fd) {
|
||||
int v;
|
||||
do {
|
||||
v = write(put_ext_event_fd, "!", 1);
|
||||
} while ((v == -1) && (errno == EINTR));
|
||||
}
|
||||
errno = saved_errno;
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
ReleaseSemaphore(*(HANDLE *)h, 1, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void clear_signal(rktio_t *rktio)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
/* Clear external event flag */
|
||||
if (rktio->external_event_fd) {
|
||||
int rc;
|
||||
char buf[10];
|
||||
do {
|
||||
rc = read(rktio->external_event_fd, buf, 10);
|
||||
} while ((rc == -1) && errno == EINTR);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void rktio_wait_until_signal_received(rktio_t *rktio)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
int r;
|
||||
# ifdef HAVE_POLL_SYSCALL
|
||||
GC_CAN_IGNORE struct pollfd pfd[1];
|
||||
pfd[0].fd = rktio->external_event_fd;
|
||||
pfd[0].events = POLLIN;
|
||||
do {
|
||||
r = poll(pfd, 1, -1);
|
||||
} while ((r == -1) && (errno == EINTR));
|
||||
# else
|
||||
DECL_FDSET(readfds, 1);
|
||||
|
||||
INIT_DECL_RD_FDSET(readfds);
|
||||
|
||||
RKTIO_FD_ZERO(readfds);
|
||||
RKTIO_FD_SET(rktio->external_event_fd, readfds);
|
||||
|
||||
do {
|
||||
r = select(rktio->external_event_fd + 1, RKTIO_FDS(readfds), NULL, NULL, NULL);
|
||||
} while ((r == -1) && (errno == EINTR));
|
||||
# endif
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
WaitForSingleObject(rktio->break_semaphore, INFINITE);
|
||||
#endif
|
||||
|
||||
clear_signal(rktio);
|
||||
}
|
||||
|
||||
/****************** Windows cleanup *****************/
|
||||
|
||||
#if RKTIO_SYSTEM_WINDOWS
|
||||
|
||||
static void clean_up_wait(intptr_t result, OS_SEMAPHORE_TYPE *array,
|
||||
int *rps, int count)
|
||||
{
|
||||
if ((result >= (intptr_t)WAIT_OBJECT_0) && (result < (intptr_t)WAIT_OBJECT_0 + count)) {
|
||||
result -= WAIT_OBJECT_0;
|
||||
if (rps[result])
|
||||
ReleaseSemaphore(array[result], 1, NULL);
|
||||
}
|
||||
|
||||
/* Clear out break semaphore */
|
||||
WaitForSingleObject((HANDLE)scheme_break_semaphore, 0);
|
||||
}
|
||||
|
||||
static int made_progress;
|
||||
static DWORD max_sleep_time;
|
||||
|
||||
void rkio_notify_sleep_progress(void)
|
||||
{
|
||||
made_progress = 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void rkio_notify_sleep_progress(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/******************** Main sleep function *****************/
|
||||
/* The simple select() stuff is buried in various kinds of complexity. */
|
||||
|
||||
/* FIXME: don't forget SIGCHILD_DOESNT_INTERRUPT_SELECT handling in Racket */
|
||||
|
||||
void rktio_sleep(rktio_t *rktio, float nsecs, rktio_poll_set_t *fds)
|
||||
{
|
||||
if (!fds) {
|
||||
/* Nothing to block on - just sleep for some amount of time. */
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
# ifdef HAVE_POLL_SYSCALL
|
||||
int timeout;
|
||||
if (nsecs <= 0.0)
|
||||
timeout = -1;
|
||||
else {
|
||||
timeout = (int)(nsecs * 1000.0);
|
||||
if (timeout < 0)
|
||||
timeout = 0;
|
||||
}
|
||||
if (external_event_fd) {
|
||||
GC_CAN_IGNORE struct pollfd pfd[1];
|
||||
pfd[0].fd = external_event_fd;
|
||||
pfd[0].events = POLLIN;
|
||||
poll(pfd, 1, timeout);
|
||||
} else {
|
||||
poll(NULL, 0, timeout);
|
||||
}
|
||||
# else
|
||||
/* Sleep by selecting on the external event fd */
|
||||
struct timeval time;
|
||||
intptr_t secs = (intptr_t)nsecs;
|
||||
intptr_t usecs = (intptr_t)(fmod(nsecs, 1.0) * 1000000);
|
||||
|
||||
if (nsecs && (nsecs > 100000))
|
||||
secs = 100000;
|
||||
if (usecs < 0)
|
||||
usecs = 0;
|
||||
if (usecs >= 1000000)
|
||||
usecs = 999999;
|
||||
|
||||
time.tv_sec = secs;
|
||||
time.tv_usec = usecs;
|
||||
|
||||
if (rktio->external_event_fd) {
|
||||
DECL_FDSET(readfds, 1);
|
||||
|
||||
INIT_DECL_RD_FDSET(readfds);
|
||||
|
||||
RKTIO_FD_ZERO(readfds);
|
||||
RKTIO_FD_SET(rktio->external_event_fd, readfds);
|
||||
|
||||
select(rktio->external_event_fd + 1, RKTIO_FDS(readfds), NULL, NULL, &time);
|
||||
} else {
|
||||
select(0, NULL, NULL, NULL, &time);
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
# ifndef NO_SLEEP
|
||||
# ifndef NO_USLEEP
|
||||
usleep((unsigned)(nsecs * 1000));
|
||||
# else
|
||||
sleep(nsecs);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
} else {
|
||||
/* Something to block on.... */
|
||||
|
||||
#ifdef HAVE_POLL_SYSCALL
|
||||
|
||||
/******* poll() variant *******/
|
||||
|
||||
{
|
||||
struct mz_fd_set_data_t *data = fds->data;
|
||||
intptr_t count = data->count;
|
||||
int timeout;
|
||||
|
||||
if (v <= 0.0)
|
||||
timeout = -1;
|
||||
else if (v > 100000)
|
||||
timeout = 100000000;
|
||||
else {
|
||||
timeout = (int)(v * 1000.0);
|
||||
if (timeout < 0)
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
if (external_event_fd) {
|
||||
data->pfd[count].fd = external_event_fd;
|
||||
data->pfd[count].events = POLLIN;
|
||||
count++;
|
||||
}
|
||||
|
||||
poll(data->pfd, count, timeout);
|
||||
}
|
||||
#elif !defined(RKTIO_SYSTEM_WINDOWS)
|
||||
|
||||
/******* select() variant *******/
|
||||
|
||||
{
|
||||
int actual_limit;
|
||||
fd_set *rd, *wr, *ex;
|
||||
struct timeval time;
|
||||
intptr_t secs = (intptr_t)nsecs;
|
||||
intptr_t usecs = (intptr_t)(fmod(nsecs, 1.0) * 1000000);
|
||||
|
||||
if (nsecs && (nsecs > 100000))
|
||||
secs = 100000;
|
||||
if (usecs < 0)
|
||||
usecs = 0;
|
||||
if (usecs >= 1000000)
|
||||
usecs = 999999;
|
||||
|
||||
time.tv_sec = secs;
|
||||
time.tv_usec = usecs;
|
||||
|
||||
rd = RKTIO_FDS(fds);
|
||||
wr = RKTIO_FDS(RKTIO_GET_FDSET(fds, 1));
|
||||
ex = RKTIO_FDS(RKTIO_GET_FDSET(fds, 2));
|
||||
|
||||
actual_limit = rktio_get_fd_limit(fds);
|
||||
|
||||
/* Watch for external events, too: */
|
||||
if (rktio->external_event_fd) {
|
||||
FD_SET(rktio->external_event_fd, rd);
|
||||
if (rktio->external_event_fd >= actual_limit)
|
||||
actual_limit = rktio->external_event_fd + 1;
|
||||
}
|
||||
|
||||
select(actual_limit, rd, wr, ex, nsecs ? &time : NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/******* Windows variant *******/
|
||||
|
||||
{
|
||||
intptr_t result;
|
||||
HANDLE *array, just_two_array[2], break_sema;
|
||||
int count, rcount, *rps;
|
||||
|
||||
if (fds->no_sleep)
|
||||
return;
|
||||
|
||||
scheme_collapse_win_fd(fds); /* merges */
|
||||
|
||||
rcount = fds->num_handles;
|
||||
count = fds->combined_len;
|
||||
array = fds->combined_wait_array;
|
||||
rps = fds->repost_sema;
|
||||
|
||||
/* add break semaphore: */
|
||||
if (!count)
|
||||
array = just_two_array;
|
||||
break_sema = (HANDLE)scheme_break_semaphore;
|
||||
array[count++] = break_sema;
|
||||
|
||||
/* Extensions may handle events.
|
||||
If the event queue is empty (as reported by GetQueueStatus),
|
||||
everything's ok.
|
||||
|
||||
Otherwise, we have trouble sleeping until an event is ready. We
|
||||
sometimes leave events on th queue because, say, an eventspace is
|
||||
not ready. The problem is that MsgWait... only unblocks when a new
|
||||
event appears. Since extensions may check the queue using a sequence of
|
||||
PeekMessages, it's possible that an event is added during the
|
||||
middle of the sequence, but doesn't get handled.
|
||||
|
||||
To avoid this problem, we don't actually sleep indefinitely if an event
|
||||
is pending. Instead, we slep 10 ms, then 20 ms, etc. This exponential
|
||||
backoff ensures that we eventually handle a pending event, but we don't
|
||||
spin and eat CPU cycles. The back-off is reset whenever a thread makes
|
||||
progress. */
|
||||
|
||||
if (SCHEME_INT_VAL(((win_extended_fd_set *)fds)->wait_event_mask)
|
||||
&& GetQueueStatus(SCHEME_INT_VAL(((win_extended_fd_set *)fds)->wait_event_mask))) {
|
||||
if (!made_progress) {
|
||||
/* Ok, we've gone around at least once. */
|
||||
if (max_sleep_time < 0x20000000)
|
||||
max_sleep_time *= 2;
|
||||
} else {
|
||||
/* Starting back-off mode */
|
||||
made_progress = 0;
|
||||
max_sleep_time = 5;
|
||||
}
|
||||
} else {
|
||||
/* Disable back-off mode */
|
||||
made_progress = 1;
|
||||
max_sleep_time = 0;
|
||||
}
|
||||
|
||||
/* Wait for HANDLE-based input: */
|
||||
{
|
||||
DWORD msec;
|
||||
if (nsecs) {
|
||||
if (nsecs > 100000)
|
||||
msec = 100000000;
|
||||
else
|
||||
msec = (DWORD)(nsecs * 1000);
|
||||
if (max_sleep_time && (msec > max_sleep_time))
|
||||
msec = max_sleep_time;
|
||||
} else {
|
||||
if (max_sleep_time)
|
||||
msec = max_sleep_time;
|
||||
else
|
||||
msec = INFINITE;
|
||||
}
|
||||
|
||||
result = MsgWaitForMultipleObjects(count, array, FALSE, msec,
|
||||
SCHEME_INT_VAL(((win_extended_fd_set *)fds)->wait_event_mask));
|
||||
}
|
||||
clean_up_wait(result, array, rps, rcount);
|
||||
scheme_collapse_win_fd(fds); /* cleans up */
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
clear_signal(rktio);
|
||||
}
|
||||
|
|
|
@ -1,33 +1,15 @@
|
|||
#if ((defined(_MSC_VER) || defined(__MINGW32__)) \
|
||||
#if ((defined(_MSC_VER) || defined(__MINGW32__)) \
|
||||
&& (defined(__WIN32__) || defined(WIN32) || defined(_WIN32)))
|
||||
# define RKTIO_SYSTEM_WINDOWS
|
||||
# define MSC_IZE(n) _ ## n
|
||||
# define MSC_W_IZE(n) _w ## n
|
||||
# define MSC_WIDE_PATH_temp(n) WIDE_PATH_temp(n)
|
||||
#else
|
||||
# define RKTIO_SYSTEM_UNIX
|
||||
# define MSC_IZE(n) n
|
||||
# define MSC_W_IZE(n) MSC_IZE(n)
|
||||
# define MSC_WIDE_PATH_temp(n) n
|
||||
#endif
|
||||
|
||||
#define THREAD_LOCAL_DECL(decl) decl
|
||||
|
||||
void rktio_get_posix_error(void);
|
||||
#define get_posix_error() rktio_get_posix_error()
|
||||
|
||||
void rktio_set_racket_error(int errid);
|
||||
#define set_racket_error(e) rktio_set_racket_error(e)
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
void rktio_get_windows_error(void);
|
||||
# define get_windows_error() rktio_get_windows_error()
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
typedef struct rktio_poll_set_t rktio_poll_set_t;
|
||||
|
||||
#if RKTIO_SYSTEM_WINDOWS
|
||||
# define USE_FAR_RKTIO_FDCALLS
|
||||
#endif
|
||||
|
@ -38,19 +20,47 @@ typedef struct rktio_poll_set_t rktio_poll_set_t;
|
|||
# define USE_FAR_RKTIO_FDCALLS
|
||||
#endif
|
||||
|
||||
#ifdef USE_FAR_RKTIO_FDCALLS
|
||||
/* A single fdset that can be reused for immediate actions: */
|
||||
THREAD_LOCAL_DECL(extern rktio_poll_set_t *rktio_global_fd_set);
|
||||
/************************************************************/
|
||||
/* Globals, as gathered into `rktio_t` */
|
||||
/************************************************************/
|
||||
|
||||
struct rktio_t {
|
||||
intptr_t errid;
|
||||
int errkind;
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
struct group_member_cache_entry_t *group_member_cache;
|
||||
int external_event_fd;
|
||||
int put_external_event_fd;
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
int windows_nt_or_later;
|
||||
HANDLE break_semaphore;
|
||||
#endif
|
||||
#ifdef USE_FAR_RKTIO_FDCALLS
|
||||
/* A single fdset that can be reused for immediate actions: */
|
||||
struct rktio_poll_set_t *rktio_global_fd_set;
|
||||
#endif
|
||||
};
|
||||
|
||||
/************************************************************/
|
||||
/* Poll sets */
|
||||
/************************************************************/
|
||||
|
||||
typedef struct rktio_poll_set_t rktio_poll_set_t;
|
||||
|
||||
void rktio_alloc_global_poll_set(rktio_t *rktio);
|
||||
int rktio_initialize_signal(rktio_t *rktio);
|
||||
|
||||
#ifdef USE_FAR_RKTIO_FDCALLS
|
||||
# define DECL_FDSET(n, c) fd_set *n
|
||||
# define INIT_DECL_FDSET(r, w, e) { \
|
||||
r = RKTIO_GET_FDSET(rktio_global_poll_set, 0 ); \
|
||||
w = RKTIO_GET_FDSET(rktio_global_poll_set, 1 ); \
|
||||
e = RKTIO_GET_FDSET(rktio_global_poll_set, 2 ); \
|
||||
r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 0 ); \
|
||||
w = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 1 ); \
|
||||
e = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 2 ); \
|
||||
}
|
||||
# define INIT_DECL_RD_FDSET(r) r = RKTIO_GET_FDSET(rktio_global_poll_set, 0 )
|
||||
# define INIT_DECL_WR_FDSET(r) r = RKTIO_GET_FDSET(rktio_global_poll_set, 1 )
|
||||
# define INIT_DECL_ER_FDSET(r) r = RKTIO_GET_FDSET(rktio_global_poll_set, 2 )
|
||||
# define INIT_DECL_RD_FDSET(r) r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 0 )
|
||||
# define INIT_DECL_WR_FDSET(r) r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 1 )
|
||||
# define INIT_DECL_ER_FDSET(r) r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 2 )
|
||||
|
||||
# define RKTIO_GET_FDSET(p, n) rktio_get_fdset(p, n)
|
||||
# define RKTIO_FD_ZERO(p) rktio_fdzero(p)
|
||||
|
@ -58,6 +68,10 @@ THREAD_LOCAL_DECL(extern rktio_poll_set_t *rktio_global_fd_set);
|
|||
# define RKTIO_FD_CLR(n, p) rktio_fdclr(p, n)
|
||||
# define RKTIO_FD_ISSET(n, p) rktio_fdisset(p, n)
|
||||
|
||||
# if !defined(HAVE_POLL_SYSCALL) && !defined(RKTIO_SYSTEM_WINDOWS)
|
||||
# define RKTIO_FDS(p) ((fd_set *)fds)
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/select.h>
|
||||
|
@ -82,3 +96,34 @@ struct rktio_poll_set_t { fd_set data; };
|
|||
rktio_poll_set_t *rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds);
|
||||
void rktio_clean_fd_set(rktio_poll_set_t *fds);
|
||||
int rktio_get_fd_limit(rktio_poll_set_t *fds);
|
||||
|
||||
/************************************************************/
|
||||
/* Misc */
|
||||
/************************************************************/
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
# define MSC_IZE(n) _ ## n
|
||||
# define MSC_W_IZE(n) _w ## n
|
||||
# define MSC_WIDE_PATH_temp(n) WIDE_PATH_temp(n)
|
||||
#else
|
||||
# define MSC_IZE(n) n
|
||||
# define MSC_W_IZE(n) MSC_IZE(n)
|
||||
# define MSC_WIDE_PATH_temp(n) n
|
||||
#endif
|
||||
|
||||
void rktio_get_posix_error(rktio_t *rktio);
|
||||
#define get_posix_error() rktio_get_posix_error(rktio)
|
||||
|
||||
void rktio_set_racket_error(rktio_t *rktio, int errid);
|
||||
#define set_racket_error(e) rktio_set_racket_error(rktio, e)
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
void rktio_get_windows_error(rktio_t *rktio);
|
||||
# define get_windows_error() rktio_get_windows_error(rktio)
|
||||
#endif
|
||||
|
||||
#if defined(USE_FCNTL_O_NONBLOCK)
|
||||
# define RKTIO_NONBLOCKING O_NONBLOCK
|
||||
#else
|
||||
# define RKTIO_NONBLOCKING FNDELAY
|
||||
#endif
|
||||
|
|
|
@ -12,12 +12,6 @@
|
|||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_FCNTL_O_NONBLOCK)
|
||||
# define RKTIO_NONBLOCKING O_NONBLOCK
|
||||
#else
|
||||
# define RKTIO_NONBLOCKING FNDELAY
|
||||
#endif
|
||||
|
||||
#ifndef RKTIO_BINARY
|
||||
# define RKTIO_BINARY 0
|
||||
#endif
|
||||
|
@ -97,7 +91,7 @@ static void init_read_fd(rktio_fd_t *rfd)
|
|||
#endif
|
||||
}
|
||||
|
||||
rktio_fd_t *rktio_system_fd(intptr_t system_fd, int modes)
|
||||
rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes)
|
||||
{
|
||||
rktio_fd_t *rfd;
|
||||
|
||||
|
@ -128,7 +122,7 @@ rktio_fd_t *rktio_system_fd(intptr_t system_fd, int modes)
|
|||
return rfd;
|
||||
}
|
||||
|
||||
intptr_t rktio_fd_system_fd(rktio_fd_t *rfd)
|
||||
intptr_t rktio_fd_system_fd(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
return rfd->fd;
|
||||
}
|
||||
|
@ -137,7 +131,7 @@ intptr_t rktio_fd_system_fd(rktio_fd_t *rfd)
|
|||
/* opening a file fd */
|
||||
/*************************************************************/
|
||||
|
||||
static rktio_fd_t *open_read(char *filename)
|
||||
static rktio_fd_t *open_read(rktio_t *rktio, char *filename)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
int fd;
|
||||
|
@ -212,7 +206,7 @@ static rktio_fd_t *open_read(char *filename)
|
|||
#endif
|
||||
}
|
||||
|
||||
static rktio_fd_t *open_write(char *filename, int modes)
|
||||
static rktio_fd_t *open_write(rktio_t *rktio, char *filename, int modes)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
int fd;
|
||||
|
@ -369,19 +363,19 @@ static rktio_fd_t *open_write(char *filename, int modes)
|
|||
#endif
|
||||
}
|
||||
|
||||
rktio_fd_t *rktio_open(char *filename, int modes)
|
||||
rktio_fd_t *rktio_open(rktio_t *rktio, char *filename, int modes)
|
||||
{
|
||||
if (modes & RKTIO_OPEN_WRITE)
|
||||
return open_write(filename, modes);
|
||||
return open_write(rktio, filename, modes);
|
||||
else
|
||||
return open_read(filename);
|
||||
return open_read(rktio, filename);
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
/* closing */
|
||||
/*************************************************************/
|
||||
|
||||
int rktio_close(rktio_fd_t *rfd)
|
||||
int rktio_close(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
int cr;
|
||||
|
@ -483,7 +477,7 @@ static int try_get_fd_char(int fd, int *ready)
|
|||
}
|
||||
#endif
|
||||
|
||||
int rktio_poll_read_ready(rktio_fd_t *rfd)
|
||||
int rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
if (rfd->regfile)
|
||||
return 1;
|
||||
|
@ -573,7 +567,7 @@ int rktio_poll_read_ready(rktio_fd_t *rfd)
|
|||
#endif
|
||||
}
|
||||
|
||||
int poll_write_ready_or_flushed(rktio_fd_t *rfd, int check_flushed)
|
||||
int poll_write_ready_or_flushed(rktio_t *rktio, rktio_fd_t *rfd, int check_flushed)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
if (check_flushed)
|
||||
|
@ -645,17 +639,17 @@ int poll_write_ready_or_flushed(rktio_fd_t *rfd, int check_flushed)
|
|||
#endif
|
||||
}
|
||||
|
||||
int rktio_poll_write_ready(rktio_fd_t *rfd)
|
||||
int rktio_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
return poll_write_ready_or_flushed(rfd, 0);
|
||||
return poll_write_ready_or_flushed(rktio, rfd, 0);
|
||||
}
|
||||
|
||||
int rktio_poll_write_flushed(rktio_fd_t *rfd)
|
||||
int rktio_poll_write_flushed(rktio_t *rktio, rktio_fd_t *rfd)
|
||||
{
|
||||
return poll_write_ready_or_flushed(rfd, 1);
|
||||
return poll_write_ready_or_flushed(rktio, rfd, 1);
|
||||
}
|
||||
|
||||
void rktio_poll_add(rktio_fd_t *rfd, rktio_poll_set_t *fds, int modes)
|
||||
void rktio_poll_add(rktio_t *rktio, rktio_fd_t *rfd, rktio_poll_set_t *fds, int modes)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
rktio_poll_set_t *fds2;
|
||||
|
@ -708,7 +702,7 @@ void rktio_poll_add(rktio_fd_t *rfd, rktio_poll_set_t *fds, int modes)
|
|||
/* reading */
|
||||
/*************************************************************/
|
||||
|
||||
intptr_t rktio_read(rktio_fd_t *rfd, char *buffer, intptr_t len)
|
||||
intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
intptr_t bc;
|
||||
|
@ -875,10 +869,10 @@ static void WindowsFDICleanup(Win_FD_Input_Thread *th)
|
|||
/* writing */
|
||||
/*************************************************************/
|
||||
|
||||
intptr_t rktio_write(rktio_fd_t *rfd, char *buffer, intptr_t len)
|
||||
intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
int flags;
|
||||
int flags, errsaved;
|
||||
intptr_t amt;
|
||||
|
||||
flags = fcntl(rfd->fd, F_GETFL, 0);
|
||||
|
@ -898,15 +892,20 @@ intptr_t rktio_write(rktio_fd_t *rfd, char *buffer, intptr_t len)
|
|||
amt = amt >> 1;
|
||||
} while ((len == -1) && (errno == EAGAIN) && (amt > 0));
|
||||
|
||||
if (len == -1)
|
||||
if (len == -1) {
|
||||
errsaved = errno;
|
||||
get_posix_error();
|
||||
}
|
||||
|
||||
if (!(flags & RKTIO_NONBLOCKING))
|
||||
fcntl(rfd->fd, F_SETFL, flags);
|
||||
|
||||
if (len == -1)
|
||||
return RKTIO_WRITE_ERROR;
|
||||
else
|
||||
if (len == -1) {
|
||||
if (errsaved == EAGAIN)
|
||||
return 0;
|
||||
else
|
||||
return RKTIO_WRITE_ERROR;
|
||||
} else
|
||||
return len;
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
|
|
0
racket/src/rktio/rktio_sleep.c
Normal file
0
racket/src/rktio/rktio_sleep.c
Normal file
Loading…
Reference in New Issue
Block a user