From a767ea38fc4e50ba386b9039cd9b190da2f139ab Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 12 Jun 2017 13:43:45 -0600 Subject: [PATCH] rktio: improve organization --- racket/src/rktio/Makefile.in | 10 +- racket/src/rktio/rktio.h | 5 + .../rktio/{rktio_read_write.c => rktio_fd.c} | 279 ++---------------- racket/src/rktio/rktio_file.c | 244 +++++++++++++++ 4 files changed, 273 insertions(+), 265 deletions(-) rename racket/src/rktio/{rktio_read_write.c => rktio_fd.c} (81%) create mode 100644 racket/src/rktio/rktio_file.c diff --git a/racket/src/rktio/Makefile.in b/racket/src/rktio/Makefile.in index f6c2da162d..5076fbb10f 100644 --- a/racket/src/rktio/Makefile.in +++ b/racket/src/rktio/Makefile.in @@ -9,7 +9,8 @@ LIBS = @LIBS@ RKTIO_HEADERS = $(srcdir)/rktio.h $(srcdir)/rktio_private.h rktio_config.h OBJS = rktio_filesystem.o \ - rktio_read_write.o \ + rktio_fd.o \ + rktio_file.o \ rktio_poll_set.o \ rktio_ltps.o \ rktio_network.o \ @@ -32,8 +33,11 @@ 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 -rktio_read_write.o: $(srcdir)/rktio_read_write.c $(RKTIO_HEADERS) - $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_read_write.o -c $(srcdir)/rktio_read_write.c +rktio_fd.o: $(srcdir)/rktio_fd.c $(RKTIO_HEADERS) + $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_fd.o -c $(srcdir)/rktio_fd.c + +rktio_file.o: $(srcdir)/rktio_file.c $(RKTIO_HEADERS) + $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_file.o -c $(srcdir)/rktio_file.c rktio_poll_set.o: $(srcdir)/rktio_poll_set.c $(RKTIO_HEADERS) $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_poll_set.o -c $(srcdir)/rktio_poll_set.c diff --git a/racket/src/rktio/rktio.h b/racket/src/rktio/rktio.h index 7e533dca35..eae5df2e4f 100644 --- a/racket/src/rktio/rktio.h +++ b/racket/src/rktio/rktio.h @@ -29,6 +29,11 @@ typedef struct rktio_fd_t rktio_fd_t; #define RKTIO_OPEN_CAN_EXIST (1<<6) #define RKTIO_OPEN_SOCKET (1<<7) #define RKTIO_OPEN_UDP (1<<8) +#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 */ /* A socket registered this way should be non-blocking: */ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes); diff --git a/racket/src/rktio/rktio_read_write.c b/racket/src/rktio/rktio_fd.c similarity index 81% rename from racket/src/rktio/rktio_read_write.c rename to racket/src/rktio/rktio_fd.c index 1a2f814e84..f1c4c9aed2 100644 --- a/racket/src/rktio/rktio_read_write.c +++ b/racket/src/rktio/rktio_fd.c @@ -15,10 +15,6 @@ # include #endif -#ifndef RKTIO_BINARY -# define RKTIO_BINARY 0 -#endif - struct rktio_fd_t { int modes; @@ -38,8 +34,6 @@ struct rktio_fd_t { Win_FD_Input_Thread *th; /* input mode */ Win_FD_Output_Thread *oth; /* output mode */ #endif - - int regfile; }; /*************************************************************/ @@ -54,7 +48,7 @@ static void init_read_fd(rktio_fd_t *rfd) # endif #endif #ifdef RKTIO_SYSTEM_WINDOWS - if (!rfd->regfile) { + if (!rktio_fd_is_regular_file(rktio, rfd)) { /* To get non-blocking I/O for anything that can block, we create a separate reader thread. @@ -106,13 +100,14 @@ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes) #ifdef RKTIO_SYSTEM_UNIX rfd->fd = system_fd; - { + if (!(modes & (RKTIO_OPEN_REGFILE | RKTIO_OPEN_NOT_REGFILE | RKTIO_OPEN_SOCKET))) { struct stat buf; int cr; do { cr = fstat(rfd->fd, &buf); } while ((cr == -1) && (errno == EINTR)); - rfd->regfile = S_ISREG(buf.st_mode); + if (S_ISREG(buf.st_mode)) + rfd->modes |= RKTIO_OPEN_REGFILE; } #endif @@ -121,7 +116,10 @@ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes) rfd->s = system_fd; else rfd->fd = (HANDLE)system_fd; - rfd->regfile = (GetFileType(rfd->fd) == FILE_TYPE_DISK); + if (!(modes & (RKTIO_OPEN_REGFILE | RKTIO_OPEN_NOT_REGFILE | RKTIO_OPEN_SOCKET))) { + if ((GetFileType(rfd->fd) == FILE_TYPE_DISK)) + rfd->modes |= RKTIO_OPEN_REGFILE; + } #endif if (modes & RKTIO_OPEN_READ) @@ -145,20 +143,21 @@ intptr_t rktio_fd_system_fd(rktio_t *rktio, rktio_fd_t *rfd) int rktio_fd_is_regular_file(rktio_t *rktio, rktio_fd_t *rfd) { - return rfd->regfile; + return ((rfd->modes & RKTIO_OPEN_REGFILE) ? 1 : 0); } int rktio_fd_is_socket(rktio_t *rktio, rktio_fd_t *rfd) { - return (rfd->modes & RKTIO_OPEN_SOCKET); + return ((rfd->modes & RKTIO_OPEN_SOCKET) ? 1 : 0); } int rktio_fd_is_udp(rktio_t *rktio, rktio_fd_t *rfd) { - return (rfd->modes & RKTIO_OPEN_UDP); + return ((rfd->modes & RKTIO_OPEN_UDP) ? 1 : 0); } -rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd) { +rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd) +{ #ifdef RKTIO_SYSTEM_UNIX intptr_t nfd; @@ -193,250 +192,6 @@ rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd) { #endif } -/*************************************************************/ -/* opening a file fd */ -/*************************************************************/ - -static rktio_fd_t *open_read(rktio_t *rktio, char *filename) -{ -#ifdef RKTIO_SYSTEM_UNIX - int fd; - struct stat buf; - rktio_fd_t *rfd; - - do { - fd = open(filename, O_RDONLY | RKTIO_NONBLOCKING | RKTIO_BINARY); - } while ((fd == -1) && (errno == EINTR)); - - if (fd == -1) { - get_posix_error(); - return NULL; - } else { - int cr; - - do { - cr = fstat(fd, &buf); - } while ((cr == -1) && (errno == EINTR)); - - if (cr) { - get_posix_error(); - do { - cr = close(fd); - } while ((cr == -1) && (errno == EINTR)); - return NULL; - } - - if (S_ISDIR(buf.st_mode)) { - do { - cr = close(fd); - } while ((cr == -1) && (errno == EINTR)); - set_racket_error(RKTIO_ERROR_IS_A_DIRECTORY); - return NULL; - } else { - rfd = malloc(sizeof(rktio_fd_t)); - rfd->modes = RKTIO_OPEN_READ; - rfd->fd = fd; - rfd->regfile = S_ISREG(buf.st_mode); - - init_read_fd(rfd); - - return rfd; - } - } -#endif -#ifdef RKTIO_SYSTEM_WINDOWS - HANDLE fd; - rktio_fd_t *rfd; - - fd = CreateFileW(WIDE_PATH(filename), - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - 0, - NULL); - - if (fd == INVALID_HANDLE_VALUE) { - get_windows_error(); - return NULL; - } - - rfd = malloc(sizeof(rktio_fd_t)); - rfd->modes = RKTIO_OPEN_READ; - rfd->fd = fd; - rfd->regfile = (GetFileType(fd) == FILE_TYPE_DISK); - - init_read_fd(rfd); - - return rfd; -#endif -} - -static rktio_fd_t *open_write(rktio_t *rktio, char *filename, int modes) -{ -#ifdef RKTIO_SYSTEM_UNIX - int fd; - int flags; - struct stat buf; - int cr; - rktio_fd_t *rfd; - - flags = (((modes & RKTIO_OPEN_READ) ? O_RDWR : O_WRONLY) - | ((modes & RKTIO_OPEN_MUST_EXIST ? 0 : O_CREAT))); - - if (modes & RKTIO_OPEN_APPEND) - flags |= O_APPEND; - else if (modes & RKTIO_OPEN_TRUNCATE) - flags |= O_TRUNC; - else if (!(modes & RKTIO_OPEN_CAN_EXIST)) - flags |= O_EXCL; - - do { - fd = open(filename, flags | RKTIO_NONBLOCKING | RKTIO_BINARY, 0666); - } while ((fd == -1) && (errno == EINTR)); - - if (errno == ENXIO) { - /* FIFO with no reader? Try opening in RW mode: */ - flags -= O_WRONLY; - flags |= O_RDWR; - do { - fd = open(filename, flags | RKTIO_NONBLOCKING | RKTIO_BINARY, 0666); - } while ((fd == -1) && (errno == EINTR)); - } - - if (fd == -1) { - if (errno == EISDIR) { - set_racket_error(RKTIO_ERROR_IS_A_DIRECTORY); - return NULL; - } else if (errno == EEXIST) { - if (!(modes & RKTIO_OPEN_REPLACE)) { - set_racket_error(RKTIO_ERROR_EXISTS); - return NULL; - } else { - do { - cr = unlink(filename); - } while ((cr == -1) && (errno == EINTR)); - - if (cr) { - get_posix_error(); - return NULL; - } - - do { - fd = open(filename, flags | RKTIO_BINARY, 0666); - } while ((fd == -1) && (errno == EINTR)); - } - } - - if (fd == -1) { - get_posix_error(); - return NULL; - } - } - - do { - cr = fstat(fd, &buf); - } while ((cr == -1) && (errno == EINTR)); - - if (cr) { - get_posix_error(); - do { - cr = close(fd); - } while ((cr == -1) && (errno == EINTR)); - return NULL; - } - - rfd = malloc(sizeof(rktio_fd_t)); - rfd->modes = modes; - rfd->fd = fd; - rfd->regfile = S_ISREG(buf.st_mode); - return rfd; -#endif -#ifdef RKTIO_SYSTEM_WINDOWS - HANDLE fd; - int hmode, regfile; - BY_HANDLE_FILE_INFORMATION info; - rktio_fd_t *rfd; - - if (modes & RKTIO_OPEN_MUST_EXIST) { - if (modes & RKTIO_OPEN_TRUNNCATE) - hmode = TRUNCATE_EXISTING; - else - hmode = OPEN_EXISTING; - } else if (modes & RKTIO_OPEN_CAN_EXIST) - hmode = OPEN_ALWAYS; - else - hmode = CREATE_NEW; - - fd = CreateFileW(WIDE_PATH_temp(filename), - GENERIC_WRITE | ((modes & RKTIO_OPEN_READ) ? GENERIC_READ : 0), - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - hmode, - FILE_FLAG_BACKUP_SEMANTICS, /* lets us detect directories in NT */ - NULL); - - if (fd == INVALID_HANDLE_VALUE) { - int errv; - errv = GetLastError(); - if ((errv == ERROR_ACCESS_DENIED) && (existsok < -1)) { - /* Delete and try again... */ - if (DeleteFileW(WIDE_PATH_temp(filename))) { - fd = CreateFileW(WIDE_PATH_temp(filename), - GENERIC_WRITE | ((modes & RKTIO_OPEN_READ) ? GENERIC_READ : 0), - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - hmode, - 0, - NULL); - if (fd == INVALID_HANDLE_VALUE) { - get_windows_error(); - return NULL; - } - } else { - get_windows_error(); - return NULL; - } - } else if (errv == ERROR_FILE_EXISTS) { - set_racket_error(RKTIO_ERROR_EXISTS); - return NULL; - } - - if (fd == INVALID_HANDLE_VALUE) { - get_windows_error(); - return NULL; - } - } - - if (GetFileInformationByHandle(fd, &info)) { - if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - CloseHandle(fd); - set_racket_error(RKTIO_ERROR_IS_A_DIRECTORY); - return NULL; - } - } - - rfd = malloc(sizeof(rktio_fd_t)); - rfd->modes = modes; - rfd->fd = fd; - rfd->regfile = (GetFileType(fd) == FILE_TYPE_DISK); - - if (rfd->regfile && (modes & RKTIO_OPEN_APPEND)) { - SetFilePointer(fd, 0, NULL, FILE_END); - } - - return rfd; -#endif -} - -rktio_fd_t *rktio_open(rktio_t *rktio, char *filename, int modes) -{ - if (modes & RKTIO_OPEN_WRITE) - return open_write(rktio, filename, modes); - else - return open_read(rktio, filename); -} - /*************************************************************/ /* closing */ /*************************************************************/ @@ -560,7 +315,7 @@ static int try_get_fd_char(int fd, int *ready) int rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd) { - if (rfd->regfile) + if (rktio_fd_is_regular_file(rktio, rfd)) return RKTIO_POLL_READY; #ifdef RKTIO_SYSTEM_UNIX @@ -781,7 +536,7 @@ void rktio_poll_add(rktio_t *rktio, rktio_fd_t *rfd, rktio_poll_set_t *fds, int } } else rktio_fdset_add_handle(rfd->th->ready_sema, fds, 1); - } else if (rfd->regfile) { + } else if (rktio_fd_is_regular_file(rktio, rfd)) { /* regular files never block */ rktio_fdset_add_nosleep(fds); } else { @@ -812,7 +567,7 @@ 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); - if (rfd->regfile) { + if (rktio_fd_is_regular_file(rktio, rfd)) { /* Reading regular file never blocks */ do { bc = read(rfd->fd, buffer, len); @@ -1025,7 +780,7 @@ 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 (rfd->regfile) { + if (rktio_fd_is_regular_file(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. */ diff --git a/racket/src/rktio/rktio_file.c b/racket/src/rktio/rktio_file.c new file mode 100644 index 0000000000..186f9ab87f --- /dev/null +++ b/racket/src/rktio/rktio_file.c @@ -0,0 +1,244 @@ +#include "rktio.h" +#include "rktio_private.h" +#include +#include +#ifdef RKTIO_SYSTEM_UNIX +# include +# include +# include +# include +#endif +#ifdef RKTIO_SYSTEM_WINDOWS +# include +#endif + +#ifndef RKTIO_BINARY +# define RKTIO_BINARY 0 +#endif + +/*************************************************************/ +/* opening a file fd */ +/*************************************************************/ + +static rktio_fd_t *open_read(rktio_t *rktio, char *filename) +{ +#ifdef RKTIO_SYSTEM_UNIX + int fd; + struct stat buf; + + do { + fd = open(filename, O_RDONLY | RKTIO_NONBLOCKING | RKTIO_BINARY); + } while ((fd == -1) && (errno == EINTR)); + + if (fd == -1) { + get_posix_error(); + return NULL; + } else { + int cr; + + do { + cr = fstat(fd, &buf); + } while ((cr == -1) && (errno == EINTR)); + + if (cr) { + get_posix_error(); + do { + cr = close(fd); + } while ((cr == -1) && (errno == EINTR)); + return NULL; + } + + if (S_ISDIR(buf.st_mode)) { + do { + cr = close(fd); + } while ((cr == -1) && (errno == EINTR)); + set_racket_error(RKTIO_ERROR_IS_A_DIRECTORY); + return NULL; + } else { + return rktio_system_fd(rktio, fd, (RKTIO_OPEN_READ + | (S_ISREG(buf.st_mode) + ? RKTIO_OPEN_REGFILE + : RKTIO_OPEN_NOT_REGFILE))); + } + } +#endif +#ifdef RKTIO_SYSTEM_WINDOWS + HANDLE fd; + + fd = CreateFileW(WIDE_PATH(filename), + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + 0, + NULL); + + if (fd == INVALID_HANDLE_VALUE) { + get_windows_error(); + return NULL; + } + + return rktio_system_fd(rktio, (intptr_t)fd, RKTIO_OPEN_READ); +#endif +} + +static rktio_fd_t *open_write(rktio_t *rktio, char *filename, int modes) +{ +#ifdef RKTIO_SYSTEM_UNIX + int fd; + int flags; + struct stat buf; + int cr; + + flags = (((modes & RKTIO_OPEN_READ) ? O_RDWR : O_WRONLY) + | ((modes & RKTIO_OPEN_MUST_EXIST ? 0 : O_CREAT))); + + if (modes & RKTIO_OPEN_APPEND) + flags |= O_APPEND; + else if (modes & RKTIO_OPEN_TRUNCATE) + flags |= O_TRUNC; + else if (!(modes & RKTIO_OPEN_CAN_EXIST)) + flags |= O_EXCL; + + do { + fd = open(filename, flags | RKTIO_NONBLOCKING | RKTIO_BINARY, 0666); + } while ((fd == -1) && (errno == EINTR)); + + if (errno == ENXIO) { + /* FIFO with no reader? Try opening in RW mode: */ + flags -= O_WRONLY; + flags |= O_RDWR; + do { + fd = open(filename, flags | RKTIO_NONBLOCKING | RKTIO_BINARY, 0666); + } while ((fd == -1) && (errno == EINTR)); + } + + if (fd == -1) { + if (errno == EISDIR) { + set_racket_error(RKTIO_ERROR_IS_A_DIRECTORY); + return NULL; + } else if (errno == EEXIST) { + if (!(modes & RKTIO_OPEN_REPLACE)) { + set_racket_error(RKTIO_ERROR_EXISTS); + return NULL; + } else { + do { + cr = unlink(filename); + } while ((cr == -1) && (errno == EINTR)); + + if (cr) { + get_posix_error(); + return NULL; + } + + do { + fd = open(filename, flags | RKTIO_BINARY, 0666); + } while ((fd == -1) && (errno == EINTR)); + } + } + + if (fd == -1) { + get_posix_error(); + return NULL; + } + } + + do { + cr = fstat(fd, &buf); + } while ((cr == -1) && (errno == EINTR)); + + if (cr) { + get_posix_error(); + do { + cr = close(fd); + } while ((cr == -1) && (errno == EINTR)); + return NULL; + } + + return rktio_system_fd(rktio, fd, (modes + | (S_ISREG(buf.st_mode) + ? RKTIO_OPEN_REGFILE + : RKTIO_OPEN_NOT_REGFILE))); +#endif +#ifdef RKTIO_SYSTEM_WINDOWS + HANDLE fd; + int hmode, regfile; + BY_HANDLE_FILE_INFORMATION info; + rktio_fd_t *rfd; + + if (modes & RKTIO_OPEN_MUST_EXIST) { + if (modes & RKTIO_OPEN_TRUNNCATE) + hmode = TRUNCATE_EXISTING; + else + hmode = OPEN_EXISTING; + } else if (modes & RKTIO_OPEN_CAN_EXIST) + hmode = OPEN_ALWAYS; + else + hmode = CREATE_NEW; + + fd = CreateFileW(WIDE_PATH_temp(filename), + GENERIC_WRITE | ((modes & RKTIO_OPEN_READ) ? GENERIC_READ : 0), + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + hmode, + FILE_FLAG_BACKUP_SEMANTICS, /* lets us detect directories in NT */ + NULL); + + if (fd == INVALID_HANDLE_VALUE) { + int errv; + errv = GetLastError(); + if ((errv == ERROR_ACCESS_DENIED) && (existsok < -1)) { + /* Delete and try again... */ + if (DeleteFileW(WIDE_PATH_temp(filename))) { + fd = CreateFileW(WIDE_PATH_temp(filename), + GENERIC_WRITE | ((modes & RKTIO_OPEN_READ) ? GENERIC_READ : 0), + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + hmode, + 0, + NULL); + if (fd == INVALID_HANDLE_VALUE) { + get_windows_error(); + return NULL; + } + } else { + get_windows_error(); + return NULL; + } + } else if (errv == ERROR_FILE_EXISTS) { + set_racket_error(RKTIO_ERROR_EXISTS); + return NULL; + } + + if (fd == INVALID_HANDLE_VALUE) { + get_windows_error(); + return NULL; + } + } + + if (GetFileInformationByHandle(fd, &info)) { + if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + CloseHandle(fd); + set_racket_error(RKTIO_ERROR_IS_A_DIRECTORY); + return NULL; + } + } + + rfd = rktio_system_fd(rktio, fd, modes); + + if ((modes & RKTIO_OPEN_APPEND) && rktio_fd_is_regular_file(rktio, rfd)) { + SetFilePointer(fd, 0, NULL, FILE_END); + } + + return rfd; +#endif +} + +rktio_fd_t *rktio_open(rktio_t *rktio, char *filename, int modes) +{ + if (modes & RKTIO_OPEN_WRITE) + return open_write(rktio, filename, modes); + else + return open_read(rktio, filename); +} +