aboutsummaryrefslogtreecommitdiff
path: root/libXfont/src/fc/fsio.c
diff options
context:
space:
mode:
Diffstat (limited to 'libXfont/src/fc/fsio.c')
-rw-r--r--libXfont/src/fc/fsio.c903
1 files changed, 452 insertions, 451 deletions
diff --git a/libXfont/src/fc/fsio.c b/libXfont/src/fc/fsio.c
index 63d3b4f3c..29c0d7d26 100644
--- a/libXfont/src/fc/fsio.c
+++ b/libXfont/src/fc/fsio.c
@@ -1,451 +1,452 @@
-/*
- * Copyright 1990 Network Computing Devices
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Network Computing Devices not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. Network Computing
- * Devices makes no representations about the suitability of this software
- * for any purpose. It is provided "as is" without express or implied
- * warranty.
- *
- * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
- * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
- * OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: Dave Lemke, Network Computing Devices, Inc
- */
-/*
- * font server i/o routines
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef WIN32
-#define _WILLWINSOCK_
-#include "X11/Xwindows.h"
-#endif
-
-#define FONT_t
-#define TRANS_CLIENT
-#include "X11/Xtrans/Xtrans.h"
-#include "X11/Xpoll.h"
-#include <X11/fonts/FS.h>
-#include <X11/fonts/FSproto.h>
-#include <X11/fonts/fontmisc.h>
-#include <X11/fonts/fontstruct.h>
-#include "fservestr.h"
-
-#include <stdio.h>
-#include <signal.h>
-#include <sys/types.h>
-#if !defined(WIN32)
-#ifndef Lynx
-#include <sys/socket.h>
-#else
-#include <socket.h>
-#endif
-#endif
-#include <errno.h>
-#ifdef WIN32
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#undef EINTR
-#define EINTR WSAEINTR
-#endif
-
-
-
-static int padlength[4] = {0, 3, 2, 1};
-fd_set _fs_fd_mask;
-
-static int
-_fs_resize (FSBufPtr buf, long size);
-
-static void
-_fs_downsize (FSBufPtr buf, long size);
-
-int
-_fs_poll_connect (XtransConnInfo trans_conn, int timeout)
-{
- fd_set w_mask;
- struct timeval tv;
- int fs_fd = _FontTransGetConnectionNumber (trans_conn);
- int ret;
-
- do
- {
- tv.tv_usec = 0;
- tv.tv_sec = timeout;
- FD_ZERO (&w_mask);
- FD_SET (fs_fd, &w_mask);
- ret = Select (fs_fd + 1, NULL, &w_mask, NULL, &tv);
- } while (ret < 0 && ECHECK(EINTR));
- if (ret == 0)
- return FSIO_BLOCK;
- if (ret < 0)
- return FSIO_ERROR;
- return FSIO_READY;
-}
-
-XtransConnInfo
-_fs_connect(char *servername, int *err)
-{
- XtransConnInfo trans_conn; /* transport connection object */
- int ret;
- int i = 0;
- int retries = 5;
-
- /*
- * Open the network connection.
- */
- if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL )
- {
- *err = FSIO_ERROR;
- return 0;
- }
-
- /*
- * Set the connection non-blocking since we use select() to block.
- */
-
- _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1);
-
- do {
- i = _FontTransConnect(trans_conn,servername);
- } while ((i == TRANS_TRY_CONNECT_AGAIN) && (retries-- > 0));
-
- if (i < 0)
- {
- if (i == TRANS_IN_PROGRESS)
- ret = FSIO_BLOCK;
- else
- ret = FSIO_ERROR;
- }
- else
- ret = FSIO_READY;
-
- if (ret == FSIO_ERROR)
- {
- _FontTransClose(trans_conn);
- trans_conn = 0;
- }
-
- *err = ret;
- return trans_conn;
-}
-
-static int
-_fs_fill (FSFpePtr conn)
-{
- long avail;
- long bytes_read;
- Bool waited = FALSE;
-
- if (_fs_flush (conn) < 0)
- return FSIO_ERROR;
- /*
- * Don't go overboard here; stop reading when we've
- * got enough to satisfy the pending request
- */
- while ((conn->inNeed - (conn->inBuf.insert - conn->inBuf.remove)) > 0)
- {
- avail = conn->inBuf.size - conn->inBuf.insert;
- /*
- * For SVR4 with a unix-domain connection, ETEST() after selecting
- * readable means the server has died. To do this here, we look for
- * two consecutive reads returning ETEST().
- */
- ESET (0);
- bytes_read =_FontTransRead(conn->trans_conn,
- conn->inBuf.buf + conn->inBuf.insert,
- avail);
- if (bytes_read > 0) {
- conn->inBuf.insert += bytes_read;
- waited = FALSE;
- }
- else
- {
- if (bytes_read == 0 || ETEST ())
- {
- if (!waited)
- {
- waited = TRUE;
- if (_fs_wait_for_readable (conn, 0) == FSIO_BLOCK)
- return FSIO_BLOCK;
- continue;
- }
- }
- _fs_connection_died (conn);
- return FSIO_ERROR;
- }
- }
- return FSIO_READY;
-}
-
-/*
- * Make space and return whether data have already arrived
- */
-
-int
-_fs_start_read (FSFpePtr conn, long size, char **buf)
-{
- int ret;
-
- conn->inNeed = size;
- if (fs_inqueued(conn) < size)
- {
- if (_fs_resize (&conn->inBuf, size) != FSIO_READY)
- {
- _fs_connection_died (conn);
- return FSIO_ERROR;
- }
- ret = _fs_fill (conn);
- if (ret == FSIO_ERROR)
- return ret;
- if (ret == FSIO_BLOCK || fs_inqueued(conn) < size)
- return FSIO_BLOCK;
- }
- if (buf)
- *buf = conn->inBuf.buf + conn->inBuf.remove;
- return FSIO_READY;
-}
-
-void
-_fs_done_read (FSFpePtr conn, long size)
-{
- if (conn->inBuf.insert - conn->inBuf.remove < size)
- {
-#ifdef DEBUG
- fprintf (stderr, "_fs_done_read skipping to many bytes\n");
-#endif
- return;
- }
- conn->inBuf.remove += size;
- conn->inNeed -= size;
- _fs_downsize (&conn->inBuf, FS_BUF_MAX);
-}
-
-long
-_fs_pad_length (long len)
-{
- return len + padlength[len&3];
-}
-
-int
-_fs_flush (FSFpePtr conn)
-{
- long bytes_written;
- long remain;
-
- /* XXX - hack. The right fix is to remember that the font server
- has gone away when we first discovered it. */
- if (conn->fs_fd < 0)
- return FSIO_ERROR;
-
- while ((remain = conn->outBuf.insert - conn->outBuf.remove) > 0)
- {
- bytes_written = _FontTransWrite(conn->trans_conn,
- conn->outBuf.buf + conn->outBuf.remove,
- (int) remain);
- if (bytes_written > 0)
- {
- conn->outBuf.remove += bytes_written;
- }
- else
- {
- if (bytes_written == 0 || ETEST ())
- {
- conn->brokenWriteTime = GetTimeInMillis () + FS_FLUSH_POLL;
- _fs_mark_block (conn, FS_BROKEN_WRITE);
- break;
- }
- if (!ECHECK (EINTR))
- {
- _fs_connection_died (conn);
- return FSIO_ERROR;
- }
- }
- }
- if (conn->outBuf.remove == conn->outBuf.insert)
- {
- _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE);
- if (conn->outBuf.size > FS_BUF_INC)
- conn->outBuf.buf = realloc (conn->outBuf.buf, FS_BUF_INC);
- conn->outBuf.remove = conn->outBuf.insert = 0;
- }
- return FSIO_READY;
-}
-
-static int
-_fs_resize (FSBufPtr buf, long size)
-{
- char *new;
- long new_size;
-
- if (buf->remove)
- {
- if (buf->remove != buf->insert)
- {
- memmove (buf->buf,
- buf->buf + buf->remove,
- buf->insert - buf->remove);
- }
- buf->insert -= buf->remove;
- buf->remove = 0;
- }
- if (buf->size - buf->remove < size)
- {
- new_size = ((buf->remove + size + FS_BUF_INC) / FS_BUF_INC) * FS_BUF_INC;
- new = realloc (buf->buf, new_size);
- if (!new)
- return FSIO_ERROR;
- buf->buf = new;
- buf->size = new_size;
- }
- return FSIO_READY;
-}
-
-static void
-_fs_downsize (FSBufPtr buf, long size)
-{
- if (buf->insert == buf->remove)
- {
- buf->insert = buf->remove = 0;
- if (buf->size > size)
- {
- buf->buf = realloc (buf->buf, size);
- buf->size = size;
- }
- }
-}
-
-void
-_fs_io_reinit (FSFpePtr conn)
-{
- conn->outBuf.insert = conn->outBuf.remove = 0;
- _fs_downsize (&conn->outBuf, FS_BUF_INC);
- conn->inBuf.insert = conn->inBuf.remove = 0;
- _fs_downsize (&conn->inBuf, FS_BUF_MAX);
-}
-
-Bool
-_fs_io_init (FSFpePtr conn)
-{
- conn->outBuf.insert = conn->outBuf.remove = 0;
- conn->outBuf.buf = malloc (FS_BUF_INC);
- if (!conn->outBuf.buf)
- return FALSE;
- conn->outBuf.size = FS_BUF_INC;
-
- conn->inBuf.insert = conn->inBuf.remove = 0;
- conn->inBuf.buf = malloc (FS_BUF_INC);
- if (!conn->inBuf.buf)
- {
- free (conn->outBuf.buf);
- conn->outBuf.buf = 0;
- return FALSE;
- }
- conn->inBuf.size = FS_BUF_INC;
-
- return TRUE;
-}
-
-void
-_fs_io_fini (FSFpePtr conn)
-{
- if (conn->outBuf.buf)
- free (conn->outBuf.buf);
- if (conn->inBuf.buf)
- free (conn->inBuf.buf);
-}
-
-static int
-_fs_do_write(FSFpePtr conn, char *data, long len, long size)
-{
- if (size == 0) {
-#ifdef DEBUG
- fprintf(stderr, "tried to write 0 bytes \n");
-#endif
- return FSIO_READY;
- }
-
- if (conn->fs_fd == -1)
- return FSIO_ERROR;
-
- while (conn->outBuf.insert + size > conn->outBuf.size)
- {
- if (_fs_flush (conn) < 0)
- return FSIO_ERROR;
- if (_fs_resize (&conn->outBuf, size) < 0)
- {
- _fs_connection_died (conn);
- return FSIO_ERROR;
- }
- }
- memcpy (conn->outBuf.buf + conn->outBuf.insert, data, len);
- /* Clear pad data */
- memset (conn->outBuf.buf + conn->outBuf.insert + len, 0, size - len);
- conn->outBuf.insert += size;
- _fs_mark_block (conn, FS_PENDING_WRITE);
- return FSIO_READY;
-}
-
-/*
- * Write the indicated bytes
- */
-int
-_fs_write (FSFpePtr conn, char *data, long len)
-{
- return _fs_do_write (conn, data, len, len);
-}
-
-/*
- * Write the indicated bytes adding any appropriate pad
- */
-int
-_fs_write_pad(FSFpePtr conn, char *data, long len)
-{
- return _fs_do_write (conn, data, len, len + padlength[len & 3]);
-}
-
-int
-_fs_wait_for_readable(FSFpePtr conn, int ms)
-{
- fd_set r_mask;
- fd_set e_mask;
- int result;
- struct timeval tv;
-
- for (;;) {
- if (conn->fs_fd < 0)
- return FSIO_ERROR;
- FD_ZERO(&r_mask);
- FD_ZERO(&e_mask);
- tv.tv_sec = ms / 1000;
- tv.tv_usec = (ms % 1000) * 1000;
- FD_SET(conn->fs_fd, &r_mask);
- FD_SET(conn->fs_fd, &e_mask);
- result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, &tv);
- if (result < 0)
- {
- if (ECHECK(EINTR) || ECHECK(EAGAIN))
- continue;
- else
- return FSIO_ERROR;
- }
- if (result == 0)
- return FSIO_BLOCK;
- if (FD_ISSET(conn->fs_fd, &r_mask))
- return FSIO_READY;
- return FSIO_ERROR;
- }
-}
+/*
+ * Copyright 1990 Network Computing Devices
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Network Computing Devices not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. Network Computing
+ * Devices makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ * OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ */
+/*
+ * font server i/o routines
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+#define _WILLWINSOCK_
+#include "X11/Xwinsock.h"
+#include "X11/Xwindows.h"
+#endif
+
+#define FONT_t
+#define TRANS_CLIENT
+#include "X11/Xtrans/Xtrans.h"
+#include "X11/Xpoll.h"
+#include <X11/fonts/FS.h>
+#include <X11/fonts/FSproto.h>
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+#include "fservestr.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#if !defined(WIN32)
+#ifndef Lynx
+#include <sys/socket.h>
+#else
+#include <socket.h>
+#endif
+#endif
+#include <errno.h>
+#ifdef WIN32
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#undef EINTR
+#define EINTR WSAEINTR
+#endif
+
+
+
+static int padlength[4] = {0, 3, 2, 1};
+fd_set _fs_fd_mask;
+
+static int
+_fs_resize (FSBufPtr buf, long size);
+
+static void
+_fs_downsize (FSBufPtr buf, long size);
+
+int
+_fs_poll_connect (XtransConnInfo trans_conn, int timeout)
+{
+ fd_set w_mask;
+ struct timeval tv;
+ int fs_fd = _FontTransGetConnectionNumber (trans_conn);
+ int ret;
+
+ do
+ {
+ tv.tv_usec = 0;
+ tv.tv_sec = timeout;
+ FD_ZERO (&w_mask);
+ FD_SET (fs_fd, &w_mask);
+ ret = Select (fs_fd + 1, NULL, &w_mask, NULL, &tv);
+ } while (ret < 0 && ECHECK(EINTR));
+ if (ret == 0)
+ return FSIO_BLOCK;
+ if (ret < 0)
+ return FSIO_ERROR;
+ return FSIO_READY;
+}
+
+XtransConnInfo
+_fs_connect(char *servername, int *err)
+{
+ XtransConnInfo trans_conn; /* transport connection object */
+ int ret;
+ int i = 0;
+ int retries = 5;
+
+ /*
+ * Open the network connection.
+ */
+ if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL )
+ {
+ *err = FSIO_ERROR;
+ return 0;
+ }
+
+ /*
+ * Set the connection non-blocking since we use select() to block.
+ */
+
+ _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1);
+
+ do {
+ i = _FontTransConnect(trans_conn,servername);
+ } while ((i == TRANS_TRY_CONNECT_AGAIN) && (retries-- > 0));
+
+ if (i < 0)
+ {
+ if (i == TRANS_IN_PROGRESS)
+ ret = FSIO_BLOCK;
+ else
+ ret = FSIO_ERROR;
+ }
+ else
+ ret = FSIO_READY;
+
+ if (ret == FSIO_ERROR)
+ {
+ _FontTransClose(trans_conn);
+ trans_conn = 0;
+ }
+
+ *err = ret;
+ return trans_conn;
+}
+
+static int
+_fs_fill (FSFpePtr conn)
+{
+ long avail;
+ long bytes_read;
+ Bool waited = FALSE;
+
+ if (_fs_flush (conn) < 0)
+ return FSIO_ERROR;
+ /*
+ * Don't go overboard here; stop reading when we've
+ * got enough to satisfy the pending request
+ */
+ while ((conn->inNeed - (conn->inBuf.insert - conn->inBuf.remove)) > 0)
+ {
+ avail = conn->inBuf.size - conn->inBuf.insert;
+ /*
+ * For SVR4 with a unix-domain connection, ETEST() after selecting
+ * readable means the server has died. To do this here, we look for
+ * two consecutive reads returning ETEST().
+ */
+ ESET (0);
+ bytes_read =_FontTransRead(conn->trans_conn,
+ conn->inBuf.buf + conn->inBuf.insert,
+ avail);
+ if (bytes_read > 0) {
+ conn->inBuf.insert += bytes_read;
+ waited = FALSE;
+ }
+ else
+ {
+ if (bytes_read == 0 || ETEST ())
+ {
+ if (!waited)
+ {
+ waited = TRUE;
+ if (_fs_wait_for_readable (conn, 0) == FSIO_BLOCK)
+ return FSIO_BLOCK;
+ continue;
+ }
+ }
+ _fs_connection_died (conn);
+ return FSIO_ERROR;
+ }
+ }
+ return FSIO_READY;
+}
+
+/*
+ * Make space and return whether data have already arrived
+ */
+
+int
+_fs_start_read (FSFpePtr conn, long size, char **buf)
+{
+ int ret;
+
+ conn->inNeed = size;
+ if (fs_inqueued(conn) < size)
+ {
+ if (_fs_resize (&conn->inBuf, size) != FSIO_READY)
+ {
+ _fs_connection_died (conn);
+ return FSIO_ERROR;
+ }
+ ret = _fs_fill (conn);
+ if (ret == FSIO_ERROR)
+ return ret;
+ if (ret == FSIO_BLOCK || fs_inqueued(conn) < size)
+ return FSIO_BLOCK;
+ }
+ if (buf)
+ *buf = conn->inBuf.buf + conn->inBuf.remove;
+ return FSIO_READY;
+}
+
+void
+_fs_done_read (FSFpePtr conn, long size)
+{
+ if (conn->inBuf.insert - conn->inBuf.remove < size)
+ {
+#ifdef DEBUG
+ fprintf (stderr, "_fs_done_read skipping to many bytes\n");
+#endif
+ return;
+ }
+ conn->inBuf.remove += size;
+ conn->inNeed -= size;
+ _fs_downsize (&conn->inBuf, FS_BUF_MAX);
+}
+
+long
+_fs_pad_length (long len)
+{
+ return len + padlength[len&3];
+}
+
+int
+_fs_flush (FSFpePtr conn)
+{
+ long bytes_written;
+ long remain;
+
+ /* XXX - hack. The right fix is to remember that the font server
+ has gone away when we first discovered it. */
+ if (conn->fs_fd < 0)
+ return FSIO_ERROR;
+
+ while ((remain = conn->outBuf.insert - conn->outBuf.remove) > 0)
+ {
+ bytes_written = _FontTransWrite(conn->trans_conn,
+ conn->outBuf.buf + conn->outBuf.remove,
+ (int) remain);
+ if (bytes_written > 0)
+ {
+ conn->outBuf.remove += bytes_written;
+ }
+ else
+ {
+ if (bytes_written == 0 || ETEST ())
+ {
+ conn->brokenWriteTime = GetTimeInMillis () + FS_FLUSH_POLL;
+ _fs_mark_block (conn, FS_BROKEN_WRITE);
+ break;
+ }
+ if (!ECHECK (EINTR))
+ {
+ _fs_connection_died (conn);
+ return FSIO_ERROR;
+ }
+ }
+ }
+ if (conn->outBuf.remove == conn->outBuf.insert)
+ {
+ _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE);
+ if (conn->outBuf.size > FS_BUF_INC)
+ conn->outBuf.buf = realloc (conn->outBuf.buf, FS_BUF_INC);
+ conn->outBuf.remove = conn->outBuf.insert = 0;
+ }
+ return FSIO_READY;
+}
+
+static int
+_fs_resize (FSBufPtr buf, long size)
+{
+ char *new;
+ long new_size;
+
+ if (buf->remove)
+ {
+ if (buf->remove != buf->insert)
+ {
+ memmove (buf->buf,
+ buf->buf + buf->remove,
+ buf->insert - buf->remove);
+ }
+ buf->insert -= buf->remove;
+ buf->remove = 0;
+ }
+ if (buf->size - buf->remove < size)
+ {
+ new_size = ((buf->remove + size + FS_BUF_INC) / FS_BUF_INC) * FS_BUF_INC;
+ new = realloc (buf->buf, new_size);
+ if (!new)
+ return FSIO_ERROR;
+ buf->buf = new;
+ buf->size = new_size;
+ }
+ return FSIO_READY;
+}
+
+static void
+_fs_downsize (FSBufPtr buf, long size)
+{
+ if (buf->insert == buf->remove)
+ {
+ buf->insert = buf->remove = 0;
+ if (buf->size > size)
+ {
+ buf->buf = realloc (buf->buf, size);
+ buf->size = size;
+ }
+ }
+}
+
+void
+_fs_io_reinit (FSFpePtr conn)
+{
+ conn->outBuf.insert = conn->outBuf.remove = 0;
+ _fs_downsize (&conn->outBuf, FS_BUF_INC);
+ conn->inBuf.insert = conn->inBuf.remove = 0;
+ _fs_downsize (&conn->inBuf, FS_BUF_MAX);
+}
+
+Bool
+_fs_io_init (FSFpePtr conn)
+{
+ conn->outBuf.insert = conn->outBuf.remove = 0;
+ conn->outBuf.buf = malloc (FS_BUF_INC);
+ if (!conn->outBuf.buf)
+ return FALSE;
+ conn->outBuf.size = FS_BUF_INC;
+
+ conn->inBuf.insert = conn->inBuf.remove = 0;
+ conn->inBuf.buf = malloc (FS_BUF_INC);
+ if (!conn->inBuf.buf)
+ {
+ free (conn->outBuf.buf);
+ conn->outBuf.buf = 0;
+ return FALSE;
+ }
+ conn->inBuf.size = FS_BUF_INC;
+
+ return TRUE;
+}
+
+void
+_fs_io_fini (FSFpePtr conn)
+{
+ if (conn->outBuf.buf)
+ free (conn->outBuf.buf);
+ if (conn->inBuf.buf)
+ free (conn->inBuf.buf);
+}
+
+static int
+_fs_do_write(FSFpePtr conn, char *data, long len, long size)
+{
+ if (size == 0) {
+#ifdef DEBUG
+ fprintf(stderr, "tried to write 0 bytes \n");
+#endif
+ return FSIO_READY;
+ }
+
+ if (conn->fs_fd == -1)
+ return FSIO_ERROR;
+
+ while (conn->outBuf.insert + size > conn->outBuf.size)
+ {
+ if (_fs_flush (conn) < 0)
+ return FSIO_ERROR;
+ if (_fs_resize (&conn->outBuf, size) < 0)
+ {
+ _fs_connection_died (conn);
+ return FSIO_ERROR;
+ }
+ }
+ memcpy (conn->outBuf.buf + conn->outBuf.insert, data, len);
+ /* Clear pad data */
+ memset (conn->outBuf.buf + conn->outBuf.insert + len, 0, size - len);
+ conn->outBuf.insert += size;
+ _fs_mark_block (conn, FS_PENDING_WRITE);
+ return FSIO_READY;
+}
+
+/*
+ * Write the indicated bytes
+ */
+int
+_fs_write (FSFpePtr conn, char *data, long len)
+{
+ return _fs_do_write (conn, data, len, len);
+}
+
+/*
+ * Write the indicated bytes adding any appropriate pad
+ */
+int
+_fs_write_pad(FSFpePtr conn, char *data, long len)
+{
+ return _fs_do_write (conn, data, len, len + padlength[len & 3]);
+}
+
+int
+_fs_wait_for_readable(FSFpePtr conn, int ms)
+{
+ fd_set r_mask;
+ fd_set e_mask;
+ int result;
+ struct timeval tv;
+
+ for (;;) {
+ if (conn->fs_fd < 0)
+ return FSIO_ERROR;
+ FD_ZERO(&r_mask);
+ FD_ZERO(&e_mask);
+ tv.tv_sec = ms / 1000;
+ tv.tv_usec = (ms % 1000) * 1000;
+ FD_SET(conn->fs_fd, &r_mask);
+ FD_SET(conn->fs_fd, &e_mask);
+ result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, &tv);
+ if (result < 0)
+ {
+ if (ECHECK(EINTR) || ECHECK(EAGAIN))
+ continue;
+ else
+ return FSIO_ERROR;
+ }
+ if (result == 0)
+ return FSIO_BLOCK;
+ if (FD_ISSET(conn->fs_fd, &r_mask))
+ return FSIO_READY;
+ return FSIO_ERROR;
+ }
+}