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