From 4e6d0dc9476e5cf43ff0bc5e66a54d812ddb4225 Mon Sep 17 00:00:00 2001 From: Ron Yorston <rmy@pobox.com> Date: Thu, 22 Feb 2018 11:40:53 +0000 Subject: win32: handle /dev/zero and /dev/urandom in open and read functions Currently /dev/zero is handled as a special case in dd. Add hacks to the open and read functions in mingw.c to handle the zero and urandom devices. - Opening /dev/zero or /dev/urandom actually opens the special Windows file 'nul' which behaves like /dev/null. This allows manipulation of the file descriptor with things like seek and close - When /dev/zero or /dev/urandom is opened the resulting file descriptor is stored and used to override the behaviour of read. - No attempt is made to track duplicated file descriptors, so using these devices for redirections in the shell isn't going to work and won't be permitted. (Could be, but won't.) - Limited control of the special file descriptors is provided by allowing the internal variables to be changed. - The numbers from /dev/urandom aren't very random. --- include/mingw.h | 5 +++++ win32/mingw.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- win32/winansi.c | 2 +- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/include/mingw.h b/include/mingw.h index a59ce6fc4..46be4dc23 100644 --- a/include/mingw.h +++ b/include/mingw.h @@ -395,6 +395,10 @@ int kill(pid_t pid, int sig); int link(const char *oldpath, const char *newpath); NOIMPL(mknod,const char *name UNUSED_PARAM, mode_t mode UNUSED_PARAM, dev_t device UNUSED_PARAM); int mingw_open (const char *filename, int oflags, ...); +void mingw_read_zero(int fd); +void mingw_read_random(int fd); +ssize_t mingw_read(int fd, void *buf, size_t count); +int mingw_close(int fd); int pipe(int filedes[2]); NOIMPL(readlink,const char *path UNUSED_PARAM, char *buf UNUSED_PARAM, size_t bufsiz UNUSED_PARAM); NOIMPL(setgid,gid_t gid UNUSED_PARAM); @@ -418,6 +422,7 @@ int mingw_isatty(int fd); #define getcwd mingw_getcwd #define lchown chown #define open mingw_open +#define close mingw_close #define unlink mingw_unlink #define rmdir mingw_rmdir #undef lseek diff --git a/win32/mingw.c b/win32/mingw.c index a55fb4f40..595042d85 100644 --- a/win32/mingw.c +++ b/win32/mingw.c @@ -138,12 +138,28 @@ int err_win_to_posix(DWORD winerr) return error; } +static int zero_fd = -1; +static int rand_fd = -1; + +void mingw_read_zero(int fd) +{ + zero_fd = fd; +} + +void mingw_read_random(int fd) +{ + rand_fd = fd; +} + #undef open int mingw_open (const char *filename, int oflags, ...) { va_list args; unsigned mode; int fd; + int devnull = 0; + int devzero = 0; + int devrand = 0; va_start(args, oflags); mode = va_arg(args, int); @@ -152,14 +168,29 @@ int mingw_open (const char *filename, int oflags, ...) if (oflags & O_NONBLOCK) { oflags &= ~O_NONBLOCK; } - if (filename && !strcmp(filename, "/dev/null")) - filename = "nul"; + if (filename && !strncmp(filename, "/dev/", 5)) { + if (!strcmp(filename+5, "null")) + devnull = 1; + else if (!strcmp(filename+5, "zero")) + devzero = 1; + else if (!strcmp(filename+5, "urandom")) + devrand = 1; + + if (devnull || devzero || devrand ) + filename = "nul"; + } fd = open(filename, oflags, mode); if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) { DWORD attrs = GetFileAttributes(filename); if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) errno = EISDIR; } + if (fd >= 0 ) { + if (devzero) + zero_fd = fd; + else if (devrand) + rand_fd = fd; + } return fd; } @@ -171,6 +202,32 @@ FILE *mingw_fopen (const char *filename, const char *otype) return fopen(filename, otype); } +#undef read +ssize_t mingw_read(int fd, void *buf, size_t count) +{ + if (fd == zero_fd) { + memset(buf, 0, count); + return count; + } + else if (fd == rand_fd) { + memset(buf, 0x5A, count); + return count; + } + return read(fd, buf, count); +} + +#undef close +int mingw_close(int fd) +{ + if (fd == zero_fd) { + zero_fd = -1; + } + if (fd == rand_fd) { + rand_fd = -1; + } + return close(fd); +} + #undef dup2 int mingw_dup2 (int fd, int fdto) { diff --git a/win32/winansi.c b/win32/winansi.c index 8fffc5a00..b357fc642 100644 --- a/win32/winansi.c +++ b/win32/winansi.c @@ -695,7 +695,7 @@ int winansi_read(int fd, void *buf, size_t count) { int rv; - rv = read(fd, buf, count); + rv = mingw_read(fd, buf, count); if (!isatty(fd)) return rv; -- cgit v1.2.3-55-g6feb