gio: more implementations of GFileDescriptorBased
[platform/upstream/glib.git] / gio / gunixinputstream.c
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
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <stdio.h>
30 #include <fcntl.h>
31
32 #include <glib.h>
33 #include <glib/gstdio.h>
34 #include "gioerror.h"
35 #include "gsimpleasyncresult.h"
36 #include "gunixinputstream.h"
37 #include "gcancellable.h"
38 #include "gasynchelper.h"
39 #include "gfiledescriptorbased.h"
40 #include "glibintl.h"
41
42
43 /**
44  * SECTION:gunixinputstream
45  * @short_description: Streaming input operations for UNIX file descriptors
46  * @include: gio/gunixinputstream.h
47  * @see_also: #GInputStream
48  *
49  * #GUnixInputStream implements #GInputStream for reading from a
50  * UNIX file descriptor, including asynchronous operations. The file
51  * descriptor must be selectable, so it doesn't work with opened files.
52  *
53  * Note that <filename>&lt;gio/gunixinputstream.h&gt;</filename> belongs
54  * to the UNIX-specific GIO interfaces, thus you have to use the
55  * <filename>gio-unix-2.0.pc</filename> pkg-config file when using it.
56  */
57
58 enum {
59   PROP_0,
60   PROP_FD,
61   PROP_CLOSE_FD
62 };
63
64 static void g_unix_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface);
65 static void g_unix_input_stream_file_descriptor_based_iface_init (GFileDescriptorBasedIface *iface);
66
67 G_DEFINE_TYPE_WITH_CODE (GUnixInputStream, g_unix_input_stream, G_TYPE_INPUT_STREAM,
68                          G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM,
69                                                 g_unix_input_stream_pollable_iface_init)
70                          G_IMPLEMENT_INTERFACE (G_TYPE_FILE_DESCRIPTOR_BASED,
71                                                 g_unix_input_stream_file_descriptor_based_iface_init)
72                          )
73
74 struct _GUnixInputStreamPrivate {
75   int fd;
76   gboolean close_fd;
77 };
78
79 static void     g_unix_input_stream_set_property (GObject              *object,
80                                                   guint                 prop_id,
81                                                   const GValue         *value,
82                                                   GParamSpec           *pspec);
83 static void     g_unix_input_stream_get_property (GObject              *object,
84                                                   guint                 prop_id,
85                                                   GValue               *value,
86                                                   GParamSpec           *pspec);
87 static gssize   g_unix_input_stream_read         (GInputStream         *stream,
88                                                   void                 *buffer,
89                                                   gsize                 count,
90                                                   GCancellable         *cancellable,
91                                                   GError              **error);
92 static gboolean g_unix_input_stream_close        (GInputStream         *stream,
93                                                   GCancellable         *cancellable,
94                                                   GError              **error);
95 static void     g_unix_input_stream_read_async   (GInputStream         *stream,
96                                                   void                 *buffer,
97                                                   gsize                 count,
98                                                   int                   io_priority,
99                                                   GCancellable         *cancellable,
100                                                   GAsyncReadyCallback   callback,
101                                                   gpointer              data);
102 static gssize   g_unix_input_stream_read_finish  (GInputStream         *stream,
103                                                   GAsyncResult         *result,
104                                                   GError              **error);
105 static void     g_unix_input_stream_skip_async   (GInputStream         *stream,
106                                                   gsize                 count,
107                                                   int                   io_priority,
108                                                   GCancellable         *cancellable,
109                                                   GAsyncReadyCallback   callback,
110                                                   gpointer              data);
111 static gssize   g_unix_input_stream_skip_finish  (GInputStream         *stream,
112                                                   GAsyncResult         *result,
113                                                   GError              **error);
114 static void     g_unix_input_stream_close_async  (GInputStream         *stream,
115                                                   int                   io_priority,
116                                                   GCancellable         *cancellable,
117                                                   GAsyncReadyCallback   callback,
118                                                   gpointer              data);
119 static gboolean g_unix_input_stream_close_finish (GInputStream         *stream,
120                                                   GAsyncResult         *result,
121                                                   GError              **error);
122
123 static gboolean g_unix_input_stream_pollable_is_readable   (GPollableInputStream *stream);
124 static GSource *g_unix_input_stream_pollable_create_source (GPollableInputStream *stream,
125                                                             GCancellable         *cancellable);
126
127 static void
128 g_unix_input_stream_finalize (GObject *object)
129 {
130   G_OBJECT_CLASS (g_unix_input_stream_parent_class)->finalize (object);
131 }
132
133 static void
134 g_unix_input_stream_class_init (GUnixInputStreamClass *klass)
135 {
136   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
137   GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
138   
139   g_type_class_add_private (klass, sizeof (GUnixInputStreamPrivate));
140
141   gobject_class->get_property = g_unix_input_stream_get_property;
142   gobject_class->set_property = g_unix_input_stream_set_property;
143   gobject_class->finalize = g_unix_input_stream_finalize;
144
145   stream_class->read_fn = g_unix_input_stream_read;
146   stream_class->close_fn = g_unix_input_stream_close;
147   stream_class->read_async = g_unix_input_stream_read_async;
148   stream_class->read_finish = g_unix_input_stream_read_finish;
149   if (0)
150     {
151       /* TODO: Implement instead of using fallbacks */
152       stream_class->skip_async = g_unix_input_stream_skip_async;
153       stream_class->skip_finish = g_unix_input_stream_skip_finish;
154     }
155   stream_class->close_async = g_unix_input_stream_close_async;
156   stream_class->close_finish = g_unix_input_stream_close_finish;
157
158   /**
159    * GUnixInputStream:fd:
160    *
161    * The file descriptor that the stream reads from.
162    *
163    * Since: 2.20
164    */
165   g_object_class_install_property (gobject_class,
166                                    PROP_FD,
167                                    g_param_spec_int ("fd",
168                                                      P_("File descriptor"),
169                                                      P_("The file descriptor to read from"),
170                                                      G_MININT, G_MAXINT, -1,
171                                                      G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
172
173   /**
174    * GUnixInputStream:close-fd:
175    *
176    * Whether to close the file descriptor when the stream is closed.
177    *
178    * Since: 2.20
179    */
180   g_object_class_install_property (gobject_class,
181                                    PROP_CLOSE_FD,
182                                    g_param_spec_boolean ("close-fd",
183                                                          P_("Close file descriptor"),
184                                                          P_("Whether to close the file descriptor when the stream is closed"),
185                                                          TRUE,
186                                                          G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
187 }
188
189 static void
190 g_unix_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface)
191 {
192   iface->is_readable = g_unix_input_stream_pollable_is_readable;
193   iface->create_source = g_unix_input_stream_pollable_create_source;
194 }
195
196 static void
197 g_unix_input_stream_file_descriptor_based_iface_init (GFileDescriptorBasedIface *iface)
198 {
199   iface->get_fd = (int (*) (GFileDescriptorBased *))g_unix_input_stream_get_fd;
200 }
201
202 static void
203 g_unix_input_stream_set_property (GObject         *object,
204                                   guint            prop_id,
205                                   const GValue    *value,
206                                   GParamSpec      *pspec)
207 {
208   GUnixInputStream *unix_stream;
209   
210   unix_stream = G_UNIX_INPUT_STREAM (object);
211
212   switch (prop_id)
213     {
214     case PROP_FD:
215       unix_stream->priv->fd = g_value_get_int (value);
216       break;
217     case PROP_CLOSE_FD:
218       unix_stream->priv->close_fd = g_value_get_boolean (value);
219       break;
220     default:
221       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
222       break;
223     }
224 }
225
226 static void
227 g_unix_input_stream_get_property (GObject    *object,
228                                   guint       prop_id,
229                                   GValue     *value,
230                                   GParamSpec *pspec)
231 {
232   GUnixInputStream *unix_stream;
233
234   unix_stream = G_UNIX_INPUT_STREAM (object);
235
236   switch (prop_id)
237     {
238     case PROP_FD:
239       g_value_set_int (value, unix_stream->priv->fd);
240       break;
241     case PROP_CLOSE_FD:
242       g_value_set_boolean (value, unix_stream->priv->close_fd);
243       break;
244     default:
245       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
246     }
247 }
248
249 static void
250 g_unix_input_stream_init (GUnixInputStream *unix_stream)
251 {
252   unix_stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (unix_stream,
253                                                    G_TYPE_UNIX_INPUT_STREAM,
254                                                    GUnixInputStreamPrivate);
255
256   unix_stream->priv->fd = -1;
257   unix_stream->priv->close_fd = TRUE;
258 }
259
260 /**
261  * g_unix_input_stream_new:
262  * @fd: a UNIX file descriptor
263  * @close_fd: %TRUE to close the file descriptor when done
264  * 
265  * Creates a new #GUnixInputStream for the given @fd. 
266  *
267  * If @close_fd is %TRUE, the file descriptor will be closed 
268  * when the stream is closed.
269  * 
270  * Returns: a new #GUnixInputStream
271  **/
272 GInputStream *
273 g_unix_input_stream_new (gint     fd,
274                          gboolean close_fd)
275 {
276   GUnixInputStream *stream;
277
278   g_return_val_if_fail (fd != -1, NULL);
279
280   stream = g_object_new (G_TYPE_UNIX_INPUT_STREAM,
281                          "fd", fd,
282                          "close-fd", close_fd,
283                          NULL);
284
285   return G_INPUT_STREAM (stream);
286 }
287
288 /**
289  * g_unix_input_stream_set_close_fd:
290  * @stream: a #GUnixInputStream
291  * @close_fd: %TRUE to close the file descriptor when done
292  *
293  * Sets whether the file descriptor of @stream shall be closed
294  * when the stream is closed.
295  *
296  * Since: 2.20
297  */
298 void
299 g_unix_input_stream_set_close_fd (GUnixInputStream *stream,
300                                   gboolean          close_fd)
301 {
302   g_return_if_fail (G_IS_UNIX_INPUT_STREAM (stream));
303
304   close_fd = close_fd != FALSE;
305   if (stream->priv->close_fd != close_fd)
306     {
307       stream->priv->close_fd = close_fd;
308       g_object_notify (G_OBJECT (stream), "close-fd");
309     }
310 }
311
312 /**
313  * g_unix_input_stream_get_close_fd:
314  * @stream: a #GUnixInputStream
315  *
316  * Returns whether the file descriptor of @stream will be
317  * closed when the stream is closed.
318  *
319  * Return value: %TRUE if the file descriptor is closed when done
320  *
321  * Since: 2.20
322  */
323 gboolean
324 g_unix_input_stream_get_close_fd (GUnixInputStream *stream)
325 {
326   g_return_val_if_fail (G_IS_UNIX_INPUT_STREAM (stream), FALSE);
327
328   return stream->priv->close_fd;
329 }
330
331 /**
332  * g_unix_input_stream_get_fd:
333  * @stream: a #GUnixInputStream
334  *
335  * Return the UNIX file descriptor that the stream reads from.
336  *
337  * Return value: The file descriptor of @stream
338  *
339  * Since: 2.20
340  */
341 gint
342 g_unix_input_stream_get_fd (GUnixInputStream *stream)
343 {
344   g_return_val_if_fail (G_IS_UNIX_INPUT_STREAM (stream), -1);
345   
346   return stream->priv->fd;
347 }
348
349 static gssize
350 g_unix_input_stream_read (GInputStream  *stream,
351                           void          *buffer,
352                           gsize          count,
353                           GCancellable  *cancellable,
354                           GError       **error)
355 {
356   GUnixInputStream *unix_stream;
357   gssize res;
358   GPollFD poll_fds[2];
359   int poll_ret;
360
361   unix_stream = G_UNIX_INPUT_STREAM (stream);
362
363   if (g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
364     {
365       poll_fds[0].fd = unix_stream->priv->fd;
366       poll_fds[0].events = G_IO_IN;
367       do
368         poll_ret = g_poll (poll_fds, 2, -1);
369       while (poll_ret == -1 && errno == EINTR);
370       g_cancellable_release_fd (cancellable);
371
372       if (poll_ret == -1)
373         {
374           int errsv = errno;
375
376           g_set_error (error, G_IO_ERROR,
377                        g_io_error_from_errno (errsv),
378                        _("Error reading from unix: %s"),
379                        g_strerror (errsv));
380           return -1;
381         }
382     }
383
384   while (1)
385     {
386       if (g_cancellable_set_error_if_cancelled (cancellable, error))
387         return -1;
388       res = read (unix_stream->priv->fd, buffer, count);
389       if (res == -1)
390         {
391           int errsv = errno;
392
393           if (errsv == EINTR)
394             continue;
395           
396           g_set_error (error, G_IO_ERROR,
397                        g_io_error_from_errno (errsv),
398                        _("Error reading from unix: %s"),
399                        g_strerror (errsv));
400         }
401       
402       break;
403     }
404
405   return res;
406 }
407
408 static gboolean
409 g_unix_input_stream_close (GInputStream  *stream,
410                            GCancellable  *cancellable,
411                            GError       **error)
412 {
413   GUnixInputStream *unix_stream;
414   int res;
415
416   unix_stream = G_UNIX_INPUT_STREAM (stream);
417
418   if (!unix_stream->priv->close_fd)
419     return TRUE;
420   
421   while (1)
422     {
423       /* This might block during the close. Doesn't seem to be a way to avoid it though. */
424       res = close (unix_stream->priv->fd);
425       if (res == -1)
426         {
427           int errsv = errno;
428
429           g_set_error (error, G_IO_ERROR,
430                        g_io_error_from_errno (errsv),
431                        _("Error closing unix: %s"),
432                        g_strerror (errsv));
433         }
434       break;
435     }
436   
437   return res != -1;
438 }
439
440 typedef struct {
441   gsize count;
442   void *buffer;
443   GAsyncReadyCallback callback;
444   gpointer user_data;
445   GCancellable *cancellable;
446   GUnixInputStream *stream;
447 } ReadAsyncData;
448
449 static gboolean
450 read_async_cb (int            fd,
451                GIOCondition   condition,
452                ReadAsyncData *data)
453 {
454   GSimpleAsyncResult *simple;
455   GError *error = NULL;
456   gssize count_read;
457
458   /* We know that we can read from fd once without blocking */
459   while (1)
460     {
461       if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
462         {
463           count_read = -1;
464           break;
465         }
466       count_read = read (data->stream->priv->fd, data->buffer, data->count);
467       if (count_read == -1)
468         {
469           int errsv = errno;
470
471           if (errsv == EINTR)
472             continue;
473           
474           g_set_error (&error, G_IO_ERROR,
475                        g_io_error_from_errno (errsv),
476                        _("Error reading from unix: %s"),
477                        g_strerror (errsv));
478         }
479       break;
480     }
481
482   simple = g_simple_async_result_new (G_OBJECT (data->stream),
483                                       data->callback,
484                                       data->user_data,
485                                       g_unix_input_stream_read_async);
486
487   g_simple_async_result_set_op_res_gssize (simple, count_read);
488
489   if (count_read == -1)
490     g_simple_async_result_take_error (simple, error);
491
492   /* Complete immediately, not in idle, since we're already in a mainloop callout */
493   g_simple_async_result_complete (simple);
494   g_object_unref (simple);
495
496   return FALSE;
497 }
498
499 static void
500 g_unix_input_stream_read_async (GInputStream        *stream,
501                                 void                *buffer,
502                                 gsize                count,
503                                 int                  io_priority,
504                                 GCancellable        *cancellable,
505                                 GAsyncReadyCallback  callback,
506                                 gpointer             user_data)
507 {
508   GSource *source;
509   GUnixInputStream *unix_stream;
510   ReadAsyncData *data;
511
512   unix_stream = G_UNIX_INPUT_STREAM (stream);
513
514   data = g_new0 (ReadAsyncData, 1);
515   data->count = count;
516   data->buffer = buffer;
517   data->callback = callback;
518   data->user_data = user_data;
519   data->cancellable = cancellable;
520   data->stream = unix_stream;
521
522   source = _g_fd_source_new (unix_stream->priv->fd,
523                              G_IO_IN,
524                              cancellable);
525   g_source_set_name (source, "GUnixInputStream");
526   
527   g_source_set_callback (source, (GSourceFunc)read_async_cb, data, g_free);
528   g_source_attach (source, g_main_context_get_thread_default ());
529  
530   g_source_unref (source);
531 }
532
533 static gssize
534 g_unix_input_stream_read_finish (GInputStream  *stream,
535                                  GAsyncResult  *result,
536                                  GError       **error)
537 {
538   GSimpleAsyncResult *simple;
539   gssize nread;
540
541   simple = G_SIMPLE_ASYNC_RESULT (result);
542   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_unix_input_stream_read_async);
543   
544   nread = g_simple_async_result_get_op_res_gssize (simple);
545   return nread;
546 }
547
548 static void
549 g_unix_input_stream_skip_async (GInputStream        *stream,
550                                 gsize                count,
551                                 int                  io_priority,
552                                 GCancellable        *cancellable,
553                                 GAsyncReadyCallback  callback,
554                                 gpointer             data)
555 {
556   g_warn_if_reached ();
557   /* TODO: Not implemented */
558 }
559
560 static gssize
561 g_unix_input_stream_skip_finish  (GInputStream  *stream,
562                                   GAsyncResult  *result,
563                                   GError       **error)
564 {
565   g_warn_if_reached ();
566   return 0;
567   /* TODO: Not implemented */
568 }
569
570
571 typedef struct {
572   GInputStream *stream;
573   GAsyncReadyCallback callback;
574   gpointer user_data;
575 } CloseAsyncData;
576
577 static void
578 close_async_data_free (gpointer _data)
579 {
580   CloseAsyncData *data = _data;
581
582   g_free (data);
583 }
584
585 static gboolean
586 close_async_cb (CloseAsyncData *data)
587 {
588   GUnixInputStream *unix_stream;
589   GSimpleAsyncResult *simple;
590   GError *error = NULL;
591   gboolean result;
592   int res;
593
594   unix_stream = G_UNIX_INPUT_STREAM (data->stream);
595
596   if (!unix_stream->priv->close_fd)
597     {
598       result = TRUE;
599       goto out;
600     }
601   
602   while (1)
603     {
604       res = close (unix_stream->priv->fd);
605       if (res == -1)
606         {
607           int errsv = errno;
608
609           g_set_error (&error, G_IO_ERROR,
610                        g_io_error_from_errno (errsv),
611                        _("Error closing unix: %s"),
612                        g_strerror (errsv));
613         }
614       break;
615     }
616   
617   result = res != -1;
618
619  out:
620   simple = g_simple_async_result_new (G_OBJECT (data->stream),
621                                       data->callback,
622                                       data->user_data,
623                                       g_unix_input_stream_close_async);
624
625   if (!result)
626     g_simple_async_result_take_error (simple, error);
627
628   /* Complete immediately, not in idle, since we're already in a mainloop callout */
629   g_simple_async_result_complete (simple);
630   g_object_unref (simple);
631   
632   return FALSE;
633 }
634
635 static void
636 g_unix_input_stream_close_async (GInputStream        *stream,
637                                  int                  io_priority,
638                                  GCancellable        *cancellable,
639                                  GAsyncReadyCallback  callback,
640                                  gpointer             user_data)
641 {
642   GSource *idle;
643   CloseAsyncData *data;
644
645   data = g_new0 (CloseAsyncData, 1);
646
647   data->stream = stream;
648   data->callback = callback;
649   data->user_data = user_data;
650   
651   idle = g_idle_source_new ();
652   g_source_set_callback (idle, (GSourceFunc)close_async_cb, data, close_async_data_free);
653   g_source_attach (idle, g_main_context_get_thread_default ());
654   g_source_unref (idle);
655 }
656
657 static gboolean
658 g_unix_input_stream_close_finish (GInputStream  *stream,
659                                   GAsyncResult  *result,
660                                   GError       **error)
661 {
662   /* Failures handled in generic close_finish code */
663   return TRUE;
664 }
665
666 static gboolean
667 g_unix_input_stream_pollable_is_readable (GPollableInputStream *stream)
668 {
669   GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
670   GPollFD poll_fd;
671   gint result;
672
673   poll_fd.fd = unix_stream->priv->fd;
674   poll_fd.events = G_IO_IN;
675
676   do
677     result = g_poll (&poll_fd, 1, 0);
678   while (result == -1 && errno == EINTR);
679
680   return poll_fd.revents != 0;
681 }
682
683 static GSource *
684 g_unix_input_stream_pollable_create_source (GPollableInputStream *stream,
685                                             GCancellable         *cancellable)
686 {
687   GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
688   GSource *inner_source, *pollable_source;
689
690   pollable_source = g_pollable_source_new (G_OBJECT (stream));
691
692   inner_source = _g_fd_source_new (unix_stream->priv->fd, G_IO_IN, cancellable);
693   g_source_set_dummy_callback (inner_source);
694   g_source_add_child_source (pollable_source, inner_source);
695   g_source_unref (inner_source);
696
697   return pollable_source;
698 }