[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[platform/upstream/glib.git] / gio / gwin32outputstream.c
index 609e4f4..f69212b 100644 (file)
@@ -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 <http://www.gnu.org/licenses/>.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
  * Author: Tor Lillqvist <tml@iki.fi>
@@ -31,6 +29,7 @@
 #include <glib/gstdio.h>
 #include "gioerror.h"
 #include "gwin32outputstream.h"
+#include "giowin32-priv.h"
 #include "gcancellable.h"
 #include "gsimpleasyncresult.h"
 #include "gasynchelper.h"
@@ -46,9 +45,9 @@
  * #GWin32OutputStream implements #GOutputStream for writing to a
  * Windows file handle.
  *
- * Note that <filename>&lt;gio/gwin32outputstream.h&gt;</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.
+ * Note that `<gio/gwin32outputstream.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.
  */
 
 enum {
@@ -57,14 +56,14 @@ enum {
   PROP_CLOSE_HANDLE
 };
 
-G_DEFINE_TYPE (GWin32OutputStream, g_win32_output_stream, G_TYPE_OUTPUT_STREAM);
-
-
 struct _GWin32OutputStreamPrivate {
   HANDLE handle;
   gboolean close_handle;
+  gint fd;
 };
 
+G_DEFINE_TYPE_WITH_PRIVATE (GWin32OutputStream, g_win32_output_stream, G_TYPE_OUTPUT_STREAM)
+
 static void     g_win32_output_stream_set_property (GObject              *object,
                                                    guint                 prop_id,
                                                    const GValue         *value,
@@ -84,22 +83,13 @@ static gboolean g_win32_output_stream_close        (GOutputStream        *stream
 
 
 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;
@@ -184,12 +174,10 @@ g_win32_output_stream_get_property (GObject    *object,
 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 = g_win32_output_stream_get_instance_private (win32_stream);
   win32_stream->priv->handle = NULL;
   win32_stream->priv->close_handle = TRUE;
+  win32_stream->priv->fd = -1;
 }
 
 /**
@@ -253,7 +241,7 @@ g_win32_output_stream_set_close_handle (GWin32OutputStream *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
  */
@@ -271,7 +259,7 @@ g_win32_output_stream_get_close_handle (GWin32OutputStream *stream)
  *
  * Return the Windows handle that the stream writes to.
  *
- * Return value: The handle descriptor of @stream
+ * Returns: The handle descriptor of @stream
  *
  * Since: 2.26
  */
@@ -293,6 +281,8 @@ g_win32_output_stream_write (GOutputStream  *stream,
   GWin32OutputStream *win32_stream;
   BOOL res;
   DWORD nbytes, nwritten;
+  OVERLAPPED overlap = { 0, };
+  gssize retval = -1;
 
   win32_stream = G_WIN32_OUTPUT_STREAM (stream);
 
@@ -304,24 +294,49 @@ g_win32_output_stream_write (GOutputStream  *stream,
   else
     nbytes = count;
 
-  res = WriteFile (win32_stream->priv->handle, buffer, nbytes, &nwritten, NULL);
-  if (!res)
+  overlap.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+  g_return_val_if_fail (overlap.hEvent != NULL, -1);
+
+  res = WriteFile (win32_stream->priv->handle, buffer, nbytes, &nwritten, &overlap);
+  if (res)
+    retval = nwritten;
+  else
     {
       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;
+      if (errsv == ERROR_IO_PENDING &&
+          _g_win32_overlap_wait_result (win32_stream->priv->handle,
+                                        &overlap, &nwritten, cancellable))
+        {
+          retval = nwritten;
+          goto end;
+        }
+
+      if (g_cancellable_set_error_if_cancelled (cancellable, error))
+        goto end;
+
+      errsv = GetLastError ();
+      if (errsv == ERROR_HANDLE_EOF ||
+          errsv == ERROR_BROKEN_PIPE)
+        {
+          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 writing to handle: %s"),
+                       emsg);
+          g_free (emsg);
+        }
     }
 
-  return nwritten;
+end:
+  CloseHandle (overlap.hEvent);
+  return retval;
 }
 
 static gboolean
@@ -337,19 +352,44 @@ g_win32_output_stream_close (GOutputStream  *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;
 }
+
+GOutputStream *
+g_win32_output_stream_new_from_fd (gint      fd,
+                                 gboolean  close_fd)
+{
+  GWin32OutputStream *win32_stream;
+
+  win32_stream = G_WIN32_OUTPUT_STREAM (g_win32_output_stream_new ((HANDLE) _get_osfhandle (fd), close_fd));
+  win32_stream->priv->fd = fd;
+
+  return (GOutputStream*)win32_stream;
+}