1 /* Unix pipe-to-self. This is a utility module for tests, not a test.
2 *
3 * Copyright © 2008-2010 Red Hat, Inc.
4 * Copyright © 2011 Nokia Corporation
5 *
6 * SPDX-License-Identifier: LGPL-2.1-or-later
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General
19 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 *
21 * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
22 */
23
24 #include <errno.h>
25 #include <unistd.h>
26
27 #include <gio/gio.h>
28
29 #include "test-io-stream.h"
30 #include "test-pipe-unix.h"
31
32 #ifdef G_OS_UNIX
33 # include <gio/gunixinputstream.h>
34 # include <gio/gunixoutputstream.h>
35 #else
36 # error This module only exists on Unix
37 #endif
38
39 /**
40 * test_pipe:
41 * @is: (out) (optional): used to return a #GInputStream
42 * @os: (out) (optional): used to return a #GOutputStream
43 * @error: used to raise an error
44 *
45 * Return a "pipe to self" connecting @is to @os. This can be used
46 * as a unidirectional pipe to or from a child process, for instance.
47 *
48 * See test_bidi_pipe() if you want to emulate a bidirectional pipe
49 * via a pair of unidirectional pipes.
50 *
51 * Returns: %TRUE on success
52 */
53 gboolean
54 test_pipe (GInputStream **is,
55 GOutputStream **os,
56 GError **error)
57 {
58 int pipefd[2];
59 int ret;
60
61 ret = pipe (pipefd);
62
63 if (ret != 0)
64 {
65 int e = errno;
66
67 g_set_error (error, G_IO_ERROR, g_io_error_from_errno (e),
68 "%s", g_strerror (e));
69 return FALSE;
70 }
71
72 if (is != NULL)
73 *is = g_unix_input_stream_new (pipefd[0], TRUE);
74 else
75 close (pipefd[0]);
76
77 if (os != NULL)
78 *os = g_unix_output_stream_new (pipefd[1], TRUE);
79 else
80 close (pipefd[1]);
81
82 return TRUE;
83 }
84
85 /**
86 * test_bidi_pipe:
87 * @left: (out) (optional): used to return one #GIOStream
88 * @right: (out) (optional): used to return the other #GIOStream
89 * @error: used to raise an error
90 *
91 * Return two #GIOStreams connected to each other with pipes.
92 * The "left" input stream is connected by a unidirectional pipe
93 * to the "right" output stream, and vice versa. This can be used
94 * as a bidirectional pipe to a child process, for instance.
95 *
96 * See test_pipe() if you only need a one-way pipe.
97 *
98 * Returns: %TRUE on success
99 */
100 gboolean
101 test_bidi_pipe (GIOStream **left,
102 GIOStream **right,
103 GError **error)
104 {
105 GInputStream *left_in = NULL;
106 GOutputStream *left_out = NULL;
107 GInputStream *right_in = NULL;
108 GOutputStream *right_out = NULL;
109 gboolean ret = FALSE;
110
111 if (!test_pipe (&left_in, &right_out, error))
112 goto out;
113
114 if (!test_pipe (&right_in, &left_out, error))
115 goto out;
116
117 if (left != NULL)
118 *left = test_io_stream_new (left_in, left_out);
119
120 if (right != NULL)
121 *right = test_io_stream_new (right_in, right_out);
122
123 ret = TRUE;
124
125 out:
126 g_clear_object (&left_in);
127 g_clear_object (&left_out);
128 g_clear_object (&right_in);
129 g_clear_object (&right_out);
130 return ret;
131 }