]> git.pond.sub.org Git - empserver/commitdiff
Simple POSIX I/O emulation layer to work around Windows's defective
authorRon Koenderink <rkoenderink@yahoo.ca>
Tue, 14 Aug 2007 03:33:28 +0000 (03:33 +0000)
committerRon Koenderink <rkoenderink@yahoo.ca>
Tue, 14 Aug 2007 03:33:28 +0000 (03:33 +0000)
Unix I/O:
[_WIN32] (socklen_t, accept, posix_accept, bind. posix_bind, listen)
(posix_listen, setsockopt, posix_setsockopt, shutdown, posix_shutdown)
(socket, posix_socket, close, posix_close, creat, fstat, posix_fstat)
(lseek, posix_lseek, open, posix_open, read, posix_read, write)
(posix_write, fileno, posix_fileno, fcntl, O_NONBLOCK, F_RDLCK)
(F_WRLCK, F_GETFL, F_SETFL, F_SETLK, EWOULDBLOCK, ENOTSOCK)
(flock, fsync, posix_fsync):
New.
(ef_open, io_close, io_input, io_output, io_shutdown, io_noblocking)
(player_accept): Use them to simplify.
[_WIN32] (posix_fd2socket): New.
(empth_select): Use it.
(gen_power): Use it.

17 files changed:
src/lib/commands/add.c
src/lib/commands/new.c
src/lib/commands/powe.c
src/lib/commands/turn.c
src/lib/common/file.c
src/lib/common/fsize.c
src/lib/common/log.c
src/lib/common/wantupd.c
src/lib/empthread/ntthread.c
src/lib/gen/emp_config.c
src/lib/gen/io.c
src/lib/player/accept.c
src/lib/player/empdis.c
src/lib/player/player.c
src/lib/subs/wu.c
src/lib/w32/posixio.c [new file with mode: 0644]
src/lib/w32/unistd.h

index 89e011b6eafd72c8bcfd829e646e04ab8294ef2d..45c7114d3db62ecfd7c899cc159cc0cc7db2cc35 100644 (file)
 #include <config.h>
 
 #include <fcntl.h>
-#if defined(_WIN32)
-#include <io.h>
-#else
 #include <unistd.h>
-#endif
 #include <sys/stat.h>
 
 #include "commands.h"
index 9fc9480af65c8913d73c125e7c10f0b610879b1e..b0116eb60cd1ceef58568f74f15c28b31b5a9315 100644 (file)
 #include <config.h>
 
 #include <fcntl.h>
-#if defined(_WIN32)
-#include <io.h>
-#endif
 #include <sys/stat.h>
-#if !defined(_WIN32)
 #include <unistd.h>
-#endif
 #include "commands.h"
 #include "land.h"
 #include "optlist.h"
index b05be45eb84c54d9a828ea5c0ccd58371476f48a..a66065f323b79bfc3edea40e50a79895b9d41833 100644 (file)
  */
 
 #include <config.h>
-
+#include <unistd.h>
 #include <math.h>
-#ifdef _WIN32
-#include <io.h>
-#endif
 
 #include "commands.h"
 #include "item.h"
@@ -317,14 +314,13 @@ gen_power(struct powstr *powbuf, int save)
        return;
     for (i = 0; i < MAXNOC; i++)
        putpower(i, &powbuf[i]);
-#ifdef _WIN32
     /*
-     * At least some versions of Windows fail to update mtime on
-     * write().  Bad, because `power' displays that time.  Attempt to
-     * force an update.
+     * At least some versions of Windows fail to update st_mtime on
+     * write(), the st_mtime is not until the file is written to the
+     * disk.  Bad, because `power' displays that time.
+     * Force a sync to ensure the st_time is correct.
      */
-    _commit(empfile[EF_POWER].fd);
-#endif
+    fsync(empfile[EF_POWER].fd);
 }
 
 static int
index 4b24b4ded45a5379379451b2fee522e0b439cf28..2594341238908b4f89bdabb74e8559dc87c338fb 100644 (file)
 #include <config.h>
 
 #include <errno.h>
-#if !defined(_WIN32)
 #include <unistd.h>
-#elif defined(__GNUC__)
-#include <io.h>
-#endif
 #include "tel.h"
 #include "commands.h"
 #include "optlist.h"
