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