Branch data Line data Source code
1 : : /* GLIB - Library of useful routines for C programming
2 : : * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 : : *
4 : : * giochannel.c: IO Channel abstraction
5 : : * Copyright 1998 Owen Taylor
6 : : *
7 : : * SPDX-License-Identifier: LGPL-2.1-or-later
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : * This library is distributed in the hope that it will be useful,
15 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : : * Lesser General Public License for more details.
18 : : *
19 : : * You should have received a copy of the GNU Lesser General Public
20 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 : : */
22 : :
23 : : /*
24 : : * Modified by the GLib Team and others 1997-2000. See the AUTHORS
25 : : * file for a list of people on the GLib Team. See the ChangeLog
26 : : * files for a list of changes. These files are distributed with
27 : : * GLib at ftp://ftp.gtk.org/pub/gtk/.
28 : : */
29 : :
30 : : /*
31 : : * MT safe
32 : : */
33 : :
34 : : #include "config.h"
35 : :
36 : : #include <string.h>
37 : : #include <errno.h>
38 : :
39 : : #include "giochannel.h"
40 : :
41 : : #include "gstrfuncs.h"
42 : : #include "gtestutils.h"
43 : : #include "glibintl.h"
44 : :
45 : :
46 : : /**
47 : : * GIOChannel:
48 : : *
49 : : * The `GIOChannel` data type aims to provide a portable method for
50 : : * using file descriptors, pipes, and sockets, and integrating them
51 : : * into the main event loop (see [struct@GLib.MainContext]). Currently,
52 : : * full support is available on UNIX platforms; support for Windows
53 : : * is only partially complete.
54 : : *
55 : : * To create a new `GIOChannel` on UNIX systems use
56 : : * [ctor@GLib.IOChannel.unix_new]. This works for plain file descriptors,
57 : : * pipes and sockets. Alternatively, a channel can be created for a
58 : : * file in a system independent manner using [ctor@GLib.IOChannel.new_file].
59 : : *
60 : : * Once a `GIOChannel` has been created, it can be used in a generic
61 : : * manner with the functions [method@GLib.IOChannel.read_chars],
62 : : * [method@GLib.IOChannel.write_chars], [method@GLib.IOChannel.seek_position],
63 : : * and [method@GLib.IOChannel.shutdown].
64 : : *
65 : : * To add a `GIOChannel` to the main event loop, use [func@GLib.io_add_watch] or
66 : : * [func@GLib.io_add_watch_full]. Here you specify which events you are
67 : : * interested in on the `GIOChannel`, and provide a function to be called
68 : : * whenever these events occur.
69 : : *
70 : : * `GIOChannel` instances are created with an initial reference count of 1.
71 : : * [method@GLib.IOChannel.ref] and [method@GLib.IOChannel.unref] can be used to
72 : : * increment or decrement the reference count respectively. When the
73 : : * reference count falls to 0, the `GIOChannel` is freed. (Though it
74 : : * isn’t closed automatically, unless it was created using
75 : : * [ctor@GLib.IOChannel.new_file].) Using [func@GLib.io_add_watch] or
76 : : * [func@GLib.io_add_watch_full] increments a channel’s reference count.
77 : : *
78 : : * The new functions [method@GLib.IOChannel.read_chars],
79 : : * [method@GLib.IOChannel.read_line], [method@GLib.IOChannel.read_line_string],
80 : : * [method@GLib.IOChannel.read_to_end], [method@GLib.IOChannel.write_chars],
81 : : * [method@GLib.IOChannel.seek_position], and [method@GLib.IOChannel.flush]
82 : : * should not be mixed with the deprecated functions
83 : : * [method@GLib.IOChannel.read], [method@GLib.IOChannel.write], and
84 : : * [method@GLib.IOChannel.seek] on the same channel.
85 : : **/
86 : :
87 : : /**
88 : : * GIOFuncs:
89 : : * @io_read: reads raw bytes from the channel. This is called from
90 : : * various functions such as g_io_channel_read_chars() to
91 : : * read raw bytes from the channel. Encoding and buffering
92 : : * issues are dealt with at a higher level.
93 : : * @io_write: writes raw bytes to the channel. This is called from
94 : : * various functions such as g_io_channel_write_chars() to
95 : : * write raw bytes to the channel. Encoding and buffering
96 : : * issues are dealt with at a higher level.
97 : : * @io_seek: (optional): seeks the channel. This is called from
98 : : * g_io_channel_seek() on channels that support it.
99 : : * @io_close: closes the channel. This is called from
100 : : * g_io_channel_close() after flushing the buffers.
101 : : * @io_create_watch: creates a watch on the channel. This call
102 : : * corresponds directly to g_io_create_watch().
103 : : * @io_free: called from g_io_channel_unref() when the channel needs to
104 : : * be freed. This function must free the memory associated
105 : : * with the channel, including freeing the #GIOChannel
106 : : * structure itself. The channel buffers have been flushed
107 : : * and possibly @io_close has been called by the time this
108 : : * function is called.
109 : : * @io_set_flags: sets the #GIOFlags on the channel. This is called
110 : : * from g_io_channel_set_flags() with all flags except
111 : : * for %G_IO_FLAG_APPEND and %G_IO_FLAG_NONBLOCK masked
112 : : * out.
113 : : * @io_get_flags: gets the #GIOFlags for the channel. This function
114 : : * need only return the %G_IO_FLAG_APPEND and
115 : : * %G_IO_FLAG_NONBLOCK flags; g_io_channel_get_flags()
116 : : * automatically adds the others as appropriate.
117 : : *
118 : : * A table of functions used to handle different types of #GIOChannel
119 : : * in a generic way.
120 : : **/
121 : :
122 : : /**
123 : : * GIOStatus:
124 : : * @G_IO_STATUS_ERROR: An error occurred.
125 : : * @G_IO_STATUS_NORMAL: Success.
126 : : * @G_IO_STATUS_EOF: End of file.
127 : : * @G_IO_STATUS_AGAIN: Resource temporarily unavailable.
128 : : *
129 : : * Statuses returned by most of the #GIOFuncs functions.
130 : : **/
131 : :
132 : : /**
133 : : * GIOError:
134 : : * @G_IO_ERROR_NONE: no error
135 : : * @G_IO_ERROR_AGAIN: an EAGAIN error occurred
136 : : * @G_IO_ERROR_INVAL: an EINVAL error occurred
137 : : * @G_IO_ERROR_UNKNOWN: another error occurred
138 : : *
139 : : * #GIOError is only used by the deprecated functions
140 : : * g_io_channel_read(), g_io_channel_write(), and g_io_channel_seek().
141 : : **/
142 : :
143 : : #define G_IO_NICE_BUF_SIZE 1024
144 : :
145 : : /* This needs to be as wide as the largest character in any possible encoding */
146 : : #define MAX_CHAR_SIZE 10
147 : :
148 : : /* Some simplifying macros, which reduce the need to worry whether the
149 : : * buffers have been allocated. These also make USE_BUF () an lvalue,
150 : : * which is used in g_io_channel_read_to_end ().
151 : : */
152 : : #define USE_BUF(channel) ((channel)->encoding ? (channel)->encoded_read_buf \
153 : : : (channel)->read_buf)
154 : : #define BUF_LEN(string) ((string) ? (string)->len : 0)
155 : :
156 : : static GIOError g_io_error_get_from_g_error (GIOStatus status,
157 : : GError *err);
158 : : static void g_io_channel_purge (GIOChannel *channel);
159 : : static GIOStatus g_io_channel_fill_buffer (GIOChannel *channel,
160 : : GError **err);
161 : : static GIOStatus g_io_channel_read_line_backend (GIOChannel *channel,
162 : : gsize *length,
163 : : gsize *terminator_pos,
164 : : GError **error);
165 : :
166 : : /**
167 : : * g_io_channel_init:
168 : : * @channel: a #GIOChannel
169 : : *
170 : : * Initializes a #GIOChannel struct.
171 : : *
172 : : * This is called by each of the above functions when creating a
173 : : * #GIOChannel, and so is not often needed by the application
174 : : * programmer (unless you are creating a new type of #GIOChannel).
175 : : */
176 : : void
177 : 990 : g_io_channel_init (GIOChannel *channel)
178 : : {
179 : 990 : channel->ref_count = 1;
180 : 990 : channel->encoding = g_strdup ("UTF-8");
181 : 990 : channel->line_term = NULL;
182 : 990 : channel->line_term_len = 0;
183 : 990 : channel->buf_size = G_IO_NICE_BUF_SIZE;
184 : 990 : channel->read_cd = (GIConv) -1;
185 : 990 : channel->write_cd = (GIConv) -1;
186 : 990 : channel->read_buf = NULL; /* Lazy allocate buffers */
187 : 990 : channel->encoded_read_buf = NULL;
188 : 990 : channel->write_buf = NULL;
189 : 990 : channel->partial_write_buf[0] = '\0';
190 : 990 : channel->use_buffer = TRUE;
191 : 990 : channel->do_encode = FALSE;
192 : 990 : channel->close_on_unref = FALSE;
193 : 990 : }
194 : :
195 : : /**
196 : : * g_io_channel_ref:
197 : : * @channel: a #GIOChannel
198 : : *
199 : : * Increments the reference count of a #GIOChannel.
200 : : *
201 : : * Returns: the @channel that was passed in (since 2.6)
202 : : */
203 : : GIOChannel *
204 : 753 : g_io_channel_ref (GIOChannel *channel)
205 : : {
206 : 753 : g_return_val_if_fail (channel != NULL, NULL);
207 : :
208 : 753 : g_atomic_int_inc (&channel->ref_count);
209 : :
210 : 753 : return channel;
211 : : }
212 : :
213 : : /**
214 : : * g_io_channel_unref:
215 : : * @channel: a #GIOChannel
216 : : *
217 : : * Decrements the reference count of a #GIOChannel.
218 : : */
219 : : void
220 : 1712 : g_io_channel_unref (GIOChannel *channel)
221 : : {
222 : : gboolean is_zero;
223 : :
224 : 1712 : g_return_if_fail (channel != NULL);
225 : :
226 : 1712 : is_zero = g_atomic_int_dec_and_test (&channel->ref_count);
227 : :
228 [ + + ]: 1712 : if (G_UNLIKELY (is_zero))
229 : : {
230 [ + + ]: 959 : if (channel->close_on_unref)
231 : 700 : g_io_channel_shutdown (channel, TRUE, NULL);
232 : : else
233 : 259 : g_io_channel_purge (channel);
234 : 959 : g_free (channel->encoding);
235 [ + + ]: 959 : if (channel->read_cd != (GIConv) -1)
236 : 1 : g_iconv_close (channel->read_cd);
237 [ - + ]: 959 : if (channel->write_cd != (GIConv) -1)
238 : 0 : g_iconv_close (channel->write_cd);
239 : 959 : g_free (channel->line_term);
240 [ + + ]: 959 : if (channel->read_buf)
241 : 194 : g_string_free (channel->read_buf, TRUE);
242 [ + + ]: 959 : if (channel->write_buf)
243 : 35 : g_string_free (channel->write_buf, TRUE);
244 [ + + ]: 959 : if (channel->encoded_read_buf)
245 : 135 : g_string_free (channel->encoded_read_buf, TRUE);
246 : 959 : channel->funcs->io_free (channel);
247 : : }
248 : : }
249 : :
250 : : static GIOError
251 : 426 : g_io_error_get_from_g_error (GIOStatus status,
252 : : GError *err)
253 : : {
254 [ + - - - ]: 426 : switch (status)
255 : : {
256 : 426 : case G_IO_STATUS_NORMAL:
257 : : case G_IO_STATUS_EOF:
258 : 426 : return G_IO_ERROR_NONE;
259 : 0 : case G_IO_STATUS_AGAIN:
260 : 0 : return G_IO_ERROR_AGAIN;
261 : 0 : case G_IO_STATUS_ERROR:
262 : 0 : g_return_val_if_fail (err != NULL, G_IO_ERROR_UNKNOWN);
263 : :
264 [ # # ]: 0 : if (err->domain != G_IO_CHANNEL_ERROR)
265 : 0 : return G_IO_ERROR_UNKNOWN;
266 [ # # ]: 0 : switch (err->code)
267 : : {
268 : 0 : case G_IO_CHANNEL_ERROR_INVAL:
269 : 0 : return G_IO_ERROR_INVAL;
270 : 0 : default:
271 : 0 : return G_IO_ERROR_UNKNOWN;
272 : : }
273 : 0 : default:
274 : : g_assert_not_reached ();
275 : : }
276 : : }
277 : :
278 : : /**
279 : : * g_io_channel_read:
280 : : * @channel: a #GIOChannel
281 : : * @buf: a buffer to read the data into (which should be at least
282 : : * count bytes long)
283 : : * @count: the number of bytes to read from the #GIOChannel
284 : : * @bytes_read: returns the number of bytes actually read
285 : : *
286 : : * Reads data from a #GIOChannel.
287 : : *
288 : : * Returns: %G_IO_ERROR_NONE if the operation was successful.
289 : : *
290 : : * Deprecated:2.2: Use g_io_channel_read_chars() instead.
291 : : **/
292 : : GIOError
293 : 426 : g_io_channel_read (GIOChannel *channel,
294 : : gchar *buf,
295 : : gsize count,
296 : : gsize *bytes_read)
297 : : {
298 : 426 : GError *err = NULL;
299 : : GIOError error;
300 : : GIOStatus status;
301 : :
302 : 426 : g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
303 : 426 : g_return_val_if_fail (bytes_read != NULL, G_IO_ERROR_UNKNOWN);
304 : :
305 [ - + ]: 426 : if (count == 0)
306 : : {
307 [ # # ]: 0 : if (bytes_read)
308 : 0 : *bytes_read = 0;
309 : 0 : return G_IO_ERROR_NONE;
310 : : }
311 : :
312 : 426 : g_return_val_if_fail (buf != NULL, G_IO_ERROR_UNKNOWN);
313 : :
314 : 426 : status = channel->funcs->io_read (channel, buf, count, bytes_read, &err);
315 : :
316 : 426 : error = g_io_error_get_from_g_error (status, err);
317 : :
318 [ - + ]: 426 : if (err)
319 : 0 : g_error_free (err);
320 : :
321 : 426 : return error;
322 : : }
323 : :
324 : : /**
325 : : * g_io_channel_write:
326 : : * @channel: a #GIOChannel
327 : : * @buf: the buffer containing the data to write
328 : : * @count: the number of bytes to write
329 : : * @bytes_written: the number of bytes actually written
330 : : *
331 : : * Writes data to a #GIOChannel.
332 : : *
333 : : * Returns: %G_IO_ERROR_NONE if the operation was successful.
334 : : *
335 : : * Deprecated:2.2: Use g_io_channel_write_chars() instead.
336 : : **/
337 : : GIOError
338 : 0 : g_io_channel_write (GIOChannel *channel,
339 : : const gchar *buf,
340 : : gsize count,
341 : : gsize *bytes_written)
342 : : {
343 : 0 : GError *err = NULL;
344 : : GIOError error;
345 : : GIOStatus status;
346 : :
347 : 0 : g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
348 : 0 : g_return_val_if_fail (bytes_written != NULL, G_IO_ERROR_UNKNOWN);
349 : :
350 : 0 : status = channel->funcs->io_write (channel, buf, count, bytes_written, &err);
351 : :
352 : 0 : error = g_io_error_get_from_g_error (status, err);
353 : :
354 [ # # ]: 0 : if (err)
355 : 0 : g_error_free (err);
356 : :
357 : 0 : return error;
358 : : }
359 : :
360 : : /**
361 : : * g_io_channel_seek:
362 : : * @channel: a #GIOChannel
363 : : * @offset: an offset, in bytes, which is added to the position specified
364 : : * by @type
365 : : * @type: the position in the file, which can be %G_SEEK_CUR (the current
366 : : * position), %G_SEEK_SET (the start of the file), or %G_SEEK_END
367 : : * (the end of the file)
368 : : *
369 : : * Sets the current position in the #GIOChannel, similar to the standard
370 : : * library function fseek().
371 : : *
372 : : * Returns: %G_IO_ERROR_NONE if the operation was successful.
373 : : *
374 : : * Deprecated:2.2: Use g_io_channel_seek_position() instead.
375 : : **/
376 : : GIOError
377 : 0 : g_io_channel_seek (GIOChannel *channel,
378 : : gint64 offset,
379 : : GSeekType type)
380 : : {
381 : 0 : GError *err = NULL;
382 : : GIOError error;
383 : : GIOStatus status;
384 : :
385 : 0 : g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
386 : 0 : g_return_val_if_fail (channel->is_seekable, G_IO_ERROR_UNKNOWN);
387 : :
388 [ # # ]: 0 : switch (type)
389 : : {
390 : 0 : case G_SEEK_CUR:
391 : : case G_SEEK_SET:
392 : : case G_SEEK_END:
393 : 0 : break;
394 : 0 : default:
395 : 0 : g_warning ("g_io_channel_seek: unknown seek type");
396 : 0 : return G_IO_ERROR_UNKNOWN;
397 : : }
398 : :
399 : 0 : status = channel->funcs->io_seek (channel, offset, type, &err);
400 : :
401 : 0 : error = g_io_error_get_from_g_error (status, err);
402 : :
403 [ # # ]: 0 : if (err)
404 : 0 : g_error_free (err);
405 : :
406 : 0 : return error;
407 : : }
408 : :
409 : : /* The function g_io_channel_new_file() is prototyped in both
410 : : * giounix.c and giowin32.c, so we stick its documentation here.
411 : : */
412 : :
413 : : /**
414 : : * g_io_channel_new_file:
415 : : * @filename: (type filename): A string containing the name of a file
416 : : * @mode: One of "r", "w", "a", "r+", "w+", "a+". These have
417 : : * the same meaning as in fopen()
418 : : * @error: A location to return an error of type %G_FILE_ERROR
419 : : *
420 : : * Open a file @filename as a #GIOChannel using mode @mode. This
421 : : * channel will be closed when the last reference to it is dropped,
422 : : * so there is no need to call g_io_channel_close() (though doing
423 : : * so will not cause problems, as long as no attempt is made to
424 : : * access the channel after it is closed).
425 : : *
426 : : * Returns: A #GIOChannel on success, %NULL on failure.
427 : : **/
428 : :
429 : : /**
430 : : * g_io_channel_close:
431 : : * @channel: A #GIOChannel
432 : : *
433 : : * Close an IO channel. Any pending data to be written will be
434 : : * flushed, ignoring errors. The channel will not be freed until the
435 : : * last reference is dropped using g_io_channel_unref().
436 : : *
437 : : * Deprecated:2.2: Use g_io_channel_shutdown() instead.
438 : : **/
439 : : void
440 : 0 : g_io_channel_close (GIOChannel *channel)
441 : : {
442 : 0 : GError *err = NULL;
443 : :
444 : 0 : g_return_if_fail (channel != NULL);
445 : :
446 : 0 : g_io_channel_purge (channel);
447 : :
448 : 0 : channel->funcs->io_close (channel, &err);
449 : :
450 [ # # ]: 0 : if (err)
451 : : { /* No way to return the error */
452 : 0 : g_warning ("Error closing channel: %s", err->message);
453 : 0 : g_error_free (err);
454 : : }
455 : :
456 : 0 : channel->close_on_unref = FALSE; /* Because we already did */
457 : 0 : channel->is_readable = FALSE;
458 : 0 : channel->is_writeable = FALSE;
459 : 0 : channel->is_seekable = FALSE;
460 : : }
461 : :
462 : : /**
463 : : * g_io_channel_shutdown:
464 : : * @channel: a #GIOChannel
465 : : * @flush: if %TRUE, flush pending
466 : : * @err: location to store a #GIOChannelError
467 : : *
468 : : * Close an IO channel. Any pending data to be written will be
469 : : * flushed if @flush is %TRUE. The channel will not be freed until the
470 : : * last reference is dropped using g_io_channel_unref().
471 : : *
472 : : * Returns: the status of the operation.
473 : : **/
474 : : GIOStatus
475 : 790 : g_io_channel_shutdown (GIOChannel *channel,
476 : : gboolean flush,
477 : : GError **err)
478 : : {
479 : : GIOStatus status, result;
480 : 790 : GError *tmperr = NULL;
481 : :
482 : 790 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
483 : 790 : g_return_val_if_fail (err == NULL || *err == NULL, G_IO_STATUS_ERROR);
484 : :
485 [ + + + + ]: 790 : if (channel->write_buf && channel->write_buf->len > 0)
486 : : {
487 [ + - ]: 1 : if (flush)
488 : : {
489 : : GIOFlags flags;
490 : :
491 : : /* Set the channel to blocking, to avoid a busy loop
492 : : */
493 : 1 : flags = g_io_channel_get_flags (channel);
494 : : /* Ignore any errors here, they're irrelevant */
495 : 1 : g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL);
496 : :
497 : 1 : result = g_io_channel_flush (channel, &tmperr);
498 : : }
499 : : else
500 : 0 : result = G_IO_STATUS_NORMAL;
501 : :
502 : 1 : g_string_truncate(channel->write_buf, 0);
503 : : }
504 : : else
505 : 789 : result = G_IO_STATUS_NORMAL;
506 : :
507 [ - + ]: 790 : if (channel->partial_write_buf[0] != '\0')
508 : : {
509 [ # # ]: 0 : if (flush)
510 : 0 : g_warning ("Partial character at end of write buffer not flushed.");
511 : 0 : channel->partial_write_buf[0] = '\0';
512 : : }
513 : :
514 : 790 : status = channel->funcs->io_close (channel, err);
515 : :
516 : 790 : channel->close_on_unref = FALSE; /* Because we already did */
517 : 790 : channel->is_readable = FALSE;
518 : 790 : channel->is_writeable = FALSE;
519 : 790 : channel->is_seekable = FALSE;
520 : :
521 [ - + ]: 790 : if (status != G_IO_STATUS_NORMAL)
522 : : {
523 : 0 : g_clear_error (&tmperr);
524 : 0 : return status;
525 : : }
526 [ - + ]: 790 : else if (result != G_IO_STATUS_NORMAL)
527 : : {
528 : 0 : g_propagate_error (err, tmperr);
529 : 0 : return result;
530 : : }
531 : : else
532 : 790 : return G_IO_STATUS_NORMAL;
533 : : }
534 : :
535 : : /* This function is used for the final flush on close or unref */
536 : : static void
537 : 259 : g_io_channel_purge (GIOChannel *channel)
538 : : {
539 : 259 : GError *err = NULL;
540 : : GIOStatus status G_GNUC_UNUSED;
541 : :
542 : 259 : g_return_if_fail (channel != NULL);
543 : :
544 [ + + + - ]: 259 : if (channel->write_buf && channel->write_buf->len > 0)
545 : : {
546 : : GIOFlags flags;
547 : :
548 : : /* Set the channel to blocking, to avoid a busy loop
549 : : */
550 : 33 : flags = g_io_channel_get_flags (channel);
551 : 33 : g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL);
552 : :
553 : 33 : status = g_io_channel_flush (channel, &err);
554 : :
555 [ - + ]: 33 : if (err)
556 : : { /* No way to return the error */
557 : 0 : g_warning ("Error flushing string: %s", err->message);
558 : 0 : g_error_free (err);
559 : : }
560 : : }
561 : :
562 : : /* Flush these in case anyone tries to close without unrefing */
563 : :
564 [ + + ]: 259 : if (channel->read_buf)
565 : 191 : g_string_truncate (channel->read_buf, 0);
566 [ + + ]: 259 : if (channel->write_buf)
567 : 33 : g_string_truncate (channel->write_buf, 0);
568 [ + + ]: 259 : if (channel->encoding)
569 : : {
570 [ + + ]: 142 : if (channel->encoded_read_buf)
571 : 133 : g_string_truncate (channel->encoded_read_buf, 0);
572 : :
573 [ - + ]: 142 : if (channel->partial_write_buf[0] != '\0')
574 : : {
575 : 0 : g_warning ("Partial character at end of write buffer not flushed.");
576 : 0 : channel->partial_write_buf[0] = '\0';
577 : : }
578 : : }
579 : : }
580 : :
581 : : /**
582 : : * g_io_create_watch:
583 : : * @channel: a #GIOChannel to watch
584 : : * @condition: conditions to watch for
585 : : *
586 : : * Creates a #GSource that's dispatched when @condition is met for the
587 : : * given @channel. For example, if condition is %G_IO_IN, the source will
588 : : * be dispatched when there's data available for reading.
589 : : *
590 : : * The callback function invoked by the #GSource should be added with
591 : : * g_source_set_callback(), but it has type #GIOFunc (not #GSourceFunc).
592 : : *
593 : : * g_io_add_watch() is a simpler interface to this same functionality, for
594 : : * the case where you want to add the source to the default main loop context
595 : : * at the default priority.
596 : : *
597 : : * On Windows, polling a #GSource created to watch a channel for a socket
598 : : * puts the socket in non-blocking mode. This is a side-effect of the
599 : : * implementation and unavoidable.
600 : : *
601 : : * Returns: a new #GSource
602 : : */
603 : : GSource *
604 : 752 : g_io_create_watch (GIOChannel *channel,
605 : : GIOCondition condition)
606 : : {
607 : 752 : g_return_val_if_fail (channel != NULL, NULL);
608 : :
609 : 752 : return channel->funcs->io_create_watch (channel, condition);
610 : : }
611 : :
612 : : /**
613 : : * g_io_add_watch_full: (rename-to g_io_add_watch)
614 : : * @channel: a #GIOChannel
615 : : * @priority: the priority of the #GIOChannel source
616 : : * @condition: the condition to watch for
617 : : * @func: the function to call when the condition is satisfied
618 : : * @user_data: user data to pass to @func
619 : : * @notify: the function to call when the source is removed
620 : : *
621 : : * Adds the #GIOChannel into the default main loop context
622 : : * with the given priority.
623 : : *
624 : : * This internally creates a main loop source using g_io_create_watch()
625 : : * and attaches it to the main loop context with g_source_attach().
626 : : * You can do these steps manually if you need greater control.
627 : : *
628 : : * Returns: the event source id
629 : : */
630 : : guint
631 : 11 : g_io_add_watch_full (GIOChannel *channel,
632 : : gint priority,
633 : : GIOCondition condition,
634 : : GIOFunc func,
635 : : gpointer user_data,
636 : : GDestroyNotify notify)
637 : : {
638 : : GSource *source;
639 : : guint id;
640 : :
641 : 11 : g_return_val_if_fail (channel != NULL, 0);
642 : :
643 : 11 : source = g_io_create_watch (channel, condition);
644 : :
645 [ + + ]: 11 : if (priority != G_PRIORITY_DEFAULT)
646 : 1 : g_source_set_priority (source, priority);
647 : 11 : g_source_set_callback (source, (GSourceFunc)func, user_data, notify);
648 : :
649 : 11 : id = g_source_attach (source, NULL);
650 : 11 : g_source_unref (source);
651 : :
652 : 11 : return id;
653 : : }
654 : :
655 : : /**
656 : : * g_io_add_watch:
657 : : * @channel: a #GIOChannel
658 : : * @condition: the condition to watch for
659 : : * @func: the function to call when the condition is satisfied
660 : : * @user_data: user data to pass to @func
661 : : *
662 : : * Adds the #GIOChannel into the default main loop context
663 : : * with the default priority.
664 : : *
665 : : * Returns: the event source id
666 : : */
667 : : /**
668 : : * GIOFunc:
669 : : * @source: the #GIOChannel event source
670 : : * @condition: the condition which has been satisfied
671 : : * @data: user data set in g_io_add_watch() or g_io_add_watch_full()
672 : : *
673 : : * Specifies the type of function passed to g_io_add_watch() or
674 : : * g_io_add_watch_full(), which is called when the requested condition
675 : : * on a #GIOChannel is satisfied.
676 : : *
677 : : * Returns: the function should return %FALSE if the event source
678 : : * should be removed
679 : : **/
680 : : /**
681 : : * GIOCondition:
682 : : * @G_IO_IN: There is data to read.
683 : : * @G_IO_OUT: Data can be written (without blocking).
684 : : * @G_IO_PRI: There is urgent data to read.
685 : : * @G_IO_ERR: Error condition.
686 : : * @G_IO_HUP: Hung up (the connection has been broken, usually for
687 : : * pipes and sockets).
688 : : * @G_IO_NVAL: Invalid request. The file descriptor is not open.
689 : : *
690 : : * A bitwise combination representing a condition to watch for on an
691 : : * event source.
692 : : **/
693 : : guint
694 : 4 : g_io_add_watch (GIOChannel *channel,
695 : : GIOCondition condition,
696 : : GIOFunc func,
697 : : gpointer user_data)
698 : : {
699 : 4 : return g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, condition, func, user_data, NULL);
700 : : }
701 : :
702 : : /**
703 : : * g_io_channel_get_buffer_condition:
704 : : * @channel: A #GIOChannel
705 : : *
706 : : * This function returns a #GIOCondition depending on whether there
707 : : * is data to be read/space to write data in the internal buffers in
708 : : * the #GIOChannel. Only the flags %G_IO_IN and %G_IO_OUT may be set.
709 : : *
710 : : * Returns: A #GIOCondition
711 : : **/
712 : : GIOCondition
713 : 12246 : g_io_channel_get_buffer_condition (GIOChannel *channel)
714 : : {
715 : 12246 : GIOCondition condition = 0;
716 : :
717 [ + + ]: 12246 : if (channel->encoding)
718 : : {
719 [ + + - + ]: 2745 : if (channel->encoded_read_buf && (channel->encoded_read_buf->len > 0))
720 : 0 : condition |= G_IO_IN; /* Only return if we have full characters */
721 : : }
722 : : else
723 : : {
724 [ - + - - ]: 9501 : if (channel->read_buf && (channel->read_buf->len > 0))
725 : 0 : condition |= G_IO_IN;
726 : : }
727 : :
728 [ - + - - ]: 12246 : if (channel->write_buf && (channel->write_buf->len < channel->buf_size))
729 : 0 : condition |= G_IO_OUT;
730 : :
731 : 12246 : return condition;
732 : : }
733 : :
734 : : /**
735 : : * g_io_channel_error_from_errno:
736 : : * @en: an `errno` error number, e.g. `EINVAL`
737 : : *
738 : : * Converts an `errno` error number to a #GIOChannelError.
739 : : *
740 : : * Returns: a #GIOChannelError error number, e.g.
741 : : * %G_IO_CHANNEL_ERROR_INVAL.
742 : : **/
743 : : GIOChannelError
744 : 0 : g_io_channel_error_from_errno (gint en)
745 : : {
746 : : #ifdef EAGAIN
747 : 0 : g_return_val_if_fail (en != EAGAIN, G_IO_CHANNEL_ERROR_FAILED);
748 : : #endif
749 : :
750 [ # # # # : 0 : switch (en)
# # # # #
# # # ]
751 : : {
752 : : #ifdef EBADF
753 : 0 : case EBADF:
754 : 0 : g_warning ("Invalid file descriptor.");
755 : 0 : return G_IO_CHANNEL_ERROR_FAILED;
756 : : #endif
757 : :
758 : : #ifdef EFAULT
759 : 0 : case EFAULT:
760 : 0 : g_warning ("Buffer outside valid address space.");
761 : 0 : return G_IO_CHANNEL_ERROR_FAILED;
762 : : #endif
763 : :
764 : : #ifdef EFBIG
765 : 0 : case EFBIG:
766 : 0 : return G_IO_CHANNEL_ERROR_FBIG;
767 : : #endif
768 : :
769 : : #ifdef EINTR
770 : : /* In general, we should catch EINTR before we get here,
771 : : * but close() is allowed to return EINTR by POSIX, so
772 : : * we need to catch it here; EINTR from close() is
773 : : * unrecoverable, because it's undefined whether
774 : : * the fd was actually closed or not, so we just return
775 : : * a generic error code.
776 : : */
777 : 0 : case EINTR:
778 : 0 : return G_IO_CHANNEL_ERROR_FAILED;
779 : : #endif
780 : :
781 : : #ifdef EINVAL
782 : 0 : case EINVAL:
783 : 0 : return G_IO_CHANNEL_ERROR_INVAL;
784 : : #endif
785 : :
786 : : #ifdef EIO
787 : 0 : case EIO:
788 : 0 : return G_IO_CHANNEL_ERROR_IO;
789 : : #endif
790 : :
791 : : #ifdef EISDIR
792 : 0 : case EISDIR:
793 : 0 : return G_IO_CHANNEL_ERROR_ISDIR;
794 : : #endif
795 : :
796 : : #ifdef ENOSPC
797 : 0 : case ENOSPC:
798 : 0 : return G_IO_CHANNEL_ERROR_NOSPC;
799 : : #endif
800 : :
801 : : #ifdef ENXIO
802 : 0 : case ENXIO:
803 : 0 : return G_IO_CHANNEL_ERROR_NXIO;
804 : : #endif
805 : :
806 : : #ifdef EOVERFLOW
807 : : #if EOVERFLOW != EFBIG
808 : 0 : case EOVERFLOW:
809 : 0 : return G_IO_CHANNEL_ERROR_OVERFLOW;
810 : : #endif
811 : : #endif
812 : :
813 : : #ifdef EPIPE
814 : 0 : case EPIPE:
815 : 0 : return G_IO_CHANNEL_ERROR_PIPE;
816 : : #endif
817 : :
818 : 0 : default:
819 : 0 : return G_IO_CHANNEL_ERROR_FAILED;
820 : : }
821 : : }
822 : :
823 : : /**
824 : : * g_io_channel_set_buffer_size:
825 : : * @channel: a #GIOChannel
826 : : * @size: the size of the buffer, or 0 to let GLib pick a good size
827 : : *
828 : : * Sets the buffer size.
829 : : **/
830 : : void
831 : 2 : g_io_channel_set_buffer_size (GIOChannel *channel,
832 : : gsize size)
833 : : {
834 : 2 : g_return_if_fail (channel != NULL);
835 : :
836 [ - + ]: 2 : if (size == 0)
837 : 0 : size = G_IO_NICE_BUF_SIZE;
838 : :
839 [ - + ]: 2 : if (size < MAX_CHAR_SIZE)
840 : 0 : size = MAX_CHAR_SIZE;
841 : :
842 : 2 : channel->buf_size = size;
843 : : }
844 : :
845 : : /**
846 : : * g_io_channel_get_buffer_size:
847 : : * @channel: a #GIOChannel
848 : : *
849 : : * Gets the buffer size.
850 : : *
851 : : * Returns: the size of the buffer.
852 : : **/
853 : : gsize
854 : 1 : g_io_channel_get_buffer_size (GIOChannel *channel)
855 : : {
856 : 1 : g_return_val_if_fail (channel != NULL, 0);
857 : :
858 : 1 : return channel->buf_size;
859 : : }
860 : :
861 : : /**
862 : : * g_io_channel_set_line_term:
863 : : * @channel: a #GIOChannel
864 : : * @line_term: (nullable): The line termination string. Use %NULL for
865 : : * autodetect. Autodetection breaks on "\n", "\r\n", "\r", "\0",
866 : : * and the Unicode paragraph separator. Autodetection should not be
867 : : * used for anything other than file-based channels.
868 : : * @length: The length of the termination string. If -1 is passed, the
869 : : * string is assumed to be nul-terminated. This option allows
870 : : * termination strings with embedded nuls.
871 : : *
872 : : * This sets the string that #GIOChannel uses to determine
873 : : * where in the file a line break occurs.
874 : : **/
875 : : void
876 : 2 : g_io_channel_set_line_term (GIOChannel *channel,
877 : : const gchar *line_term,
878 : : gint length)
879 : : {
880 : : guint length_unsigned;
881 : :
882 : 2 : g_return_if_fail (channel != NULL);
883 : 2 : g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */
884 : :
885 [ - + ]: 2 : if (line_term == NULL)
886 : 0 : length_unsigned = 0;
887 [ + + ]: 2 : else if (length >= 0)
888 : 1 : length_unsigned = (guint) length;
889 : : else
890 : : {
891 : : /* FIXME: We’re constrained by line_term_len being a guint here */
892 : 1 : gsize length_size = strlen (line_term);
893 : 1 : g_return_if_fail (length_size <= G_MAXUINT);
894 : 1 : length_unsigned = (guint) length_size;
895 : : }
896 : :
897 : 2 : g_free (channel->line_term);
898 [ + - ]: 2 : channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL;
899 : 2 : channel->line_term_len = length_unsigned;
900 : : }
901 : :
902 : : /**
903 : : * g_io_channel_get_line_term:
904 : : * @channel: a #GIOChannel
905 : : * @length: (out) (optional): a location to return the length of the line terminator
906 : : *
907 : : * This returns the string that #GIOChannel uses to determine
908 : : * where in the file a line break occurs. A value of %NULL
909 : : * indicates autodetection.
910 : : *
911 : : * Returns: The line termination string. This value
912 : : * is owned by GLib and must not be freed.
913 : : **/
914 : : const gchar *
915 : 2 : g_io_channel_get_line_term (GIOChannel *channel,
916 : : gint *length)
917 : : {
918 : 2 : g_return_val_if_fail (channel != NULL, NULL);
919 : :
920 [ + + ]: 2 : if (length)
921 : 1 : *length = channel->line_term_len;
922 : :
923 : 2 : return channel->line_term;
924 : : }
925 : :
926 : : /**
927 : : * g_io_channel_set_flags:
928 : : * @channel: a #GIOChannel
929 : : * @flags: the flags to set on the IO channel
930 : : * @error: A location to return an error of type #GIOChannelError
931 : : *
932 : : * Sets the (writeable) flags in @channel to (@flags & %G_IO_FLAG_SET_MASK).
933 : : *
934 : : * Returns: the status of the operation.
935 : : **/
936 : : /**
937 : : * GIOFlags:
938 : : * @G_IO_FLAG_NONE: no special flags set. Since: 2.74
939 : : * @G_IO_FLAG_APPEND: turns on append mode, corresponds to %O_APPEND
940 : : * (see the documentation of the UNIX open() syscall)
941 : : * @G_IO_FLAG_NONBLOCK: turns on nonblocking mode, corresponds to
942 : : * %O_NONBLOCK/%O_NDELAY (see the documentation of the UNIX open()
943 : : * syscall)
944 : : * @G_IO_FLAG_IS_READABLE: indicates that the io channel is readable.
945 : : * This flag cannot be changed.
946 : : * @G_IO_FLAG_IS_WRITABLE: indicates that the io channel is writable.
947 : : * This flag cannot be changed.
948 : : * @G_IO_FLAG_IS_WRITEABLE: a misspelled version of @G_IO_FLAG_IS_WRITABLE
949 : : * that existed before the spelling was fixed in GLib 2.30. It is kept
950 : : * here for compatibility reasons. Deprecated since 2.30
951 : : * @G_IO_FLAG_IS_SEEKABLE: indicates that the io channel is seekable,
952 : : * i.e. that g_io_channel_seek_position() can be used on it.
953 : : * This flag cannot be changed.
954 : : * @G_IO_FLAG_MASK: the mask that specifies all the valid flags.
955 : : * @G_IO_FLAG_GET_MASK: the mask of the flags that are returned from
956 : : * g_io_channel_get_flags()
957 : : * @G_IO_FLAG_SET_MASK: the mask of the flags that the user can modify
958 : : * with g_io_channel_set_flags()
959 : : *
960 : : * Specifies properties of a #GIOChannel. Some of the flags can only be
961 : : * read with g_io_channel_get_flags(), but not changed with
962 : : * g_io_channel_set_flags().
963 : : */
964 : : GIOStatus
965 : 40 : g_io_channel_set_flags (GIOChannel *channel,
966 : : GIOFlags flags,
967 : : GError **error)
968 : : {
969 : 40 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
970 : 40 : g_return_val_if_fail ((error == NULL) || (*error == NULL),
971 : : G_IO_STATUS_ERROR);
972 : :
973 : 40 : return (*channel->funcs->io_set_flags) (channel,
974 : 40 : flags & G_IO_FLAG_SET_MASK,
975 : : error);
976 : : }
977 : :
978 : : /**
979 : : * g_io_channel_get_flags:
980 : : * @channel: a #GIOChannel
981 : : *
982 : : * Gets the current flags for a #GIOChannel, including read-only
983 : : * flags such as %G_IO_FLAG_IS_READABLE.
984 : : *
985 : : * The values of the flags %G_IO_FLAG_IS_READABLE and %G_IO_FLAG_IS_WRITABLE
986 : : * are cached for internal use by the channel when it is created.
987 : : * If they should change at some later point (e.g. partial shutdown
988 : : * of a socket with the UNIX shutdown() function), the user
989 : : * should immediately call g_io_channel_get_flags() to update
990 : : * the internal values of these flags.
991 : : *
992 : : * Returns: the flags which are set on the channel
993 : : **/
994 : : GIOFlags
995 : 34 : g_io_channel_get_flags (GIOChannel *channel)
996 : : {
997 : : GIOFlags flags;
998 : :
999 : 34 : g_return_val_if_fail (channel != NULL, 0);
1000 : :
1001 : 34 : flags = (* channel->funcs->io_get_flags) (channel);
1002 : :
1003 : : /* Cross implementation code */
1004 : :
1005 [ + + ]: 34 : if (channel->is_seekable)
1006 : 8 : flags |= G_IO_FLAG_IS_SEEKABLE;
1007 [ + + ]: 34 : if (channel->is_readable)
1008 : 2 : flags |= G_IO_FLAG_IS_READABLE;
1009 [ + - ]: 34 : if (channel->is_writeable)
1010 : 34 : flags |= G_IO_FLAG_IS_WRITABLE;
1011 : :
1012 : 34 : return flags;
1013 : : }
1014 : :
1015 : : /**
1016 : : * g_io_channel_set_close_on_unref:
1017 : : * @channel: a #GIOChannel
1018 : : * @do_close: Whether to close the channel on the final unref of
1019 : : * the GIOChannel data structure.
1020 : : *
1021 : : * Whether to close the channel on the final unref of the #GIOChannel
1022 : : * data structure. The default value of this is %TRUE for channels
1023 : : * created by g_io_channel_new_file (), and %FALSE for all other channels.
1024 : : *
1025 : : * Setting this flag to %TRUE for a channel you have already closed
1026 : : * can cause problems when the final reference to the #GIOChannel is dropped.
1027 : : **/
1028 : : void
1029 : 756 : g_io_channel_set_close_on_unref (GIOChannel *channel,
1030 : : gboolean do_close)
1031 : : {
1032 : 756 : g_return_if_fail (channel != NULL);
1033 : :
1034 : 756 : channel->close_on_unref = do_close;
1035 : : }
1036 : :
1037 : : /**
1038 : : * g_io_channel_get_close_on_unref:
1039 : : * @channel: a #GIOChannel.
1040 : : *
1041 : : * Returns whether the file/socket/whatever associated with @channel
1042 : : * will be closed when @channel receives its final unref and is
1043 : : * destroyed. The default value of this is %TRUE for channels created
1044 : : * by g_io_channel_new_file (), and %FALSE for all other channels.
1045 : : *
1046 : : * Returns: %TRUE if the channel will be closed, %FALSE otherwise.
1047 : : **/
1048 : : gboolean
1049 : 1 : g_io_channel_get_close_on_unref (GIOChannel *channel)
1050 : : {
1051 : 1 : g_return_val_if_fail (channel != NULL, FALSE);
1052 : :
1053 : 1 : return channel->close_on_unref;
1054 : : }
1055 : :
1056 : : /**
1057 : : * g_io_channel_seek_position:
1058 : : * @channel: a #GIOChannel
1059 : : * @offset: The offset in bytes from the position specified by @type
1060 : : * @type: a #GSeekType. The type %G_SEEK_CUR is only allowed in those
1061 : : * cases where a call to g_io_channel_set_encoding ()
1062 : : * is allowed. See the documentation for
1063 : : * g_io_channel_set_encoding () for details.
1064 : : * @error: A location to return an error of type #GIOChannelError
1065 : : *
1066 : : * Replacement for g_io_channel_seek() with the new API.
1067 : : *
1068 : : * Returns: the status of the operation.
1069 : : **/
1070 : : /**
1071 : : * GSeekType:
1072 : : * @G_SEEK_CUR: the current position in the file.
1073 : : * @G_SEEK_SET: the start of the file.
1074 : : * @G_SEEK_END: the end of the file.
1075 : : *
1076 : : * An enumeration specifying the base position for a
1077 : : * g_io_channel_seek_position() operation.
1078 : : **/
1079 : : GIOStatus
1080 : 0 : g_io_channel_seek_position (GIOChannel *channel,
1081 : : gint64 offset,
1082 : : GSeekType type,
1083 : : GError **error)
1084 : : {
1085 : : GIOStatus status;
1086 : :
1087 : : /* For files, only one of the read and write buffers can contain data.
1088 : : * For sockets, both can contain data.
1089 : : */
1090 : :
1091 : 0 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
1092 : 0 : g_return_val_if_fail ((error == NULL) || (*error == NULL),
1093 : : G_IO_STATUS_ERROR);
1094 : 0 : g_return_val_if_fail (channel->is_seekable, G_IO_STATUS_ERROR);
1095 : :
1096 [ # # # ]: 0 : switch (type)
1097 : : {
1098 : 0 : case G_SEEK_CUR: /* The user is seeking relative to the head of the buffer */
1099 [ # # ]: 0 : if (channel->use_buffer)
1100 : : {
1101 [ # # # # ]: 0 : if (channel->do_encode && channel->encoded_read_buf
1102 [ # # ]: 0 : && channel->encoded_read_buf->len > 0)
1103 : : {
1104 : 0 : g_warning ("Seek type G_SEEK_CUR not allowed for this"
1105 : : " channel's encoding.");
1106 : 0 : return G_IO_STATUS_ERROR;
1107 : : }
1108 [ # # ]: 0 : if (channel->read_buf)
1109 : 0 : offset -= channel->read_buf->len;
1110 [ # # ]: 0 : if (channel->encoded_read_buf)
1111 : : {
1112 : 0 : g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode);
1113 : :
1114 : : /* If there's anything here, it's because the encoding is UTF-8,
1115 : : * so we can just subtract the buffer length, the same as for
1116 : : * the unencoded data.
1117 : : */
1118 : :
1119 : 0 : offset -= channel->encoded_read_buf->len;
1120 : : }
1121 : : }
1122 : 0 : break;
1123 : 0 : case G_SEEK_SET:
1124 : : case G_SEEK_END:
1125 : 0 : break;
1126 : 0 : default:
1127 : 0 : g_warning ("g_io_channel_seek_position: unknown seek type");
1128 : 0 : return G_IO_STATUS_ERROR;
1129 : : }
1130 : :
1131 [ # # ]: 0 : if (channel->use_buffer)
1132 : : {
1133 : 0 : status = g_io_channel_flush (channel, error);
1134 [ # # ]: 0 : if (status != G_IO_STATUS_NORMAL)
1135 : 0 : return status;
1136 : : }
1137 : :
1138 : 0 : status = channel->funcs->io_seek (channel, offset, type, error);
1139 : :
1140 [ # # # # ]: 0 : if ((status == G_IO_STATUS_NORMAL) && (channel->use_buffer))
1141 : : {
1142 [ # # ]: 0 : if (channel->read_buf)
1143 : 0 : g_string_truncate (channel->read_buf, 0);
1144 : :
1145 : : /* Conversion state no longer matches position in file */
1146 [ # # ]: 0 : if (channel->read_cd != (GIConv) -1)
1147 : 0 : g_iconv (channel->read_cd, NULL, NULL, NULL, NULL);
1148 [ # # ]: 0 : if (channel->write_cd != (GIConv) -1)
1149 : 0 : g_iconv (channel->write_cd, NULL, NULL, NULL, NULL);
1150 : :
1151 [ # # ]: 0 : if (channel->encoded_read_buf)
1152 : : {
1153 : 0 : g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode);
1154 : 0 : g_string_truncate (channel->encoded_read_buf, 0);
1155 : : }
1156 : :
1157 [ # # ]: 0 : if (channel->partial_write_buf[0] != '\0')
1158 : : {
1159 : 0 : g_warning ("Partial character at end of write buffer not flushed.");
1160 : 0 : channel->partial_write_buf[0] = '\0';
1161 : : }
1162 : : }
1163 : :
1164 : 0 : return status;
1165 : : }
1166 : :
1167 : : /**
1168 : : * g_io_channel_flush:
1169 : : * @channel: a #GIOChannel
1170 : : * @error: location to store an error of type #GIOChannelError
1171 : : *
1172 : : * Flushes the write buffer for the GIOChannel.
1173 : : *
1174 : : * Returns: the status of the operation: One of
1175 : : * %G_IO_STATUS_NORMAL, %G_IO_STATUS_AGAIN, or
1176 : : * %G_IO_STATUS_ERROR.
1177 : : **/
1178 : : GIOStatus
1179 : 154 : g_io_channel_flush (GIOChannel *channel,
1180 : : GError **error)
1181 : : {
1182 : : GIOStatus status;
1183 : 154 : gsize this_time = 1, bytes_written = 0;
1184 : :
1185 : 154 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
1186 : 154 : g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR);
1187 : :
1188 [ + - - + ]: 154 : if (channel->write_buf == NULL || channel->write_buf->len == 0)
1189 : 0 : return G_IO_STATUS_NORMAL;
1190 : :
1191 : : do
1192 : : {
1193 : 154 : g_assert (this_time > 0);
1194 : :
1195 : 154 : status = channel->funcs->io_write (channel,
1196 : 154 : channel->write_buf->str + bytes_written,
1197 : 154 : channel->write_buf->len - bytes_written,
1198 : : &this_time, error);
1199 : 154 : bytes_written += this_time;
1200 : : }
1201 : 154 : while ((bytes_written < channel->write_buf->len)
1202 [ - + - - ]: 154 : && (status == G_IO_STATUS_NORMAL));
1203 : :
1204 : 154 : g_string_erase (channel->write_buf, 0, bytes_written);
1205 : :
1206 : 154 : return status;
1207 : : }
1208 : :
1209 : : /**
1210 : : * g_io_channel_set_buffered:
1211 : : * @channel: a #GIOChannel
1212 : : * @buffered: whether to set the channel buffered or unbuffered
1213 : : *
1214 : : * The buffering state can only be set if the channel's encoding
1215 : : * is %NULL. For any other encoding, the channel must be buffered.
1216 : : *
1217 : : * A buffered channel can only be set unbuffered if the channel's
1218 : : * internal buffers have been flushed. Newly created channels or
1219 : : * channels which have returned %G_IO_STATUS_EOF
1220 : : * not require such a flush. For write-only channels, a call to
1221 : : * g_io_channel_flush () is sufficient. For all other channels,
1222 : : * the buffers may be flushed by a call to g_io_channel_seek_position ().
1223 : : * This includes the possibility of seeking with seek type %G_SEEK_CUR
1224 : : * and an offset of zero. Note that this means that socket-based
1225 : : * channels cannot be set unbuffered once they have had data
1226 : : * read from them.
1227 : : *
1228 : : * On unbuffered channels, it is safe to mix read and write
1229 : : * calls from the new and old APIs, if this is necessary for
1230 : : * maintaining old code.
1231 : : *
1232 : : * The default state of the channel is buffered.
1233 : : **/
1234 : : void
1235 : 697 : g_io_channel_set_buffered (GIOChannel *channel,
1236 : : gboolean buffered)
1237 : : {
1238 : 697 : g_return_if_fail (channel != NULL);
1239 : :
1240 [ - + ]: 697 : if (channel->encoding != NULL)
1241 : : {
1242 : 0 : g_warning ("Need to have NULL encoding to set the buffering state of the "
1243 : : "channel.");
1244 : 0 : return;
1245 : : }
1246 : :
1247 : 697 : g_return_if_fail (!channel->read_buf || channel->read_buf->len == 0);
1248 : 697 : g_return_if_fail (!channel->write_buf || channel->write_buf->len == 0);
1249 : :
1250 : 697 : channel->use_buffer = buffered;
1251 : : }
1252 : :
1253 : : /**
1254 : : * g_io_channel_get_buffered:
1255 : : * @channel: a #GIOChannel
1256 : : *
1257 : : * Returns whether @channel is buffered.
1258 : : *
1259 : : * Return Value: %TRUE if the @channel is buffered.
1260 : : **/
1261 : : gboolean
1262 : 1 : g_io_channel_get_buffered (GIOChannel *channel)
1263 : : {
1264 : 1 : g_return_val_if_fail (channel != NULL, FALSE);
1265 : :
1266 : 1 : return channel->use_buffer;
1267 : : }
1268 : :
1269 : : /**
1270 : : * g_io_channel_set_encoding:
1271 : : * @channel: a #GIOChannel
1272 : : * @encoding: (nullable): the encoding type
1273 : : * @error: location to store an error of type #GConvertError
1274 : : *
1275 : : * Sets the encoding for the input/output of the channel.
1276 : : * The internal encoding is always UTF-8. The default encoding
1277 : : * for the external file is UTF-8.
1278 : : *
1279 : : * The encoding %NULL is safe to use with binary data.
1280 : : *
1281 : : * The encoding can only be set if one of the following conditions
1282 : : * is true:
1283 : : *
1284 : : * - The channel was just created, and has not been written to or read from yet.
1285 : : *
1286 : : * - The channel is write-only.
1287 : : *
1288 : : * - The channel is a file, and the file pointer was just repositioned
1289 : : * by a call to g_io_channel_seek_position(). (This flushes all the
1290 : : * internal buffers.)
1291 : : *
1292 : : * - The current encoding is %NULL or UTF-8.
1293 : : *
1294 : : * - One of the (new API) read functions has just returned %G_IO_STATUS_EOF
1295 : : * (or, in the case of g_io_channel_read_to_end(), %G_IO_STATUS_NORMAL).
1296 : : *
1297 : : * - One of the functions g_io_channel_read_chars() or
1298 : : * g_io_channel_read_unichar() has returned %G_IO_STATUS_AGAIN or
1299 : : * %G_IO_STATUS_ERROR. This may be useful in the case of
1300 : : * %G_CONVERT_ERROR_ILLEGAL_SEQUENCE.
1301 : : * Returning one of these statuses from g_io_channel_read_line(),
1302 : : * g_io_channel_read_line_string(), or g_io_channel_read_to_end()
1303 : : * does not guarantee that the encoding can be changed.
1304 : : *
1305 : : * Channels which do not meet one of the above conditions cannot call
1306 : : * g_io_channel_seek_position() with an offset of %G_SEEK_CUR, and, if
1307 : : * they are "seekable", cannot call g_io_channel_write_chars() after
1308 : : * calling one of the API "read" functions.
1309 : : *
1310 : : * Return Value: %G_IO_STATUS_NORMAL if the encoding was successfully set
1311 : : */
1312 : : GIOStatus
1313 : 816 : g_io_channel_set_encoding (GIOChannel *channel,
1314 : : const gchar *encoding,
1315 : : GError **error)
1316 : : {
1317 : : GIConv read_cd, write_cd;
1318 : : #ifndef G_DISABLE_ASSERT
1319 : : gboolean did_encode;
1320 : : #endif
1321 : :
1322 : 816 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
1323 : 816 : g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR);
1324 : :
1325 : : /* Make sure the encoded buffers are empty */
1326 : :
1327 : 816 : g_return_val_if_fail (!channel->do_encode || !channel->encoded_read_buf ||
1328 : : channel->encoded_read_buf->len == 0, G_IO_STATUS_ERROR);
1329 : :
1330 [ - + ]: 816 : if (!channel->use_buffer)
1331 : : {
1332 : 0 : g_warning ("Need to set the channel buffered before setting the encoding.");
1333 : 0 : g_warning ("Assuming this is what you meant and acting accordingly.");
1334 : :
1335 : 0 : channel->use_buffer = TRUE;
1336 : : }
1337 : :
1338 [ - + ]: 816 : if (channel->partial_write_buf[0] != '\0')
1339 : : {
1340 : 0 : g_warning ("Partial character at end of write buffer not flushed.");
1341 : 0 : channel->partial_write_buf[0] = '\0';
1342 : : }
1343 : :
1344 : : #ifndef G_DISABLE_ASSERT
1345 : 816 : did_encode = channel->do_encode;
1346 : : #endif
1347 : :
1348 [ + + + - : 816 : if (!encoding || strcmp (encoding, "UTF8") == 0 || strcmp (encoding, "UTF-8") == 0)
- + ]
1349 : : {
1350 : 815 : channel->do_encode = FALSE;
1351 : 815 : read_cd = write_cd = (GIConv) -1;
1352 : : }
1353 : : else
1354 : : {
1355 : 1 : gint err = 0;
1356 : 1 : const gchar *from_enc = NULL, *to_enc = NULL;
1357 : :
1358 [ + - ]: 1 : if (channel->is_readable)
1359 : : {
1360 : 1 : read_cd = g_iconv_open ("UTF-8", encoding);
1361 : :
1362 [ - + ]: 1 : if (read_cd == (GIConv) -1)
1363 : : {
1364 : 0 : err = errno;
1365 : 0 : from_enc = encoding;
1366 : 0 : to_enc = "UTF-8";
1367 : : }
1368 : : }
1369 : : else
1370 : 0 : read_cd = (GIConv) -1;
1371 : :
1372 [ - + - - ]: 1 : if (channel->is_writeable && err == 0)
1373 : : {
1374 : 0 : write_cd = g_iconv_open (encoding, "UTF-8");
1375 : :
1376 [ # # ]: 0 : if (write_cd == (GIConv) -1)
1377 : : {
1378 : 0 : err = errno;
1379 : 0 : from_enc = "UTF-8";
1380 : 0 : to_enc = encoding;
1381 : : }
1382 : : }
1383 : : else
1384 : 1 : write_cd = (GIConv) -1;
1385 : :
1386 [ - + ]: 1 : if (err != 0)
1387 : : {
1388 : 0 : g_assert (from_enc);
1389 : 0 : g_assert (to_enc);
1390 : :
1391 [ # # ]: 0 : if (err == EINVAL)
1392 : 0 : g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION,
1393 : : _("Conversion from character set “%s” to “%s” is not supported"),
1394 : : from_enc, to_enc);
1395 : : else
1396 : 0 : g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
1397 : : _("Could not open converter from “%s” to “%s”: %s"),
1398 : : from_enc, to_enc, g_strerror (err));
1399 : :
1400 [ # # ]: 0 : if (read_cd != (GIConv) -1)
1401 : 0 : g_iconv_close (read_cd);
1402 [ # # ]: 0 : if (write_cd != (GIConv) -1)
1403 : 0 : g_iconv_close (write_cd);
1404 : :
1405 : 0 : return G_IO_STATUS_ERROR;
1406 : : }
1407 : :
1408 : 1 : channel->do_encode = TRUE;
1409 : : }
1410 : :
1411 : : /* The encoding is ok, so set the fields in channel */
1412 : :
1413 [ - + ]: 816 : if (channel->read_cd != (GIConv) -1)
1414 : 0 : g_iconv_close (channel->read_cd);
1415 [ - + ]: 816 : if (channel->write_cd != (GIConv) -1)
1416 : 0 : g_iconv_close (channel->write_cd);
1417 : :
1418 [ - + - - ]: 816 : if (channel->encoded_read_buf && channel->encoded_read_buf->len > 0)
1419 : : {
1420 : 0 : g_assert (!did_encode); /* Encoding UTF-8, NULL doesn't use encoded_read_buf */
1421 : :
1422 : : /* This is just validated UTF-8, so we can copy it back into read_buf
1423 : : * so it can be encoded in whatever the new encoding is.
1424 : : */
1425 : :
1426 : 0 : g_string_prepend_len (channel->read_buf, channel->encoded_read_buf->str,
1427 : 0 : channel->encoded_read_buf->len);
1428 : 0 : g_string_truncate (channel->encoded_read_buf, 0);
1429 : : }
1430 : :
1431 : 816 : channel->read_cd = read_cd;
1432 : 816 : channel->write_cd = write_cd;
1433 : :
1434 : 816 : g_free (channel->encoding);
1435 : 816 : channel->encoding = g_strdup (encoding);
1436 : :
1437 : 816 : return G_IO_STATUS_NORMAL;
1438 : : }
1439 : :
1440 : : /**
1441 : : * g_io_channel_get_encoding:
1442 : : * @channel: a #GIOChannel
1443 : : *
1444 : : * Gets the encoding for the input/output of the channel.
1445 : : * The internal encoding is always UTF-8. The encoding %NULL
1446 : : * makes the channel safe for binary data.
1447 : : *
1448 : : * Returns: A string containing the encoding, this string is
1449 : : * owned by GLib and must not be freed.
1450 : : **/
1451 : : const gchar *
1452 : 1 : g_io_channel_get_encoding (GIOChannel *channel)
1453 : : {
1454 : 1 : g_return_val_if_fail (channel != NULL, NULL);
1455 : :
1456 : 1 : return channel->encoding;
1457 : : }
1458 : :
1459 : : static GIOStatus
1460 : 3708 : g_io_channel_fill_buffer (GIOChannel *channel,
1461 : : GError **err)
1462 : : {
1463 : : gsize read_size, cur_len, oldlen;
1464 : : GIOStatus status;
1465 : :
1466 [ + + - + : 3708 : if (channel->is_seekable && channel->write_buf && channel->write_buf->len > 0)
- - ]
1467 : : {
1468 : 0 : status = g_io_channel_flush (channel, err);
1469 [ # # ]: 0 : if (status != G_IO_STATUS_NORMAL)
1470 : 0 : return status;
1471 : : }
1472 [ + + - + ]: 3708 : if (channel->is_seekable && channel->partial_write_buf[0] != '\0')
1473 : : {
1474 : 0 : g_warning ("Partial character at end of write buffer not flushed.");
1475 : 0 : channel->partial_write_buf[0] = '\0';
1476 : : }
1477 : :
1478 [ + + ]: 3708 : if (!channel->read_buf)
1479 : 194 : channel->read_buf = g_string_sized_new (channel->buf_size);
1480 : :
1481 : 3708 : cur_len = channel->read_buf->len;
1482 : :
1483 : 3708 : g_string_set_size (channel->read_buf, channel->read_buf->len + channel->buf_size);
1484 : :
1485 : 3708 : status = channel->funcs->io_read (channel, channel->read_buf->str + cur_len,
1486 : : channel->buf_size, &read_size, err);
1487 : :
1488 : 3708 : g_assert ((status == G_IO_STATUS_NORMAL) || (read_size == 0));
1489 : :
1490 : 3708 : g_string_truncate (channel->read_buf, read_size + cur_len);
1491 : :
1492 [ + + + - ]: 3708 : if ((status != G_IO_STATUS_NORMAL) &&
1493 [ + + ]: 176 : ((status != G_IO_STATUS_EOF) || (channel->read_buf->len == 0)))
1494 : 143 : return status;
1495 : :
1496 : 3565 : g_assert (channel->read_buf->len > 0);
1497 : :
1498 [ + + ]: 3565 : if (channel->encoded_read_buf)
1499 : 2656 : oldlen = channel->encoded_read_buf->len;
1500 : : else
1501 : : {
1502 : 909 : oldlen = 0;
1503 [ + + ]: 909 : if (channel->encoding)
1504 : 135 : channel->encoded_read_buf = g_string_sized_new (channel->buf_size);
1505 : : }
1506 : :
1507 [ + + ]: 3565 : if (channel->do_encode)
1508 : : {
1509 : : gsize errnum, inbytes_left, outbytes_left;
1510 : : gchar *inbuf, *outbuf;
1511 : : int errval;
1512 : :
1513 : 1 : g_assert (channel->encoded_read_buf);
1514 : :
1515 : 1 : reencode:
1516 : :
1517 : 1 : inbytes_left = channel->read_buf->len;
1518 : 1 : outbytes_left = MAX (channel->read_buf->len,
1519 : : channel->encoded_read_buf->allocated_len
1520 : : - channel->encoded_read_buf->len - 1); /* 1 for NULL */
1521 : 1 : outbytes_left = MAX (outbytes_left, 6);
1522 : :
1523 : 1 : inbuf = channel->read_buf->str;
1524 : 1 : g_string_set_size (channel->encoded_read_buf,
1525 : 1 : channel->encoded_read_buf->len + outbytes_left);
1526 : 1 : outbuf = channel->encoded_read_buf->str + channel->encoded_read_buf->len
1527 : 1 : - outbytes_left;
1528 : :
1529 : 1 : errnum = g_iconv (channel->read_cd, &inbuf, &inbytes_left,
1530 : : &outbuf, &outbytes_left);
1531 : 1 : errval = errno;
1532 : :
1533 : 1 : g_assert (inbuf + inbytes_left == channel->read_buf->str
1534 : : + channel->read_buf->len);
1535 : 1 : g_assert (outbuf + outbytes_left == channel->encoded_read_buf->str
1536 : : + channel->encoded_read_buf->len);
1537 : :
1538 : 1 : g_string_erase (channel->read_buf, 0,
1539 : 1 : channel->read_buf->len - inbytes_left);
1540 : 1 : g_string_truncate (channel->encoded_read_buf,
1541 : : channel->encoded_read_buf->len - outbytes_left);
1542 : :
1543 [ - + ]: 1 : if (errnum == (gsize) -1)
1544 : : {
1545 [ # # # # ]: 0 : switch (errval)
1546 : : {
1547 : 0 : case EINVAL:
1548 [ # # ]: 0 : if ((oldlen == channel->encoded_read_buf->len)
1549 [ # # ]: 0 : && (status == G_IO_STATUS_EOF))
1550 : 0 : status = G_IO_STATUS_EOF;
1551 : : else
1552 : 0 : status = G_IO_STATUS_NORMAL;
1553 : 0 : break;
1554 : 0 : case E2BIG:
1555 : : /* Buffer size at least 6, wrote at least on character */
1556 : 0 : g_assert (inbuf != channel->read_buf->str);
1557 : 0 : goto reencode;
1558 : 0 : case EILSEQ:
1559 [ # # ]: 0 : if (oldlen < channel->encoded_read_buf->len)
1560 : 0 : status = G_IO_STATUS_NORMAL;
1561 : : else
1562 : : {
1563 : 0 : g_set_error_literal (err, G_CONVERT_ERROR,
1564 : : G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1565 : : _("Invalid byte sequence in conversion input"));
1566 : 0 : return G_IO_STATUS_ERROR;
1567 : : }
1568 : 0 : break;
1569 : 0 : default:
1570 : 0 : g_assert (errval != EBADF); /* The converter should be open */
1571 : 0 : g_set_error (err, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
1572 : : _("Error during conversion: %s"), g_strerror (errval));
1573 : 0 : return G_IO_STATUS_ERROR;
1574 : : }
1575 : : }
1576 : 1 : g_assert ((status != G_IO_STATUS_NORMAL)
1577 : : || (channel->encoded_read_buf->len > 0));
1578 : : }
1579 [ + + ]: 3564 : else if (channel->encoding) /* UTF-8 */
1580 : : {
1581 : : gchar *nextchar, *lastchar;
1582 : :
1583 : 2790 : g_assert (channel->encoded_read_buf);
1584 : :
1585 : 2790 : nextchar = channel->read_buf->str;
1586 : 2790 : lastchar = channel->read_buf->str + channel->read_buf->len;
1587 : :
1588 [ + + ]: 2243304 : while (nextchar < lastchar)
1589 : : {
1590 : : gunichar val_char;
1591 : :
1592 : 2240514 : val_char = g_utf8_get_char_validated (nextchar, lastchar - nextchar);
1593 : :
1594 [ + - + ]: 2240514 : switch (val_char)
1595 : : {
1596 : 370 : case -2:
1597 : : /* stop, leave partial character in buffer */
1598 : 370 : lastchar = nextchar;
1599 : 370 : break;
1600 : 0 : case -1:
1601 [ # # ]: 0 : if (oldlen < channel->encoded_read_buf->len)
1602 : 0 : status = G_IO_STATUS_NORMAL;
1603 : : else
1604 : : {
1605 : 0 : g_set_error_literal (err, G_CONVERT_ERROR,
1606 : : G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1607 : : _("Invalid byte sequence in conversion input"));
1608 : 0 : status = G_IO_STATUS_ERROR;
1609 : : }
1610 : 0 : lastchar = nextchar;
1611 : 0 : break;
1612 : 2240144 : default:
1613 : 2240144 : nextchar = g_utf8_next_char (nextchar);
1614 : 2240144 : break;
1615 : : }
1616 : : }
1617 : :
1618 [ + - ]: 2790 : if (lastchar > channel->read_buf->str)
1619 : : {
1620 : 2790 : gint copy_len = lastchar - channel->read_buf->str;
1621 : :
1622 [ - + ]: 2790 : g_string_append_len (channel->encoded_read_buf, channel->read_buf->str,
1623 : : copy_len);
1624 : 2790 : g_string_erase (channel->read_buf, 0, copy_len);
1625 : : }
1626 : : }
1627 : :
1628 : 3565 : return status;
1629 : : }
1630 : :
1631 : : /**
1632 : : * g_io_channel_read_line:
1633 : : * @channel: a #GIOChannel
1634 : : * @str_return: (out): The line read from the #GIOChannel, including the
1635 : : * line terminator. This data should be freed with g_free()
1636 : : * when no longer needed. This is a nul-terminated string.
1637 : : * If a @length of zero is returned, this will be %NULL instead.
1638 : : * @length: (out) (optional): location to store length of the read data, or %NULL
1639 : : * @terminator_pos: (out) (optional): location to store position of line terminator, or %NULL
1640 : : * @error: A location to return an error of type #GConvertError
1641 : : * or #GIOChannelError
1642 : : *
1643 : : * Reads a line, including the terminating character(s),
1644 : : * from a #GIOChannel into a newly-allocated string.
1645 : : * @str_return will contain allocated memory if the return
1646 : : * is %G_IO_STATUS_NORMAL.
1647 : : *
1648 : : * Returns: the status of the operation.
1649 : : **/
1650 : : GIOStatus
1651 : 184 : g_io_channel_read_line (GIOChannel *channel,
1652 : : gchar **str_return,
1653 : : gsize *length,
1654 : : gsize *terminator_pos,
1655 : : GError **error)
1656 : : {
1657 : : GIOStatus status;
1658 : : gsize got_length;
1659 : :
1660 : 184 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
1661 : 184 : g_return_val_if_fail (str_return != NULL, G_IO_STATUS_ERROR);
1662 : 184 : g_return_val_if_fail ((error == NULL) || (*error == NULL),
1663 : : G_IO_STATUS_ERROR);
1664 : 184 : g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
1665 : :
1666 : 184 : status = g_io_channel_read_line_backend (channel, &got_length, terminator_pos, error);
1667 : :
1668 [ + + + - ]: 184 : if (length && status != G_IO_STATUS_ERROR)
1669 : 1 : *length = got_length;
1670 : :
1671 [ + - ]: 184 : if (status == G_IO_STATUS_NORMAL)
1672 : : {
1673 : : gchar *line;
1674 : :
1675 : : /* Copy the read bytes (including any embedded nuls) and nul-terminate.
1676 : : * `USE_BUF (channel)->str` is guaranteed to be nul-terminated as it’s a
1677 : : * #GString, so it’s safe to call g_memdup2() with +1 length to allocate
1678 : : * a nul-terminator. */
1679 : 184 : g_assert (USE_BUF (channel));
1680 [ + + ]: 184 : line = g_memdup2 (USE_BUF (channel)->str, got_length + 1);
1681 : 184 : line[got_length] = '\0';
1682 : 184 : *str_return = g_steal_pointer (&line);
1683 [ + + ]: 184 : g_string_erase (USE_BUF (channel), 0, got_length);
1684 : : }
1685 : : else
1686 : 0 : *str_return = NULL;
1687 : :
1688 : 184 : return status;
1689 : : }
1690 : :
1691 : : /**
1692 : : * g_io_channel_read_line_string:
1693 : : * @channel: a #GIOChannel
1694 : : * @buffer: a #GString into which the line will be written.
1695 : : * If @buffer already contains data, the old data will
1696 : : * be overwritten.
1697 : : * @terminator_pos: (nullable): location to store position of line terminator, or %NULL
1698 : : * @error: a location to store an error of type #GConvertError
1699 : : * or #GIOChannelError
1700 : : *
1701 : : * Reads a line from a #GIOChannel, using a #GString as a buffer.
1702 : : *
1703 : : * Returns: the status of the operation.
1704 : : **/
1705 : : GIOStatus
1706 : 19136 : g_io_channel_read_line_string (GIOChannel *channel,
1707 : : GString *buffer,
1708 : : gsize *terminator_pos,
1709 : : GError **error)
1710 : : {
1711 : : gsize length;
1712 : : GIOStatus status;
1713 : :
1714 : 19136 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
1715 : 19136 : g_return_val_if_fail (buffer != NULL, G_IO_STATUS_ERROR);
1716 : 19136 : g_return_val_if_fail ((error == NULL) || (*error == NULL),
1717 : : G_IO_STATUS_ERROR);
1718 : 19136 : g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
1719 : :
1720 [ - + ]: 19136 : if (buffer->len > 0)
1721 : : g_string_truncate (buffer, 0); /* clear out the buffer */
1722 : :
1723 : 19136 : status = g_io_channel_read_line_backend (channel, &length, terminator_pos, error);
1724 : :
1725 [ + + ]: 19136 : if (status == G_IO_STATUS_NORMAL)
1726 : : {
1727 : 19134 : g_assert (USE_BUF (channel));
1728 [ + - - + ]: 19134 : g_string_append_len (buffer, USE_BUF (channel)->str, length);
1729 [ + - ]: 19134 : g_string_erase (USE_BUF (channel), 0, length);
1730 : : }
1731 : :
1732 : 19136 : return status;
1733 : : }
1734 : :
1735 : :
1736 : : static GIOStatus
1737 : 19320 : g_io_channel_read_line_backend (GIOChannel *channel,
1738 : : gsize *length,
1739 : : gsize *terminator_pos,
1740 : : GError **error)
1741 : : {
1742 : : GIOStatus status;
1743 : : gsize checked_to, line_term_len, line_length, got_term_len;
1744 : 19320 : gboolean first_time = TRUE;
1745 : :
1746 [ - + ]: 19320 : if (!channel->use_buffer)
1747 : : {
1748 : : /* Can't do a raw read in read_line */
1749 : 0 : g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
1750 : : _("Can’t do a raw read in g_io_channel_read_line_string"));
1751 : 0 : return G_IO_STATUS_ERROR;
1752 : : }
1753 : :
1754 : 19320 : status = G_IO_STATUS_NORMAL;
1755 : :
1756 [ + + ]: 19320 : if (channel->line_term)
1757 : 1 : line_term_len = channel->line_term_len;
1758 : : else
1759 : 19319 : line_term_len = 3;
1760 : : /* This value used for setting checked_to, it's the longest of the four
1761 : : * we autodetect for.
1762 : : */
1763 : :
1764 : 19320 : checked_to = 0;
1765 : :
1766 : : while (TRUE)
1767 : 2540 : {
1768 : : gchar *nextchar, *lastchar;
1769 : : GString *use_buf;
1770 : :
1771 [ + + + + : 21860 : if (!first_time || (BUF_LEN (USE_BUF (channel)) == 0))
+ + + - +
+ ]
1772 : : {
1773 : 2751 : read_again:
1774 : 2751 : status = g_io_channel_fill_buffer (channel, error);
1775 [ + + - ]: 2751 : switch (status)
1776 : : {
1777 : 2749 : case G_IO_STATUS_NORMAL:
1778 [ + + + - : 2749 : if (BUF_LEN (USE_BUF (channel)) == 0)
+ + - + ]
1779 : : /* Can happen when using conversion and only read
1780 : : * part of a character
1781 : : */
1782 : : {
1783 : 0 : first_time = FALSE;
1784 : 0 : continue;
1785 : : }
1786 : 2749 : break;
1787 : 2 : case G_IO_STATUS_EOF:
1788 [ + - + - : 2 : if (BUF_LEN (USE_BUF (channel)) == 0)
+ - + - ]
1789 : : {
1790 [ + - ]: 2 : if (length)
1791 : 2 : *length = 0;
1792 : :
1793 [ + - - + ]: 2 : if (channel->encoding && channel->read_buf->len != 0)
1794 : : {
1795 : 0 : g_set_error_literal (error, G_CONVERT_ERROR,
1796 : : G_CONVERT_ERROR_PARTIAL_INPUT,
1797 : : _("Leftover unconverted data in "
1798 : : "read buffer"));
1799 : 0 : return G_IO_STATUS_ERROR;
1800 : : }
1801 : : else
1802 : 2 : return G_IO_STATUS_EOF;
1803 : : }
1804 : 0 : break;
1805 : 0 : default:
1806 [ # # ]: 0 : if (length)
1807 : 0 : *length = 0;
1808 : 0 : return status;
1809 : : }
1810 : : }
1811 : :
1812 : 21858 : g_assert (BUF_LEN (USE_BUF (channel)) != 0);
1813 : :
1814 [ + + ]: 21858 : use_buf = USE_BUF (channel); /* The buffer has been created by this point */
1815 : :
1816 : 21858 : first_time = FALSE;
1817 : :
1818 : 21858 : lastchar = use_buf->str + use_buf->len;
1819 : :
1820 [ + + ]: 2247359 : for (nextchar = use_buf->str + checked_to; nextchar < lastchar;
1821 [ + + ]: 2225501 : channel->encoding ? nextchar = g_utf8_next_char (nextchar) : nextchar++)
1822 : : {
1823 [ + + ]: 2244819 : if (channel->line_term)
1824 : : {
1825 [ + + ]: 8 : if (memcmp (channel->line_term, nextchar, line_term_len) == 0)
1826 : : {
1827 : 1 : line_length = nextchar - use_buf->str;
1828 : 1 : got_term_len = line_term_len;
1829 : 1 : goto done;
1830 : : }
1831 : : }
1832 : : else /* auto detect */
1833 : : {
1834 [ + - + - : 2244811 : switch (*nextchar)
+ ]
1835 : : {
1836 : 19317 : case '\n': /* unix */
1837 : 19317 : line_length = nextchar - use_buf->str;
1838 : 19317 : got_term_len = 1;
1839 : 19317 : goto done;
1840 : 0 : case '\r': /* Warning: do not use with sockets */
1841 : 0 : line_length = nextchar - use_buf->str;
1842 [ # # # # ]: 0 : if ((nextchar == lastchar - 1) && (status != G_IO_STATUS_EOF)
1843 [ # # ]: 0 : && (lastchar == use_buf->str + use_buf->len))
1844 : 0 : goto read_again; /* Try to read more data */
1845 [ # # # # ]: 0 : if ((nextchar < lastchar - 1) && (*(nextchar + 1) == '\n')) /* dos */
1846 : 0 : got_term_len = 2;
1847 : : else /* mac */
1848 : 0 : got_term_len = 1;
1849 : 0 : goto done;
1850 : 41427 : case '\xe2': /* Unicode paragraph separator */
1851 [ - + ]: 41427 : if (strncmp ("\xe2\x80\xa9", nextchar, 3) == 0)
1852 : : {
1853 : 0 : line_length = nextchar - use_buf->str;
1854 : 0 : got_term_len = 3;
1855 : 0 : goto done;
1856 : : }
1857 : 41427 : break;
1858 : 0 : case '\0': /* Embedded null in input */
1859 : 0 : line_length = nextchar - use_buf->str;
1860 : 0 : got_term_len = 1;
1861 : 0 : goto done;
1862 : 2184067 : default: /* no match */
1863 : 2184067 : break;
1864 : : }
1865 : : }
1866 : : }
1867 : :
1868 : : /* If encoding != NULL, valid UTF-8, didn't overshoot */
1869 : 2540 : g_assert (nextchar == lastchar);
1870 : :
1871 : : /* Check for EOF */
1872 : :
1873 [ - + ]: 2540 : if (status == G_IO_STATUS_EOF)
1874 : : {
1875 [ # # # # ]: 0 : if (channel->encoding && channel->read_buf->len > 0)
1876 : : {
1877 : 0 : g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
1878 : : _("Channel terminates in a partial character"));
1879 : 0 : return G_IO_STATUS_ERROR;
1880 : : }
1881 : 0 : line_length = use_buf->len;
1882 : 0 : got_term_len = 0;
1883 : 0 : break;
1884 : : }
1885 : :
1886 [ + + ]: 2540 : if (use_buf->len > line_term_len - 1)
1887 : 2502 : checked_to = use_buf->len - (line_term_len - 1);
1888 : : else
1889 : 38 : checked_to = 0;
1890 : : }
1891 : :
1892 : 19318 : done:
1893 : :
1894 [ + + ]: 19318 : if (terminator_pos)
1895 : 19190 : *terminator_pos = line_length;
1896 : :
1897 [ + - ]: 19318 : if (length)
1898 : 19318 : *length = line_length + got_term_len;
1899 : :
1900 : 19318 : return G_IO_STATUS_NORMAL;
1901 : : }
1902 : :
1903 : : /**
1904 : : * g_io_channel_read_to_end:
1905 : : * @channel: a #GIOChannel
1906 : : * @str_return: (out) (array length=length) (element-type guint8): Location to
1907 : : * store a pointer to a string holding the remaining data in the
1908 : : * #GIOChannel. This data should be freed with g_free() when no
1909 : : * longer needed. This data is terminated by an extra nul
1910 : : * character, but there may be other nuls in the intervening data.
1911 : : * @length: (out): location to store length of the data
1912 : : * @error: location to return an error of type #GConvertError
1913 : : * or #GIOChannelError
1914 : : *
1915 : : * Reads all the remaining data from the file.
1916 : : *
1917 : : * Returns: %G_IO_STATUS_NORMAL on success.
1918 : : * This function never returns %G_IO_STATUS_EOF.
1919 : : **/
1920 : : GIOStatus
1921 : 0 : g_io_channel_read_to_end (GIOChannel *channel,
1922 : : gchar **str_return,
1923 : : gsize *length,
1924 : : GError **error)
1925 : : {
1926 : : GIOStatus status;
1927 : :
1928 : 0 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
1929 : 0 : g_return_val_if_fail ((error == NULL) || (*error == NULL),
1930 : : G_IO_STATUS_ERROR);
1931 : 0 : g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
1932 : :
1933 [ # # ]: 0 : if (str_return)
1934 : 0 : *str_return = NULL;
1935 [ # # ]: 0 : if (length)
1936 : 0 : *length = 0;
1937 : :
1938 [ # # ]: 0 : if (!channel->use_buffer)
1939 : : {
1940 : 0 : g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
1941 : : _("Can’t do a raw read in g_io_channel_read_to_end"));
1942 : 0 : return G_IO_STATUS_ERROR;
1943 : : }
1944 : :
1945 : : do
1946 : 0 : status = g_io_channel_fill_buffer (channel, error);
1947 [ # # ]: 0 : while (status == G_IO_STATUS_NORMAL);
1948 : :
1949 [ # # ]: 0 : if (status != G_IO_STATUS_EOF)
1950 : 0 : return status;
1951 : :
1952 [ # # # # ]: 0 : if (channel->encoding && channel->read_buf->len > 0)
1953 : : {
1954 : 0 : g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
1955 : : _("Channel terminates in a partial character"));
1956 : 0 : return G_IO_STATUS_ERROR;
1957 : : }
1958 : :
1959 [ # # # # ]: 0 : if (USE_BUF (channel) == NULL)
1960 : : {
1961 : : /* length is already set to zero */
1962 [ # # ]: 0 : if (str_return)
1963 : 0 : *str_return = g_strdup ("");
1964 : : }
1965 : : else
1966 : : {
1967 [ # # ]: 0 : if (length)
1968 [ # # ]: 0 : *length = USE_BUF (channel)->len;
1969 : :
1970 [ # # ]: 0 : if (str_return)
1971 [ # # ]: 0 : *str_return = g_string_free (USE_BUF (channel), FALSE);
1972 : : else
1973 [ # # ]: 0 : g_string_free (USE_BUF (channel), TRUE);
1974 : :
1975 [ # # ]: 0 : if (channel->encoding)
1976 : 0 : channel->encoded_read_buf = NULL;
1977 : : else
1978 : 0 : channel->read_buf = NULL;
1979 : : }
1980 : :
1981 : 0 : return G_IO_STATUS_NORMAL;
1982 : : }
1983 : :
1984 : : /**
1985 : : * g_io_channel_read_chars:
1986 : : * @channel: a #GIOChannel
1987 : : * @buf: (out caller-allocates) (array length=count) (element-type guint8):
1988 : : * a buffer to read data into
1989 : : * @count: (in): the size of the buffer. Note that the buffer may not be
1990 : : * completely filled even if there is data in the buffer if the
1991 : : * remaining data is not a complete character.
1992 : : * @bytes_read: (out) (optional): The number of bytes read. This may be
1993 : : * zero even on success if count < 6 and the channel's encoding
1994 : : * is non-%NULL. This indicates that the next UTF-8 character is
1995 : : * too wide for the buffer.
1996 : : * @error: a location to return an error of type #GConvertError
1997 : : * or #GIOChannelError.
1998 : : *
1999 : : * Replacement for g_io_channel_read() with the new API.
2000 : : *
2001 : : * Returns: the status of the operation.
2002 : : */
2003 : : GIOStatus
2004 : 1348 : g_io_channel_read_chars (GIOChannel *channel,
2005 : : gchar *buf,
2006 : : gsize count,
2007 : : gsize *bytes_read,
2008 : : GError **error)
2009 : : {
2010 : : GIOStatus status;
2011 : : gsize got_bytes;
2012 : :
2013 : 1348 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
2014 : 1348 : g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR);
2015 : 1348 : g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
2016 : :
2017 [ - + ]: 1348 : if (count == 0)
2018 : : {
2019 [ # # ]: 0 : if (bytes_read)
2020 : 0 : *bytes_read = 0;
2021 : 0 : return G_IO_STATUS_NORMAL;
2022 : : }
2023 : 1348 : g_return_val_if_fail (buf != NULL, G_IO_STATUS_ERROR);
2024 : :
2025 [ + + ]: 1348 : if (!channel->use_buffer)
2026 : : {
2027 : : gsize tmp_bytes;
2028 : :
2029 : 1099 : g_assert (!channel->read_buf || channel->read_buf->len == 0);
2030 : :
2031 : 1099 : status = channel->funcs->io_read (channel, buf, count, &tmp_bytes, error);
2032 : :
2033 [ + - ]: 1099 : if (bytes_read)
2034 : 1099 : *bytes_read = tmp_bytes;
2035 : :
2036 : 1099 : return status;
2037 : : }
2038 : :
2039 : 249 : status = G_IO_STATUS_NORMAL;
2040 : :
2041 [ + + + + : 1206 : while (BUF_LEN (USE_BUF (channel)) < count && status == G_IO_STATUS_NORMAL)
+ + + + +
+ ]
2042 : 957 : status = g_io_channel_fill_buffer (channel, error);
2043 : :
2044 : : /* Only return an error if we have no data */
2045 : :
2046 [ + + + - : 249 : if (BUF_LEN (USE_BUF (channel)) == 0)
+ + + + ]
2047 : : {
2048 : 98 : g_assert (status != G_IO_STATUS_NORMAL);
2049 : :
2050 [ + - + + ]: 98 : if (status == G_IO_STATUS_EOF && channel->encoding
2051 [ + - - + ]: 40 : && BUF_LEN (channel->read_buf) > 0)
2052 : : {
2053 : 0 : g_set_error_literal (error, G_CONVERT_ERROR,
2054 : : G_CONVERT_ERROR_PARTIAL_INPUT,
2055 : : _("Leftover unconverted data in read buffer"));
2056 : 0 : status = G_IO_STATUS_ERROR;
2057 : : }
2058 : :
2059 [ + - ]: 98 : if (bytes_read)
2060 : 98 : *bytes_read = 0;
2061 : :
2062 : 98 : return status;
2063 : : }
2064 : :
2065 [ - + ]: 151 : if (status == G_IO_STATUS_ERROR)
2066 : 0 : g_clear_error (error);
2067 : :
2068 [ + + + - : 151 : got_bytes = MIN (count, BUF_LEN (USE_BUF (channel)));
+ + ]
2069 : :
2070 : 151 : g_assert (got_bytes > 0);
2071 : :
2072 [ + + ]: 151 : if (channel->encoding)
2073 : : /* Don't validate for NULL encoding, binary safe */
2074 : : {
2075 : : gchar *nextchar, *prevchar;
2076 : :
2077 : 43 : g_assert (USE_BUF (channel) == channel->encoded_read_buf);
2078 : :
2079 : 43 : nextchar = channel->encoded_read_buf->str;
2080 : :
2081 : : do
2082 : : {
2083 : 380 : prevchar = nextchar;
2084 : 380 : nextchar = g_utf8_next_char (nextchar);
2085 : 380 : g_assert (nextchar != prevchar); /* Possible for *prevchar of -1 or -2 */
2086 : : }
2087 [ + + ]: 380 : while (nextchar < channel->encoded_read_buf->str + got_bytes);
2088 : :
2089 [ - + ]: 43 : if (nextchar > channel->encoded_read_buf->str + got_bytes)
2090 : 0 : got_bytes = prevchar - channel->encoded_read_buf->str;
2091 : :
2092 : 43 : g_assert (got_bytes > 0 || count < 6);
2093 : : }
2094 : :
2095 [ + + ]: 151 : memcpy (buf, USE_BUF (channel)->str, got_bytes);
2096 [ + + ]: 151 : g_string_erase (USE_BUF (channel), 0, got_bytes);
2097 : :
2098 [ + - ]: 151 : if (bytes_read)
2099 : 151 : *bytes_read = got_bytes;
2100 : :
2101 : 151 : return G_IO_STATUS_NORMAL;
2102 : : }
2103 : :
2104 : : /**
2105 : : * g_io_channel_read_unichar:
2106 : : * @channel: a #GIOChannel
2107 : : * @thechar: (out): a location to return a character
2108 : : * @error: a location to return an error of type #GConvertError
2109 : : * or #GIOChannelError
2110 : : *
2111 : : * Reads a Unicode character from @channel.
2112 : : * This function cannot be called on a channel with %NULL encoding.
2113 : : *
2114 : : * Returns: a #GIOStatus
2115 : : **/
2116 : : GIOStatus
2117 : 0 : g_io_channel_read_unichar (GIOChannel *channel,
2118 : : gunichar *thechar,
2119 : : GError **error)
2120 : : {
2121 : 0 : GIOStatus status = G_IO_STATUS_NORMAL;
2122 : :
2123 : 0 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
2124 : 0 : g_return_val_if_fail (channel->encoding != NULL, G_IO_STATUS_ERROR);
2125 : 0 : g_return_val_if_fail ((error == NULL) || (*error == NULL),
2126 : : G_IO_STATUS_ERROR);
2127 : 0 : g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR);
2128 : :
2129 [ # # # # : 0 : while (BUF_LEN (channel->encoded_read_buf) == 0 && status == G_IO_STATUS_NORMAL)
# # ]
2130 : 0 : status = g_io_channel_fill_buffer (channel, error);
2131 : :
2132 : : /* Only return an error if we have no data */
2133 : :
2134 [ # # # # : 0 : if (BUF_LEN (USE_BUF (channel)) == 0)
# # # # ]
2135 : : {
2136 : 0 : g_assert (status != G_IO_STATUS_NORMAL);
2137 : :
2138 [ # # # # : 0 : if (status == G_IO_STATUS_EOF && BUF_LEN (channel->read_buf) > 0)
# # ]
2139 : : {
2140 : 0 : g_set_error_literal (error, G_CONVERT_ERROR,
2141 : : G_CONVERT_ERROR_PARTIAL_INPUT,
2142 : : _("Leftover unconverted data in read buffer"));
2143 : 0 : status = G_IO_STATUS_ERROR;
2144 : : }
2145 : :
2146 [ # # ]: 0 : if (thechar)
2147 : 0 : *thechar = (gunichar) -1;
2148 : :
2149 : 0 : return status;
2150 : : }
2151 : :
2152 [ # # ]: 0 : if (status == G_IO_STATUS_ERROR)
2153 : 0 : g_clear_error (error);
2154 : :
2155 [ # # ]: 0 : if (thechar)
2156 : 0 : *thechar = g_utf8_get_char (channel->encoded_read_buf->str);
2157 : :
2158 : 0 : g_string_erase (channel->encoded_read_buf, 0,
2159 : 0 : g_utf8_next_char (channel->encoded_read_buf->str)
2160 : 0 : - channel->encoded_read_buf->str);
2161 : :
2162 : 0 : return G_IO_STATUS_NORMAL;
2163 : : }
2164 : :
2165 : : /**
2166 : : * g_io_channel_write_chars:
2167 : : * @channel: a #GIOChannel
2168 : : * @buf: (array) (element-type guint8): a buffer to write data from
2169 : : * @count: the size of the buffer. If -1, the buffer
2170 : : * is taken to be a nul-terminated string.
2171 : : * @bytes_written: (out): The number of bytes written. This can be nonzero
2172 : : * even if the return value is not %G_IO_STATUS_NORMAL.
2173 : : * If the return value is %G_IO_STATUS_NORMAL and the
2174 : : * channel is blocking, this will always be equal
2175 : : * to @count if @count >= 0.
2176 : : * @error: a location to return an error of type #GConvertError
2177 : : * or #GIOChannelError
2178 : : *
2179 : : * Replacement for g_io_channel_write() with the new API.
2180 : : *
2181 : : * On seekable channels with encodings other than %NULL or UTF-8, generic
2182 : : * mixing of reading and writing is not allowed. A call to g_io_channel_write_chars ()
2183 : : * may only be made on a channel from which data has been read in the
2184 : : * cases described in the documentation for g_io_channel_set_encoding ().
2185 : : *
2186 : : * Returns: the status of the operation.
2187 : : **/
2188 : : GIOStatus
2189 : 2276 : g_io_channel_write_chars (GIOChannel *channel,
2190 : : const gchar *buf,
2191 : : gssize count,
2192 : : gsize *bytes_written,
2193 : : GError **error)
2194 : : {
2195 : : gsize count_unsigned;
2196 : : GIOStatus status;
2197 : 2276 : gsize wrote_bytes = 0;
2198 : :
2199 : 2276 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
2200 : 2276 : g_return_val_if_fail (buf != NULL || count == 0, G_IO_STATUS_ERROR);
2201 : 2276 : g_return_val_if_fail ((error == NULL) || (*error == NULL),
2202 : : G_IO_STATUS_ERROR);
2203 : 2276 : g_return_val_if_fail (channel->is_writeable, G_IO_STATUS_ERROR);
2204 : :
2205 [ + + ]: 2276 : if (count < 0)
2206 : 119 : count_unsigned = strlen (buf);
2207 : : else
2208 : 2157 : count_unsigned = count;
2209 : :
2210 [ - + ]: 2276 : if (count_unsigned == 0)
2211 : : {
2212 [ # # ]: 0 : if (bytes_written)
2213 : 0 : *bytes_written = 0;
2214 : 0 : return G_IO_STATUS_NORMAL;
2215 : : }
2216 : :
2217 : 2276 : g_assert (count_unsigned > 0);
2218 : :
2219 : : /* Raw write case */
2220 : :
2221 [ - + ]: 2276 : if (!channel->use_buffer)
2222 : : {
2223 : : gsize tmp_bytes;
2224 : :
2225 : 0 : g_assert (!channel->write_buf || channel->write_buf->len == 0);
2226 : 0 : g_assert (channel->partial_write_buf[0] == '\0');
2227 : :
2228 : 0 : status = channel->funcs->io_write (channel, buf, count_unsigned,
2229 : : &tmp_bytes, error);
2230 : :
2231 [ # # ]: 0 : if (bytes_written)
2232 : 0 : *bytes_written = tmp_bytes;
2233 : :
2234 : 0 : return status;
2235 : : }
2236 : :
2237 : : /* General case */
2238 : :
2239 [ + + - + : 2276 : if (channel->is_seekable && (( BUF_LEN (channel->read_buf) > 0)
- - ]
2240 [ - + - - ]: 2056 : || (BUF_LEN (channel->encoded_read_buf) > 0)))
2241 : : {
2242 [ # # # # : 0 : if (channel->do_encode && BUF_LEN (channel->encoded_read_buf) > 0)
# # ]
2243 : : {
2244 : 0 : g_warning ("Mixed reading and writing not allowed on encoded files");
2245 : 0 : return G_IO_STATUS_ERROR;
2246 : : }
2247 : 0 : status = g_io_channel_seek_position (channel, 0, G_SEEK_CUR, error);
2248 [ # # ]: 0 : if (status != G_IO_STATUS_NORMAL)
2249 : : {
2250 [ # # ]: 0 : if (bytes_written)
2251 : 0 : *bytes_written = 0;
2252 : 0 : return status;
2253 : : }
2254 : : }
2255 : :
2256 [ + + ]: 2276 : if (!channel->write_buf)
2257 : 63 : channel->write_buf = g_string_sized_new (channel->buf_size);
2258 : :
2259 [ + + ]: 4552 : while (wrote_bytes < count_unsigned)
2260 : : {
2261 : : gsize space_in_buf;
2262 : :
2263 : : /* If the buffer is full, try a write immediately. In
2264 : : * the nonblocking case, this prevents the user from
2265 : : * writing just a little bit to the buffer every time
2266 : : * and never receiving an EAGAIN.
2267 : : */
2268 : :
2269 [ + + ]: 2276 : if (channel->write_buf->len >= channel->buf_size - MAX_CHAR_SIZE)
2270 : : {
2271 : 77 : gsize did_write = 0, this_time;
2272 : :
2273 : : do
2274 : : {
2275 : 77 : status = channel->funcs->io_write (channel, channel->write_buf->str
2276 : 77 : + did_write, channel->write_buf->len
2277 : : - did_write, &this_time, error);
2278 : 77 : did_write += this_time;
2279 : : }
2280 [ + - ]: 77 : while (status == G_IO_STATUS_NORMAL &&
2281 [ - + ]: 77 : did_write < MIN (channel->write_buf->len, MAX_CHAR_SIZE));
2282 : :
2283 : 77 : g_string_erase (channel->write_buf, 0, did_write);
2284 : :
2285 [ - + ]: 77 : if (status != G_IO_STATUS_NORMAL)
2286 : : {
2287 [ # # # # ]: 0 : if (status == G_IO_STATUS_AGAIN && wrote_bytes > 0)
2288 : 0 : status = G_IO_STATUS_NORMAL;
2289 [ # # ]: 0 : if (bytes_written)
2290 : 0 : *bytes_written = wrote_bytes;
2291 : 0 : return status;
2292 : : }
2293 : : }
2294 : :
2295 : 2276 : space_in_buf = MAX (channel->buf_size, channel->write_buf->allocated_len - 1)
2296 : 2276 : - channel->write_buf->len; /* 1 for NULL */
2297 : :
2298 : : /* This is only true because g_io_channel_set_buffer_size ()
2299 : : * ensures that channel->buf_size >= MAX_CHAR_SIZE.
2300 : : */
2301 : 2276 : g_assert (space_in_buf >= MAX_CHAR_SIZE);
2302 : :
2303 [ + + ]: 2276 : if (!channel->encoding)
2304 : : {
2305 : 2152 : gsize write_this = MIN (space_in_buf, count_unsigned - wrote_bytes);
2306 : :
2307 : : /* g_string_append_len() takes a gssize, so don’t overflow it*/
2308 [ - + ]: 2152 : if (write_this > G_MAXSSIZE)
2309 : 0 : write_this = G_MAXSSIZE;
2310 : :
2311 [ - + ]: 2152 : g_string_append_len (channel->write_buf, buf, write_this);
2312 : 2152 : buf += write_this;
2313 : 2152 : wrote_bytes += write_this;
2314 : : }
2315 : : else
2316 : : {
2317 : : const gchar *from_buf;
2318 : : gsize from_buf_len, from_buf_old_len, left_len;
2319 : : gsize err;
2320 : : gint errnum;
2321 : :
2322 [ - + ]: 124 : if (channel->partial_write_buf[0] != '\0')
2323 : : {
2324 : 0 : g_assert (wrote_bytes == 0);
2325 : :
2326 : 0 : from_buf = channel->partial_write_buf;
2327 : 0 : from_buf_old_len = strlen (channel->partial_write_buf);
2328 : 0 : g_assert (from_buf_old_len > 0);
2329 : 0 : from_buf_len = MIN (6, from_buf_old_len + count_unsigned);
2330 : :
2331 : 0 : memcpy (channel->partial_write_buf + from_buf_old_len, buf,
2332 : : from_buf_len - from_buf_old_len);
2333 : : }
2334 : : else
2335 : : {
2336 : 124 : from_buf = buf;
2337 : 124 : from_buf_len = count_unsigned - wrote_bytes;
2338 : 124 : from_buf_old_len = 0;
2339 : : }
2340 : :
2341 : 124 : reconvert:
2342 : :
2343 [ + - ]: 124 : if (!channel->do_encode) /* UTF-8 encoding */
2344 : : {
2345 : : const gchar *badchar;
2346 : 124 : gsize try_len = MIN (from_buf_len, space_in_buf);
2347 : :
2348 : : /* UTF-8, just validate, emulate g_iconv */
2349 : :
2350 [ - + ]: 124 : if (!g_utf8_validate_len (from_buf, try_len, &badchar))
2351 : : {
2352 : : gunichar try_char;
2353 : 0 : gsize incomplete_len = from_buf + try_len - badchar;
2354 : :
2355 : 0 : left_len = from_buf + from_buf_len - badchar;
2356 : :
2357 : 0 : try_char = g_utf8_get_char_validated (badchar, incomplete_len);
2358 : :
2359 [ # # # ]: 0 : switch (try_char)
2360 : : {
2361 : 0 : case -2:
2362 : 0 : g_assert (incomplete_len < 6);
2363 [ # # ]: 0 : if (try_len == from_buf_len)
2364 : : {
2365 : 0 : errnum = EINVAL;
2366 : 0 : err = (gsize) -1;
2367 : : }
2368 : : else
2369 : : {
2370 : 0 : errnum = 0;
2371 : 0 : err = (gsize) 0;
2372 : : }
2373 : 0 : break;
2374 : 0 : case -1:
2375 : 0 : g_warning ("Invalid UTF-8 passed to g_io_channel_write_chars().");
2376 : : /* FIXME bail here? */
2377 : 0 : errnum = EILSEQ;
2378 : 0 : err = (gsize) -1;
2379 : 0 : break;
2380 : 0 : default:
2381 : : g_assert_not_reached ();
2382 : : err = (gsize) -1;
2383 : : errnum = 0; /* Don't confuse the compiler */
2384 : : }
2385 : : }
2386 : : else
2387 : : {
2388 : 124 : err = (gsize) 0;
2389 : 124 : errnum = 0;
2390 : 124 : left_len = from_buf_len - try_len;
2391 : : }
2392 : :
2393 [ - + ]: 124 : g_string_append_len (channel->write_buf, from_buf,
2394 : : from_buf_len - left_len);
2395 : 124 : from_buf += from_buf_len - left_len;
2396 : : }
2397 : : else
2398 : : {
2399 : : gchar *outbuf;
2400 : :
2401 : 0 : left_len = from_buf_len;
2402 : 0 : g_string_set_size (channel->write_buf, channel->write_buf->len
2403 : : + space_in_buf);
2404 : 0 : outbuf = channel->write_buf->str + channel->write_buf->len
2405 : 0 : - space_in_buf;
2406 : 0 : err = g_iconv (channel->write_cd, (gchar **) &from_buf, &left_len,
2407 : : &outbuf, &space_in_buf);
2408 : 0 : errnum = errno;
2409 : 0 : g_string_truncate (channel->write_buf, channel->write_buf->len
2410 : : - space_in_buf);
2411 : : }
2412 : :
2413 [ - + ]: 124 : if (err == (gsize) -1)
2414 : : {
2415 [ # # # # ]: 0 : switch (errnum)
2416 : : {
2417 : 0 : case EINVAL:
2418 : 0 : g_assert (left_len < 6);
2419 : :
2420 [ # # ]: 0 : if (from_buf_old_len == 0)
2421 : : {
2422 : : /* Not from partial_write_buf */
2423 : :
2424 : 0 : memcpy (channel->partial_write_buf, from_buf, left_len);
2425 : 0 : channel->partial_write_buf[left_len] = '\0';
2426 [ # # ]: 0 : if (bytes_written)
2427 : 0 : *bytes_written = count_unsigned;
2428 : 0 : return G_IO_STATUS_NORMAL;
2429 : : }
2430 : :
2431 : : /* Working in partial_write_buf */
2432 : :
2433 [ # # ]: 0 : if (left_len == from_buf_len)
2434 : : {
2435 : : /* Didn't convert anything, must still have
2436 : : * less than a full character
2437 : : */
2438 : :
2439 : 0 : g_assert (count_unsigned == from_buf_len - from_buf_old_len);
2440 : :
2441 : 0 : channel->partial_write_buf[from_buf_len] = '\0';
2442 : :
2443 [ # # ]: 0 : if (bytes_written)
2444 : 0 : *bytes_written = count_unsigned;
2445 : :
2446 : 0 : return G_IO_STATUS_NORMAL;
2447 : : }
2448 : :
2449 : 0 : g_assert (from_buf_len - left_len >= from_buf_old_len);
2450 : :
2451 : : /* We converted all the old data. This is fine */
2452 : :
2453 : 0 : break;
2454 : 0 : case E2BIG:
2455 [ # # ]: 0 : if (from_buf_len == left_len)
2456 : : {
2457 : : /* Nothing was written, add enough space for
2458 : : * at least one character.
2459 : : */
2460 : 0 : space_in_buf += MAX_CHAR_SIZE;
2461 : 0 : goto reconvert;
2462 : : }
2463 : 0 : break;
2464 : 0 : case EILSEQ:
2465 : 0 : g_set_error_literal (error, G_CONVERT_ERROR,
2466 : : G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
2467 : : _("Invalid byte sequence in conversion input"));
2468 [ # # # # ]: 0 : if (from_buf_old_len > 0 && from_buf_len == left_len)
2469 : 0 : g_warning ("Illegal sequence due to partial character "
2470 : : "at the end of a previous write.");
2471 : : else
2472 : : {
2473 : 0 : g_assert (from_buf_len >= left_len + from_buf_old_len);
2474 : 0 : wrote_bytes += from_buf_len - left_len - from_buf_old_len;
2475 : : }
2476 [ # # ]: 0 : if (bytes_written)
2477 : 0 : *bytes_written = wrote_bytes;
2478 : 0 : channel->partial_write_buf[0] = '\0';
2479 : 0 : return G_IO_STATUS_ERROR;
2480 : 0 : default:
2481 : 0 : g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
2482 : : _("Error during conversion: %s"), g_strerror (errnum));
2483 [ # # ]: 0 : if (from_buf_len >= left_len + from_buf_old_len)
2484 : 0 : wrote_bytes += from_buf_len - left_len - from_buf_old_len;
2485 [ # # ]: 0 : if (bytes_written)
2486 : 0 : *bytes_written = wrote_bytes;
2487 : 0 : channel->partial_write_buf[0] = '\0';
2488 : 0 : return G_IO_STATUS_ERROR;
2489 : : }
2490 : : }
2491 : :
2492 : 124 : g_assert (from_buf_len - left_len >= from_buf_old_len);
2493 : :
2494 : 124 : wrote_bytes += from_buf_len - left_len - from_buf_old_len;
2495 : :
2496 [ - + ]: 124 : if (from_buf_old_len > 0)
2497 : : {
2498 : : /* We were working in partial_write_buf */
2499 : :
2500 : 0 : buf += from_buf_len - left_len - from_buf_old_len;
2501 : 0 : channel->partial_write_buf[0] = '\0';
2502 : : }
2503 : : else
2504 : 124 : buf = from_buf;
2505 : : }
2506 : : }
2507 : :
2508 [ + + ]: 2276 : if (bytes_written)
2509 : 113 : *bytes_written = count_unsigned;
2510 : :
2511 : 2276 : return G_IO_STATUS_NORMAL;
2512 : : }
2513 : :
2514 : : /**
2515 : : * g_io_channel_write_unichar:
2516 : : * @channel: a #GIOChannel
2517 : : * @thechar: a character
2518 : : * @error: location to return an error of type #GConvertError
2519 : : * or #GIOChannelError
2520 : : *
2521 : : * Writes a Unicode character to @channel.
2522 : : * This function cannot be called on a channel with %NULL encoding.
2523 : : *
2524 : : * Returns: a #GIOStatus
2525 : : **/
2526 : : GIOStatus
2527 : 0 : g_io_channel_write_unichar (GIOChannel *channel,
2528 : : gunichar thechar,
2529 : : GError **error)
2530 : : {
2531 : : GIOStatus status;
2532 : : gchar static_buf[6];
2533 : : gsize char_len, wrote_len;
2534 : :
2535 : 0 : g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
2536 : 0 : g_return_val_if_fail (channel->encoding != NULL, G_IO_STATUS_ERROR);
2537 : 0 : g_return_val_if_fail ((error == NULL) || (*error == NULL),
2538 : : G_IO_STATUS_ERROR);
2539 : 0 : g_return_val_if_fail (channel->is_writeable, G_IO_STATUS_ERROR);
2540 : :
2541 : 0 : char_len = g_unichar_to_utf8 (thechar, static_buf);
2542 : :
2543 [ # # ]: 0 : if (channel->partial_write_buf[0] != '\0')
2544 : : {
2545 : 0 : g_warning ("Partial character written before writing unichar.");
2546 : 0 : channel->partial_write_buf[0] = '\0';
2547 : : }
2548 : :
2549 : 0 : status = g_io_channel_write_chars (channel, static_buf,
2550 : : char_len, &wrote_len, error);
2551 : :
2552 : : /* We validate UTF-8, so we can't get a partial write */
2553 : :
2554 : 0 : g_assert (wrote_len == char_len || status != G_IO_STATUS_NORMAL);
2555 : :
2556 : 0 : return status;
2557 : : }
2558 : :
2559 : : /**
2560 : : * G_IO_CHANNEL_ERROR:
2561 : : *
2562 : : * Error domain for #GIOChannel operations. Errors in this domain will
2563 : : * be from the #GIOChannelError enumeration. See #GError for
2564 : : * information on error domains.
2565 : : **/
2566 : : /**
2567 : : * GIOChannelError:
2568 : : * @G_IO_CHANNEL_ERROR_FBIG: File too large.
2569 : : * @G_IO_CHANNEL_ERROR_INVAL: Invalid argument.
2570 : : * @G_IO_CHANNEL_ERROR_IO: IO error.
2571 : : * @G_IO_CHANNEL_ERROR_ISDIR: File is a directory.
2572 : : * @G_IO_CHANNEL_ERROR_NOSPC: No space left on device.
2573 : : * @G_IO_CHANNEL_ERROR_NXIO: No such device or address.
2574 : : * @G_IO_CHANNEL_ERROR_OVERFLOW: Value too large for defined datatype.
2575 : : * @G_IO_CHANNEL_ERROR_PIPE: Broken pipe.
2576 : : * @G_IO_CHANNEL_ERROR_FAILED: Some other error.
2577 : : *
2578 : : * Error codes returned by #GIOChannel operations.
2579 : : **/
2580 : :
2581 [ + - ]: 1 : G_DEFINE_QUARK (g-io-channel-error-quark, g_io_channel_error)
|