1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
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.
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.
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.
20 * Author: Alexander Larsson <alexl@redhat.com>
25 #include <sys/types.h>
34 #include <glib/gstdio.h>
36 #include "gsimpleasyncresult.h"
37 #include "gunixinputstream.h"
38 #include "gcancellable.h"
39 #include "gasynchelper.h"
45 * SECTION:gunixinputstream
46 * @short_description: Streaming input operations for Unix file descriptors
47 * @include: gio/gunixinputstream.h
48 * @see_also: #GInputStream
50 * #GUnixInputStream implements #GInputStream for reading from a
51 * unix file descriptor, including asynchronous operations. The file
52 * descriptor must be selectable, so it doesn't work with opened files.
55 G_DEFINE_TYPE (GUnixInputStream
, g_unix_input_stream
, G_TYPE_INPUT_STREAM
);
57 struct _GUnixInputStreamPrivate
{
59 gboolean close_fd_at_close
;
62 static gssize
g_unix_input_stream_read (GInputStream
*stream
,
65 GCancellable
*cancellable
,
67 static gboolean
g_unix_input_stream_close (GInputStream
*stream
,
68 GCancellable
*cancellable
,
70 static void g_unix_input_stream_read_async (GInputStream
*stream
,
74 GCancellable
*cancellable
,
75 GAsyncReadyCallback callback
,
77 static gssize
g_unix_input_stream_read_finish (GInputStream
*stream
,
80 static void g_unix_input_stream_skip_async (GInputStream
*stream
,
83 GCancellable
*cancellable
,
84 GAsyncReadyCallback callback
,
86 static gssize
g_unix_input_stream_skip_finish (GInputStream
*stream
,
89 static void g_unix_input_stream_close_async (GInputStream
*stream
,
91 GCancellable
*cancellable
,
92 GAsyncReadyCallback callback
,
94 static gboolean
g_unix_input_stream_close_finish (GInputStream
*stream
,
100 g_unix_input_stream_finalize (GObject
*object
)
102 GUnixInputStream
*stream
;
104 stream
= G_UNIX_INPUT_STREAM (object
);
106 G_OBJECT_CLASS (g_unix_input_stream_parent_class
)->finalize (object
);
110 g_unix_input_stream_class_init (GUnixInputStreamClass
*klass
)
112 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
113 GInputStreamClass
*stream_class
= G_INPUT_STREAM_CLASS (klass
);
115 g_type_class_add_private (klass
, sizeof (GUnixInputStreamPrivate
));
117 gobject_class
->finalize
= g_unix_input_stream_finalize
;
119 stream_class
->read_fn
= g_unix_input_stream_read
;
120 stream_class
->close_fn
= g_unix_input_stream_close
;
121 stream_class
->read_async
= g_unix_input_stream_read_async
;
122 stream_class
->read_finish
= g_unix_input_stream_read_finish
;
125 /* TODO: Implement instead of using fallbacks */
126 stream_class
->skip_async
= g_unix_input_stream_skip_async
;
127 stream_class
->skip_finish
= g_unix_input_stream_skip_finish
;
129 stream_class
->close_async
= g_unix_input_stream_close_async
;
130 stream_class
->close_finish
= g_unix_input_stream_close_finish
;
134 g_unix_input_stream_init (GUnixInputStream
*unix_stream
)
136 unix_stream
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (unix_stream
,
137 G_TYPE_UNIX_INPUT_STREAM
,
138 GUnixInputStreamPrivate
);
142 * g_unix_input_stream_new:
143 * @fd: unix file descriptor.
144 * @close_fd_at_close: a #gboolean.
146 * Creates a new #GUnixInputStream for the given @fd. If @close_fd_at_close
147 * is %TRUE, the file descriptor will be closed when the stream is closed.
149 * Returns: a #GUnixInputStream.
152 g_unix_input_stream_new (int fd
,
153 gboolean close_fd_at_close
)
155 GUnixInputStream
*stream
;
157 g_return_val_if_fail (fd
!= -1, NULL
);
159 stream
= g_object_new (G_TYPE_UNIX_INPUT_STREAM
, NULL
);
161 stream
->priv
->fd
= fd
;
162 stream
->priv
->close_fd_at_close
= close_fd_at_close
;
164 return G_INPUT_STREAM (stream
);
168 g_unix_input_stream_read (GInputStream
*stream
,
171 GCancellable
*cancellable
,
174 GUnixInputStream
*unix_stream
;
176 struct pollfd poll_fds
[2];
180 unix_stream
= G_UNIX_INPUT_STREAM (stream
);
182 cancel_fd
= g_cancellable_get_fd (cancellable
);
187 poll_fds
[0].events
= POLLIN
;
188 poll_fds
[0].fd
= unix_stream
->priv
->fd
;
189 poll_fds
[1].events
= POLLIN
;
190 poll_fds
[1].fd
= cancel_fd
;
191 poll_ret
= poll (poll_fds
, 2, -1);
193 while (poll_ret
== -1 && errno
== EINTR
);
199 g_set_error (error
, G_IO_ERROR
,
200 g_io_error_from_errno (errsv
),
201 _("Error reading from unix: %s"),
209 if (g_cancellable_set_error_if_cancelled (cancellable
, error
))
211 res
= read (unix_stream
->priv
->fd
, buffer
, count
);
219 g_set_error (error
, G_IO_ERROR
,
220 g_io_error_from_errno (errsv
),
221 _("Error reading from unix: %s"),
232 g_unix_input_stream_close (GInputStream
*stream
,
233 GCancellable
*cancellable
,
236 GUnixInputStream
*unix_stream
;
239 unix_stream
= G_UNIX_INPUT_STREAM (stream
);
241 if (!unix_stream
->priv
->close_fd_at_close
)
246 /* This might block during the close. Doesn't seem to be a way to avoid it though. */
247 res
= close (unix_stream
->priv
->fd
);
252 g_set_error (error
, G_IO_ERROR
,
253 g_io_error_from_errno (errsv
),
254 _("Error closing unix: %s"),
266 GAsyncReadyCallback callback
;
268 GCancellable
*cancellable
;
269 GUnixInputStream
*stream
;
273 read_async_cb (ReadAsyncData
*data
,
274 GIOCondition condition
,
277 GSimpleAsyncResult
*simple
;
278 GError
*error
= NULL
;
281 /* We know that we can read from fd once without blocking */
284 if (g_cancellable_set_error_if_cancelled (data
->cancellable
, &error
))
289 count_read
= read (data
->stream
->priv
->fd
, data
->buffer
, data
->count
);
290 if (count_read
== -1)
297 g_set_error (&error
, G_IO_ERROR
,
298 g_io_error_from_errno (errsv
),
299 _("Error reading from unix: %s"),
305 simple
= g_simple_async_result_new (G_OBJECT (data
->stream
),
308 g_unix_input_stream_read_async
);
310 g_simple_async_result_set_op_res_gssize (simple
, count_read
);
312 if (count_read
== -1)
314 g_simple_async_result_set_from_error (simple
, error
);
315 g_error_free (error
);
318 /* Complete immediately, not in idle, since we're already in a mainloop callout */
319 g_simple_async_result_complete (simple
);
320 g_object_unref (simple
);
326 g_unix_input_stream_read_async (GInputStream
*stream
,
330 GCancellable
*cancellable
,
331 GAsyncReadyCallback callback
,
335 GUnixInputStream
*unix_stream
;
338 unix_stream
= G_UNIX_INPUT_STREAM (stream
);
340 data
= g_new0 (ReadAsyncData
, 1);
342 data
->buffer
= buffer
;
343 data
->callback
= callback
;
344 data
->user_data
= user_data
;
345 data
->cancellable
= cancellable
;
346 data
->stream
= unix_stream
;
348 source
= _g_fd_source_new (unix_stream
->priv
->fd
,
352 g_source_set_callback (source
, (GSourceFunc
)read_async_cb
, data
, g_free
);
353 g_source_attach (source
, NULL
);
355 g_source_unref (source
);
359 g_unix_input_stream_read_finish (GInputStream
*stream
,
360 GAsyncResult
*result
,
363 GSimpleAsyncResult
*simple
;
366 simple
= G_SIMPLE_ASYNC_RESULT (result
);
367 g_warn_if_fail (g_simple_async_result_get_source_tag (simple
) == g_unix_input_stream_read_async
);
369 nread
= g_simple_async_result_get_op_res_gssize (simple
);
374 g_unix_input_stream_skip_async (GInputStream
*stream
,
377 GCancellable
*cancellable
,
378 GAsyncReadyCallback callback
,
381 g_warn_if_reached ();
382 /* TODO: Not implemented */
386 g_unix_input_stream_skip_finish (GInputStream
*stream
,
387 GAsyncResult
*result
,
390 g_warn_if_reached ();
392 /* TODO: Not implemented */
397 GInputStream
*stream
;
398 GAsyncReadyCallback callback
;
403 close_async_data_free (gpointer _data
)
405 CloseAsyncData
*data
= _data
;
411 close_async_cb (CloseAsyncData
*data
)
413 GUnixInputStream
*unix_stream
;
414 GSimpleAsyncResult
*simple
;
415 GError
*error
= NULL
;
419 unix_stream
= G_UNIX_INPUT_STREAM (data
->stream
);
421 if (!unix_stream
->priv
->close_fd_at_close
)
429 res
= close (unix_stream
->priv
->fd
);
434 g_set_error (&error
, G_IO_ERROR
,
435 g_io_error_from_errno (errsv
),
436 _("Error closing unix: %s"),
445 simple
= g_simple_async_result_new (G_OBJECT (data
->stream
),
448 g_unix_input_stream_close_async
);
452 g_simple_async_result_set_from_error (simple
, error
);
453 g_error_free (error
);
456 /* Complete immediately, not in idle, since we're already in a mainloop callout */
457 g_simple_async_result_complete (simple
);
458 g_object_unref (simple
);
464 g_unix_input_stream_close_async (GInputStream
*stream
,
466 GCancellable
*cancellable
,
467 GAsyncReadyCallback callback
,
471 CloseAsyncData
*data
;
473 data
= g_new0 (CloseAsyncData
, 1);
475 data
->stream
= stream
;
476 data
->callback
= callback
;
477 data
->user_data
= user_data
;
479 idle
= g_idle_source_new ();
480 g_source_set_callback (idle
, (GSourceFunc
)close_async_cb
, data
, close_async_data_free
);
481 g_source_attach (idle
, NULL
);
482 g_source_unref (idle
);
486 g_unix_input_stream_close_finish (GInputStream
*stream
,
487 GAsyncResult
*result
,
490 /* Failures handled in generic close_finish code */
494 #define __G_UNIX_INPUT_STREAM_C__
495 #include "gioaliasdef.c"