• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22 
23 #include "config.h"
24 #include "goutputstream.h"
25 #include "gcancellable.h"
26 #include "gasyncresult.h"
27 #include "gsimpleasyncresult.h"
28 #include "ginputstream.h"
29 #include "gioerror.h"
30 #include "glibintl.h"
31 
32 #include "gioalias.h"
33 
34 /**
35  * SECTION:goutputstream
36  * @short_description: Base class for implementing streaming output
37  * @include: gio/gio.h
38  *
39  * GOutputStream has functions to write to a stream (g_output_stream_write()),
40  * to close a stream (g_output_stream_close()) and to flush pending writes
41  * (g_output_stream_flush()).
42  *
43  * To copy the content of an input stream to an output stream without
44  * manually handling the reads and writes, use g_output_stream_splice().
45  *
46  * All of these functions have async variants too.
47  **/
48 
49 G_DEFINE_TYPE (GOutputStream, g_output_stream, G_TYPE_OBJECT);
50 
51 struct _GOutputStreamPrivate {
52   guint closed : 1;
53   guint pending : 1;
54   guint cancelled : 1;
55   GAsyncReadyCallback outstanding_callback;
56 };
57 
58 static gssize   g_output_stream_real_splice        (GOutputStream             *stream,
59 						    GInputStream              *source,
60 						    GOutputStreamSpliceFlags   flags,
61 						    GCancellable              *cancellable,
62 						    GError                   **error);
63 static void     g_output_stream_real_write_async   (GOutputStream             *stream,
64 						    const void                *buffer,
65 						    gsize                      count,
66 						    int                        io_priority,
67 						    GCancellable              *cancellable,
68 						    GAsyncReadyCallback        callback,
69 						    gpointer                   data);
70 static gssize   g_output_stream_real_write_finish  (GOutputStream             *stream,
71 						    GAsyncResult              *result,
72 						    GError                   **error);
73 static void     g_output_stream_real_splice_async  (GOutputStream             *stream,
74 						    GInputStream              *source,
75 						    GOutputStreamSpliceFlags   flags,
76 						    int                        io_priority,
77 						    GCancellable              *cancellable,
78 						    GAsyncReadyCallback        callback,
79 						    gpointer                   data);
80 static gssize   g_output_stream_real_splice_finish (GOutputStream             *stream,
81 						    GAsyncResult              *result,
82 						    GError                   **error);
83 static void     g_output_stream_real_flush_async   (GOutputStream             *stream,
84 						    int                        io_priority,
85 						    GCancellable              *cancellable,
86 						    GAsyncReadyCallback        callback,
87 						    gpointer                   data);
88 static gboolean g_output_stream_real_flush_finish  (GOutputStream             *stream,
89 						    GAsyncResult              *result,
90 						    GError                   **error);
91 static void     g_output_stream_real_close_async   (GOutputStream             *stream,
92 						    int                        io_priority,
93 						    GCancellable              *cancellable,
94 						    GAsyncReadyCallback        callback,
95 						    gpointer                   data);
96 static gboolean g_output_stream_real_close_finish  (GOutputStream             *stream,
97 						    GAsyncResult              *result,
98 						    GError                   **error);
99 
100 static void
g_output_stream_finalize(GObject * object)101 g_output_stream_finalize (GObject *object)
102 {
103   GOutputStream *stream;
104 
105   stream = G_OUTPUT_STREAM (object);
106 
107   G_OBJECT_CLASS (g_output_stream_parent_class)->finalize (object);
108 }
109 
110 static void
g_output_stream_dispose(GObject * object)111 g_output_stream_dispose (GObject *object)
112 {
113   GOutputStream *stream;
114 
115   stream = G_OUTPUT_STREAM (object);
116 
117   if (!stream->priv->closed)
118     g_output_stream_close (stream, NULL, NULL);
119 
120   G_OBJECT_CLASS (g_output_stream_parent_class)->dispose (object);
121 }
122 
123 static void
g_output_stream_class_init(GOutputStreamClass * klass)124 g_output_stream_class_init (GOutputStreamClass *klass)
125 {
126   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
127 
128   g_type_class_add_private (klass, sizeof (GOutputStreamPrivate));
129 
130   gobject_class->finalize = g_output_stream_finalize;
131   gobject_class->dispose = g_output_stream_dispose;
132 
133   klass->splice = g_output_stream_real_splice;
134 
135   klass->write_async = g_output_stream_real_write_async;
136   klass->write_finish = g_output_stream_real_write_finish;
137   klass->splice_async = g_output_stream_real_splice_async;
138   klass->splice_finish = g_output_stream_real_splice_finish;
139   klass->flush_async = g_output_stream_real_flush_async;
140   klass->flush_finish = g_output_stream_real_flush_finish;
141   klass->close_async = g_output_stream_real_close_async;
142   klass->close_finish = g_output_stream_real_close_finish;
143 }
144 
145 static void
g_output_stream_init(GOutputStream * stream)146 g_output_stream_init (GOutputStream *stream)
147 {
148   stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
149 					      G_TYPE_OUTPUT_STREAM,
150 					      GOutputStreamPrivate);
151 }
152 
153 /**
154  * g_output_stream_write:
155  * @stream: a #GOutputStream.
156  * @buffer: the buffer containing the data to write.
157  * @count: the number of bytes to write
158  * @cancellable: optional cancellable object
159  * @error: location to store the error occuring, or %NULL to ignore
160  *
161  * Tries to write @count bytes from @buffer into the stream. Will block
162  * during the operation.
163  *
164  * If count is zero returns zero and does nothing. A value of @count
165  * larger than %G_MAXSSIZE will cause a %G_IO_ERROR_INVALID_ARGUMENT error.
166  *
167  * On success, the number of bytes written to the stream is returned.
168  * It is not an error if this is not the same as the requested size, as it
169  * can happen e.g. on a partial i/o error, or if there is not enough
170  * storage in the stream. All writes either block until at least one byte
171  * is written, so zero is never returned (unless @count is zero).
172  *
173  * If @cancellable is not NULL, then the operation can be cancelled by
174  * triggering the cancellable object from another thread. If the operation
175  * was cancelled, the error G_IO_ERROR_CANCELLED will be returned. If an
176  * operation was partially finished when the operation was cancelled the
177  * partial result will be returned, without an error.
178  *
179  * On error -1 is returned and @error is set accordingly.
180  *
181  * Return value: Number of bytes written, or -1 on error
182  **/
183 gssize
g_output_stream_write(GOutputStream * stream,const void * buffer,gsize count,GCancellable * cancellable,GError ** error)184 g_output_stream_write (GOutputStream  *stream,
185 		       const void     *buffer,
186 		       gsize           count,
187 		       GCancellable   *cancellable,
188 		       GError        **error)
189 {
190   GOutputStreamClass *class;
191   gssize res;
192 
193   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
194   g_return_val_if_fail (buffer != NULL, 0);
195 
196   if (count == 0)
197     return 0;
198 
199   if (((gssize) count) < 0)
200     {
201       g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
202 		   _("Too large count value passed to %s"), G_STRFUNC);
203       return -1;
204     }
205 
206   class = G_OUTPUT_STREAM_GET_CLASS (stream);
207 
208   if (class->write_fn == NULL)
209     {
210       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
211                            _("Output stream doesn't implement write"));
212       return -1;
213     }
214 
215   if (!g_output_stream_set_pending (stream, error))
216     return -1;
217 
218   if (cancellable)
219     g_cancellable_push_current (cancellable);
220 
221   res = class->write_fn (stream, buffer, count, cancellable, error);
222 
223   if (cancellable)
224     g_cancellable_pop_current (cancellable);
225 
226   g_output_stream_clear_pending (stream);
227 
228   return res;
229 }
230 
231 /**
232  * g_output_stream_write_all:
233  * @stream: a #GOutputStream.
234  * @buffer: the buffer containing the data to write.
235  * @count: the number of bytes to write
236  * @bytes_written: location to store the number of bytes that was
237  *     written to the stream
238  * @cancellable: optional #GCancellable object, %NULL to ignore.
239  * @error: location to store the error occuring, or %NULL to ignore
240  *
241  * Tries to write @count bytes from @buffer into the stream. Will block
242  * during the operation.
243  *
244  * This function is similar to g_output_stream_write(), except it tries to
245  * write as many bytes as requested, only stopping on an error.
246  *
247  * On a successful write of @count bytes, %TRUE is returned, and @bytes_written
248  * is set to @count.
249  *
250  * If there is an error during the operation FALSE is returned and @error
251  * is set to indicate the error status, @bytes_written is updated to contain
252  * the number of bytes written into the stream before the error occurred.
253  *
254  * Return value: %TRUE on success, %FALSE if there was an error
255  **/
256 gboolean
g_output_stream_write_all(GOutputStream * stream,const void * buffer,gsize count,gsize * bytes_written,GCancellable * cancellable,GError ** error)257 g_output_stream_write_all (GOutputStream  *stream,
258 			   const void     *buffer,
259 			   gsize           count,
260 			   gsize          *bytes_written,
261 			   GCancellable   *cancellable,
262 			   GError        **error)
263 {
264   gsize _bytes_written;
265   gssize res;
266 
267   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
268   g_return_val_if_fail (buffer != NULL, FALSE);
269 
270   _bytes_written = 0;
271   while (_bytes_written < count)
272     {
273       res = g_output_stream_write (stream, (char *)buffer + _bytes_written, count - _bytes_written,
274 				   cancellable, error);
275       if (res == -1)
276 	{
277 	  if (bytes_written)
278 	    *bytes_written = _bytes_written;
279 	  return FALSE;
280 	}
281 
282       if (res == 0)
283 	g_warning ("Write returned zero without error");
284 
285       _bytes_written += res;
286     }
287 
288   if (bytes_written)
289     *bytes_written = _bytes_written;
290 
291   return TRUE;
292 }
293 
294 /**
295  * g_output_stream_flush:
296  * @stream: a #GOutputStream.
297  * @cancellable: optional cancellable object
298  * @error: location to store the error occuring, or %NULL to ignore
299  *
300  * Flushed any outstanding buffers in the stream. Will block during
301  * the operation. Closing the stream will implicitly cause a flush.
302  *
303  * This function is optional for inherited classes.
304  *
305  * If @cancellable is not %NULL, then the operation can be cancelled by
306  * triggering the cancellable object from another thread. If the operation
307  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
308  *
309  * Return value: %TRUE on success, %FALSE on error
310  **/
311 gboolean
g_output_stream_flush(GOutputStream * stream,GCancellable * cancellable,GError ** error)312 g_output_stream_flush (GOutputStream  *stream,
313                        GCancellable   *cancellable,
314                        GError        **error)
315 {
316   GOutputStreamClass *class;
317   gboolean res;
318 
319   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
320 
321   if (!g_output_stream_set_pending (stream, error))
322     return FALSE;
323 
324   class = G_OUTPUT_STREAM_GET_CLASS (stream);
325 
326   res = TRUE;
327   if (class->flush)
328     {
329       if (cancellable)
330 	g_cancellable_push_current (cancellable);
331 
332       res = class->flush (stream, cancellable, error);
333 
334       if (cancellable)
335 	g_cancellable_pop_current (cancellable);
336     }
337 
338   g_output_stream_clear_pending (stream);
339 
340   return res;
341 }
342 
343 /**
344  * g_output_stream_splice:
345  * @stream: a #GOutputStream.
346  * @source: a #GInputStream.
347  * @flags: a set of #GOutputStreamSpliceFlags.
348  * @cancellable: optional #GCancellable object, %NULL to ignore.
349  * @error: a #GError location to store the error occuring, or %NULL to
350  * ignore.
351  *
352  * Splices an input stream into an output stream.
353  *
354  * Returns: a #gssize containing the size of the data spliced.
355  **/
356 gssize
g_output_stream_splice(GOutputStream * stream,GInputStream * source,GOutputStreamSpliceFlags flags,GCancellable * cancellable,GError ** error)357 g_output_stream_splice (GOutputStream             *stream,
358 			GInputStream              *source,
359 			GOutputStreamSpliceFlags   flags,
360 			GCancellable              *cancellable,
361 			GError                   **error)
362 {
363   GOutputStreamClass *class;
364   gboolean res;
365 
366   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
367   g_return_val_if_fail (G_IS_INPUT_STREAM (source), -1);
368 
369   if (g_input_stream_is_closed (source))
370     {
371       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
372                            _("Source stream is already closed"));
373       return -1;
374     }
375 
376   if (!g_output_stream_set_pending (stream, error))
377     return -1;
378 
379   class = G_OUTPUT_STREAM_GET_CLASS (stream);
380 
381   res = TRUE;
382   if (cancellable)
383     g_cancellable_push_current (cancellable);
384 
385   res = class->splice (stream, source, flags, cancellable, error);
386 
387   if (cancellable)
388     g_cancellable_pop_current (cancellable);
389 
390   g_output_stream_clear_pending (stream);
391 
392   return res;
393 }
394 
395 static gssize
g_output_stream_real_splice(GOutputStream * stream,GInputStream * source,GOutputStreamSpliceFlags flags,GCancellable * cancellable,GError ** error)396 g_output_stream_real_splice (GOutputStream             *stream,
397                              GInputStream              *source,
398                              GOutputStreamSpliceFlags   flags,
399                              GCancellable              *cancellable,
400                              GError                   **error)
401 {
402   GOutputStreamClass *class = G_OUTPUT_STREAM_GET_CLASS (stream);
403   gssize n_read, n_written;
404   gssize bytes_copied;
405   char buffer[8192], *p;
406   gboolean res;
407 
408   bytes_copied = 0;
409   if (class->write_fn == NULL)
410     {
411       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
412                            _("Output stream doesn't implement write"));
413       res = FALSE;
414       goto notsupported;
415     }
416 
417   res = TRUE;
418   do
419     {
420       n_read = g_input_stream_read (source, buffer, sizeof (buffer), cancellable, error);
421       if (n_read == -1)
422 	{
423 	  res = FALSE;
424 	  break;
425 	}
426 
427       if (n_read == 0)
428 	break;
429 
430       p = buffer;
431       while (n_read > 0)
432 	{
433 	  n_written = class->write_fn (stream, p, n_read, cancellable, error);
434 	  if (n_written == -1)
435 	    {
436 	      res = FALSE;
437 	      break;
438 	    }
439 
440 	  p += n_written;
441 	  n_read -= n_written;
442 	  bytes_copied += n_written;
443 	}
444     }
445   while (res);
446 
447  notsupported:
448   if (!res)
449     error = NULL; /* Ignore further errors */
450 
451   if (flags & G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE)
452     {
453       /* Don't care about errors in source here */
454       g_input_stream_close (source, cancellable, NULL);
455     }
456 
457   if (flags & G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET)
458     {
459       /* But write errors on close are bad! */
460       if (!class->close_fn (stream, cancellable, error))
461 	res = FALSE;
462     }
463 
464   if (res)
465     return bytes_copied;
466 
467   return -1;
468 }
469 
470 
471 /**
472  * g_output_stream_close:
473  * @stream: A #GOutputStream.
474  * @cancellable: optional cancellable object
475  * @error: location to store the error occuring, or %NULL to ignore
476  *
477  * Closes the stream, releasing resources related to it.
478  *
479  * Once the stream is closed, all other operations will return %G_IO_ERROR_CLOSED.
480  * Closing a stream multiple times will not return an error.
481  *
482  * Closing a stream will automatically flush any outstanding buffers in the
483  * stream.
484  *
485  * Streams will be automatically closed when the last reference
486  * is dropped, but you might want to call this function to make sure
487  * resources are released as early as possible.
488  *
489  * Some streams might keep the backing store of the stream (e.g. a file descriptor)
490  * open after the stream is closed. See the documentation for the individual
491  * stream for details.
492  *
493  * On failure the first error that happened will be reported, but the close
494  * operation will finish as much as possible. A stream that failed to
495  * close will still return %G_IO_ERROR_CLOSED for all operations. Still, it
496  * is important to check and report the error to the user, otherwise
497  * there might be a loss of data as all data might not be written.
498  *
499  * If @cancellable is not NULL, then the operation can be cancelled by
500  * triggering the cancellable object from another thread. If the operation
501  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
502  * Cancelling a close will still leave the stream closed, but there some streams
503  * can use a faster close that doesn't block to e.g. check errors. On
504  * cancellation (as with any error) there is no guarantee that all written
505  * data will reach the target.
506  *
507  * Return value: %TRUE on success, %FALSE on failure
508  **/
509 gboolean
g_output_stream_close(GOutputStream * stream,GCancellable * cancellable,GError ** error)510 g_output_stream_close (GOutputStream  *stream,
511 		       GCancellable   *cancellable,
512 		       GError        **error)
513 {
514   GOutputStreamClass *class;
515   gboolean res;
516 
517   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
518 
519   class = G_OUTPUT_STREAM_GET_CLASS (stream);
520 
521   if (stream->priv->closed)
522     return TRUE;
523 
524   if (!g_output_stream_set_pending (stream, error))
525     return FALSE;
526 
527   if (cancellable)
528     g_cancellable_push_current (cancellable);
529 
530   if (class->flush)
531     res = class->flush (stream, cancellable, error);
532   else
533     res = TRUE;
534 
535   if (!res)
536     {
537       /* flushing caused the error that we want to return,
538        * but we still want to close the underlying stream if possible
539        */
540       if (class->close_fn)
541 	class->close_fn (stream, cancellable, NULL);
542     }
543   else
544     {
545       res = TRUE;
546       if (class->close_fn)
547 	res = class->close_fn (stream, cancellable, error);
548     }
549 
550   if (cancellable)
551     g_cancellable_pop_current (cancellable);
552 
553   stream->priv->closed = TRUE;
554   g_output_stream_clear_pending (stream);
555 
556   return res;
557 }
558 
559 static void
async_ready_callback_wrapper(GObject * source_object,GAsyncResult * res,gpointer user_data)560 async_ready_callback_wrapper (GObject      *source_object,
561                               GAsyncResult *res,
562                               gpointer      user_data)
563 {
564   GOutputStream *stream = G_OUTPUT_STREAM (source_object);
565 
566   g_output_stream_clear_pending (stream);
567   if (stream->priv->outstanding_callback)
568     (*stream->priv->outstanding_callback) (source_object, res, user_data);
569   g_object_unref (stream);
570 }
571 
572 static void
async_ready_close_callback_wrapper(GObject * source_object,GAsyncResult * res,gpointer user_data)573 async_ready_close_callback_wrapper (GObject      *source_object,
574                                     GAsyncResult *res,
575                                     gpointer      user_data)
576 {
577   GOutputStream *stream = G_OUTPUT_STREAM (source_object);
578 
579   stream->priv->closed = TRUE;
580   g_output_stream_clear_pending (stream);
581   if (stream->priv->outstanding_callback)
582     (*stream->priv->outstanding_callback) (source_object, res, user_data);
583   g_object_unref (stream);
584 }
585 
586 /**
587  * g_output_stream_write_async:
588  * @stream: A #GOutputStream.
589  * @buffer: the buffer containing the data to write.
590  * @count: the number of bytes to write
591  * @io_priority: the io priority of the request.
592  * @cancellable: optional #GCancellable object, %NULL to ignore.
593  * @callback: callback to call when the request is satisfied
594  * @user_data: the data to pass to callback function
595  *
596  * Request an asynchronous write of @count bytes from @buffer into
597  * the stream. When the operation is finished @callback will be called.
598  * You can then call g_output_stream_write_finish() to get the result of the
599  * operation.
600  *
601  * During an async request no other sync and async calls are allowed,
602  * and will result in %G_IO_ERROR_PENDING errors.
603  *
604  * A value of @count larger than %G_MAXSSIZE will cause a
605  * %G_IO_ERROR_INVALID_ARGUMENT error.
606  *
607  * On success, the number of bytes written will be passed to the
608  * @callback. It is not an error if this is not the same as the
609  * requested size, as it can happen e.g. on a partial I/O error,
610  * but generally we try to write as many bytes as requested.
611  *
612  * Any outstanding I/O request with higher priority (lower numerical
613  * value) will be executed before an outstanding request with lower
614  * priority. Default priority is %G_PRIORITY_DEFAULT.
615  *
616  * The asyncronous methods have a default fallback that uses threads
617  * to implement asynchronicity, so they are optional for inheriting
618  * classes. However, if you override one you must override all.
619  *
620  * For the synchronous, blocking version of this function, see
621  * g_output_stream_write().
622  **/
623 void
g_output_stream_write_async(GOutputStream * stream,const void * buffer,gsize count,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)624 g_output_stream_write_async (GOutputStream       *stream,
625 			     const void          *buffer,
626 			     gsize                count,
627 			     int                  io_priority,
628 			     GCancellable        *cancellable,
629 			     GAsyncReadyCallback  callback,
630 			     gpointer             user_data)
631 {
632   GOutputStreamClass *class;
633   GSimpleAsyncResult *simple;
634   GError *error = NULL;
635 
636   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
637   g_return_if_fail (buffer != NULL);
638 
639   if (count == 0)
640     {
641       simple = g_simple_async_result_new (G_OBJECT (stream),
642 					  callback,
643 					  user_data,
644 					  g_output_stream_write_async);
645       g_simple_async_result_complete_in_idle (simple);
646       g_object_unref (simple);
647       return;
648     }
649 
650   if (((gssize) count) < 0)
651     {
652       g_simple_async_report_error_in_idle (G_OBJECT (stream),
653 					   callback,
654 					   user_data,
655 					   G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
656 					   _("Too large count value passed to %s"),
657 					   G_STRFUNC);
658       return;
659     }
660 
661   if (!g_output_stream_set_pending (stream, &error))
662     {
663       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
664 					    callback,
665 					    user_data,
666 					    error);
667       g_error_free (error);
668       return;
669     }
670 
671   class = G_OUTPUT_STREAM_GET_CLASS (stream);
672 
673   stream->priv->outstanding_callback = callback;
674   g_object_ref (stream);
675   class->write_async (stream, buffer, count, io_priority, cancellable,
676 		      async_ready_callback_wrapper, user_data);
677 }
678 
679 /**
680  * g_output_stream_write_finish:
681  * @stream: a #GOutputStream.
682  * @result: a #GAsyncResult.
683  * @error: a #GError location to store the error occuring, or %NULL to
684  * ignore.
685  *
686  * Finishes a stream write operation.
687  *
688  * Returns: a #gssize containing the number of bytes written to the stream.
689  **/
690 gssize
g_output_stream_write_finish(GOutputStream * stream,GAsyncResult * result,GError ** error)691 g_output_stream_write_finish (GOutputStream  *stream,
692                               GAsyncResult   *result,
693                               GError        **error)
694 {
695   GSimpleAsyncResult *simple;
696   GOutputStreamClass *class;
697 
698   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
699   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
700 
701   if (G_IS_SIMPLE_ASYNC_RESULT (result))
702     {
703       simple = G_SIMPLE_ASYNC_RESULT (result);
704       if (g_simple_async_result_propagate_error (simple, error))
705 	return -1;
706 
707       /* Special case writes of 0 bytes */
708       if (g_simple_async_result_get_source_tag (simple) == g_output_stream_write_async)
709 	return 0;
710     }
711 
712   class = G_OUTPUT_STREAM_GET_CLASS (stream);
713   return class->write_finish (stream, result, error);
714 }
715 
716 typedef struct {
717   GInputStream *source;
718   gpointer user_data;
719   GAsyncReadyCallback callback;
720 } SpliceUserData;
721 
722 static void
async_ready_splice_callback_wrapper(GObject * source_object,GAsyncResult * res,gpointer _data)723 async_ready_splice_callback_wrapper (GObject      *source_object,
724                                      GAsyncResult *res,
725                                      gpointer     _data)
726 {
727   GOutputStream *stream = G_OUTPUT_STREAM (source_object);
728   SpliceUserData *data = _data;
729 
730   g_output_stream_clear_pending (stream);
731 
732   if (data->callback)
733     (*data->callback) (source_object, res, data->user_data);
734 
735   g_object_unref (stream);
736   g_object_unref (data->source);
737   g_free (data);
738 }
739 
740 /**
741  * g_output_stream_splice_async:
742  * @stream: a #GOutputStream.
743  * @source: a #GInputStream.
744  * @flags: a set of #GOutputStreamSpliceFlags.
745  * @io_priority: the io priority of the request.
746  * @cancellable: optional #GCancellable object, %NULL to ignore.
747  * @callback: a #GAsyncReadyCallback.
748  * @user_data: user data passed to @callback.
749  *
750  * Splices a stream asynchronously.
751  * When the operation is finished @callback will be called.
752  * You can then call g_output_stream_splice_finish() to get the
753  * result of the operation.
754  *
755  * For the synchronous, blocking version of this function, see
756  * g_output_stream_splice().
757  **/
758 void
g_output_stream_splice_async(GOutputStream * stream,GInputStream * source,GOutputStreamSpliceFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)759 g_output_stream_splice_async (GOutputStream            *stream,
760 			      GInputStream             *source,
761 			      GOutputStreamSpliceFlags  flags,
762 			      int                       io_priority,
763 			      GCancellable             *cancellable,
764 			      GAsyncReadyCallback       callback,
765 			      gpointer                  user_data)
766 {
767   GOutputStreamClass *class;
768   SpliceUserData *data;
769   GError *error = NULL;
770 
771   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
772   g_return_if_fail (G_IS_INPUT_STREAM (source));
773 
774   if (g_input_stream_is_closed (source))
775     {
776       g_simple_async_report_error_in_idle (G_OBJECT (stream),
777 					   callback,
778 					   user_data,
779 					   G_IO_ERROR, G_IO_ERROR_CLOSED,
780 					   _("Source stream is already closed"));
781       return;
782     }
783 
784   if (!g_output_stream_set_pending (stream, &error))
785     {
786       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
787 					    callback,
788 					    user_data,
789 					    error);
790       g_error_free (error);
791       return;
792     }
793 
794   class = G_OUTPUT_STREAM_GET_CLASS (stream);
795 
796   data = g_new0 (SpliceUserData, 1);
797   data->callback = callback;
798   data->user_data = user_data;
799   data->source = g_object_ref (source);
800 
801   g_object_ref (stream);
802   class->splice_async (stream, source, flags, io_priority, cancellable,
803 		      async_ready_splice_callback_wrapper, data);
804 }
805 
806 /**
807  * g_output_stream_splice_finish:
808  * @stream: a #GOutputStream.
809  * @result: a #GAsyncResult.
810  * @error: a #GError location to store the error occuring, or %NULL to
811  * ignore.
812  *
813  * Finishes an asynchronous stream splice operation.
814  *
815  * Returns: a #gssize of the number of bytes spliced.
816  **/
817 gssize
g_output_stream_splice_finish(GOutputStream * stream,GAsyncResult * result,GError ** error)818 g_output_stream_splice_finish (GOutputStream  *stream,
819 			       GAsyncResult   *result,
820 			       GError        **error)
821 {
822   GSimpleAsyncResult *simple;
823   GOutputStreamClass *class;
824 
825   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
826   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
827 
828   if (G_IS_SIMPLE_ASYNC_RESULT (result))
829     {
830       simple = G_SIMPLE_ASYNC_RESULT (result);
831       if (g_simple_async_result_propagate_error (simple, error))
832 	return -1;
833     }
834 
835   class = G_OUTPUT_STREAM_GET_CLASS (stream);
836   return class->splice_finish (stream, result, error);
837 }
838 
839 /**
840  * g_output_stream_flush_async:
841  * @stream: a #GOutputStream.
842  * @io_priority: the io priority of the request.
843  * @cancellable: optional #GCancellable object, %NULL to ignore.
844  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
845  * @user_data: the data to pass to callback function
846  *
847  * Flushes a stream asynchronously.
848  * For behaviour details see g_output_stream_flush().
849  *
850  * When the operation is finished @callback will be
851  * called. You can then call g_output_stream_flush_finish() to get the
852  * result of the operation.
853  **/
854 void
g_output_stream_flush_async(GOutputStream * stream,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)855 g_output_stream_flush_async (GOutputStream       *stream,
856                              int                  io_priority,
857                              GCancellable        *cancellable,
858                              GAsyncReadyCallback  callback,
859                              gpointer             user_data)
860 {
861   GOutputStreamClass *class;
862   GSimpleAsyncResult *simple;
863   GError *error = NULL;
864 
865   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
866 
867   if (!g_output_stream_set_pending (stream, &error))
868     {
869       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
870 					    callback,
871 					    user_data,
872 					    error);
873       g_error_free (error);
874       return;
875     }
876 
877   stream->priv->outstanding_callback = callback;
878   g_object_ref (stream);
879 
880   class = G_OUTPUT_STREAM_GET_CLASS (stream);
881 
882   if (class->flush_async == NULL)
883     {
884       simple = g_simple_async_result_new (G_OBJECT (stream),
885 					  async_ready_callback_wrapper,
886 					  user_data,
887 					  g_output_stream_flush_async);
888       g_simple_async_result_complete_in_idle (simple);
889       g_object_unref (simple);
890       return;
891     }
892 
893   class->flush_async (stream, io_priority, cancellable,
894 		      async_ready_callback_wrapper, user_data);
895 }
896 
897 /**
898  * g_output_stream_flush_finish:
899  * @stream: a #GOutputStream.
900  * @result: a GAsyncResult.
901  * @error: a #GError location to store the error occuring, or %NULL to
902  * ignore.
903  *
904  * Finishes flushing an output stream.
905  *
906  * Returns: %TRUE if flush operation suceeded, %FALSE otherwise.
907  **/
908 gboolean
g_output_stream_flush_finish(GOutputStream * stream,GAsyncResult * result,GError ** error)909 g_output_stream_flush_finish (GOutputStream  *stream,
910                               GAsyncResult   *result,
911                               GError        **error)
912 {
913   GSimpleAsyncResult *simple;
914   GOutputStreamClass *klass;
915 
916   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
917   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
918 
919   if (G_IS_SIMPLE_ASYNC_RESULT (result))
920     {
921       simple = G_SIMPLE_ASYNC_RESULT (result);
922       if (g_simple_async_result_propagate_error (simple, error))
923 	return FALSE;
924 
925       /* Special case default implementation */
926       if (g_simple_async_result_get_source_tag (simple) == g_output_stream_flush_async)
927 	return TRUE;
928     }
929 
930   klass = G_OUTPUT_STREAM_GET_CLASS (stream);
931   return klass->flush_finish (stream, result, error);
932 }
933 
934 
935 /**
936  * g_output_stream_close_async:
937  * @stream: A #GOutputStream.
938  * @io_priority: the io priority of the request.
939  * @callback: callback to call when the request is satisfied
940  * @user_data: the data to pass to callback function
941  * @cancellable: optional cancellable object
942  *
943  * Requests an asynchronous close of the stream, releasing resources
944  * related to it. When the operation is finished @callback will be
945  * called. You can then call g_output_stream_close_finish() to get
946  * the result of the operation.
947  *
948  * For behaviour details see g_output_stream_close().
949  *
950  * The asyncronous methods have a default fallback that uses threads
951  * to implement asynchronicity, so they are optional for inheriting
952  * classes. However, if you override one you must override all.
953  **/
954 void
g_output_stream_close_async(GOutputStream * stream,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)955 g_output_stream_close_async (GOutputStream       *stream,
956                              int                  io_priority,
957                              GCancellable        *cancellable,
958                              GAsyncReadyCallback  callback,
959                              gpointer             user_data)
960 {
961   GOutputStreamClass *class;
962   GSimpleAsyncResult *simple;
963   GError *error = NULL;
964 
965   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
966 
967   if (stream->priv->closed)
968     {
969       simple = g_simple_async_result_new (G_OBJECT (stream),
970 					  callback,
971 					  user_data,
972 					  g_output_stream_close_async);
973       g_simple_async_result_complete_in_idle (simple);
974       g_object_unref (simple);
975       return;
976     }
977 
978   if (!g_output_stream_set_pending (stream, &error))
979     {
980       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
981 					    callback,
982 					    user_data,
983 					    error);
984       g_error_free (error);
985       return;
986     }
987 
988   class = G_OUTPUT_STREAM_GET_CLASS (stream);
989   stream->priv->outstanding_callback = callback;
990   g_object_ref (stream);
991   class->close_async (stream, io_priority, cancellable,
992 		      async_ready_close_callback_wrapper, user_data);
993 }
994 
995 /**
996  * g_output_stream_close_finish:
997  * @stream: a #GOutputStream.
998  * @result: a #GAsyncResult.
999  * @error: a #GError location to store the error occuring, or %NULL to
1000  * ignore.
1001  *
1002  * Closes an output stream.
1003  *
1004  * Returns: %TRUE if stream was successfully closed, %FALSE otherwise.
1005  **/
1006 gboolean
g_output_stream_close_finish(GOutputStream * stream,GAsyncResult * result,GError ** error)1007 g_output_stream_close_finish (GOutputStream  *stream,
1008                               GAsyncResult   *result,
1009                               GError        **error)
1010 {
1011   GSimpleAsyncResult *simple;
1012   GOutputStreamClass *class;
1013 
1014   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1015   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
1016 
1017   if (G_IS_SIMPLE_ASYNC_RESULT (result))
1018     {
1019       simple = G_SIMPLE_ASYNC_RESULT (result);
1020       if (g_simple_async_result_propagate_error (simple, error))
1021 	return FALSE;
1022 
1023       /* Special case already closed */
1024       if (g_simple_async_result_get_source_tag (simple) == g_output_stream_close_async)
1025 	return TRUE;
1026     }
1027 
1028   class = G_OUTPUT_STREAM_GET_CLASS (stream);
1029   return class->close_finish (stream, result, error);
1030 }
1031 
1032 /**
1033  * g_output_stream_is_closed:
1034  * @stream: a #GOutputStream.
1035  *
1036  * Checks if an output stream has already been closed.
1037  *
1038  * Returns: %TRUE if @stream is closed. %FALSE otherwise.
1039  **/
1040 gboolean
g_output_stream_is_closed(GOutputStream * stream)1041 g_output_stream_is_closed (GOutputStream *stream)
1042 {
1043   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), TRUE);
1044 
1045   return stream->priv->closed;
1046 }
1047 
1048 /**
1049  * g_output_stream_has_pending:
1050  * @stream: a #GOutputStream.
1051  *
1052  * Checks if an ouput stream has pending actions.
1053  *
1054  * Returns: %TRUE if @stream has pending actions.
1055  **/
1056 gboolean
g_output_stream_has_pending(GOutputStream * stream)1057 g_output_stream_has_pending (GOutputStream *stream)
1058 {
1059   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1060 
1061   return stream->priv->pending;
1062 }
1063 
1064 /**
1065  * g_output_stream_set_pending:
1066  * @stream: a #GOutputStream.
1067  * @error: a #GError location to store the error occuring, or %NULL to
1068  * ignore.
1069  *
1070  * Sets @stream to have actions pending. If the pending flag is
1071  * already set or @stream is closed, it will return %FALSE and set
1072  * @error.
1073  *
1074  * Return value: %TRUE if pending was previously unset and is now set.
1075  **/
1076 gboolean
g_output_stream_set_pending(GOutputStream * stream,GError ** error)1077 g_output_stream_set_pending (GOutputStream *stream,
1078 			     GError **error)
1079 {
1080   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1081 
1082   if (stream->priv->closed)
1083     {
1084       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
1085                            _("Stream is already closed"));
1086       return FALSE;
1087     }
1088 
1089   if (stream->priv->pending)
1090     {
1091       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
1092                            /* Translators: This is an error you get if there is
1093                             * already an operation running against this stream when
1094                             * you try to start one */
1095                            _("Stream has outstanding operation"));
1096       return FALSE;
1097     }
1098 
1099   stream->priv->pending = TRUE;
1100   return TRUE;
1101 }
1102 
1103 /**
1104  * g_output_stream_clear_pending:
1105  * @stream: output stream
1106  *
1107  * Clears the pending flag on @stream.
1108  **/
1109 void
g_output_stream_clear_pending(GOutputStream * stream)1110 g_output_stream_clear_pending (GOutputStream *stream)
1111 {
1112   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
1113 
1114   stream->priv->pending = FALSE;
1115 }
1116 
1117 
1118 /********************************************
1119  *   Default implementation of async ops    *
1120  ********************************************/
1121 
1122 typedef struct {
1123   const void         *buffer;
1124   gsize               count_requested;
1125   gssize              count_written;
1126 } WriteData;
1127 
1128 static void
write_async_thread(GSimpleAsyncResult * res,GObject * object,GCancellable * cancellable)1129 write_async_thread (GSimpleAsyncResult *res,
1130                     GObject            *object,
1131                     GCancellable       *cancellable)
1132 {
1133   WriteData *op;
1134   GOutputStreamClass *class;
1135   GError *error = NULL;
1136 
1137   class = G_OUTPUT_STREAM_GET_CLASS (object);
1138   op = g_simple_async_result_get_op_res_gpointer (res);
1139   op->count_written = class->write_fn (G_OUTPUT_STREAM (object), op->buffer, op->count_requested,
1140 				       cancellable, &error);
1141   if (op->count_written == -1)
1142     {
1143       g_simple_async_result_set_from_error (res, error);
1144       g_error_free (error);
1145     }
1146 }
1147 
1148 static void
g_output_stream_real_write_async(GOutputStream * stream,const void * buffer,gsize count,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1149 g_output_stream_real_write_async (GOutputStream       *stream,
1150                                   const void          *buffer,
1151                                   gsize                count,
1152                                   int                  io_priority,
1153                                   GCancellable        *cancellable,
1154                                   GAsyncReadyCallback  callback,
1155                                   gpointer             user_data)
1156 {
1157   GSimpleAsyncResult *res;
1158   WriteData *op;
1159 
1160   op = g_new0 (WriteData, 1);
1161   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_write_async);
1162   g_simple_async_result_set_op_res_gpointer (res, op, g_free);
1163   op->buffer = buffer;
1164   op->count_requested = count;
1165 
1166   g_simple_async_result_run_in_thread (res, write_async_thread, io_priority, cancellable);
1167   g_object_unref (res);
1168 }
1169 
1170 static gssize
g_output_stream_real_write_finish(GOutputStream * stream,GAsyncResult * result,GError ** error)1171 g_output_stream_real_write_finish (GOutputStream  *stream,
1172                                    GAsyncResult   *result,
1173                                    GError        **error)
1174 {
1175   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1176   WriteData *op;
1177 
1178   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_write_async);
1179   op = g_simple_async_result_get_op_res_gpointer (simple);
1180   return op->count_written;
1181 }
1182 
1183 typedef struct {
1184   GInputStream *source;
1185   GOutputStreamSpliceFlags flags;
1186   gssize bytes_copied;
1187 } SpliceData;
1188 
1189 static void
splice_async_thread(GSimpleAsyncResult * result,GObject * object,GCancellable * cancellable)1190 splice_async_thread (GSimpleAsyncResult *result,
1191                      GObject            *object,
1192                      GCancellable       *cancellable)
1193 {
1194   SpliceData *op;
1195   GOutputStreamClass *class;
1196   GError *error = NULL;
1197   GOutputStream *stream;
1198 
1199   stream = G_OUTPUT_STREAM (object);
1200   class = G_OUTPUT_STREAM_GET_CLASS (object);
1201   op = g_simple_async_result_get_op_res_gpointer (result);
1202 
1203   op->bytes_copied = class->splice (stream,
1204 				    op->source,
1205 				    op->flags,
1206 				    cancellable,
1207 				    &error);
1208   if (op->bytes_copied == -1)
1209     {
1210       g_simple_async_result_set_from_error (result, error);
1211       g_error_free (error);
1212     }
1213 }
1214 
1215 static void
g_output_stream_real_splice_async(GOutputStream * stream,GInputStream * source,GOutputStreamSpliceFlags flags,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1216 g_output_stream_real_splice_async (GOutputStream             *stream,
1217                                    GInputStream              *source,
1218                                    GOutputStreamSpliceFlags   flags,
1219                                    int                        io_priority,
1220                                    GCancellable              *cancellable,
1221                                    GAsyncReadyCallback        callback,
1222                                    gpointer                   user_data)
1223 {
1224   GSimpleAsyncResult *res;
1225   SpliceData *op;
1226 
1227   op = g_new0 (SpliceData, 1);
1228   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_splice_async);
1229   g_simple_async_result_set_op_res_gpointer (res, op, g_free);
1230   op->flags = flags;
1231   op->source = source;
1232 
1233   /* TODO: In the case where both source and destintion have
1234      non-threadbased async calls we can use a true async copy here */
1235 
1236   g_simple_async_result_run_in_thread (res, splice_async_thread, io_priority, cancellable);
1237   g_object_unref (res);
1238 }
1239 
1240 static gssize
g_output_stream_real_splice_finish(GOutputStream * stream,GAsyncResult * result,GError ** error)1241 g_output_stream_real_splice_finish (GOutputStream  *stream,
1242                                     GAsyncResult   *result,
1243                                     GError        **error)
1244 {
1245   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1246   SpliceData *op;
1247 
1248   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_splice_async);
1249   op = g_simple_async_result_get_op_res_gpointer (simple);
1250   return op->bytes_copied;
1251 }
1252 
1253 
1254 static void
flush_async_thread(GSimpleAsyncResult * res,GObject * object,GCancellable * cancellable)1255 flush_async_thread (GSimpleAsyncResult *res,
1256                     GObject            *object,
1257                     GCancellable       *cancellable)
1258 {
1259   GOutputStreamClass *class;
1260   gboolean result;
1261   GError *error = NULL;
1262 
1263   class = G_OUTPUT_STREAM_GET_CLASS (object);
1264   result = TRUE;
1265   if (class->flush)
1266     result = class->flush (G_OUTPUT_STREAM (object), cancellable, &error);
1267 
1268   if (!result)
1269     {
1270       g_simple_async_result_set_from_error (res, error);
1271       g_error_free (error);
1272     }
1273 }
1274 
1275 static void
g_output_stream_real_flush_async(GOutputStream * stream,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1276 g_output_stream_real_flush_async (GOutputStream       *stream,
1277                                   int                  io_priority,
1278                                   GCancellable        *cancellable,
1279                                   GAsyncReadyCallback  callback,
1280                                   gpointer             user_data)
1281 {
1282   GSimpleAsyncResult *res;
1283 
1284   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_write_async);
1285 
1286   g_simple_async_result_run_in_thread (res, flush_async_thread, io_priority, cancellable);
1287   g_object_unref (res);
1288 }
1289 
1290 static gboolean
g_output_stream_real_flush_finish(GOutputStream * stream,GAsyncResult * result,GError ** error)1291 g_output_stream_real_flush_finish (GOutputStream  *stream,
1292                                    GAsyncResult   *result,
1293                                    GError        **error)
1294 {
1295   return TRUE;
1296 }
1297 
1298 static void
close_async_thread(GSimpleAsyncResult * res,GObject * object,GCancellable * cancellable)1299 close_async_thread (GSimpleAsyncResult *res,
1300                     GObject            *object,
1301                     GCancellable       *cancellable)
1302 {
1303   GOutputStreamClass *class;
1304   GError *error = NULL;
1305   gboolean result;
1306 
1307   /* Auto handling of cancelation disabled, and ignore
1308      cancellation, since we want to close things anyway, although
1309      possibly in a quick-n-dirty way. At least we never want to leak
1310      open handles */
1311 
1312   class = G_OUTPUT_STREAM_GET_CLASS (object);
1313   result = class->close_fn (G_OUTPUT_STREAM (object), cancellable, &error);
1314   if (!result)
1315     {
1316       g_simple_async_result_set_from_error (res, error);
1317       g_error_free (error);
1318     }
1319 }
1320 
1321 static void
g_output_stream_real_close_async(GOutputStream * stream,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1322 g_output_stream_real_close_async (GOutputStream       *stream,
1323                                   int                  io_priority,
1324                                   GCancellable        *cancellable,
1325                                   GAsyncReadyCallback  callback,
1326                                   gpointer             user_data)
1327 {
1328   GSimpleAsyncResult *res;
1329 
1330   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_close_async);
1331 
1332   g_simple_async_result_set_handle_cancellation (res, FALSE);
1333 
1334   g_simple_async_result_run_in_thread (res, close_async_thread, io_priority, cancellable);
1335   g_object_unref (res);
1336 }
1337 
1338 static gboolean
g_output_stream_real_close_finish(GOutputStream * stream,GAsyncResult * result,GError ** error)1339 g_output_stream_real_close_finish (GOutputStream  *stream,
1340                                    GAsyncResult   *result,
1341                                    GError        **error)
1342 {
1343   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1344   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_close_async);
1345   return TRUE;
1346 }
1347 
1348 #define __G_OUTPUT_STREAM_C__
1349 #include "gioaliasdef.c"
1350