index 3a9488c258f376b2641d12a1701732f6b4f9a8a1..f7e25b4d3464688897f3434af38af67ba335f9e4 100644 (file)
 #include <config.h>
 
 #include <errno.h>
-#if defined(_WIN32)
-#include <io.h>
-#include <share.h>
-#endif
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <signal.h>
 #include <sys/types.h>
-#if !defined(_WIN32)
 #include <unistd.h>
-#endif
 #include "file.h"
 #include "match.h"
 #include "misc.h"
@@ -68,9 +62,7 @@ int
 ef_open(int type, int how)
 {
     struct empfile *ep;
-#if !defined(_WIN32)
     struct flock lock;
-#endif
     int oflags, fd, fsiz, size;
 
     if (ef_check(type) < 0)
@@ -89,13 +81,7 @@ ef_open(int type, int how)
        oflags |= O_CREAT | O_TRUNC;
 #if defined(_WIN32)
     oflags |= O_BINARY;
-    if ((fd = sopen(ep->file, oflags,
-       how & EFF_RDONLY ? SH_DENYNO : SH_DENYWR,
-       S_IRWUG)) < 0) {
-       logerror("Can't open %s (%s)", ep->file, strerror(errno));
-       return 0;
-    }
-#else
+#endif
     if ((fd = open(ep->file, oflags, S_IRWUG)) < 0) {
        logerror("Can't open %s (%s)", ep->file, strerror(errno));
        return 0;
@@ -109,7 +95,6 @@ ef_open(int type, int how)
        close(fd);
        return 0;
     }
-#endif
 
     /* get file size */
     fsiz = fsize(fd);
index 0107231edc652736ee6c7f9569165c1821eaf83c..34cad2c0b9faeefa48e2697869659db82894d8b4 100644 (file)
@@ -37,9 +37,7 @@
 
 #include <fcntl.h>
 #include <sys/stat.h>
-#if !defined(_WIN32)
 #include <unistd.h>
-#endif
 
 #include "prototypes.h"
 
index 52869112c45cdce7e3bfb0a29d384d9f950ef656..50cf3d2472b108d2ddaaf817507395870ddbd987 100644 (file)
 
 #include <config.h>
 
-#if defined(_WIN32)
-#include <io.h>
-#endif
-#if !defined(_WIN32)
 #include <unistd.h>
-#endif
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <stdarg.h>
index 439b33af88c57e0f184473e8e98c60817e8b52ac..439a9294806793eb2d8363decc2b4d0fa5614840 100644 (file)
 
 #include <fcntl.h>
 #include <stdio.h>
-#if defined(_WIN32)
-#include <io.h>
-#endif
 #include <time.h>
-#if !defined(_WIN32)
 #include <unistd.h>
-#endif
 #include "file.h"
 #include "game.h"
 #include "misc.h"
index 878c19407f83083d3fdbee1738b4012ac8cf2d0b..1bb2945372571d889391d62b53eb77a8a71a12c3 100644 (file)
 #undef NS_ALL
 #include <windows.h>
 #include <process.h>
+/* Note: unistd.h(posixio.c) is not thread-safe.
+ * It may be used *only* while holding hThreadMutex.
+ */
+#include "unistd.h"
 #include "misc.h"
 #include "empthread.h"
 #include "prototypes.h"
@@ -313,6 +317,9 @@ loc_Exit_Handler(DWORD fdwCtrlType)
  *
  * This is the main line of each thread.
  * This is really a static local func....
+ * Note: As the POSIX compatibility layer is not thread safe
+ * this function can not open or create any files or sockets until
+ * loc_RunThisThread() is called
  */
 static void
 empth_threadMain(void *pvData)
@@ -535,6 +542,7 @@ empth_terminate(empth_t *pThread)
 void
 empth_select(int fd, int flags)
 {
+    int handle;
     WSAEVENT hEventObject[2];
     empth_t *pThread = TlsGetValue(dwTLSIndex);
 
@@ -545,10 +553,13 @@ empth_select(int fd, int flags)
     hEventObject[0] = WSACreateEvent();
     hEventObject[1] = pThread->hThreadEvent;
 
+    handle = posix_fd2socket(fd);
+    CANT_HAPPEN(handle < 0);
+
     if (flags == EMPTH_FD_READ)
-       WSAEventSelect(fd, hEventObject[0], FD_READ | FD_ACCEPT | FD_CLOSE);
+       WSAEventSelect(handle, hEventObject[0], FD_READ | FD_ACCEPT | FD_CLOSE);
     else if (flags == EMPTH_FD_WRITE)
-       WSAEventSelect(fd, hEventObject[0], FD_WRITE | FD_CLOSE);
+       WSAEventSelect(handle, hEventObject[0], FD_WRITE | FD_CLOSE);
     else {
        logerror("bad flag %d passed to empth_select", flags);
        empth_exit();
@@ -556,7 +567,7 @@ empth_select(int fd, int flags)
 
     WSAWaitForMultipleEvents(2, hEventObject, FALSE, WSA_INFINITE, FALSE);
 
-    WSAEventSelect(fd, hEventObject[0], 0);
+    WSAEventSelect(handle, hEventObject[0], 0);
 
     WSACloseEvent(hEventObject[0]);
 
index 10cedc8f0fa7e66a60acb57467307ee31ed26e0a..37ba63ba35ada648e2272ca21061342dbbc3b4d8 100644 (file)
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
-#ifdef _WIN32
-#include <direct.h>
-#else
 #include <unistd.h>
-#endif
 
 #include "file.h"
 #include "misc.h"
index 8744df63de96af8eeb3edd2f05d3999f1ba7e92d..ef83f6dd70c75eb2c0a7884b6bfc11b0f8be48b0 100644 (file)
 #include <sys/types.h>
 #ifdef _WIN32
 #include <winsock2.h>
-#undef NS_ALL
 #else
 #include <sys/uio.h>
 #include <sys/file.h>
 #include <sys/socket.h>
-#include <unistd.h>
 #endif
+#include <unistd.h>
 #include <time.h>
 
 #include "empio.h"
@@ -111,11 +110,7 @@ io_close(struct iop *iop)
        ioq_destroy(iop->input);
     if (iop->output != 0)
        ioq_destroy(iop->output);
-#if !defined(_WIN32)
     (void)close(iop->fd);
-#else
-    closesocket(iop->fd);
-#endif
     free(iop);
 }
 
@@ -135,7 +130,6 @@ io_input(struct iop *iop, int waitforinput)
     if (waitforinput) {
        empth_select(iop->fd, EMPTH_FD_READ);
     }
-#if !defined(_WIN32)
     /* Do the actual read. */
     cc = read(iop->fd, buf, sizeof(buf));
     if (cc < 0) {
@@ -147,19 +141,6 @@ io_input(struct iop *iop, int waitforinput)
        iop->flags |= IO_ERROR;
        return -1;
     }
-#else
-    cc = recv(iop->fd, buf, sizeof(buf), 0);
-    if (cc == SOCKET_ERROR) {
-       int err = WSAGetLastError();
-       /* Hmm, it would block.  file is opened noblock, soooooo.. */
-       if (err == WSAEWOULDBLOCK)
-           return 0;
-
-       /* Some form of file error occurred... */
-       iop->flags |= IO_ERROR;
-       return -1;
-    }
-#endif
 
     /* We eof'd */
     if (cc == 0) {
@@ -232,6 +213,9 @@ io_output(struct iop *iop, int waitforoutput)
     /* Do the actual write. */
 #if !defined(_WIN32)
     cc = writev(iop->fd, iov, n);
+#else
+    cc = write(iop->fd, buf, n);
+#endif
 
     /* if it failed.... */
     if (cc < 0) {
@@ -244,22 +228,6 @@ io_output(struct iop *iop, int waitforoutput)
        iop->flags |= IO_ERROR;
        return -1;
     }
-#else
-    cc = send(iop->fd, buf, n, 0);
-
-    /* if it failed.... */
-    if (cc == SOCKET_ERROR) {
-       int err = WSAGetLastError();
-       /* Hmm, it would block.  file is opened noblock, soooooo.. */
-       if (err == WSAEWOULDBLOCK) {
-           /* If there are remaining bytes, set the IO as remaining.. */
-           remain = ioq_qsize(iop->output);
-           return remain;
-       }
-       iop->flags |= IO_ERROR;
-       return -1;
-    }
-#endif
 
     /* If no bytes were written, something happened..  Like an EOF. */
     if (cc == 0) {
@@ -366,7 +334,6 @@ io_shutdown(struct iop *iop, int flags)
 int
 io_noblocking(struct iop *iop, int value)
 {
-#if !defined(_WIN32)
     int flags;
 
     flags = fcntl(iop->fd, F_GETFL, 0);
@@ -378,10 +345,6 @@ io_noblocking(struct iop *iop, int value)
        flags |= O_NONBLOCK;
     if (fcntl(iop->fd, F_SETFL, flags) < 0)
        return -1;
-#else
-    u_long arg = value;
-    ioctlsocket(iop->fd, FIONBIO, &arg);
-#endif
     if (value == 0)
        iop->flags &= ~IO_NBLOCK;
     else
index 9249adf0d5333a3ae9a863fa439939093fd39660..2255164cf91169a5e6dc3fa0159ff3dbbb65a4a5 100644 (file)
@@ -47,8 +47,8 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <sys/ioctl.h>
-#include <unistd.h>
 #endif
+#include <unistd.h>
 #include <signal.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -170,7 +170,7 @@ player_accept(void *unused)
     void *inaddr;
     int s = player_socket;
     struct player *np;
-    int len;
+    socklen_t len;
     int ns;
     int set = 1;
     int stacksize;
index b37ea4b05f8c16809b5f790b806bb62002871304..2e2dc267a2251df9f1c28117891747dcacb9e087 100644 (file)
@@ -38,9 +38,7 @@
 #include <stdio.h>
 #include <fcntl.h>
 #include <time.h>
-#if !defined(_WIN32)
 #include <unistd.h>
-#endif
 #include <signal.h>
 
 #include "com.h"
index 9f57dbf281abd55433fbcee37cf206e275012f54..a52d8608a936f647448aab0b62042d939808a9a3 100644 (file)
@@ -32,9 +32,7 @@
  */
 
 #include <config.h>
-#if !defined(_WIN32)
 #include <unistd.h>
-#endif
 #include <stdio.h>
 #include <errno.h>
 #include <fcntl.h>
index 23a503da2d0c1c475cc2543c27ea96b5381ee23b..85fccc5609f6c08671b14602f1788f55258cf0ef 100644 (file)
 
 #include <config.h>
 
-#if defined(_WIN32)
-#include <io.h>
-#endif
 #include <fcntl.h>
 #include <stdarg.h>
 #include <stdlib.h>
-#if !defined(_WIN32)
 #include <unistd.h>
+#if !defined(_WIN32)
 #include <sys/uio.h>
 #endif
 #include "file.h"
diff --git a/src/lib/w32/posixio.c b/src/lib/w32/posixio.c
new file mode 100644 (file)
index 0000000..d7e88b6
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ *  Empire - A multi-player, client/server Internet based war game.
+ *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *                           Ken Stevens, Steve McClure
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  ---
+ *
+ *  See files README, COPYING and CREDITS in the root of the source
+ *  tree for related information and legal notices.  It is expected
+ *  that future projects/authors will amend these files as needed.
+ *
+ *  ---
+ *
+ *  posixio.c: POSIX IO emulation layer for WIN32
+ * 
+ *  Known contributors to this file:
+ *     Ron Koenderink, 2007
+ */
+
+/*
+ * POSIX has just one kind of file descriptors, while Windows has (at
+ * least) two: one for sockets and one for files, with separate
+ * functions to operate on them.  To present a more POSIX-like
+ * interface to our application code, we provide a compatibility layer
+ * that maps POSIX file descriptors to sockets and file handles behind
+ * the scenes.  This actual mapping is done by the fdmap.  It doesn't
+ * implement the finer points of POSIX correctly.  In particular, the
+ * actual values of the file descriptors usually differ.
+ */
+
+#include <config.h>
+#include <winsock2.h>
+#undef NS_ALL
+#include <io.h>
+#include <direct.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <share.h>
+
+#include <errno.h>
+
+#include "unistd.h"
+#include "empio.h"
+#include "prototypes.h"
+
+/*
+ * FD_SETSIZE is the size for the maximum number of sockets.
+ * The number of file descriptors is in a variable _nhandle
+ * based on the assertion output.  In order the simplify the
+ * code and skip dynamic allocation, used double the socket size.
+ */
+#define MAX_FDS (FD_SETSIZE * 2)
+
+enum fdmap_io_type {
+    FDMAP_IO_NOTUSED = 0,
+    FDMAP_IO_FILE,
+    FDMAP_IO_SOCKET,
+    FDMAP_IO_ANY /* used for searching only (lookup_handle) */
+};
+
+struct fdmap {
+    int handle;
+    enum fdmap_io_type type;
+};
+
+static struct fdmap fdmap[MAX_FDS] = {
+    {0, FDMAP_IO_FILE},
+    {1, FDMAP_IO_FILE},
+    {2, FDMAP_IO_FILE}
+};
+static int nfd = 3;
+
+/*
+ * Allocate a POSIX equivalent file descriptor.
+ * Note once get_fd() is called either free_fd() or set_fd()
+ * must be called before thread mutex is released as the
+ * allocation/deallocation code is not thread safe.
+ */
+static int
+get_fd(void)
+{
+    int fd;
+
+    for (fd = 0; fd < nfd && fdmap[fd].type != FDMAP_IO_NOTUSED; fd++) ;
+    if (fd == MAX_FDS) {
+       errno = EMFILE;
+       return -1;
+    }
+    if (fd == nfd) {
+       fdmap[fd].type = FDMAP_IO_NOTUSED;
+       nfd++;
+    }
+    return fd;
+}
+
+/*
+ * Deallocate a POSIX equivalent file descriptor.
+ */
+static void
+free_fd(int fd)
+{
+    fdmap[fd].type = FDMAP_IO_NOTUSED;
+    for(; fdmap[nfd - 1].type == FDMAP_IO_NOTUSED; nfd--) ;
+}
+
+/*
+ * Complete the allocation of the file descriptor.
+ */
+static void
+set_fd(int fd, enum fdmap_io_type type, int handle)
+{
+    int i;
+
+    fdmap[fd].handle = handle;
+    fdmap[fd].type = type;
+
+    /*
+     * Garbage collection for posix_fileno(), currently not
+     * replacing fclose() and fcloseall() so do not know when
+     * a stream is closed.
+     */
+    for (i = 0; i < nfd; i++) {
+       if (i != fd && type == fdmap[i].type && handle == fdmap[i].handle)
+           free_fd(i);
+    }
+}
+
+/*
+ * Find the windows handle (file or socket) for file descriptor.
+ * Return windows handle and type of handle.
+ * You can search for a specific type (FDMAP_IO_FILE or FDMAP_IO_SOCKET)
+ * or for both search by using FDMAP_IO_ANY.
+ * FDMAP_IO_NOTUSED is not valid type to search with.
+ */
+static int
+lookup_handle(int fd, enum fdmap_io_type d_type, int error,
+       enum fdmap_io_type *type_ptr, int *handle_ptr)
+{
+
+    if (fd < 0 || fd >= MAX_FDS) {
+       if (error != 0)
+           errno = error;
+       return 0;
+    } else if ((fdmap[fd].type != d_type && d_type != FDMAP_IO_ANY) ||
+       (fdmap[fd].type == FDMAP_IO_NOTUSED && d_type == FDMAP_IO_ANY)) {
+       if (error != 0)
+           errno = error;
+       return 0;
+    }
+    if (type_ptr != NULL)
+       *type_ptr = fdmap[fd].type;
+    if (handle_ptr != NULL)
+       *handle_ptr = fdmap[fd].handle;
+    return 1;
+}
+
+/*
+ * Find and return the file descriptor associated with windows handle.
+ * You can search for FDMAP_IO_FILE or FDMAP_IO_SOCKET.
+ * FDMAP_IO_ANY or FDMAP_IO_NOTUSED is not considered valid search
+ * criteria.
+ */
+static int
+lookup_fd(int handle, enum fdmap_io_type d_type)
+{
+    int i;
+
+    for (i = 0; i < nfd; i++)
+       if (fdmap[i].handle == handle && fdmap[i].type == d_type)
+           return i;
+    return -1;
+}
+
+/*
+ * Get the window socket handle for POSIX file descriptor.
+ */
+int
+posix_fd2socket(int fd)
+{
+    int handle;
+    enum dmap_io_type type;
+
+    if (!lookup_handle(fd, FDMAP_IO_SOCKET, WSAENOTSOCK,
+       &type, &handle))
+       return INVALID_SOCKET;
+    return handle;
+}
+
+#define SOCKET_FUNCTION(expr)                          \
+    int result;                                                \
+    int handle;                                                \
+                                                       \
+    if (!lookup_handle(fd, FDMAP_IO_SOCKET,            \
+       ENOTSOCK, NULL, &handle))                       \
+       return -1;                                      \
+                                                       \
+    result = (expr);                                   \
+    if (result == SOCKET_ERROR) {                      \
+       errno = WSAGetLastError();                      \
+       return -1;                                      \
+    }                                                  \
+    return result;
+
+/*
+ * POSIX equivalent for accept().
+ */
+#undef accept
+int
+posix_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
+{
+    int new_fd;
+    int handle, new_handle;
+
+    if (!lookup_handle(fd, FDMAP_IO_SOCKET, ENOTSOCK, NULL, &handle))
+       return -1;
+
+    new_fd = get_fd();
+    if (new_fd < 0)
+       return -1;
+
+    new_handle = accept(handle, addr, addrlen);
+    if (new_handle == INVALID_SOCKET) {
+       free_fd(new_fd);
+       errno = WSAGetLastError();
+       return -1;
+    }
+    set_fd(new_fd, FDMAP_IO_SOCKET, new_handle);
+    return new_fd;
+}
+
+/*
+ * POSIX equivalent for bind().
+ */
+#undef bind
+int
+posix_bind(int fd, const struct sockaddr *name, int namelen)
+{
+    SOCKET_FUNCTION(bind(handle, name, namelen))
+}
+
+/*
+ * POSIX equivalent for listen().
+ */
+#undef listen
+int
+posix_listen(int fd, int backlog)
+{
+    SOCKET_FUNCTION(listen(handle, backlog))
+}
+
+/*
+ * POSIX equivalent for setsockopt().
+ */
+#undef setsockopt
+int
+posix_setsockopt(int fd, int level, int optname,
+                     const char *optval, int optlen)
+{
+    SOCKET_FUNCTION(setsockopt(handle, level, optname,
+                   optval, optlen))
+}
+
+/*
+ * POSIX equivalent for shutdown().
+ */
+#undef shutdown
+int
+posix_shutdown(int fd, int how)
+{
+    SOCKET_FUNCTION(shutdown(handle, how))
+}
+
+/*
+ * POSIX equivalent for socket().
+ */
+#undef socket
+int
+posix_socket(int domain, int type, int protocol)
+{
+    int handle;
+    int new_fd;
+    
+    if ((new_fd = get_fd()) < 0)
+       return -1;
+
+    handle = socket(domain, type, protocol);
+    if (handle == INVALID_SOCKET) {
+       free_fd(new_fd);
+       errno = WSAGetLastError();
+       return -1;
+    }
+    set_fd(new_fd, FDMAP_IO_SOCKET, handle);
+    return new_fd;
+}
+
+#define FILE_FUNCTION(type, expr)                              \
+    int handle;                                                        \
+                                                               \
+    if (!lookup_handle(fd, (type), EBADF, NULL, &handle))      \
+       return -1;                                              \
+                                                               \
+    return (expr);
+
+/*
+ * POSIX equivalent for close().
+ */
+int
+posix_close(int fd)
+{
+    int result;
+    int handle;
+    enum fdmap_io_type type;
+
+    if (!lookup_handle(fd, FDMAP_IO_ANY, EBADF, &type, &handle))
+       return -1;
+
+    free_fd(fd);
+    switch (type) {
+    case FDMAP_IO_SOCKET:
+       result = closesocket(handle);
+       if (result == SOCKET_ERROR) {
+           errno = WSAGetLastError();
+           return -1;
+       }
+       return result;
+    case FDMAP_IO_FILE:
+       return _close(handle);
+    }
+    CANT_REACH();
+    return -1;
+}
+
+/*
+ * posix_fsync forces file sync with the disk.
+ * In order for the power report report to accurate timestamp,
+ * the _commit() is to force a sync with disk and therefore
+ * an update for file time.
+ */
+int
+posix_fsync(int fd)
+{
+    FILE_FUNCTION(FDMAP_IO_FILE, _commit(handle))
+}
+
+/*
+ * POSIX equivalent for fstat().
+ * fstat() is used instead of _fstat(),
+ * otherwise problems with the 32/64 time definitions
+ * in WIN32.
+ */
+#undef fstat
+int
+posix_fstat(int fd, struct stat *buffer)
+{
+    FILE_FUNCTION(FDMAP_IO_ANY, fstat(handle, buffer))
+}
+
+/*
+ * POSIX equivalent for lseek().
+ */
+int
+posix_lseek(int fd, long offset, int origin)
+{
+    FILE_FUNCTION(FDMAP_IO_FILE, _lseek(handle, offset, origin))
+}
+
+/*
+ * POSIX equivalent for open().
+ * Implements file locks when opening files to provide equivalent
+ * F_GETLK/F_SETLK.
+ */
+int
+posix_open(const char *fname, int oflag, ...)
+{
+    va_list ap;
+    int pmode = 0, new_fd;
+    int handle;
+
+    if (oflag & O_CREAT) {
+       va_start(ap, oflag);
+       pmode = va_arg(ap, int);
+       va_end(ap);
+    }
+
+    if ((new_fd = get_fd()) < 0)
+       return -1;
+
+    /*
+     * We don't implement fcntl() for F_SETLK.  Instead, we lock *all*
+     * files we open.  Not ideal, but it works for Empire.
+     */
+    _sopen_s(&handle, fname, oflag,
+       oflag & O_RDONLY ? SH_DENYNO : SH_DENYWR, pmode);
+    if (handle == -1) {
+       free_fd(new_fd);
+       return -1;
+    }
+    set_fd(new_fd, FDMAP_IO_FILE, handle);
+    return new_fd;
+}
+
+#define SHARED_FUNCTION(socket_expr, file_expr)                            \
+    int result;                                                            \
+    int handle;                                                            \
+    enum fdmap_io_type type;                                       \
+                                                                   \
+    if (!lookup_handle(fd, FDMAP_IO_ANY, EBADF, &type, &handle))    \
+       return -1;                                                  \
+                                                                   \
+    switch (type) {                                                \
+    case FDMAP_IO_SOCKET:                                          \
+       result = (socket_expr);                                     \
+       if (result == SOCKET_ERROR) {                               \
+           errno = WSAGetLastError();                              \
+           return -1;                                              \
+       }                                                           \
+       return result;                                              \
+    case FDMAP_IO_FILE:                                                    \
+       return (file_expr);                                         \
+    }                                                              \
+    CANT_REACH();                                                  \
+    return -1;
+
+/*
+ * POSIX equivalent for read().
+ */
+int
+posix_read(int fd, void *buffer, unsigned int count)
+{
+    SHARED_FUNCTION(recv(handle, buffer, count, 0),
+       _read(handle, buffer, count))
+}
+
+/*
+ * POSIX equivalent for write().
+ */
+int
+posix_write(int fd, const void *buffer, unsigned int count)
+{
+    SHARED_FUNCTION(send(handle, buffer, count, 0),
+       _write(handle, buffer, count))
+}
+
+/*
+ * POSIX equivalent for fileno().
+ * As fopen/fclose/fcloseall are not implemented as POSIX
+ * equivalent functions, the mapping is done when required
+ * by a call to fileno().  The garbage collection of the
+ * file descriptors allocated is done in set_fd() when the
+ * handle is reused.
+ */
+int
+posix_fileno(FILE *stream)
+{
+    int fd;
+    int handle;
+
+    if (stream == NULL) {
+       errno = EBADF;
+       return -1;
+    }
+
+    handle = _fileno(stream);
+
+    fd = lookup_fd(handle, FDMAP_IO_FILE);
+    if (fd >= 0)
+       return fd;
+
+    if ((fd = get_fd()) < 0) {
+       errno = EBADF;
+       return -1;
+    }
+
+    set_fd(fd, FDMAP_IO_FILE, handle);
+    return fd;
+}
+
+/*
+ * POSIX equivalent for fcntl().
+ * Currently supports only the F_GETFL/F_SETFL/O_NONBLOCK
+ * Currently ignores F_GETLK/F_SETLK as the file locks are
+ * implement in open()
+ */
+int
+fcntl(int fd, int cmd, ...)
+{
+    va_list ap;
+    int value;
+    unsigned int nonblocking;
+    int result;
+    long bytes_returned;
+    int handle;
+    enum fdmap_io_type type;
+
+    if (!lookup_handle(fd, FDMAP_IO_ANY, EBADF, &type, &handle))
+        return -1;
+
+    switch (cmd)
+    {
+    case F_GETFL:
+       /*
+        * F_GETFL and F_SETFL only support O_NONBLOCK
+        * for sockets currently
+        */
+       if (type == FDMAP_IO_SOCKET) {
+           result = WSAIoctl(handle, FIONBIO, NULL, 0,&nonblocking,
+               sizeof (nonblocking), &bytes_returned, NULL, NULL);
+       
+           if(result < 0) {
+               errno = WSAGetLastError();
+               return -1;
+           }
+
+           if (nonblocking)
+               return O_NONBLOCK;
+           else
+               return 0;
+       }
+       break;
+    case F_SETFL:
+       if (type == FDMAP_IO_SOCKET) {
+           va_start(ap, cmd);
+           value = va_arg(ap, int);
+           va_end(ap);
+           if (value & O_NONBLOCK)
+               nonblocking = 1;
+           else
+               nonblocking = 0;
+
+           result = WSAIoctl(handle, FIONBIO, &nonblocking,
+               sizeof (nonblocking), NULL, 0, &bytes_returned,
+               NULL, NULL);
+
+           if(result < 0) {
+               errno = WSAGetLastError();
+               return -1;
+           }
+           return result;
+       }
+       break;
+    case F_SETLK:
+       /*
+        * The POSIX equivalent is not available in WIN32
+        * That implement the file locking in the file open
+        * by using sopen instead of open.
+        */
+       return 0;
+    }
+    errno = EINVAL;
+    return -1;
+}
index 80be3c2c1129e954339d4906a42d1b87127e26a4..fd024a0e792637f23b7b90f349879320a8c22bc7 100644 (file)
@@ -34,7 +34,9 @@
 #ifndef UNISTD_H
 #define UNISTD_H
 
+#include <stdio.h>
 #include "getopt.h"
+#include <sys/stat.h>
 
 /*
  * posixfile.c
 
 extern int posix_mkdir(const char *dirname, int perm);
 
+/*
+ * posixio.c
+ */
+
+typedef int socklen_t;
+
+#define accept(fd, addr, addrlen) \
+    posix_accept((fd), (addr), (addrlen))
+#define bind(fd, name, namelen) \
+    posix_bind((fd), (name), (namelen))
+#define listen(fd, backlog) \
+    posix_listen((fd), (backlog))
+#define setsockopt(fd, level, optname, optval, optlen) \
+    posix_setsockopt((fd), (level), (optname), (optval), (optlen))
+#define shutdown(fd, how) \
+    posix_shutdown((fd), (how))
+#define socket(domain, type, protocol) \
+    posix_socket((domain), (type), (protocol))
+
+#define close(fd) \
+    posix_close((fd))
+#define creat(fname, pmode) \
+    posix_open((fname), _O_WRONLY | _O_CREAT |_O_TRUNC, (pmode))
+#define fstat(fd, buffer) \
+    posix_fstat((fd), (buffer))
+#define lseek(fd, offset, origin) \
+    posix_lseek((fd), (offset), (origin))
+#define open(fname, oflag, ...) \
+    posix_open((fname), (oflag), __VA_ARGS__)
+#define read   posix_read
+#define write(fd, buffer, count) \
+    posix_write((fd), (buffer), (count))
+#define fileno(stream) \
+    posix_fileno((stream))
+#define fsync(fd) \
+    posix_fsync((fd))
+
+#define O_NONBLOCK  1
+#define F_RDLCK            0
+#define F_WRLCK            1
+#define F_GETFL            1
+#define F_SETFL            2
+#define F_SETLK            3
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define ENOTSOCK    WSAENOTSOCK
+
+struct flock
+{
+    int l_type;
+    int l_whence;
+    int l_start;
+    int l_len;
+};
+
+extern int posix_fd2socket(int fd);
+
+extern int posix_accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
+extern int posix_bind(int fd, const struct sockaddr *name, int namelen);
+extern int posix_listen(int fd, int backlog);
+extern int posix_setsockopt(int fd, int level, int optname,
+                     const char *optval, int optlen);
+extern int posix_shutdown(int fd, int how);
+extern int posix_socket(int domain, int type, int protocol);
+
+extern int posix_close(int fd);
+extern int posix_fstat(int fd, struct stat *buffer);
+extern int posix_lseek(int fd, long offset, int origin);
+extern int posix_open(const char *fname, int oflag, ...);
+extern int posix_read(int fd, void *buffer, unsigned int count);
+extern int posix_write(int fd, const void *buffer, unsigned int count);
+
+extern int posix_fileno(FILE *stream);
+extern int posix_fsync(int fd);
+extern int fcntl(int fd, int cmd, ...);
 #endif /* UNISTD_H */