Another round of trivial doc fixes
[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 #include <poll.h>
32
33 #include <glib.h>
34 #include <glib/gstdio.h>
35 #include "gioerror.h"
36 #include "gsimpleasyncresult.h"
37 #include "gunixinputstream.h"
38 #include "gcancellable.h"
39 #include "gasynchelper.h"
40 #include "glibintl.h"
41
42 /**
43  * SECTION:gunixinputstream
44  * @short_description: Unix Input Stream
45  * @see_also: #GInputStream
46  *
47  * #GUnixInputStream implements #GInputStream for reading from a
48  * unix file descriptor, including asynchronous operations. The file
49  * descriptor much be selectable, so it doesn't work with opened files.
50  **/
51
52 G_DEFINE_TYPE (GUnixInputStream, g_unix_input_stream, G_TYPE_INPUT_STREAM);
53
54 struct _GUnixInputStreamPrivate {
55   int fd;
56   gboolean close_fd_at_close;
57 };
58
59 static gssize   g_unix_input_stream_read         (GInputStream         *stream,
60                                                   void                 *buffer,
61                                                   gsize                 count,
62                                                   GCancellable         *cancellable,
63                                                   GError              **error);
64 static gboolean g_unix_input_stream_close        (GInputStream         *stream,
65                                                   GCancellable         *cancellable,
66                                                   GError              **error);
67 static void     g_unix_input_stream_read_async   (GInputStream         *stream,
68                                                   void                 *buffer,
69                                                   gsize                 count,
70                                                   int                   io_priority,
71                                                   GCancellable         *cancellable,
72                                                   GAsyncReadyCallback   callback,
73                                                   gpointer              data);
74 static gssize   g_unix_input_stream_read_finish  (GInputStream         *stream,
75                                                   GAsyncResult         *result,
76                                                   GError              **error);
77 static void     g_unix_input_stream_skip_async   (GInputStream         *stream,
78                                                   gsize                 count,
79                                                   int                   io_priority,
80                                                   GCancellable         *cancellable,
81                                                   GAsyncReadyCallback   callback,
82                                                   gpointer              data);
83 static gssize   g_unix_input_stream_skip_finish  (GInputStream         *stream,
84                                                   GAsyncResult         *result,
85                                                   GError              **error);
86 static void     g_unix_input_stream_close_async  (GInputStream         *stream,
87                                                   int                   io_priority,
88                                                   GCancellable         *cancellable,
89                                                   GAsyncReadyCallback   callback,
90                                                   gpointer              data);
91 static gboolean g_unix_input_stream_close_finish (GInputStream         *stream,
92                                                   GAsyncResult         *result,
93                                                   GError              **error);
94
95
96 static void
97 g_unix_input_stream_finalize (GObject *object)
98 {
99   GUnixInputStream *stream;
100   
101   stream = G_UNIX_INPUT_STREAM (object);
102
103   if (G_OBJECT_CLASS (g_unix_input_stream_parent_class)->finalize)
104     (*G_OBJECT_CLASS (g_unix_input_stream_parent_class)->finalize) (object);
105 }
106
107 static void
108 g_unix_input_stream_class_init (GUnixInputStreamClass *klass)
109 {
110   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
111   GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
112   
113   g_type_class_add_private (klass, sizeof (GUnixInputStreamPrivate));
114   
115   gobject_class->finalize = g_unix_input_stream_finalize;
116
117   stream_class->read = g_unix_input_stream_read;
118   stream_class->close = g_unix_input_stream_close;
119   stream_class->read_async = g_unix_input_stream_read_async;
120   stream_class->read_finish = g_unix_input_stream_read_finish;
121   if (0)
122     {
123       /* TODO: Implement instead of using fallbacks */
124       stream_class->skip_async = g_unix_input_stream_skip_async;
125       stream_class->skip_finish = g_unix_input_stream_skip_finish;
126     }
127   stream_class->close_async = g_unix_input_stream_close_async;
128   stream_class->close_finish = g_unix_input_stream_close_finish;
129 }
130
131 static void
132 g_unix_input_stream_init (GUnixInputStream *unix_stream)
133 {
134   unix_stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (unix_stream,
135                                                    G_TYPE_UNIX_INPUT_STREAM,
136                                                    GUnixInputStreamPrivate);
137 }
138
139 /**
140  * g_unix_input_stream_new:
141  * @fd: unix file descriptor.
142  * @close_fd_at_close: a #gboolean.
143  * 
144  * Creates a new #GUnixInputStream for the given @fd. If @close_fd_at_close
145  * is %TRUE, the file descriptor will be closed when the stream is closed.
146  * 
147  * Returns: a #GUnixInputStream. 
148  **/
149 GInputStream *
150 g_unix_input_stream_new (int fd,
151                          gboolean close_fd_at_close)
152 {
153   GUnixInputStream *stream;
154
155   g_return_val_if_fail (fd != -1, NULL);
156
157   stream = g_object_new (G_TYPE_UNIX_INPUT_STREAM, NULL);
158
159   stream->priv->fd = fd;
160   stream->priv->close_fd_at_close = close_fd_at_close;
161   
162   return G_INPUT_STREAM (stream);
163 }
164
165 static gssize
166 g_unix_input_stream_read (GInputStream *stream,
167                           void         *buffer,
168                           gsize         count,
169                           GCancellable *cancellable,
170                           GError      **error)
171 {
172   GUnixInputStream *unix_stream;
173   gssize res;
174   struct pollfd poll_fds[2];
175   int poll_ret;
176   int cancel_fd;
177
178   unix_stream = G_UNIX_INPUT_STREAM (stream);
179
180   cancel_fd = g_cancellable_get_fd (cancellable);
181   if (cancel_fd != -1)
182     {
183       do
184         {
185           poll_fds[0].events = POLLIN;
186           poll_fds[0].fd = unix_stream->priv->fd;
187           poll_fds[1].events = POLLIN;
188           poll_fds[1].fd = cancel_fd;
189           poll_ret = poll (poll_fds, 2, -1);
190         }
191       while (poll_ret == -1 && errno == EINTR);
192       
193       if (poll_ret == -1)
194         {
195           g_set_error (error, G_IO_ERROR,
196                        g_io_error_from_errno (errno),
197                        _("Error reading from unix: %s"),
198                        g_strerror (errno));
199           return -1;
200         }
201     }
202
203   while (1)
204     {
205       if (g_cancellable_set_error_if_cancelled (cancellable, error))
206         break;
207       res = read (unix_stream->priv->fd, buffer, count);
208       if (res == -1)
209         {
210           if (errno == EINTR)
211             continue;
212           
213           g_set_error (error, G_IO_ERROR,
214                        g_io_error_from_errno (errno),
215                        _("Error reading from unix: %s"),
216                        g_strerror (errno));
217         }
218       
219       break;
220     }
221
222   return res;
223 }
224
225 static gboolean
226 g_unix_input_stream_close (GInputStream *stream,
227                            GCancellable *cancellable,
228                            GError      **error)
229 {
230   GUnixInputStream *unix_stream;
231   int res;
232
233   unix_stream = G_UNIX_INPUT_STREAM (stream);
234
235   if (!unix_stream->priv->close_fd_at_close)
236     return TRUE;
237   
238   while (1)
239     {
240       /* This might block during the close. Doesn't seem to be a way to avoid it though. */
241       res = close (unix_stream->priv->fd);
242       if (res == -1)
243         {
244           g_set_error (error, G_IO_ERROR,
245                        g_io_error_from_errno (errno),
246                        _("Error closing unix: %s"),
247                        g_strerror (errno));
248         }
249       break;
250     }
251   
252   return res != -1;
253 }
254
255 typedef struct {
256   gsize count;
257   void *buffer;
258   GAsyncReadyCallback callback;
259   gpointer user_data;
260   GCancellable *cancellable;
261   GUnixInputStream *stream;
262 } ReadAsyncData;
263
264 static gboolean
265 read_async_cb (ReadAsyncData *data,
266                GIOCondition condition,
267                int fd)
268 {
269   GSimpleAsyncResult *simple;
270   GError *error = NULL;
271   gssize count_read;
272
273   /* We know that we can read from fd once without blocking */
274   while (1)
275     {
276       if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
277         {
278           count_read = -1;
279           break;
280         }
281       count_read = read (data->stream->priv->fd, data->buffer, data->count);
282       if (count_read == -1)
283         {
284           if (errno == EINTR)
285             continue;
286           
287           g_set_error (&error, G_IO_ERROR,
288                        g_io_error_from_errno (errno),
289                        _("Error reading from unix: %s"),
290                        g_strerror (errno));
291         }
292       break;
293     }
294
295   simple = g_simple_async_result_new (G_OBJECT (data->stream),
296                                       data->callback,
297                                       data->user_data,
298                                       g_unix_input_stream_read_async);
299
300   g_simple_async_result_set_op_res_gssize (simple, count_read);
301
302   if (count_read == -1)
303     {
304       g_simple_async_result_set_from_error (simple, error);
305       g_error_free (error);
306     }
307
308   /* Complete immediately, not in idle, since we're already in a mainloop callout */
309   g_simple_async_result_complete (simple);
310   g_object_unref (simple);
311
312   return FALSE;
313 }
314
315 static void
316 g_unix_input_stream_read_async (GInputStream        *stream,
317                                 void                *buffer,
318                                 gsize                count,
319                                 int                  io_priority,
320                                 GCancellable        *cancellable,
321                                 GAsyncReadyCallback  callback,
322                                 gpointer             user_data)
323 {
324   GSource *source;
325   GUnixInputStream *unix_stream;
326   ReadAsyncData *data;
327
328   unix_stream = G_UNIX_INPUT_STREAM (stream);
329
330   data = g_new0 (ReadAsyncData, 1);
331   data->count = count;
332   data->buffer = buffer;
333   data->callback = callback;
334   data->user_data = user_data;
335   data->cancellable = cancellable;
336   data->stream = unix_stream;
337
338   source = _g_fd_source_new (unix_stream->priv->fd,
339                              POLLIN,
340                              cancellable);
341   
342   g_source_set_callback (source, (GSourceFunc)read_async_cb, data, g_free);
343   g_source_attach (source, NULL);
344  
345   g_source_unref (source);
346 }
347
348 static gssize
349 g_unix_input_stream_read_finish (GInputStream              *stream,
350                                  GAsyncResult              *result,
351                                  GError                   **error)
352 {
353   GSimpleAsyncResult *simple;
354   gssize nread;
355
356   simple = G_SIMPLE_ASYNC_RESULT (result);
357   g_assert (g_simple_async_result_get_source_tag (simple) == g_unix_input_stream_read_async);
358   
359   nread = g_simple_async_result_get_op_res_gssize (simple);
360   return nread;
361 }
362
363 static void
364 g_unix_input_stream_skip_async (GInputStream        *stream,
365                                 gsize                count,
366                                 int                  io_priority,
367                                 GCancellable        *cancellable,
368                                 GAsyncReadyCallback  callback,
369                                 gpointer             data)
370 {
371   g_assert_not_reached ();
372   /* TODO: Not implemented */
373 }
374
375 static gssize
376 g_unix_input_stream_skip_finish  (GInputStream              *stream,
377                                   GAsyncResult              *result,
378                                   GError                   **error)
379 {
380   g_assert_not_reached ();
381   /* TODO: Not implemented */
382 }
383
384
385 typedef struct {
386   GInputStream *stream;
387   GAsyncReadyCallback callback;
388   gpointer user_data;
389 } CloseAsyncData;
390
391 static void
392 close_async_data_free (gpointer _data)
393 {
394   CloseAsyncData *data = _data;
395
396   g_free (data);
397 }
398
399 static gboolean
400 close_async_cb (CloseAsyncData *data)
401 {
402   GUnixInputStream *unix_stream;
403   GSimpleAsyncResult *simple;
404   GError *error = NULL;
405   gboolean result;
406   int res;
407
408   unix_stream = G_UNIX_INPUT_STREAM (data->stream);
409
410   if (!unix_stream->priv->close_fd_at_close)
411     {
412       result = TRUE;
413       goto out;
414     }
415   
416   while (1)
417     {
418       res = close (unix_stream->priv->fd);
419       if (res == -1)
420         {
421           g_set_error (&error, G_IO_ERROR,
422                        g_io_error_from_errno (errno),
423                        _("Error closing unix: %s"),
424                        g_strerror (errno));
425         }
426       break;
427     }
428   
429   result = res != -1;
430
431  out:
432   simple = g_simple_async_result_new (G_OBJECT (data->stream),
433                                       data->callback,
434                                       data->user_data,
435                                       g_unix_input_stream_close_async);
436
437   if (!result)
438     {
439       g_simple_async_result_set_from_error (simple, error);
440       g_error_free (error);
441     }
442
443   /* Complete immediately, not in idle, since we're already in a mainloop callout */
444   g_simple_async_result_complete (simple);
445   g_object_unref (simple);
446   
447   return FALSE;
448 }
449
450 static void
451 g_unix_input_stream_close_async (GInputStream       *stream,
452                                  int                 io_priority,
453                                  GCancellable       *cancellable,
454                                  GAsyncReadyCallback callback,
455                                  gpointer            user_data)
456 {
457   GSource *idle;
458   CloseAsyncData *data;
459
460   data = g_new0 (CloseAsyncData, 1);
461
462   data->stream = stream;
463   data->callback = callback;
464   data->user_data = user_data;
465   
466   idle = g_idle_source_new ();
467   g_source_set_callback (idle, (GSourceFunc)close_async_cb, data, close_async_data_free);
468   g_source_attach (idle, NULL);
469   g_source_unref (idle);
470 }
471
472 static gboolean
473 g_unix_input_stream_close_finish (GInputStream              *stream,
474                                   GAsyncResult              *result,
475                                   GError                   **error)
476 {
477   /* Failures handled in generic close_finish code */
478   return TRUE;
479 }
480