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