X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgwin32inputstream.c;h=179e139919731b7fc793360a7cf54b9cfa869124;hb=3389489f0f25a3a324ad62d9df5a6f1c038d5986;hp=a545981b3883f3836309c47914e72444ee4f44ba;hpb=73ca8b47540d005d5227c03aac143d6780da654c;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; +}