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>
33 #include <glib/gstdio.h>
35 #include "gsimpleasyncresult.h"
36 #include "gunixinputstream.h"
37 #include "gcancellable.h"
38 #include "gasynchelper.h"
39 #include "gfiledescriptorbased.h"
44 * SECTION:gunixinputstream
45 * @short_description: Streaming input operations for UNIX file descriptors
46 * @include: gio/gunixinputstream.h
47 * @see_also: #GInputStream
49 * #GUnixInputStream implements #GInputStream for reading from a UNIX
50 * file descriptor, including asynchronous operations. (If the file
51 * descriptor refers to a socket or pipe, this will use poll() to do
52 * asynchronous I/O. If it refers to a regular file, it will fall back
53 * to doing asynchronous I/O in another thread.)
55 * Note that <filename><gio/gunixinputstream.h></filename> belongs
56 * to the UNIX-specific GIO interfaces, thus you have to use the
57 * <filename>gio-unix-2.0.pc</filename> pkg-config file when using it.
66 struct _GUnixInputStreamPrivate {
69 guint is_pipe_or_socket : 1;
72 static void g_unix_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface);
73 static void g_unix_input_stream_file_descriptor_based_iface_init (GFileDescriptorBasedIface *iface);
75 G_DEFINE_TYPE_WITH_CODE (GUnixInputStream, g_unix_input_stream, G_TYPE_INPUT_STREAM,
76 G_ADD_PRIVATE (GUnixInputStream)
77 G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM,
78 g_unix_input_stream_pollable_iface_init)
79 G_IMPLEMENT_INTERFACE (G_TYPE_FILE_DESCRIPTOR_BASED,
80 g_unix_input_stream_file_descriptor_based_iface_init)
83 static void g_unix_input_stream_set_property (GObject *object,
87 static void g_unix_input_stream_get_property (GObject *object,
91 static gssize g_unix_input_stream_read (GInputStream *stream,
94 GCancellable *cancellable,
96 static gboolean g_unix_input_stream_close (GInputStream *stream,
97 GCancellable *cancellable,
99 static void g_unix_input_stream_skip_async (GInputStream *stream,
102 GCancellable *cancellable,
103 GAsyncReadyCallback callback,
105 static gssize g_unix_input_stream_skip_finish (GInputStream *stream,
106 GAsyncResult *result,
108 static void g_unix_input_stream_close_async (GInputStream *stream,
110 GCancellable *cancellable,
111 GAsyncReadyCallback callback,
113 static gboolean g_unix_input_stream_close_finish (GInputStream *stream,
114 GAsyncResult *result,
117 static gboolean g_unix_input_stream_pollable_can_poll (GPollableInputStream *stream);
118 static gboolean g_unix_input_stream_pollable_is_readable (GPollableInputStream *stream);
119 static GSource *g_unix_input_stream_pollable_create_source (GPollableInputStream *stream,
120 GCancellable *cancellable);
123 g_unix_input_stream_class_init (GUnixInputStreamClass *klass)
125 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
126 GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
128 gobject_class->get_property = g_unix_input_stream_get_property;
129 gobject_class->set_property = g_unix_input_stream_set_property;
131 stream_class->read_fn = g_unix_input_stream_read;
132 stream_class->close_fn = g_unix_input_stream_close;
135 /* TODO: Implement instead of using fallbacks */
136 stream_class->skip_async = g_unix_input_stream_skip_async;
137 stream_class->skip_finish = g_unix_input_stream_skip_finish;
139 stream_class->close_async = g_unix_input_stream_close_async;
140 stream_class->close_finish = g_unix_input_stream_close_finish;
143 * GUnixInputStream:fd:
145 * The file descriptor that the stream reads from.
149 g_object_class_install_property (gobject_class,
151 g_param_spec_int ("fd",
152 P_("File descriptor"),
153 P_("The file descriptor to read from"),
154 G_MININT, G_MAXINT, -1,
155 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
158 * GUnixInputStream:close-fd:
160 * Whether to close the file descriptor when the stream is closed.
164 g_object_class_install_property (gobject_class,
166 g_param_spec_boolean ("close-fd",
167 P_("Close file descriptor"),
168 P_("Whether to close the file descriptor when the stream is closed"),
170 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
174 g_unix_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface)
176 iface->can_poll = g_unix_input_stream_pollable_can_poll;
177 iface->is_readable = g_unix_input_stream_pollable_is_readable;
178 iface->create_source = g_unix_input_stream_pollable_create_source;
182 g_unix_input_stream_file_descriptor_based_iface_init (GFileDescriptorBasedIface *iface)
184 iface->get_fd = (int (*) (GFileDescriptorBased *))g_unix_input_stream_get_fd;
188 g_unix_input_stream_set_property (GObject *object,
193 GUnixInputStream *unix_stream;
195 unix_stream = G_UNIX_INPUT_STREAM (object);
200 unix_stream->priv->fd = g_value_get_int (value);
201 if (lseek (unix_stream->priv->fd, 0, SEEK_CUR) == -1 && errno == ESPIPE)
202 unix_stream->priv->is_pipe_or_socket = TRUE;
204 unix_stream->priv->is_pipe_or_socket = FALSE;
207 unix_stream->priv->close_fd = g_value_get_boolean (value);
210 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
216 g_unix_input_stream_get_property (GObject *object,
221 GUnixInputStream *unix_stream;
223 unix_stream = G_UNIX_INPUT_STREAM (object);
228 g_value_set_int (value, unix_stream->priv->fd);
231 g_value_set_boolean (value, unix_stream->priv->close_fd);
234 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
239 g_unix_input_stream_init (GUnixInputStream *unix_stream)
241 unix_stream->priv = g_unix_input_stream_get_private (unix_stream);
242 unix_stream->priv->fd = -1;
243 unix_stream->priv->close_fd = TRUE;
247 * g_unix_input_stream_new:
248 * @fd: a UNIX file descriptor
249 * @close_fd: %TRUE to close the file descriptor when done
251 * Creates a new #GUnixInputStream for the given @fd.
253 * If @close_fd is %TRUE, the file descriptor will be closed
254 * when the stream is closed.
256 * Returns: a new #GUnixInputStream
259 g_unix_input_stream_new (gint fd,
262 GUnixInputStream *stream;
264 g_return_val_if_fail (fd != -1, NULL);
266 stream = g_object_new (G_TYPE_UNIX_INPUT_STREAM,
268 "close-fd", close_fd,
271 return G_INPUT_STREAM (stream);
275 * g_unix_input_stream_set_close_fd:
276 * @stream: a #GUnixInputStream
277 * @close_fd: %TRUE to close the file descriptor when done
279 * Sets whether the file descriptor of @stream shall be closed
280 * when the stream is closed.
285 g_unix_input_stream_set_close_fd (GUnixInputStream *stream,
288 g_return_if_fail (G_IS_UNIX_INPUT_STREAM (stream));
290 close_fd = close_fd != FALSE;
291 if (stream->priv->close_fd != close_fd)
293 stream->priv->close_fd = close_fd;
294 g_object_notify (G_OBJECT (stream), "close-fd");
299 * g_unix_input_stream_get_close_fd:
300 * @stream: a #GUnixInputStream
302 * Returns whether the file descriptor of @stream will be
303 * closed when the stream is closed.
305 * Return value: %TRUE if the file descriptor is closed when done
310 g_unix_input_stream_get_close_fd (GUnixInputStream *stream)
312 g_return_val_if_fail (G_IS_UNIX_INPUT_STREAM (stream), FALSE);
314 return stream->priv->close_fd;
318 * g_unix_input_stream_get_fd:
319 * @stream: a #GUnixInputStream
321 * Return the UNIX file descriptor that the stream reads from.
323 * Return value: The file descriptor of @stream
328 g_unix_input_stream_get_fd (GUnixInputStream *stream)
330 g_return_val_if_fail (G_IS_UNIX_INPUT_STREAM (stream), -1);
332 return stream->priv->fd;
336 g_unix_input_stream_read (GInputStream *stream,
339 GCancellable *cancellable,
342 GUnixInputStream *unix_stream;
348 unix_stream = G_UNIX_INPUT_STREAM (stream);
350 poll_fds[0].fd = unix_stream->priv->fd;
351 poll_fds[0].events = G_IO_IN;
352 if (unix_stream->priv->is_pipe_or_socket &&
353 g_cancellable_make_pollfd (cancellable, &poll_fds[1]))
360 poll_fds[0].revents = poll_fds[1].revents = 0;
362 poll_ret = g_poll (poll_fds, nfds, -1);
363 while (poll_ret == -1 && errno == EINTR);
369 g_set_error (error, G_IO_ERROR,
370 g_io_error_from_errno (errsv),
371 _("Error reading from file descriptor: %s"),
376 if (g_cancellable_set_error_if_cancelled (cancellable, error))
379 if (!poll_fds[0].revents)
382 res = read (unix_stream->priv->fd, buffer, count);
387 if (errsv == EINTR || errsv == EAGAIN)
390 g_set_error (error, G_IO_ERROR,
391 g_io_error_from_errno (errsv),
392 _("Error reading from file descriptor: %s"),
400 g_cancellable_release_fd (cancellable);
405 g_unix_input_stream_close (GInputStream *stream,
406 GCancellable *cancellable,
409 GUnixInputStream *unix_stream;
412 unix_stream = G_UNIX_INPUT_STREAM (stream);
414 if (!unix_stream->priv->close_fd)
417 /* This might block during the close. Doesn't seem to be a way to avoid it though. */
418 res = close (unix_stream->priv->fd);
423 g_set_error (error, G_IO_ERROR,
424 g_io_error_from_errno (errsv),
425 _("Error closing file descriptor: %s"),
433 g_unix_input_stream_skip_async (GInputStream *stream,
436 GCancellable *cancellable,
437 GAsyncReadyCallback callback,
440 g_warn_if_reached ();
441 /* TODO: Not implemented */
445 g_unix_input_stream_skip_finish (GInputStream *stream,
446 GAsyncResult *result,
449 g_warn_if_reached ();
451 /* TODO: Not implemented */
455 g_unix_input_stream_close_async (GInputStream *stream,
457 GCancellable *cancellable,
458 GAsyncReadyCallback callback,
462 GError *error = NULL;
464 task = g_task_new (stream, cancellable, callback, user_data);
465 g_task_set_priority (task, io_priority);
467 if (g_unix_input_stream_close (stream, cancellable, &error))
468 g_task_return_boolean (task, TRUE);
470 g_task_return_error (task, error);
471 g_object_unref (task);
475 g_unix_input_stream_close_finish (GInputStream *stream,
476 GAsyncResult *result,
479 g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
481 return g_task_propagate_boolean (G_TASK (result), error);
485 g_unix_input_stream_pollable_can_poll (GPollableInputStream *stream)
487 return G_UNIX_INPUT_STREAM (stream)->priv->is_pipe_or_socket;
491 g_unix_input_stream_pollable_is_readable (GPollableInputStream *stream)
493 GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
497 poll_fd.fd = unix_stream->priv->fd;
498 poll_fd.events = G_IO_IN;
502 result = g_poll (&poll_fd, 1, 0);
503 while (result == -1 && errno == EINTR);
505 return poll_fd.revents != 0;
509 g_unix_input_stream_pollable_create_source (GPollableInputStream *stream,
510 GCancellable *cancellable)
512 GUnixInputStream *unix_stream = G_UNIX_INPUT_STREAM (stream);
513 GSource *inner_source, *pollable_source;
515 pollable_source = g_pollable_source_new (G_OBJECT (stream));
517 inner_source = _g_fd_source_new (unix_stream->priv->fd, G_IO_IN, cancellable);
518 g_source_set_dummy_callback (inner_source);
519 g_source_add_child_source (pollable_source, inner_source);
520 g_source_unref (inner_source);
522 return pollable_source;