X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=gio%2Fgwin32inputstream.c;h=179e139919731b7fc793360a7cf54b9cfa869124;hb=2a53b4d0e2c98a14aedf31e38f0ad1fb2e8fe26f;hp=a545981b3883f3836309c47914e72444ee4f44ba;hpb=631d0c3534661e549f7df18fbb9832bdf19c5eaf;p=platform%2Fupstream%2Fglib.git
diff --git a/gio/gwin32inputstream.c b/gio/gwin32inputstream.c
index a545981..179e139 100644
--- a/gio/gwin32inputstream.c
+++ b/gio/gwin32inputstream.c
@@ -13,9 +13,7 @@
* 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.
+ * Public License along with this library; if not, see .
*
* Author: Alexander Larsson
* Author: Tor Lillqvist
@@ -31,6 +29,7 @@
#include "gioerror.h"
#include "gsimpleasyncresult.h"
#include "gwin32inputstream.h"
+#include "giowin32-priv.h"
#include "gcancellable.h"
#include "gasynchelper.h"
#include "glibintl.h"
@@ -45,9 +44,9 @@
* #GWin32InputStream implements #GInputStream for reading from a
* Windows file handle.
*
- * Note that <gio/gwin32inputstream.h> belongs
- * to the Windows-specific GIO interfaces, thus you have to use the
- * gio-windows-2.0.pc pkg-config file when using it.
+ * Note that `` belongs to the Windows-specific GIO
+ * interfaces, thus you have to use the `gio-windows-2.0.pc` pkg-config file
+ * when using it.
*/
enum {
@@ -56,13 +55,14 @@ enum {
PROP_CLOSE_HANDLE
};
-G_DEFINE_TYPE (GWin32InputStream, g_win32_input_stream, G_TYPE_INPUT_STREAM);
-
struct _GWin32InputStreamPrivate {
HANDLE handle;
gboolean close_handle;
+ gint fd;
};
+G_DEFINE_TYPE_WITH_PRIVATE (GWin32InputStream, g_win32_input_stream, G_TYPE_INPUT_STREAM)
+
static void g_win32_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -81,22 +81,13 @@ static gboolean g_win32_input_stream_close (GInputStream *stream,
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;
@@ -181,20 +172,18 @@ g_win32_input_stream_get_property (GObject *object,
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 = g_win32_input_stream_get_instance_private (win32_stream);
win32_stream->priv->handle = NULL;
win32_stream->priv->close_handle = TRUE;
+ win32_stream->priv->fd = -1;
}
/**
* g_win32_input_stream_new:
* @handle: a Win32 file handle
- * @close_fd: %TRUE to close the handle when done
+ * @close_handle: %TRUE to close the handle when done
*
- * Creates a new #GWin32InputStream for the given @fd.
+ * Creates a new #GWin32InputStream for the given @handle.
*
* If @close_handle is %TRUE, the handle will be closed
* when the stream is closed.
@@ -251,7 +240,7 @@ g_win32_input_stream_set_close_handle (GWin32InputStream *stream,
* Returns whether the handle of @stream will be
* closed when the stream is closed.
*
- * Return value: %TRUE if the handle is closed when done
+ * Returns: %TRUE if the handle is closed when done
*
* Since: 2.26
*/
@@ -269,7 +258,7 @@ g_win32_input_stream_get_close_handle (GWin32InputStream *stream)
*
* Return the Windows file handle that the stream reads from.
*
- * Return value: The file handle of @stream
+ * Returns: The file handle of @stream
*
* Since: 2.26
*/
@@ -291,6 +280,8 @@ g_win32_input_stream_read (GInputStream *stream,
GWin32InputStream *win32_stream;
BOOL res;
DWORD nbytes, nread;
+ OVERLAPPED overlap = { 0, };
+ gssize retval = -1;
win32_stream = G_WIN32_INPUT_STREAM (stream);
@@ -302,26 +293,63 @@ g_win32_input_stream_read (GInputStream *stream,
else
nbytes = count;
- res = ReadFile (win32_stream->priv->handle, buffer, nbytes, &nread, NULL);
- if (!res)
+ overlap.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+ g_return_val_if_fail (overlap.hEvent != NULL, -1);
+
+ res = ReadFile (win32_stream->priv->handle, buffer, nbytes, &nread, &overlap);
+ if (res)
+ retval = nread;
+ else
{
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;
+
+ if (errsv == ERROR_IO_PENDING &&
+ _g_win32_overlap_wait_result (win32_stream->priv->handle,
+ &overlap, &nread, cancellable))
+ {
+ retval = nread;
+ goto end;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ goto end;
+
+ errsv = GetLastError ();
+ if (errsv == ERROR_MORE_DATA)
+ {
+ /* If a named pipe is being read in message mode and the
+ * next message is longer than the nNumberOfBytesToRead
+ * parameter specifies, ReadFile returns FALSE and
+ * GetLastError returns ERROR_MORE_DATA */
+ retval = nread;
+ goto end;
+ }
+ else if (errsv == ERROR_HANDLE_EOF ||
+ errsv == ERROR_BROKEN_PIPE)
+ {
+ /* TODO: the other end of a pipe may call the WriteFile
+ * function with nNumberOfBytesToWrite set to zero. In this
+ * case, it's not possible for the caller to know if it's
+ * broken pipe or a read of 0. Perhaps we should add a
+ * is_broken flag for this win32 case.. */
+ retval = 0;
+ }
+ else
+ {
+ gchar *emsg;
+
+ 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 nread;
+end:
+ CloseHandle (overlap.hEvent);
+ return retval;
}
static gboolean
@@ -337,19 +365,44 @@ g_win32_input_stream_close (GInputStream *stream,
if (!win32_stream->priv->close_handle)
return TRUE;
- res = CloseHandle (win32_stream->priv->handle);
- if (!res)
+ if (win32_stream->priv->fd != -1)
{
- 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;
+ if (close (win32_stream->priv->fd) < 0)
+ {
+ g_set_error_literal (error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ g_strerror (errno));
+ return FALSE;
+ }
+ }
+ else
+ {
+ 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;
}
+
+GInputStream *
+g_win32_input_stream_new_from_fd (gint fd,
+ gboolean close_fd)
+{
+ GWin32InputStream *win32_stream;
+
+ win32_stream = G_WIN32_INPUT_STREAM (g_win32_input_stream_new ((HANDLE) _get_osfhandle (fd), close_fd));
+ win32_stream->priv->fd = fd;
+
+ return (GInputStream*)win32_stream;
+}