+2007-11-27 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile.am:
+ * gsocketinputstream.[ch]: Removed.
+ * gsocketoutputstream.[ch]: Removed.
+ * gunixinputstream.[ch]: Added.
+ * gunixoutputstream.[ch]: Added.
+ Renamed GSocket*Stream to GUnix*Stream and made
+ it unix-only, since its not really only for sockets
+ and it only works on unix (but is highly useful there).
+
2007-11-27 Andrew Walton <awalton@svn.gnome.org>
* gappinfo.c:
* gappinfo.h:
appinfo_sources += gdesktopappinfo.c gdesktopappinfo.h
platform_libadd += xdgmime/libxdgmime.la
unix_sources = \
- gunixdrive.c \
- gunixdrive.h \
- gunixmounts.c \
- gunixmounts.h \
- gunixvolume.c \
- gunixvolume.h \
- gunixvolumemonitor.c \
- gunixvolumemonitor.h \
+ gunixdrive.c \
+ gunixdrive.h \
+ gunixmounts.c \
+ gunixmounts.h \
+ gunixvolume.c \
+ gunixvolume.h \
+ gunixvolumemonitor.c \
+ gunixvolumemonitor.h \
+ gunixinputstream.c \
+ gunixoutputstream.c \
$(NULL)
giounixincludedir=$(includedir)/gio-unix-2.0/gio
giounixinclude_HEADERS = \
gunixmounts.h \
+ gunixinputstream.h \
+ gunixoutputstream.h \
$(NULL)
endif
gpollfilemonitor.h \
gseekable.c \
gsimpleasyncresult.c \
- gsocketinputstream.c \
- gsocketoutputstream.c \
gthemedicon.c \
gunionvolumemonitor.c \
gunionvolumemonitor.h \
goutputstream.h \
gseekable.h \
gsimpleasyncresult.h \
- gsocketinputstream.h \
- gsocketoutputstream.h \
gthemedicon.h \
gvfs.h \
gvolume.h \
+++ /dev/null
-/* GIO - GLib Input, Output and Streaming Library
- *
- * Copyright (C) 2006-2007 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Alexander Larsson <alexl@redhat.com>
- */
-
-#include <config.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <poll.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include "gioerror.h"
-#include "gsimpleasyncresult.h"
-#include "gsocketinputstream.h"
-#include "gcancellable.h"
-#include "gasynchelper.h"
-#include "glibintl.h"
-
-/**
- * SECTION:gsocketinputstream
- * @short_description: Socket Input Stream
- * @see_also: #GInputStream.
- *
- * #GSocketInputStream implements #GInputStream for reading from a socket,
- * including asynchronous operations.
- **/
-
-G_DEFINE_TYPE (GSocketInputStream, g_socket_input_stream, G_TYPE_INPUT_STREAM);
-
-struct _GSocketInputStreamPrivate {
- int fd;
- gboolean close_fd_at_close;
-};
-
-static gssize g_socket_input_stream_read (GInputStream *stream,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error);
-static gboolean g_socket_input_stream_close (GInputStream *stream,
- GCancellable *cancellable,
- GError **error);
-static void g_socket_input_stream_read_async (GInputStream *stream,
- void *buffer,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data);
-static gssize g_socket_input_stream_read_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error);
-static void g_socket_input_stream_skip_async (GInputStream *stream,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data);
-static gssize g_socket_input_stream_skip_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error);
-static void g_socket_input_stream_close_async (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data);
-static gboolean g_socket_input_stream_close_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error);
-
-static void
-g_socket_input_stream_finalize (GObject *object)
-{
- GSocketInputStream *stream;
-
- stream = G_SOCKET_INPUT_STREAM (object);
-
- if (G_OBJECT_CLASS (g_socket_input_stream_parent_class)->finalize)
- (*G_OBJECT_CLASS (g_socket_input_stream_parent_class)->finalize) (object);
-}
-
-static void
-g_socket_input_stream_class_init (GSocketInputStreamClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (GSocketInputStreamPrivate));
-
- gobject_class->finalize = g_socket_input_stream_finalize;
-
- stream_class->read = g_socket_input_stream_read;
- stream_class->close = g_socket_input_stream_close;
- stream_class->read_async = g_socket_input_stream_read_async;
- stream_class->read_finish = g_socket_input_stream_read_finish;
- if (0)
- {
- /* TODO: Implement instead of using fallbacks */
- stream_class->skip_async = g_socket_input_stream_skip_async;
- stream_class->skip_finish = g_socket_input_stream_skip_finish;
- }
- stream_class->close_async = g_socket_input_stream_close_async;
- stream_class->close_finish = g_socket_input_stream_close_finish;
-}
-
-static void
-g_socket_input_stream_init (GSocketInputStream *socket)
-{
- socket->priv = G_TYPE_INSTANCE_GET_PRIVATE (socket,
- G_TYPE_SOCKET_INPUT_STREAM,
- GSocketInputStreamPrivate);
-}
-
-/**
- * g_socket_input_stream_new:
- * @fd: socket file descriptor.
- * @close_fd_at_close: a #gboolean.
- *
- * Creates a new #GSocketInputStream for the given @fd. If @close_fd_at_close
- * is %TRUE, the socket will be closed when the stream is closed.
- *
- * Returns: a #GSocketInputStream.
- **/
-GInputStream *
-g_socket_input_stream_new (int fd,
- gboolean close_fd_at_close)
-{
- GSocketInputStream *stream;
-
- g_return_val_if_fail (fd != -1, NULL);
-
- stream = g_object_new (G_TYPE_SOCKET_INPUT_STREAM, NULL);
-
- stream->priv->fd = fd;
- stream->priv->close_fd_at_close = close_fd_at_close;
-
- return G_INPUT_STREAM (stream);
-}
-
-static gssize
-g_socket_input_stream_read (GInputStream *stream,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
-{
- GSocketInputStream *socket_stream;
- gssize res;
- struct pollfd poll_fds[2];
- int poll_ret;
- int cancel_fd;
-
- socket_stream = G_SOCKET_INPUT_STREAM (stream);
-
- cancel_fd = g_cancellable_get_fd (cancellable);
- if (cancel_fd != -1)
- {
- do
- {
- poll_fds[0].events = POLLIN;
- poll_fds[0].fd = socket_stream->priv->fd;
- poll_fds[1].events = POLLIN;
- poll_fds[1].fd = cancel_fd;
- poll_ret = poll (poll_fds, 2, -1);
- }
- while (poll_ret == -1 && errno == EINTR);
-
- if (poll_ret == -1)
- {
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error reading from socket: %s"),
- g_strerror (errno));
- return -1;
- }
- }
-
- while (1)
- {
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- break;
- res = read (socket_stream->priv->fd, buffer, count);
- if (res == -1)
- {
- if (errno == EINTR)
- continue;
-
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error reading from socket: %s"),
- g_strerror (errno));
- }
-
- break;
- }
-
- return res;
-}
-
-static gboolean
-g_socket_input_stream_close (GInputStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- GSocketInputStream *socket_stream;
- int res;
-
- socket_stream = G_SOCKET_INPUT_STREAM (stream);
-
- if (!socket_stream->priv->close_fd_at_close)
- return TRUE;
-
- while (1)
- {
- /* This might block during the close. Doesn't seem to be a way to avoid it though. */
- res = close (socket_stream->priv->fd);
- if (res == -1)
- {
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error closing socket: %s"),
- g_strerror (errno));
- }
- break;
- }
-
- return res != -1;
-}
-
-typedef struct {
- gsize count;
- void *buffer;
- GAsyncReadyCallback callback;
- gpointer user_data;
- GCancellable *cancellable;
- GSocketInputStream *stream;
-} ReadAsyncData;
-
-static gboolean
-read_async_cb (ReadAsyncData *data,
- GIOCondition condition,
- int fd)
-{
- GSimpleAsyncResult *simple;
- GError *error = NULL;
- gssize count_read;
-
- /* We know that we can read from fd once without blocking */
- while (1)
- {
- if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
- {
- count_read = -1;
- break;
- }
- count_read = read (data->stream->priv->fd, data->buffer, data->count);
- if (count_read == -1)
- {
- if (errno == EINTR)
- continue;
-
- g_set_error (&error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error reading from socket: %s"),
- g_strerror (errno));
- }
- break;
- }
-
- simple = g_simple_async_result_new (G_OBJECT (data->stream),
- data->callback,
- data->user_data,
- g_socket_input_stream_read_async);
-
- g_simple_async_result_set_op_res_gssize (simple, count_read);
-
- if (count_read == -1)
- {
- g_simple_async_result_set_from_error (simple, error);
- g_error_free (error);
- }
-
- /* Complete immediately, not in idle, since we're already in a mainloop callout */
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-
- return FALSE;
-}
-
-static void
-g_socket_input_stream_read_async (GInputStream *stream,
- void *buffer,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSource *source;
- GSocketInputStream *socket_stream;
- ReadAsyncData *data;
-
- socket_stream = G_SOCKET_INPUT_STREAM (stream);
-
- data = g_new0 (ReadAsyncData, 1);
- data->count = count;
- data->buffer = buffer;
- data->callback = callback;
- data->user_data = user_data;
- data->cancellable = cancellable;
- data->stream = socket_stream;
-
- source = _g_fd_source_new (socket_stream->priv->fd,
- POLLIN,
- cancellable);
-
- g_source_set_callback (source, (GSourceFunc)read_async_cb, data, g_free);
- g_source_attach (source, NULL);
-
- g_source_unref (source);
-}
-
-static gssize
-g_socket_input_stream_read_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
- gssize nread;
-
- simple = G_SIMPLE_ASYNC_RESULT (result);
- g_assert (g_simple_async_result_get_source_tag (simple) == g_socket_input_stream_read_async);
-
- nread = g_simple_async_result_get_op_res_gssize (simple);
- return nread;
-}
-
-static void
-g_socket_input_stream_skip_async (GInputStream *stream,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data)
-{
- g_assert_not_reached ();
- /* TODO: Not implemented */
-}
-
-static gssize
-g_socket_input_stream_skip_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- g_assert_not_reached ();
- /* TODO: Not implemented */
-}
-
-
-typedef struct {
- GInputStream *stream;
- GAsyncReadyCallback callback;
- gpointer user_data;
-} CloseAsyncData;
-
-static void
-close_async_data_free (gpointer _data)
-{
- CloseAsyncData *data = _data;
-
- g_free (data);
-}
-
-static gboolean
-close_async_cb (CloseAsyncData *data)
-{
- GSocketInputStream *socket_stream;
- GSimpleAsyncResult *simple;
- GError *error = NULL;
- gboolean result;
- int res;
-
- socket_stream = G_SOCKET_INPUT_STREAM (data->stream);
-
- if (!socket_stream->priv->close_fd_at_close)
- {
- result = TRUE;
- goto out;
- }
-
- while (1)
- {
- res = close (socket_stream->priv->fd);
- if (res == -1)
- {
- g_set_error (&error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error closing socket: %s"),
- g_strerror (errno));
- }
- break;
- }
-
- result = res != -1;
-
- out:
- simple = g_simple_async_result_new (G_OBJECT (data->stream),
- data->callback,
- data->user_data,
- g_socket_input_stream_close_async);
-
- if (!result)
- {
- g_simple_async_result_set_from_error (simple, error);
- g_error_free (error);
- }
-
- /* Complete immediately, not in idle, since we're already in a mainloop callout */
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-
- return FALSE;
-}
-
-static void
-g_socket_input_stream_close_async (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSource *idle;
- CloseAsyncData *data;
-
- data = g_new0 (CloseAsyncData, 1);
-
- data->stream = stream;
- data->callback = callback;
- data->user_data = user_data;
-
- idle = g_idle_source_new ();
- g_source_set_callback (idle, (GSourceFunc)close_async_cb, data, close_async_data_free);
- g_source_attach (idle, NULL);
- g_source_unref (idle);
-}
-
-static gboolean
-g_socket_input_stream_close_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- /* Failures handled in generic close_finish code */
- return TRUE;
-}
-
+++ /dev/null
-/* GIO - GLib Input, Output and Streaming Library
- *
- * Copyright (C) 2006-2007 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Alexander Larsson <alexl@redhat.com>
- */
-
-#ifndef __G_SOCKET_INPUT_STREAM_H__
-#define __G_SOCKET_INPUT_STREAM_H__
-
-#include <gio/ginputstream.h>
-
-G_BEGIN_DECLS
-
-#define G_TYPE_SOCKET_INPUT_STREAM (g_socket_input_stream_get_type ())
-#define G_SOCKET_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_SOCKET_INPUT_STREAM, GSocketInputStream))
-#define G_SOCKET_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_SOCKET_INPUT_STREAM, GSocketInputStreamClass))
-#define G_IS_SOCKET_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_SOCKET_INPUT_STREAM))
-#define G_IS_SOCKET_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_SOCKET_INPUT_STREAM))
-#define G_SOCKET_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_SOCKET_INPUT_STREAM, GSocketInputStreamClass))
-
-/**
- * GSocketInputStream:
- *
- * Implements #GInputStream for reading from sockets.
- **/
-typedef struct _GSocketInputStream GSocketInputStream;
-typedef struct _GSocketInputStreamClass GSocketInputStreamClass;
-typedef struct _GSocketInputStreamPrivate GSocketInputStreamPrivate;
-
-struct _GSocketInputStream
-{
- GInputStream parent;
-
- /*< private >*/
- GSocketInputStreamPrivate *priv;
-};
-
-struct _GSocketInputStreamClass
-{
- GInputStreamClass parent_class;
-
- /*< private >*/
- /* Padding for future expansion */
- void (*_g_reserved1) (void);
- void (*_g_reserved2) (void);
- void (*_g_reserved3) (void);
- void (*_g_reserved4) (void);
- void (*_g_reserved5) (void);
-};
-
-GType g_socket_input_stream_get_type (void) G_GNUC_CONST;
-
-GInputStream *g_socket_input_stream_new (int fd,
- gboolean close_fd_at_close);
-
-G_END_DECLS
-
-#endif /* __G_SOCKET_INPUT_STREAM_H__ */
+++ /dev/null
-/* GIO - GLib Input, Output and Streaming Library
- *
- * Copyright (C) 2006-2007 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Alexander Larsson <alexl@redhat.com>
- */
-
-#include <config.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <poll.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include "gioerror.h"
-#include "gsocketoutputstream.h"
-#include "gcancellable.h"
-#include "gsimpleasyncresult.h"
-#include "gasynchelper.h"
-#include "glibintl.h"
-
-/**
- * SECTION:gsocketoutputstream
- * @short_description: Socket Output Stream
- * @see_also: #GOutputStream.
- *
- * #GSocketOutputStream implements #GOutputStream for writing to a socket, including
- * asynchronous operations.
- **/
-
-G_DEFINE_TYPE (GSocketOutputStream, g_socket_output_stream, G_TYPE_OUTPUT_STREAM);
-
-
-struct _GSocketOutputStreamPrivate {
- int fd;
- gboolean close_fd_at_close;
-};
-
-static gssize g_socket_output_stream_write (GOutputStream *stream,
- const void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error);
-static gboolean g_socket_output_stream_close (GOutputStream *stream,
- GCancellable *cancellable,
- GError **error);
-static void g_socket_output_stream_write_async (GOutputStream *stream,
- const void *buffer,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data);
-static gssize g_socket_output_stream_write_finish (GOutputStream *stream,
- GAsyncResult *result,
- GError **error);
-static void g_socket_output_stream_close_async (GOutputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data);
-static gboolean g_socket_output_stream_close_finish (GOutputStream *stream,
- GAsyncResult *result,
- GError **error);
-
-
-static void
-g_socket_output_stream_finalize (GObject *object)
-{
- GSocketOutputStream *stream;
-
- stream = G_SOCKET_OUTPUT_STREAM (object);
-
- if (G_OBJECT_CLASS (g_socket_output_stream_parent_class)->finalize)
- (*G_OBJECT_CLASS (g_socket_output_stream_parent_class)->finalize) (object);
-}
-
-static void
-g_socket_output_stream_class_init (GSocketOutputStreamClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (GSocketOutputStreamPrivate));
-
- gobject_class->finalize = g_socket_output_stream_finalize;
-
- stream_class->write = g_socket_output_stream_write;
- stream_class->close = g_socket_output_stream_close;
- stream_class->write_async = g_socket_output_stream_write_async;
- stream_class->write_finish = g_socket_output_stream_write_finish;
- stream_class->close_async = g_socket_output_stream_close_async;
- stream_class->close_finish = g_socket_output_stream_close_finish;
-}
-
-static void
-g_socket_output_stream_init (GSocketOutputStream *socket)
-{
- socket->priv = G_TYPE_INSTANCE_GET_PRIVATE (socket,
- G_TYPE_SOCKET_OUTPUT_STREAM,
- GSocketOutputStreamPrivate);
-}
-
-
-/**
- * g_socket_output_stream_new:
- * @fd: socket's file descriptor.
- * @close_fd_at_close: a #gboolean.
- *
- * Creates a new socket output stream for @fd. If @close_fd_at_close
- * is %TRUE, the socket will be closed when the output stream is destroyed.
- *
- * Returns: #GOutputStream. If @close_fd_at_close is %TRUE, then
- * @fd will be closed when the #GOutputStream is closed.
- **/
-GOutputStream *
-g_socket_output_stream_new (int fd,
- gboolean close_fd_at_close)
-{
- GSocketOutputStream *stream;
-
- g_return_val_if_fail (fd != -1, NULL);
-
- stream = g_object_new (G_TYPE_SOCKET_OUTPUT_STREAM, NULL);
-
- stream->priv->fd = fd;
- stream->priv->close_fd_at_close = close_fd_at_close;
-
- return G_OUTPUT_STREAM (stream);
-}
-
-static gssize
-g_socket_output_stream_write (GOutputStream *stream,
- const void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
-{
- GSocketOutputStream *socket_stream;
- gssize res;
- struct pollfd poll_fds[2];
- int poll_ret;
- int cancel_fd;
-
- socket_stream = G_SOCKET_OUTPUT_STREAM (stream);
-
- cancel_fd = g_cancellable_get_fd (cancellable);
- if (cancel_fd != -1)
- {
- do
- {
- poll_fds[0].events = POLLOUT;
- poll_fds[0].fd = socket_stream->priv->fd;
- poll_fds[1].events = POLLIN;
- poll_fds[1].fd = cancel_fd;
- poll_ret = poll (poll_fds, 2, -1);
- }
- while (poll_ret == -1 && errno == EINTR);
-
- if (poll_ret == -1)
- {
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error writing to socket: %s"),
- g_strerror (errno));
- return -1;
- }
- }
-
- while (1)
- {
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return -1;
-
- res = write (socket_stream->priv->fd, buffer, count);
- if (res == -1)
- {
- if (errno == EINTR)
- continue;
-
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error writing to socket: %s"),
- g_strerror (errno));
- }
-
- break;
- }
-
- return res;
-}
-
-static gboolean
-g_socket_output_stream_close (GOutputStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- GSocketOutputStream *socket_stream;
- int res;
-
- socket_stream = G_SOCKET_OUTPUT_STREAM (stream);
-
- if (!socket_stream->priv->close_fd_at_close)
- return TRUE;
-
- while (1)
- {
- /* This might block during the close. Doesn't seem to be a way to avoid it though. */
- res = close (socket_stream->priv->fd);
- if (res == -1)
- {
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error closing socket: %s"),
- g_strerror (errno));
- }
- break;
- }
-
- return res != -1;
-}
-
-typedef struct {
- gsize count;
- const void *buffer;
- GAsyncReadyCallback callback;
- gpointer user_data;
- GCancellable *cancellable;
- GSocketOutputStream *stream;
-} WriteAsyncData;
-
-static gboolean
-write_async_cb (WriteAsyncData *data,
- GIOCondition condition,
- int fd)
-{
- GSimpleAsyncResult *simple;
- GError *error = NULL;
- gssize count_written;
-
- while (1)
- {
- if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
- {
- count_written = -1;
- break;
- }
-
- count_written = write (data->stream->priv->fd, data->buffer, data->count);
- if (count_written == -1)
- {
- if (errno == EINTR)
- continue;
-
- g_set_error (&error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error reading from socket: %s"),
- g_strerror (errno));
- }
- break;
- }
-
- simple = g_simple_async_result_new (G_OBJECT (data->stream),
- data->callback,
- data->user_data,
- g_socket_output_stream_write_async);
-
- g_simple_async_result_set_op_res_gssize (simple, count_written);
-
- if (count_written == -1)
- {
- g_simple_async_result_set_from_error (simple, error);
- g_error_free (error);
- }
-
- /* Complete immediately, not in idle, since we're already in a mainloop callout */
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-
- return FALSE;
-}
-
-static void
-g_socket_output_stream_write_async (GOutputStream *stream,
- const void *buffer,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSource *source;
- GSocketOutputStream *socket_stream;
- WriteAsyncData *data;
-
- socket_stream = G_SOCKET_OUTPUT_STREAM (stream);
-
- data = g_new0 (WriteAsyncData, 1);
- data->count = count;
- data->buffer = buffer;
- data->callback = callback;
- data->user_data = user_data;
- data->cancellable = cancellable;
- data->stream = socket_stream;
-
- source = _g_fd_source_new (socket_stream->priv->fd,
- POLLOUT,
- cancellable);
-
- g_source_set_callback (source, (GSourceFunc)write_async_cb, data, g_free);
- g_source_attach (source, NULL);
-
- g_source_unref (source);
-}
-
-static gssize
-g_socket_output_stream_write_finish (GOutputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
- gssize nwritten;
-
- simple = G_SIMPLE_ASYNC_RESULT (result);
- g_assert (g_simple_async_result_get_source_tag (simple) == g_socket_output_stream_write_async);
-
- nwritten = g_simple_async_result_get_op_res_gssize (simple);
- return nwritten;
-}
-
-typedef struct {
- GOutputStream *stream;
- GAsyncReadyCallback callback;
- gpointer user_data;
-} CloseAsyncData;
-
-static gboolean
-close_async_cb (CloseAsyncData *data)
-{
- GSocketOutputStream *socket_stream;
- GSimpleAsyncResult *simple;
- GError *error = NULL;
- gboolean result;
- int res;
-
- socket_stream = G_SOCKET_OUTPUT_STREAM (data->stream);
-
- if (!socket_stream->priv->close_fd_at_close)
- {
- result = TRUE;
- goto out;
- }
-
- while (1)
- {
- res = close (socket_stream->priv->fd);
- if (res == -1)
- {
- g_set_error (&error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- _("Error closing socket: %s"),
- g_strerror (errno));
- }
- break;
- }
-
- result = res != -1;
-
- out:
- simple = g_simple_async_result_new (G_OBJECT (data->stream),
- data->callback,
- data->user_data,
- g_socket_output_stream_close_async);
-
- if (!result)
- {
- g_simple_async_result_set_from_error (simple, error);
- g_error_free (error);
- }
-
- /* Complete immediately, not in idle, since we're already in a mainloop callout */
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-
- return FALSE;
-}
-
-static void
-g_socket_output_stream_close_async (GOutputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSource *idle;
- CloseAsyncData *data;
-
- data = g_new0 (CloseAsyncData, 1);
-
- data->stream = stream;
- data->callback = callback;
- data->user_data = user_data;
-
- idle = g_idle_source_new ();
- g_source_set_callback (idle, (GSourceFunc)close_async_cb, data, g_free);
- g_source_attach (idle, NULL);
- g_source_unref (idle);
-}
-
-static gboolean
-g_socket_output_stream_close_finish (GOutputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- /* Failures handled in generic close_finish code */
- return TRUE;
-}
+++ /dev/null
-/* GIO - GLib Input, Output and Streaming Library
- *
- * Copyright (C) 2006-2007 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Alexander Larsson <alexl@redhat.com>
- */
-
-#ifndef __G_SOCKET_OUTPUT_STREAM_H__
-#define __G_SOCKET_OUTPUT_STREAM_H__
-
-#include <gio/goutputstream.h>
-
-G_BEGIN_DECLS
-
-#define G_TYPE_SOCKET_OUTPUT_STREAM (g_socket_output_stream_get_type ())
-#define G_SOCKET_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_SOCKET_OUTPUT_STREAM, GSocketOutputStream))
-#define G_SOCKET_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_SOCKET_OUTPUT_STREAM, GSocketOutputStreamClass))
-#define G_IS_SOCKET_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_SOCKET_OUTPUT_STREAM))
-#define G_IS_SOCKET_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_SOCKET_OUTPUT_STREAM))
-#define G_SOCKET_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_SOCKET_OUTPUT_STREAM, GSocketOutputStreamClass))
-
-/**
- * GSocketOutputStream:
- *
- * Implements #GOutputStream for outputting to sockets.
- **/
-typedef struct _GSocketOutputStream GSocketOutputStream;
-typedef struct _GSocketOutputStreamClass GSocketOutputStreamClass;
-typedef struct _GSocketOutputStreamPrivate GSocketOutputStreamPrivate;
-
-struct _GSocketOutputStream
-{
- GOutputStream parent;
-
- /*< private >*/
- GSocketOutputStreamPrivate *priv;
-};
-
-struct _GSocketOutputStreamClass
-{
- GOutputStreamClass parent_class;
-
- /*< private >*/
- /* Padding for future expansion */
- void (*_g_reserved1) (void);
- void (*_g_reserved2) (void);
- void (*_g_reserved3) (void);
- void (*_g_reserved4) (void);
- void (*_g_reserved5) (void);
-};
-
-GType g_socket_output_stream_get_type (void) G_GNUC_CONST;
-
-GOutputStream *g_socket_output_stream_new (int fd,
- gboolean close_fd_at_close);
-
-G_END_DECLS
-
-#endif /* __G_SOCKET_OUTPUT_STREAM_H__ */
--- /dev/null
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <poll.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include "gioerror.h"
+#include "gsimpleasyncresult.h"
+#include "gunixinputstream.h"
+#include "gcancellable.h"
+#include "gasynchelper.h"
+#include "glibintl.h"
+
+/**
+ * SECTION:gunixinputstream
+ * @short_description: Unix Input Stream
+ * @see_also: #GInputStream.
+ *
+ * #GUnixInputStream implements #GInputStream for reading from a
+ * unix file descriptor, including asynchronous operations. The file
+ * descriptor much be selectable, so it doesn't work with opened files.
+ **/
+
+G_DEFINE_TYPE (GUnixInputStream, g_unix_input_stream, G_TYPE_INPUT_STREAM);
+
+struct _GUnixInputStreamPrivate {
+ int fd;
+ gboolean close_fd_at_close;
+};
+
+static gssize g_unix_input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean g_unix_input_stream_close (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static void g_unix_input_stream_read_async (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gssize g_unix_input_stream_read_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void g_unix_input_stream_skip_async (GInputStream *stream,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gssize g_unix_input_stream_skip_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void g_unix_input_stream_close_async (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gboolean g_unix_input_stream_close_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+
+
+static void
+g_unix_input_stream_finalize (GObject *object)
+{
+ GUnixInputStream *stream;
+
+ stream = G_UNIX_INPUT_STREAM (object);
+
+ if (G_OBJECT_CLASS (g_unix_input_stream_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_unix_input_stream_parent_class)->finalize) (object);
+}
+
+static void
+g_unix_input_stream_class_init (GUnixInputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GUnixInputStreamPrivate));
+
+ gobject_class->finalize = g_unix_input_stream_finalize;
+
+ stream_class->read = g_unix_input_stream_read;
+ stream_class->close = g_unix_input_stream_close;
+ stream_class->read_async = g_unix_input_stream_read_async;
+ stream_class->read_finish = g_unix_input_stream_read_finish;
+ if (0)
+ {
+ /* TODO: Implement instead of using fallbacks */
+ stream_class->skip_async = g_unix_input_stream_skip_async;
+ stream_class->skip_finish = g_unix_input_stream_skip_finish;
+ }
+ stream_class->close_async = g_unix_input_stream_close_async;
+ stream_class->close_finish = g_unix_input_stream_close_finish;
+}
+
+static void
+g_unix_input_stream_init (GUnixInputStream *unix_stream)
+{
+ unix_stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (unix_stream,
+ G_TYPE_UNIX_INPUT_STREAM,
+ GUnixInputStreamPrivate);
+}
+
+/**
+ * g_unix_input_stream_new:
+ * @fd: unix file descriptor.
+ * @close_fd_at_close: a #gboolean.
+ *
+ * Creates a new #GUnixInputStream for the given @fd. If @close_fd_at_close
+ * is %TRUE, the file descriptor will be closed when the stream is closed.
+ *
+ * Returns: a #GUnixInputStream.
+ **/
+GInputStream *
+g_unix_input_stream_new (int fd,
+ gboolean close_fd_at_close)
+{
+ GUnixInputStream *stream;
+
+ g_return_val_if_fail (fd != -1, NULL);
+
+ stream = g_object_new (G_TYPE_UNIX_INPUT_STREAM, NULL);
+
+ stream->priv->fd = fd;
+ stream->priv->close_fd_at_close = close_fd_at_close;
+
+ return G_INPUT_STREAM (stream);
+}
+
+static gssize
+g_unix_input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GUnixInputStream *unix_stream;
+ gssize res;
+ struct pollfd poll_fds[2];
+ int poll_ret;
+ int cancel_fd;
+
+ unix_stream = G_UNIX_INPUT_STREAM (stream);
+
+ cancel_fd = g_cancellable_get_fd (cancellable);
+ if (cancel_fd != -1)
+ {
+ do
+ {
+ poll_fds[0].events = POLLIN;
+ poll_fds[0].fd = unix_stream->priv->fd;
+ poll_fds[1].events = POLLIN;
+ poll_fds[1].fd = cancel_fd;
+ poll_ret = poll (poll_fds, 2, -1);
+ }
+ while (poll_ret == -1 && errno == EINTR);
+
+ if (poll_ret == -1)
+ {
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error reading from unix: %s"),
+ g_strerror (errno));
+ return -1;
+ }
+ }
+
+ while (1)
+ {
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ break;
+ res = read (unix_stream->priv->fd, buffer, count);
+ if (res == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error reading from unix: %s"),
+ g_strerror (errno));
+ }
+
+ break;
+ }
+
+ return res;
+}
+
+static gboolean
+g_unix_input_stream_close (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GUnixInputStream *unix_stream;
+ int res;
+
+ unix_stream = G_UNIX_INPUT_STREAM (stream);
+
+ if (!unix_stream->priv->close_fd_at_close)
+ return TRUE;
+
+ while (1)
+ {
+ /* This might block during the close. Doesn't seem to be a way to avoid it though. */
+ res = close (unix_stream->priv->fd);
+ if (res == -1)
+ {
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error closing unix: %s"),
+ g_strerror (errno));
+ }
+ break;
+ }
+
+ return res != -1;
+}
+
+typedef struct {
+ gsize count;
+ void *buffer;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+ GUnixInputStream *stream;
+} ReadAsyncData;
+
+static gboolean
+read_async_cb (ReadAsyncData *data,
+ GIOCondition condition,
+ int fd)
+{
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+ gssize count_read;
+
+ /* We know that we can read from fd once without blocking */
+ while (1)
+ {
+ if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
+ {
+ count_read = -1;
+ break;
+ }
+ count_read = read (data->stream->priv->fd, data->buffer, data->count);
+ if (count_read == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ g_set_error (&error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error reading from unix: %s"),
+ g_strerror (errno));
+ }
+ break;
+ }
+
+ simple = g_simple_async_result_new (G_OBJECT (data->stream),
+ data->callback,
+ data->user_data,
+ g_unix_input_stream_read_async);
+
+ g_simple_async_result_set_op_res_gssize (simple, count_read);
+
+ if (count_read == -1)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ return FALSE;
+}
+
+static void
+g_unix_input_stream_read_async (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSource *source;
+ GUnixInputStream *unix_stream;
+ ReadAsyncData *data;
+
+ unix_stream = G_UNIX_INPUT_STREAM (stream);
+
+ data = g_new0 (ReadAsyncData, 1);
+ data->count = count;
+ data->buffer = buffer;
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+ data->stream = unix_stream;
+
+ source = _g_fd_source_new (unix_stream->priv->fd,
+ POLLIN,
+ cancellable);
+
+ g_source_set_callback (source, (GSourceFunc)read_async_cb, data, g_free);
+ g_source_attach (source, NULL);
+
+ g_source_unref (source);
+}
+
+static gssize
+g_unix_input_stream_read_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ gssize nread;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_assert (g_simple_async_result_get_source_tag (simple) == g_unix_input_stream_read_async);
+
+ nread = g_simple_async_result_get_op_res_gssize (simple);
+ return nread;
+}
+
+static void
+g_unix_input_stream_skip_async (GInputStream *stream,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ g_assert_not_reached ();
+ /* TODO: Not implemented */
+}
+
+static gssize
+g_unix_input_stream_skip_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_assert_not_reached ();
+ /* TODO: Not implemented */
+}
+
+
+typedef struct {
+ GInputStream *stream;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} CloseAsyncData;
+
+static void
+close_async_data_free (gpointer _data)
+{
+ CloseAsyncData *data = _data;
+
+ g_free (data);
+}
+
+static gboolean
+close_async_cb (CloseAsyncData *data)
+{
+ GUnixInputStream *unix_stream;
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+ gboolean result;
+ int res;
+
+ unix_stream = G_UNIX_INPUT_STREAM (data->stream);
+
+ if (!unix_stream->priv->close_fd_at_close)
+ {
+ result = TRUE;
+ goto out;
+ }
+
+ while (1)
+ {
+ res = close (unix_stream->priv->fd);
+ if (res == -1)
+ {
+ g_set_error (&error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error closing unix: %s"),
+ g_strerror (errno));
+ }
+ break;
+ }
+
+ result = res != -1;
+
+ out:
+ simple = g_simple_async_result_new (G_OBJECT (data->stream),
+ data->callback,
+ data->user_data,
+ g_unix_input_stream_close_async);
+
+ if (!result)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ return FALSE;
+}
+
+static void
+g_unix_input_stream_close_async (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSource *idle;
+ CloseAsyncData *data;
+
+ data = g_new0 (CloseAsyncData, 1);
+
+ data->stream = stream;
+ data->callback = callback;
+ data->user_data = user_data;
+
+ idle = g_idle_source_new ();
+ g_source_set_callback (idle, (GSourceFunc)close_async_cb, data, close_async_data_free);
+ g_source_attach (idle, NULL);
+ g_source_unref (idle);
+}
+
+static gboolean
+g_unix_input_stream_close_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ /* Failures handled in generic close_finish code */
+ return TRUE;
+}
+
--- /dev/null
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_UNIX_INPUT_STREAM_H__
+#define __G_UNIX_INPUT_STREAM_H__
+
+#include <gio/ginputstream.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_UNIX_INPUT_STREAM (g_unix_input_stream_get_type ())
+#define G_UNIX_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_UNIX_INPUT_STREAM, GUnixInputStream))
+#define G_UNIX_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_UNIX_INPUT_STREAM, GUnixInputStreamClass))
+#define G_IS_UNIX_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_UNIX_INPUT_STREAM))
+#define G_IS_UNIX_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_UNIX_INPUT_STREAM))
+#define G_UNIX_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_UNIX_INPUT_STREAM, GUnixInputStreamClass))
+
+/**
+ * GUnixInputStream:
+ *
+ * Implements #GInputStream for reading from selectable unix file descriptors
+ **/
+typedef struct _GUnixInputStream GUnixInputStream;
+typedef struct _GUnixInputStreamClass GUnixInputStreamClass;
+typedef struct _GUnixInputStreamPrivate GUnixInputStreamPrivate;
+
+struct _GUnixInputStream
+{
+ GInputStream parent;
+
+ /*< private >*/
+ GUnixInputStreamPrivate *priv;
+};
+
+struct _GUnixInputStreamClass
+{
+ GInputStreamClass parent_class;
+
+ /*< private >*/
+ /* Padding for future expansion */
+ void (*_g_reserved1) (void);
+ void (*_g_reserved2) (void);
+ void (*_g_reserved3) (void);
+ void (*_g_reserved4) (void);
+ void (*_g_reserved5) (void);
+};
+
+GType g_unix_input_stream_get_type (void) G_GNUC_CONST;
+
+GInputStream *g_unix_input_stream_new (int fd,
+ gboolean close_fd_at_close);
+
+G_END_DECLS
+
+#endif /* __G_UNIX_INPUT_STREAM_H__ */
--- /dev/null
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <poll.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include "gioerror.h"
+#include "gunixoutputstream.h"
+#include "gcancellable.h"
+#include "gsimpleasyncresult.h"
+#include "gasynchelper.h"
+#include "glibintl.h"
+
+/**
+ * SECTION:gunixoutputstream
+ * @short_description: Unix Output Stream
+ * @see_also: #GOutputStream.
+ *
+ * #GUnixOutputStream implements #GOutputStream for writing to a a
+ * unix file descriptor, including asynchronous operations. The file
+ * descriptor much be selectable, so it doesn't work with opened files.
+ **/
+
+G_DEFINE_TYPE (GUnixOutputStream, g_unix_output_stream, G_TYPE_OUTPUT_STREAM);
+
+
+struct _GUnixOutputStreamPrivate {
+ int fd;
+ gboolean close_fd_at_close;
+};
+
+static gssize g_unix_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean g_unix_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static void g_unix_output_stream_write_async (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gssize g_unix_output_stream_write_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void g_unix_output_stream_close_async (GOutputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gboolean g_unix_output_stream_close_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+
+
+static void
+g_unix_output_stream_finalize (GObject *object)
+{
+ GUnixOutputStream *stream;
+
+ stream = G_UNIX_OUTPUT_STREAM (object);
+
+ if (G_OBJECT_CLASS (g_unix_output_stream_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_unix_output_stream_parent_class)->finalize) (object);
+}
+
+static void
+g_unix_output_stream_class_init (GUnixOutputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GUnixOutputStreamPrivate));
+
+ gobject_class->finalize = g_unix_output_stream_finalize;
+
+ stream_class->write = g_unix_output_stream_write;
+ stream_class->close = g_unix_output_stream_close;
+ stream_class->write_async = g_unix_output_stream_write_async;
+ stream_class->write_finish = g_unix_output_stream_write_finish;
+ stream_class->close_async = g_unix_output_stream_close_async;
+ stream_class->close_finish = g_unix_output_stream_close_finish;
+}
+
+static void
+g_unix_output_stream_init (GUnixOutputStream *unix_stream)
+{
+ unix_stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (unix_stream,
+ G_TYPE_UNIX_OUTPUT_STREAM,
+ GUnixOutputStreamPrivate);
+}
+
+
+/**
+ * g_unix_output_stream_new:
+ * @fd: unix's file descriptor.
+ * @close_fd_at_close: a #gboolean.
+ *
+ * Creates a new unix output stream for @fd. If @close_fd_at_close
+ * is %TRUE, the fd will be closed when the output stream is destroyed.
+ *
+ * Returns: #GOutputStream. If @close_fd_at_close is %TRUE, then
+ * @fd will be closed when the #GOutputStream is closed.
+ **/
+GOutputStream *
+g_unix_output_stream_new (int fd,
+ gboolean close_fd_at_close)
+{
+ GUnixOutputStream *stream;
+
+ g_return_val_if_fail (fd != -1, NULL);
+
+ stream = g_object_new (G_TYPE_UNIX_OUTPUT_STREAM, NULL);
+
+ stream->priv->fd = fd;
+ stream->priv->close_fd_at_close = close_fd_at_close;
+
+ return G_OUTPUT_STREAM (stream);
+}
+
+static gssize
+g_unix_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GUnixOutputStream *unix_stream;
+ gssize res;
+ struct pollfd poll_fds[2];
+ int poll_ret;
+ int cancel_fd;
+
+ unix_stream = G_UNIX_OUTPUT_STREAM (stream);
+
+ cancel_fd = g_cancellable_get_fd (cancellable);
+ if (cancel_fd != -1)
+ {
+ do
+ {
+ poll_fds[0].events = POLLOUT;
+ poll_fds[0].fd = unix_stream->priv->fd;
+ poll_fds[1].events = POLLIN;
+ poll_fds[1].fd = cancel_fd;
+ poll_ret = poll (poll_fds, 2, -1);
+ }
+ while (poll_ret == -1 && errno == EINTR);
+
+ if (poll_ret == -1)
+ {
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error writing to unix: %s"),
+ g_strerror (errno));
+ return -1;
+ }
+ }
+
+ while (1)
+ {
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return -1;
+
+ res = write (unix_stream->priv->fd, buffer, count);
+ if (res == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error writing to unix: %s"),
+ g_strerror (errno));
+ }
+
+ break;
+ }
+
+ return res;
+}
+
+static gboolean
+g_unix_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GUnixOutputStream *unix_stream;
+ int res;
+
+ unix_stream = G_UNIX_OUTPUT_STREAM (stream);
+
+ if (!unix_stream->priv->close_fd_at_close)
+ return TRUE;
+
+ while (1)
+ {
+ /* This might block during the close. Doesn't seem to be a way to avoid it though. */
+ res = close (unix_stream->priv->fd);
+ if (res == -1)
+ {
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error closing unix: %s"),
+ g_strerror (errno));
+ }
+ break;
+ }
+
+ return res != -1;
+}
+
+typedef struct {
+ gsize count;
+ const void *buffer;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+ GUnixOutputStream *stream;
+} WriteAsyncData;
+
+static gboolean
+write_async_cb (WriteAsyncData *data,
+ GIOCondition condition,
+ int fd)
+{
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+ gssize count_written;
+
+ while (1)
+ {
+ if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
+ {
+ count_written = -1;
+ break;
+ }
+
+ count_written = write (data->stream->priv->fd, data->buffer, data->count);
+ if (count_written == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ g_set_error (&error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error reading from unix: %s"),
+ g_strerror (errno));
+ }
+ break;
+ }
+
+ simple = g_simple_async_result_new (G_OBJECT (data->stream),
+ data->callback,
+ data->user_data,
+ g_unix_output_stream_write_async);
+
+ g_simple_async_result_set_op_res_gssize (simple, count_written);
+
+ if (count_written == -1)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ return FALSE;
+}
+
+static void
+g_unix_output_stream_write_async (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSource *source;
+ GUnixOutputStream *unix_stream;
+ WriteAsyncData *data;
+
+ unix_stream = G_UNIX_OUTPUT_STREAM (stream);
+
+ data = g_new0 (WriteAsyncData, 1);
+ data->count = count;
+ data->buffer = buffer;
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+ data->stream = unix_stream;
+
+ source = _g_fd_source_new (unix_stream->priv->fd,
+ POLLOUT,
+ cancellable);
+
+ g_source_set_callback (source, (GSourceFunc)write_async_cb, data, g_free);
+ g_source_attach (source, NULL);
+
+ g_source_unref (source);
+}
+
+static gssize
+g_unix_output_stream_write_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ gssize nwritten;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_assert (g_simple_async_result_get_source_tag (simple) == g_unix_output_stream_write_async);
+
+ nwritten = g_simple_async_result_get_op_res_gssize (simple);
+ return nwritten;
+}
+
+typedef struct {
+ GOutputStream *stream;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} CloseAsyncData;
+
+static gboolean
+close_async_cb (CloseAsyncData *data)
+{
+ GUnixOutputStream *unix_stream;
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+ gboolean result;
+ int res;
+
+ unix_stream = G_UNIX_OUTPUT_STREAM (data->stream);
+
+ if (!unix_stream->priv->close_fd_at_close)
+ {
+ result = TRUE;
+ goto out;
+ }
+
+ while (1)
+ {
+ res = close (unix_stream->priv->fd);
+ if (res == -1)
+ {
+ g_set_error (&error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Error closing unix: %s"),
+ g_strerror (errno));
+ }
+ break;
+ }
+
+ result = res != -1;
+
+ out:
+ simple = g_simple_async_result_new (G_OBJECT (data->stream),
+ data->callback,
+ data->user_data,
+ g_unix_output_stream_close_async);
+
+ if (!result)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ return FALSE;
+}
+
+static void
+g_unix_output_stream_close_async (GOutputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSource *idle;
+ CloseAsyncData *data;
+
+ data = g_new0 (CloseAsyncData, 1);
+
+ data->stream = stream;
+ data->callback = callback;
+ data->user_data = user_data;
+
+ idle = g_idle_source_new ();
+ g_source_set_callback (idle, (GSourceFunc)close_async_cb, data, g_free);
+ g_source_attach (idle, NULL);
+ g_source_unref (idle);
+}
+
+static gboolean
+g_unix_output_stream_close_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ /* Failures handled in generic close_finish code */
+ return TRUE;
+}
--- /dev/null
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_UNIX_OUTPUT_STREAM_H__
+#define __G_UNIX_OUTPUT_STREAM_H__
+
+#include <gio/goutputstream.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_UNIX_OUTPUT_STREAM (g_unix_output_stream_get_type ())
+#define G_UNIX_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_UNIX_OUTPUT_STREAM, GUnixOutputStream))
+#define G_UNIX_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_UNIX_OUTPUT_STREAM, GUnixOutputStreamClass))
+#define G_IS_UNIX_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_UNIX_OUTPUT_STREAM))
+#define G_IS_UNIX_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_UNIX_OUTPUT_STREAM))
+#define G_UNIX_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_UNIX_OUTPUT_STREAM, GUnixOutputStreamClass))
+
+/**
+ * GUnixOutputStream:
+ *
+ * Implements #GOutputStream for outputting to selectable unix file descriptors
+ **/
+typedef struct _GUnixOutputStream GUnixOutputStream;
+typedef struct _GUnixOutputStreamClass GUnixOutputStreamClass;
+typedef struct _GUnixOutputStreamPrivate GUnixOutputStreamPrivate;
+
+struct _GUnixOutputStream
+{
+ GOutputStream parent;
+
+ /*< private >*/
+ GUnixOutputStreamPrivate *priv;
+};
+
+struct _GUnixOutputStreamClass
+{
+ GOutputStreamClass parent_class;
+
+ /*< private >*/
+ /* Padding for future expansion */
+ void (*_g_reserved1) (void);
+ void (*_g_reserved2) (void);
+ void (*_g_reserved3) (void);
+ void (*_g_reserved4) (void);
+ void (*_g_reserved5) (void);
+};
+
+GType g_unix_output_stream_get_type (void) G_GNUC_CONST;
+
+GOutputStream *g_unix_output_stream_new (int fd,
+ gboolean close_fd_at_close);
+
+G_END_DECLS
+
+#endif /* __G_UNIX_OUTPUT_STREAM_H__ */