gthread-2.0.pc.in \
gio-2.0.pc.in \
gio-unix-2.0.pc.in \
+ gio-windows-2.0.pc.in \
glib-2.0-uninstalled.pc.in \
gobject-2.0-uninstalled.pc.in \
gmodule-2.0-uninstalled.pc.in \
pkgconfig_DATA += gio-unix-2.0.pc
endif
+if OS_WIN32
+pkgconfig_DATA += gio-windows-2.0.pc
+endif
+
$(pkgconfig_DATA): config.status
# install mkinstalldirs for glib-gettextize's benefit
copy ..\..\..\gio\gzlibcompressor.h $(OutDir)\include\glib-2.0\gio
\r
copy ..\..\..\gio\gzlibdecompressor.h $(OutDir)\include\glib-2.0\gio
\r
\r
+mkdir $(OutDir)\include\gio-win32-2.0\gio
\r
+copy ..\..\..\gio\gwin32inputstream.h $(OutDir)\include\gio-win32-2.0\gio
\r
+copy ..\..\..\gio\gwin32outputstream.h $(OutDir)\include\gio-win32-2.0\gio
\r
+\r
mkdir $(OutDir)\lib\glib-2.0\include
\r
copy ..\..\..\glibconfig.h $(OutDir)\lib\glib-2.0\include
\r
\r
gobject-2.0-uninstalled.pc
gio-2.0.pc
gio-unix-2.0.pc
+gio-windows-2.0.pc
gio-2.0-uninstalled.pc
gio-unix-2.0-uninstalled.pc
glib-zip
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: GIO Windows specific APIs
+Description: Windows specific headers for glib I/O library
+Version: @VERSION@
+Requires: gobject-2.0,gmodule-no-export-2.0,gio-2.0
+Libs: -L${libdir} -lgio-2.0
+Cflags: -I${includedir}/gio-win32-2.0/
gwin32resolver.h \
gwin32volumemonitor.c \
gwin32volumemonitor.h \
+ gwin32inputstream.c \
+ gwin32outputstream.c \
+ gwin32outputstream.h \
+ $(NULL)
+
+giowin32includedir=$(includedir)/gio-win32-2.0/gio
+giowin32include_HEADERS = \
+ gwin32inputstream.h \
+ gwin32outputstream.h \
$(NULL)
endif
cp $$d/$$f $(distdir) || exit 1; done
../build/win32/vs9/gio.vcproj: $(top_srcdir)/build/win32/vs9/gio.vcprojin
- for F in $(libgio_2_0_la_SOURCES); do \
+ for F in $(libgio_2_0_la_SOURCES) $(win32_sources); do \
case $$F in \
*.c) echo ' <File RelativePath="..\..\..\gio\'$$F'" />' \
;; \
#if IN_FILE(__G_IO_ERROR_C__)
g_io_error_quark
g_io_error_from_errno
+#ifdef G_OS_WIN32
+g_io_error_from_win32_error
+#endif
#endif
#endif
#endif
#endif
+#if IN_HEADER(__G_WIN32_INPUT_STREAM_H__)
+#if IN_FILE(__G_WIN32_INPUT_STREAM_C__)
+#ifdef G_OS_WIN32
+g_win32_input_stream_get_type G_GNUC_CONST
+g_win32_input_stream_new
+g_win32_input_stream_set_close_handle
+g_win32_input_stream_get_close_handle
+g_win32_input_stream_get_handle
+#endif /* G_OS_WIN32 */
+#endif
+#endif
+
+#if IN_HEADER(__G_WIN32_OUTPUT_STREAM_H__)
+#if IN_FILE(__G_WIN32_OUTPUT_STREAM_C__)
+#ifdef G_OS_WIN32
+g_win32_output_stream_get_type G_GNUC_CONST
+g_win32_output_stream_new
+g_win32_output_stream_set_close_handle
+g_win32_output_stream_get_close_handle
+g_win32_output_stream_get_handle
+#endif /* G_OS_WIN32 */
+#endif
+#endif
+
#if IN_HEADER(__G_MOUNT_H__)
#if IN_FILE(__G_MOUNT_C__)
g_mount_get_type G_GNUC_CONST
}
}
+#ifdef G_OS_WIN32
+
+/**
+ * g_io_error_from_win32_error:
+ * @error_code: Windows error number.
+ *
+ * Converts some common error codes into GIO error codes. The
+ * fallback value G_IO_ERROR_FAILED is returned for error codes not
+ * handled.
+ *
+ * Returns: #GIOErrorEnum value for the given error number.
+ *
+ * Since: 2.26
+ **/
+GIOErrorEnum
+g_io_error_from_win32_error (gint error_code)
+{
+ switch (error_code)
+ {
+ default:
+ return G_IO_ERROR_FAILED;
+ break;
+ }
+}
+
+#endif
+
#define __G_IO_ERROR_C__
#include "gioaliasdef.c"
GQuark g_io_error_quark (void);
GIOErrorEnum g_io_error_from_errno (gint err_no);
+#ifdef G_OS_WIN32
+GIOErrorEnum g_io_error_from_win32_error (gint error_code);
+#endif
+
G_END_DECLS
#endif /* __G_IO_ERROR_H__ */
--- /dev/null
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2010 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>
+ * Author: Tor Lillqvist <tml@iki.fi>
+ */
+
+#include "config.h"
+
+#include <windows.h>
+
+#include <io.h>
+
+#include <glib.h>
+#include "gioerror.h"
+#include "gsimpleasyncresult.h"
+#include "gwin32inputstream.h"
+#include "gcancellable.h"
+#include "gasynchelper.h"
+#include "glibintl.h"
+
+#include "gioalias.h"
+
+/**
+ * SECTION:gwin32inputstream
+ * @short_description: Streaming input operations for Windows file handles
+ * @include: gio/gwin32inputstream.h
+ * @see_also: #GInputStream
+ *
+ * #GWin32InputStream implements #GInputStream for reading from a
+ * Windows file handle.
+ *
+ * Note that <filename><gio/gwin32inputstream.h></filename> belongs
+ * to the Windows-specific GIO interfaces, thus you have to use the
+ * <filename>gio-windows-2.0.pc</filename> pkg-config file when using it.
+ */
+
+enum {
+ PROP_0,
+ PROP_HANDLE,
+ PROP_CLOSE_HANDLE
+};
+
+G_DEFINE_TYPE (GWin32InputStream, g_win32_input_stream, G_TYPE_INPUT_STREAM);
+
+struct _GWin32InputStreamPrivate {
+ HANDLE handle;
+ gboolean close_handle;
+};
+
+static void g_win32_input_stream_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void g_win32_input_stream_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static gssize g_win32_input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean g_win32_input_stream_close (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+
+static void
+g_win32_input_stream_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (g_win32_input_stream_parent_class)->finalize (object);
+}
+
+static void
+g_win32_input_stream_class_init (GWin32InputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GWin32InputStreamPrivate));
+
+ gobject_class->get_property = g_win32_input_stream_get_property;
+ gobject_class->set_property = g_win32_input_stream_set_property;
+ gobject_class->finalize = g_win32_input_stream_finalize;
+
+ stream_class->read_fn = g_win32_input_stream_read;
+ stream_class->close_fn = g_win32_input_stream_close;
+
+ /**
+ * GWin32InputStream:handle:
+ *
+ * The handle that the stream reads from.
+ *
+ * Since: 2.26
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_HANDLE,
+ g_param_spec_pointer ("handle",
+ P_("File handle"),
+ P_("The file handle to read from"),
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+ /**
+ * GWin32InputStream:close-handle:
+ *
+ * Whether to close the file handle when the stream is closed.
+ *
+ * Since: 2.26
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_CLOSE_HANDLE,
+ g_param_spec_boolean ("close-handle",
+ P_("Close file handle"),
+ P_("Whether to close the file handle when the stream is closed"),
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+}
+
+static void
+g_win32_input_stream_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GWin32InputStream *win32_stream;
+
+ win32_stream = G_WIN32_INPUT_STREAM (object);
+
+ switch (prop_id)
+ {
+ case PROP_HANDLE:
+ win32_stream->priv->handle = g_value_get_pointer (value);
+ break;
+ case PROP_CLOSE_HANDLE:
+ win32_stream->priv->close_handle = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_win32_input_stream_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GWin32InputStream *win32_stream;
+
+ win32_stream = G_WIN32_INPUT_STREAM (object);
+
+ switch (prop_id)
+ {
+ case PROP_HANDLE:
+ g_value_set_pointer (value, win32_stream->priv->handle);
+ break;
+ case PROP_CLOSE_HANDLE:
+ g_value_set_boolean (value, win32_stream->priv->close_handle);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_win32_input_stream_init (GWin32InputStream *win32_stream)
+{
+ win32_stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (win32_stream,
+ G_TYPE_WIN32_INPUT_STREAM,
+ GWin32InputStreamPrivate);
+
+ win32_stream->priv->handle = NULL;
+ win32_stream->priv->close_handle = TRUE;
+}
+
+/**
+ * g_win32_input_stream_new:
+ * @handle: a Win32 file handle
+ * @close_fd: %TRUE to close the handle when done
+ *
+ * Creates a new #GWin32InputStream for the given @fd.
+ *
+ * If @close_handle is %TRUE, the handle will be closed
+ * when the stream is closed.
+ *
+ * Note that "handle" here means a Win32 HANDLE, not a "file descriptor"
+ * as used in the Windows C libraries.
+ *
+ * Returns: a new #GWin32InputStream
+ **/
+GInputStream *
+g_win32_input_stream_new (void *handle,
+ gboolean close_handle)
+{
+ GWin32InputStream *stream;
+
+ g_return_val_if_fail (handle != NULL, NULL);
+
+ stream = g_object_new (G_TYPE_WIN32_INPUT_STREAM,
+ "handle", handle,
+ "close-handle", close_handle,
+ NULL);
+
+ return G_INPUT_STREAM (stream);
+}
+
+/**
+ * g_win32_input_stream_set_close_handle:
+ * @stream: a #GWin32InputStream
+ * @close_handle: %TRUE to close the handle when done
+ *
+ * Sets whether the handle of @stream shall be closed
+ * when the stream is closed.
+ *
+ * Since: 2.26
+ */
+void
+g_win32_input_stream_set_close_handle (GWin32InputStream *stream,
+ gboolean close_handle)
+{
+ g_return_if_fail (G_IS_WIN32_INPUT_STREAM (stream));
+
+ close_handle = close_handle != FALSE;
+ if (stream->priv->close_handle != close_handle)
+ {
+ stream->priv->close_handle = close_handle;
+ g_object_notify (G_OBJECT (stream), "close-handle");
+ }
+}
+
+/**
+ * g_win32_input_stream_get_close_handle:
+ * @stream: a #GWin32InputStream
+ *
+ * Returns whether the handle of @stream will be
+ * closed when the stream is closed.
+ *
+ * Return value: %TRUE if the handle is closed when done
+ *
+ * Since: 2.26
+ */
+gboolean
+g_win32_input_stream_get_close_handle (GWin32InputStream *stream)
+{
+ g_return_val_if_fail (G_IS_WIN32_INPUT_STREAM (stream), FALSE);
+
+ return stream->priv->close_handle;
+}
+
+/**
+ * g_win32_input_stream_get_handle:
+ * @stream: a #GWin32InputStream
+ *
+ * Return the Windows file handle that the stream reads from.
+ *
+ * Return value: The file handle of @stream
+ *
+ * Since: 2.26
+ */
+void *
+g_win32_input_stream_get_handle (GWin32InputStream *stream)
+{
+ g_return_val_if_fail (G_IS_WIN32_INPUT_STREAM (stream), NULL);
+
+ return stream->priv->handle;
+}
+
+static gssize
+g_win32_input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GWin32InputStream *win32_stream;
+ BOOL res;
+ DWORD nbytes, nread;
+
+ win32_stream = G_WIN32_INPUT_STREAM (stream);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return -1;
+
+ if (count > G_MAXINT)
+ nbytes = G_MAXINT;
+ else
+ nbytes = count;
+
+ res = ReadFile (win32_stream->priv->handle, buffer, nbytes, &nread, NULL);
+ if (!res)
+ {
+ int errsv = GetLastError ();
+ gchar *emsg;
+
+ if (errsv == ERROR_HANDLE_EOF ||
+ errsv == ERROR_BROKEN_PIPE)
+ return 0;
+
+ emsg = g_win32_error_message (errsv);
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ _("Error reading from handle: %s"),
+ emsg);
+ g_free (emsg);
+ return -1;
+ }
+
+ return nread;
+}
+
+static gboolean
+g_win32_input_stream_close (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GWin32InputStream *win32_stream;
+ BOOL res;
+
+ win32_stream = G_WIN32_INPUT_STREAM (stream);
+
+ if (!win32_stream->priv->close_handle)
+ return TRUE;
+
+ res = CloseHandle (win32_stream->priv->handle);
+ if (!res)
+ {
+ int errsv = GetLastError ();
+ gchar *emsg = g_win32_error_message (errsv);
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ _("Error closing handle: %s"),
+ emsg);
+ g_free (emsg);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#define __G_WIN32_INPUT_STREAM_C__
+#include "gioaliasdef.c"
--- /dev/null
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2010 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>
+ * Author: Tor Lillqvist <tml@iki.fi>
+ */
+
+#ifndef __G_WIN32_INPUT_STREAM_H__
+#define __G_WIN32_INPUT_STREAM_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_WIN32_INPUT_STREAM (g_win32_input_stream_get_type ())
+#define G_WIN32_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_WIN32_INPUT_STREAM, GWin32InputStream))
+#define G_WIN32_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_WIN32_INPUT_STREAM, GWin32InputStreamClass))
+#define G_IS_WIN32_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_WIN32_INPUT_STREAM))
+#define G_IS_WIN32_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_WIN32_INPUT_STREAM))
+#define G_WIN32_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_WIN32_INPUT_STREAM, GWin32InputStreamClass))
+
+/**
+ * GWin32InputStream:
+ *
+ * Implements #GInputStream for reading from selectable Windows file handles
+ **/
+typedef struct _GWin32InputStream GWin32InputStream;
+typedef struct _GWin32InputStreamClass GWin32InputStreamClass;
+typedef struct _GWin32InputStreamPrivate GWin32InputStreamPrivate;
+
+struct _GWin32InputStream
+{
+ GInputStream parent_instance;
+
+ /*< private >*/
+ GWin32InputStreamPrivate *priv;
+};
+
+struct _GWin32InputStreamClass
+{
+ 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_win32_input_stream_get_type (void) G_GNUC_CONST;
+
+GInputStream * g_win32_input_stream_new (void *handle,
+ gboolean close_handle);
+void g_win32_input_stream_set_close_handle (GWin32InputStream *stream,
+ gboolean close_handle);
+gboolean g_win32_input_stream_get_close_handle (GWin32InputStream *stream);
+void *g_win32_input_stream_get_handle (GWin32InputStream *stream);
+
+G_END_DECLS
+
+#endif /* __G_WIN32_INPUT_STREAM_H__ */
--- /dev/null
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2010 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>
+ * Author: Tor Lillqvist <tml@iki.fi>
+ */
+
+#include "config.h"
+
+#include <windows.h>
+
+#include <io.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include "gioerror.h"
+#include "gwin32outputstream.h"
+#include "gcancellable.h"
+#include "gsimpleasyncresult.h"
+#include "gasynchelper.h"
+#include "glibintl.h"
+
+#include "gioalias.h"
+
+/**
+ * SECTION:gwin32outputstream
+ * @short_description: Streaming output operations for Windows file handles
+ * @include: gio/gwin32outputstream.h
+ * @see_also: #GOutputStream
+ *
+ * #GWin32OutputStream implements #GOutputStream for writing to a
+ * Windows file handle.
+ *
+ * Note that <filename><gio/gwin32outputstream.h></filename> belongs
+ * to the Windows-specific GIO interfaces, thus you have to use the
+ * <filename>gio-windows-2.0.pc</filename> pkg-config file when using it.
+ */
+
+enum {
+ PROP_0,
+ PROP_HANDLE,
+ PROP_CLOSE_HANDLE
+};
+
+G_DEFINE_TYPE (GWin32OutputStream, g_win32_output_stream, G_TYPE_OUTPUT_STREAM);
+
+
+struct _GWin32OutputStreamPrivate {
+ HANDLE handle;
+ gboolean close_handle;
+};
+
+static void g_win32_output_stream_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void g_win32_output_stream_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static gssize g_win32_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean g_win32_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+
+
+static void
+g_win32_output_stream_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (g_win32_output_stream_parent_class)->finalize (object);
+}
+
+static void
+g_win32_output_stream_class_init (GWin32OutputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GWin32OutputStreamPrivate));
+
+ gobject_class->get_property = g_win32_output_stream_get_property;
+ gobject_class->set_property = g_win32_output_stream_set_property;
+ gobject_class->finalize = g_win32_output_stream_finalize;
+
+ stream_class->write_fn = g_win32_output_stream_write;
+ stream_class->close_fn = g_win32_output_stream_close;
+
+ /**
+ * GWin32OutputStream:handle:
+ *
+ * The file handle that the stream writes to.
+ *
+ * Since: 2.26
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_HANDLE,
+ g_param_spec_pointer ("handle",
+ P_("File handle"),
+ P_("The file handle to write to"),
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+ /**
+ * GWin32OutputStream:close-handle:
+ *
+ * Whether to close the file handle when the stream is closed.
+ *
+ * Since: 2.26
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_CLOSE_HANDLE,
+ g_param_spec_boolean ("close-handle",
+ P_("Close file handle"),
+ P_("Whether to close the file handle when the stream is closed"),
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+}
+
+static void
+g_win32_output_stream_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GWin32OutputStream *win32_stream;
+
+ win32_stream = G_WIN32_OUTPUT_STREAM (object);
+
+ switch (prop_id)
+ {
+ case PROP_HANDLE:
+ win32_stream->priv->handle = g_value_get_pointer (value);
+ break;
+ case PROP_CLOSE_HANDLE:
+ win32_stream->priv->close_handle = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_win32_output_stream_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GWin32OutputStream *win32_stream;
+
+ win32_stream = G_WIN32_OUTPUT_STREAM (object);
+
+ switch (prop_id)
+ {
+ case PROP_HANDLE:
+ g_value_set_pointer (value, win32_stream->priv->handle);
+ break;
+ case PROP_CLOSE_HANDLE:
+ g_value_set_boolean (value, win32_stream->priv->close_handle);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_win32_output_stream_init (GWin32OutputStream *win32_stream)
+{
+ win32_stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (win32_stream,
+ G_TYPE_WIN32_OUTPUT_STREAM,
+ GWin32OutputStreamPrivate);
+
+ win32_stream->priv->handle = NULL;
+ win32_stream->priv->close_handle = TRUE;
+}
+
+/**
+ * g_win32_output_stream_new:
+ * @handle: a Win32 file handle
+ * @close_handle: %TRUE to close the handle when done
+ *
+ * Creates a new #GWin32OutputStream for the given @handle.
+ *
+ * If @close_handle, is %TRUE, the handle will be closed when the
+ * output stream is destroyed.
+ *
+ * Returns: a new #GOutputStream
+ *
+ * Since: 2.26
+**/
+GOutputStream *
+g_win32_output_stream_new (void *handle,
+ gboolean close_handle)
+{
+ GWin32OutputStream *stream;
+
+ g_return_val_if_fail (handle != NULL, NULL);
+
+ stream = g_object_new (G_TYPE_WIN32_OUTPUT_STREAM,
+ "handle", handle,
+ "close-handle", close_handle,
+ NULL);
+
+ return G_OUTPUT_STREAM (stream);
+}
+
+/**
+ * g_win32_output_stream_set_close_handle:
+ * @stream: a #GWin32OutputStream
+ * @close_handle: %TRUE to close the handle when done
+ *
+ * Sets whether the handle of @stream shall be closed when the stream
+ * is closed.
+ *
+ * Since: 2.26
+ */
+void
+g_win32_output_stream_set_close_handle (GWin32OutputStream *stream,
+ gboolean close_handle)
+{
+ g_return_if_fail (G_IS_WIN32_OUTPUT_STREAM (stream));
+
+ close_handle = close_handle != FALSE;
+ if (stream->priv->close_handle != close_handle)
+ {
+ stream->priv->close_handle = close_handle;
+ g_object_notify (G_OBJECT (stream), "close-handle");
+ }
+}
+
+/**
+ * g_win32_output_stream_get_close_handle:
+ * @stream: a #GWin32OutputStream
+ *
+ * Returns whether the handle of @stream will be closed when the
+ * stream is closed.
+ *
+ * Return value: %TRUE if the handle is closed when done
+ *
+ * Since: 2.26
+ */
+gboolean
+g_win32_output_stream_get_close_handle (GWin32OutputStream *stream)
+{
+ g_return_val_if_fail (G_IS_WIN32_OUTPUT_STREAM (stream), FALSE);
+
+ return stream->priv->close_handle;
+}
+
+/**
+ * g_win32_output_stream_get_handle:
+ * @stream: a #GWin32OutputStream
+ *
+ * Return the Windows handle that the stream writes to.
+ *
+ * Return value: The handle descriptor of @stream
+ *
+ * Since: 2.26
+ */
+void *
+g_win32_output_stream_get_handle (GWin32OutputStream *stream)
+{
+ g_return_val_if_fail (G_IS_WIN32_OUTPUT_STREAM (stream), NULL);
+
+ return stream->priv->handle;
+}
+
+static gssize
+g_win32_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GWin32OutputStream *win32_stream;
+ BOOL res;
+ DWORD nbytes, nwritten;
+
+ win32_stream = G_WIN32_OUTPUT_STREAM (stream);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return -1;
+
+ if (count > G_MAXINT)
+ nbytes = G_MAXINT;
+ else
+ nbytes = count;
+
+ res = WriteFile (win32_stream->priv->handle, buffer, nbytes, &nwritten, NULL);
+ if (!res)
+ {
+ int errsv = GetLastError ();
+ gchar *emsg = g_win32_error_message (errsv);
+
+ if (errsv == ERROR_HANDLE_EOF)
+ return 0;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ _("Error writing to handle: %s"),
+ emsg);
+ g_free (emsg);
+ return -1;
+ }
+
+ return nwritten;
+}
+
+static gboolean
+g_win32_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GWin32OutputStream *win32_stream;
+ BOOL res;
+
+ win32_stream = G_WIN32_OUTPUT_STREAM (stream);
+
+ if (!win32_stream->priv->close_handle)
+ return TRUE;
+
+ res = CloseHandle (win32_stream->priv->handle);
+ if (!res)
+ {
+ int errsv = GetLastError ();
+ gchar *emsg = g_win32_error_message (errsv);
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ _("Error closing handle: %s"),
+ emsg);
+ g_free (emsg);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#define __G_WIN32_OUTPUT_STREAM_C__
+#include "gioaliasdef.c"
--- /dev/null
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2010 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>
+ * Author: Tor Lillqvist <tml@iki.fi>
+ */
+
+#ifndef __G_WIN32_OUTPUT_STREAM_H__
+#define __G_WIN32_OUTPUT_STREAM_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_WIN32_OUTPUT_STREAM (g_win32_output_stream_get_type ())
+#define G_WIN32_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_WIN32_OUTPUT_STREAM, GWin32OutputStream))
+#define G_WIN32_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_WIN32_OUTPUT_STREAM, GWin32OutputStreamClass))
+#define G_IS_WIN32_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_WIN32_OUTPUT_STREAM))
+#define G_IS_WIN32_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_WIN32_OUTPUT_STREAM))
+#define G_WIN32_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_WIN32_OUTPUT_STREAM, GWin32OutputStreamClass))
+
+/**
+ * GWin32OutputStream:
+ *
+ * Implements #GOutputStream for outputting to Windows file handles
+ **/
+typedef struct _GWin32OutputStream GWin32OutputStream;
+typedef struct _GWin32OutputStreamClass GWin32OutputStreamClass;
+typedef struct _GWin32OutputStreamPrivate GWin32OutputStreamPrivate;
+
+struct _GWin32OutputStream
+{
+ GOutputStream parent_instance;
+
+ /*< private >*/
+ GWin32OutputStreamPrivate *priv;
+};
+
+struct _GWin32OutputStreamClass
+{
+ 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_win32_output_stream_get_type (void) G_GNUC_CONST;
+
+GOutputStream * g_win32_output_stream_new (void *handle,
+ gboolean close_handle);
+void g_win32_output_stream_set_close_handle (GWin32OutputStream *stream,
+ gboolean close_handle);
+gboolean g_win32_output_stream_get_close_handle (GWin32OutputStream *stream);
+void *g_win32_output_stream_get_handle (GWin32OutputStream *stream);
+G_END_DECLS
+
+#endif /* __G_WIN32_OUTPUT_STREAM_H__ */
TEST_PROGS += live-g-file desktop-app-info unix-fd #unix-streams
endif
+if OS_WIN32
+TEST_PROGS += win32-streams
+endif
+
memory_input_stream_SOURCES = memory-input-stream.c
memory_input_stream_LDADD = $(progs_ldadd)
unix_streams_LDADD = $(progs_ldadd) \
$(top_builddir)/gthread/libgthread-2.0.la
+win32_streams_SOURCES = win32-streams.c
+win32_streams_LDADD = $(progs_ldadd) \
+ $(top_builddir)/gthread/libgthread-2.0.la
+
unix_fd_SOURCES = unix-fd.c
unix_fd_LDADD = $(progs_ldadd)
--- /dev/null
+/* GLib testing framework examples and tests
+ * Copyright (C) 2008 Red Hat, Inc
+ *
+ * This work is provided "as is"; redistribution and modification
+ * in whole or in part, in any medium, physical or electronic is
+ * permitted without restriction.
+ *
+ * This work 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.
+ *
+ * In no event shall the authors or contributors be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential
+ * damages (including, but not limited to, procurement of substitute
+ * goods or services; loss of use, data, or profits; or business
+ * interruption) however caused and on any theory of liability, whether
+ * in contract, strict liability, or tort (including negligence or
+ * otherwise) arising in any way out of the use of this software, even
+ * if advised of the possibility of such damage.
+ */
+
+#include <glib/glib.h>
+#include <gio/gio.h>
+#include <gio/gwin32inputstream.h>
+#include <gio/gwin32outputstream.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <io.h>
+
+#include <windows.h>
+
+#define DATA "abcdefghijklmnopqrstuvwxyz"
+
+int writer_pipe[2], reader_pipe[2];
+GCancellable *writer_cancel, *reader_cancel, *main_cancel;
+GMainLoop *loop;
+
+static gpointer
+writer_thread (gpointer user_data)
+{
+ GOutputStream *out;
+ gssize nwrote, offset;
+ GError *err = NULL;
+ HANDLE out_handle;
+
+ g_assert (DuplicateHandle (GetCurrentProcess (),
+ (HANDLE) (gintptr) _get_osfhandle (writer_pipe[1]),
+ GetCurrentProcess (),
+ &out_handle,
+ 0, FALSE,
+ DUPLICATE_SAME_ACCESS));
+ close (writer_pipe[1]);
+
+ out = g_win32_output_stream_new (out_handle, TRUE);
+ do
+ {
+ g_usleep (10);
+
+ offset = 0;
+ while (offset < (gssize) sizeof (DATA))
+ {
+ nwrote = g_output_stream_write (out, DATA + offset,
+ sizeof (DATA) - offset,
+ writer_cancel, &err);
+ if (nwrote <= 0 || err != NULL)
+ break;
+ offset += nwrote;
+ }
+
+ g_assert (nwrote > 0 || err != NULL);
+ }
+ while (err == NULL);
+
+ if (g_cancellable_is_cancelled (writer_cancel))
+ {
+ g_cancellable_cancel (main_cancel);
+ g_object_unref (out);
+ return NULL;
+ }
+
+ g_warning ("writer: %s", err->message);
+ g_assert_not_reached ();
+}
+
+static gpointer
+reader_thread (gpointer user_data)
+{
+ GInputStream *in;
+ gssize nread = 0, total;
+ GError *err = NULL;
+ char buf[sizeof (DATA)];
+ HANDLE in_handle;
+
+ g_assert (DuplicateHandle (GetCurrentProcess (),
+ (HANDLE) (gintptr) _get_osfhandle (reader_pipe[0]),
+ GetCurrentProcess (),
+ &in_handle,
+ 0, FALSE,
+ DUPLICATE_SAME_ACCESS));
+ close (reader_pipe[0]);
+
+ in = g_win32_input_stream_new (in_handle, TRUE);
+
+ do
+ {
+ total = 0;
+ while (total < (gssize) sizeof (DATA))
+ {
+ nread = g_input_stream_read (in, buf + total, sizeof (buf) - total,
+ reader_cancel, &err);
+ if (nread <= 0 || err != NULL)
+ break;
+ total += nread;
+ }
+
+ if (err)
+ break;
+
+ if (nread == 0)
+ {
+ g_assert (err == NULL);
+ /* pipe closed */
+ g_object_unref (in);
+ return NULL;
+ }
+
+ g_assert_cmpstr (buf, ==, DATA);
+ g_assert (!g_cancellable_is_cancelled (reader_cancel));
+ }
+ while (err == NULL);
+
+ g_warning ("reader: %s", err->message);
+ g_assert_not_reached ();
+}
+
+char main_buf[sizeof (DATA)];
+gssize main_len, main_offset;
+
+static void readable (GObject *source, GAsyncResult *res, gpointer user_data);
+static void writable (GObject *source, GAsyncResult *res, gpointer user_data);
+
+static void
+do_main_cancel (GOutputStream *out)
+{
+ g_output_stream_close (out, NULL, NULL);
+ g_main_loop_quit (loop);
+}
+
+static void
+readable (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ GInputStream *in = G_INPUT_STREAM (source);
+ GOutputStream *out = user_data;
+ GError *err = NULL;
+
+ main_len = g_input_stream_read_finish (in, res, &err);
+
+ if (g_cancellable_is_cancelled (main_cancel))
+ {
+ do_main_cancel (out);
+ return;
+ }
+
+ g_assert (err == NULL);
+
+ main_offset = 0;
+ g_output_stream_write_async (out, main_buf, main_len,
+ G_PRIORITY_DEFAULT, main_cancel,
+ writable, in);
+}
+
+static void
+writable (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ GOutputStream *out = G_OUTPUT_STREAM (source);
+ GInputStream *in = user_data;
+ GError *err = NULL;
+ gssize nwrote;
+
+ nwrote = g_output_stream_write_finish (out, res, &err);
+
+ if (g_cancellable_is_cancelled (main_cancel))
+ {
+ do_main_cancel (out);
+ return;
+ }
+
+ g_assert (err == NULL);
+ g_assert_cmpint (nwrote, <=, main_len - main_offset);
+
+ main_offset += nwrote;
+ if (main_offset == main_len)
+ {
+ g_input_stream_read_async (in, main_buf, sizeof (main_buf),
+ G_PRIORITY_DEFAULT, main_cancel,
+ readable, out);
+ }
+ else
+ {
+ g_output_stream_write_async (out, main_buf + main_offset,
+ main_len - main_offset,
+ G_PRIORITY_DEFAULT, main_cancel,
+ writable, in);
+ }
+}
+
+static gboolean
+timeout (gpointer cancellable)
+{
+ g_cancellable_cancel (cancellable);
+ return FALSE;
+}
+
+static void
+test_pipe_io (void)
+{
+ GThread *writer, *reader;
+ GInputStream *in;
+ GOutputStream *out;
+ HANDLE in_handle, out_handle;
+
+ /* Split off two (additional) threads, a reader and a writer. From
+ * the writer thread, write data synchronously in small chunks,
+ * which gets read asynchronously by the main thread and then
+ * written asynchronously to the reader thread, which reads it
+ * synchronously. Eventually a timeout in the main thread will cause
+ * it to cancel the writer thread, which will in turn cancel the
+ * read op in the main thread, which will then close the pipe to
+ * the reader thread, causing the read op to fail.
+ */
+
+ g_assert (_pipe (writer_pipe, 10, _O_BINARY) == 0 && _pipe (reader_pipe, 10, _O_BINARY) == 0);
+
+ writer_cancel = g_cancellable_new ();
+ reader_cancel = g_cancellable_new ();
+ main_cancel = g_cancellable_new ();
+
+ writer = g_thread_create (writer_thread, NULL, TRUE, NULL);
+ reader = g_thread_create (reader_thread, NULL, TRUE, NULL);
+
+ g_assert (DuplicateHandle (GetCurrentProcess (),
+ (HANDLE) (gintptr) _get_osfhandle (writer_pipe[0]),
+ GetCurrentProcess (),
+ &in_handle,
+ 0, FALSE,
+ DUPLICATE_SAME_ACCESS));
+ close (writer_pipe[0]);
+
+ g_assert (DuplicateHandle (GetCurrentProcess (),
+ (HANDLE) (gintptr) _get_osfhandle (reader_pipe[1]),
+ GetCurrentProcess (),
+ &out_handle,
+ 0, FALSE,
+ DUPLICATE_SAME_ACCESS));
+ close (reader_pipe[1]);
+
+ in = g_win32_input_stream_new (in_handle, TRUE);
+ out = g_win32_output_stream_new (out_handle, TRUE);
+
+ g_input_stream_read_async (in, main_buf, sizeof (main_buf),
+ G_PRIORITY_DEFAULT, main_cancel,
+ readable, out);
+
+ g_timeout_add (500, timeout, writer_cancel);
+
+ loop = g_main_loop_new (NULL, TRUE);
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ g_thread_join (reader);
+ g_thread_join (writer);
+
+ g_object_unref (main_cancel);
+ g_object_unref (reader_cancel);
+ g_object_unref (writer_cancel);
+ g_object_unref (in);
+ g_object_unref (out);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ g_thread_init (NULL);
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/win32-streams/pipe-io-test", test_pipe_io);
+
+ return g_test_run();
+}
lib/pkgconfig/gobject-2.0.pc
lib/pkgconfig/gthread-2.0.pc
lib/pkgconfig/gio-2.0.pc
+lib/pkgconfig/gio-windows-2.0.pc
share/aclocal/glib-2.0.m4
share/aclocal/glib-gettext.m4
share/glib-2.0