/src/glib-2.80.0/glib/giochannel.c
Line | Count | Source |
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 | 0 | #define G_IO_NICE_BUF_SIZE 1024 |
144 | | |
145 | | /* This needs to be as wide as the largest character in any possible encoding */ |
146 | 0 | #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 | 0 | #define USE_BUF(channel) ((channel)->encoding ? (channel)->encoded_read_buf \ |
153 | 0 | : (channel)->read_buf) |
154 | 0 | #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 | | g_io_channel_init (GIOChannel *channel) |
178 | 0 | { |
179 | 0 | channel->ref_count = 1; |
180 | 0 | channel->encoding = g_strdup ("UTF-8"); |
181 | 0 | channel->line_term = NULL; |
182 | 0 | channel->line_term_len = 0; |
183 | 0 | channel->buf_size = G_IO_NICE_BUF_SIZE; |
184 | 0 | channel->read_cd = (GIConv) -1; |
185 | 0 | channel->write_cd = (GIConv) -1; |
186 | 0 | channel->read_buf = NULL; /* Lazy allocate buffers */ |
187 | 0 | channel->encoded_read_buf = NULL; |
188 | 0 | channel->write_buf = NULL; |
189 | 0 | channel->partial_write_buf[0] = '\0'; |
190 | 0 | channel->use_buffer = TRUE; |
191 | 0 | channel->do_encode = FALSE; |
192 | 0 | channel->close_on_unref = FALSE; |
193 | 0 | } |
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 | | g_io_channel_ref (GIOChannel *channel) |
205 | 0 | { |
206 | 0 | g_return_val_if_fail (channel != NULL, NULL); |
207 | | |
208 | 0 | g_atomic_int_inc (&channel->ref_count); |
209 | |
|
210 | 0 | return channel; |
211 | 0 | } |
212 | | |
213 | | /** |
214 | | * g_io_channel_unref: |
215 | | * @channel: a #GIOChannel |
216 | | * |
217 | | * Decrements the reference count of a #GIOChannel. |
218 | | */ |
219 | | void |
220 | | g_io_channel_unref (GIOChannel *channel) |
221 | 0 | { |
222 | 0 | gboolean is_zero; |
223 | |
|
224 | 0 | g_return_if_fail (channel != NULL); |
225 | | |
226 | 0 | is_zero = g_atomic_int_dec_and_test (&channel->ref_count); |
227 | |
|
228 | 0 | if (G_UNLIKELY (is_zero)) |
229 | 0 | { |
230 | 0 | if (channel->close_on_unref) |
231 | 0 | g_io_channel_shutdown (channel, TRUE, NULL); |
232 | 0 | else |
233 | 0 | g_io_channel_purge (channel); |
234 | 0 | g_free (channel->encoding); |
235 | 0 | if (channel->read_cd != (GIConv) -1) |
236 | 0 | g_iconv_close (channel->read_cd); |
237 | 0 | if (channel->write_cd != (GIConv) -1) |
238 | 0 | g_iconv_close (channel->write_cd); |
239 | 0 | g_free (channel->line_term); |
240 | 0 | if (channel->read_buf) |
241 | 0 | g_string_free (channel->read_buf, TRUE); |
242 | 0 | if (channel->write_buf) |
243 | 0 | g_string_free (channel->write_buf, TRUE); |
244 | 0 | if (channel->encoded_read_buf) |
245 | 0 | g_string_free (channel->encoded_read_buf, TRUE); |
246 | 0 | channel->funcs->io_free (channel); |
247 | 0 | } |
248 | 0 | } |
249 | | |
250 | | static GIOError |
251 | | g_io_error_get_from_g_error (GIOStatus status, |
252 | | GError *err) |
253 | 0 | { |
254 | 0 | switch (status) |
255 | 0 | { |
256 | 0 | case G_IO_STATUS_NORMAL: |
257 | 0 | case G_IO_STATUS_EOF: |
258 | 0 | 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 | 0 | { |
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 | 0 | } |
273 | 0 | default: |
274 | 0 | g_assert_not_reached (); |
275 | 0 | } |
276 | 0 | } |
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 | | g_io_channel_read (GIOChannel *channel, |
294 | | gchar *buf, |
295 | | gsize count, |
296 | | gsize *bytes_read) |
297 | 0 | { |
298 | 0 | GError *err = NULL; |
299 | 0 | GIOError error; |
300 | 0 | GIOStatus status; |
301 | |
|
302 | 0 | g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN); |
303 | 0 | g_return_val_if_fail (bytes_read != NULL, G_IO_ERROR_UNKNOWN); |
304 | | |
305 | 0 | if (count == 0) |
306 | 0 | { |
307 | 0 | if (bytes_read) |
308 | 0 | *bytes_read = 0; |
309 | 0 | return G_IO_ERROR_NONE; |
310 | 0 | } |
311 | | |
312 | 0 | g_return_val_if_fail (buf != NULL, G_IO_ERROR_UNKNOWN); |
313 | | |
314 | 0 | status = channel->funcs->io_read (channel, buf, count, bytes_read, &err); |
315 | |
|
316 | 0 | error = g_io_error_get_from_g_error (status, err); |
317 | |
|
318 | 0 | if (err) |
319 | 0 | g_error_free (err); |
320 | |
|
321 | 0 | return error; |
322 | 0 | } |
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 | | g_io_channel_write (GIOChannel *channel, |
339 | | const gchar *buf, |
340 | | gsize count, |
341 | | gsize *bytes_written) |
342 | 0 | { |
343 | 0 | GError *err = NULL; |
344 | 0 | GIOError error; |
345 | 0 | 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 | 0 | } |
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 | | g_io_channel_seek (GIOChannel *channel, |
378 | | gint64 offset, |
379 | | GSeekType type) |
380 | 0 | { |
381 | 0 | GError *err = NULL; |
382 | 0 | GIOError error; |
383 | 0 | 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 | 0 | { |
390 | 0 | case G_SEEK_CUR: |
391 | 0 | case G_SEEK_SET: |
392 | 0 | 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 | 0 | } |
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 | 0 | } |
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 | | g_io_channel_close (GIOChannel *channel) |
441 | 0 | { |
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 | 0 | { /* No way to return the error */ |
452 | 0 | g_warning ("Error closing channel: %s", err->message); |
453 | 0 | g_error_free (err); |
454 | 0 | } |
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 | 0 | } |
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 | | g_io_channel_shutdown (GIOChannel *channel, |
476 | | gboolean flush, |
477 | | GError **err) |
478 | 0 | { |
479 | 0 | GIOStatus status, result; |
480 | 0 | GError *tmperr = NULL; |
481 | | |
482 | 0 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
483 | 0 | g_return_val_if_fail (err == NULL || *err == NULL, G_IO_STATUS_ERROR); |
484 | | |
485 | 0 | if (channel->write_buf && channel->write_buf->len > 0) |
486 | 0 | { |
487 | 0 | if (flush) |
488 | 0 | { |
489 | 0 | GIOFlags flags; |
490 | | |
491 | | /* Set the channel to blocking, to avoid a busy loop |
492 | | */ |
493 | 0 | flags = g_io_channel_get_flags (channel); |
494 | | /* Ignore any errors here, they're irrelevant */ |
495 | 0 | g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL); |
496 | |
|
497 | 0 | result = g_io_channel_flush (channel, &tmperr); |
498 | 0 | } |
499 | 0 | else |
500 | 0 | result = G_IO_STATUS_NORMAL; |
501 | |
|
502 | 0 | g_string_truncate(channel->write_buf, 0); |
503 | 0 | } |
504 | 0 | else |
505 | 0 | result = G_IO_STATUS_NORMAL; |
506 | |
|
507 | 0 | if (channel->partial_write_buf[0] != '\0') |
508 | 0 | { |
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 | 0 | } |
513 | |
|
514 | 0 | status = channel->funcs->io_close (channel, err); |
515 | |
|
516 | 0 | channel->close_on_unref = FALSE; /* Because we already did */ |
517 | 0 | channel->is_readable = FALSE; |
518 | 0 | channel->is_writeable = FALSE; |
519 | 0 | channel->is_seekable = FALSE; |
520 | |
|
521 | 0 | if (status != G_IO_STATUS_NORMAL) |
522 | 0 | { |
523 | 0 | g_clear_error (&tmperr); |
524 | 0 | return status; |
525 | 0 | } |
526 | 0 | else if (result != G_IO_STATUS_NORMAL) |
527 | 0 | { |
528 | 0 | g_propagate_error (err, tmperr); |
529 | 0 | return result; |
530 | 0 | } |
531 | 0 | else |
532 | 0 | return G_IO_STATUS_NORMAL; |
533 | 0 | } |
534 | | |
535 | | /* This function is used for the final flush on close or unref */ |
536 | | static void |
537 | | g_io_channel_purge (GIOChannel *channel) |
538 | 0 | { |
539 | 0 | GError *err = NULL; |
540 | 0 | GIOStatus status G_GNUC_UNUSED; |
541 | |
|
542 | 0 | g_return_if_fail (channel != NULL); |
543 | | |
544 | 0 | if (channel->write_buf && channel->write_buf->len > 0) |
545 | 0 | { |
546 | 0 | GIOFlags flags; |
547 | | |
548 | | /* Set the channel to blocking, to avoid a busy loop |
549 | | */ |
550 | 0 | flags = g_io_channel_get_flags (channel); |
551 | 0 | g_io_channel_set_flags (channel, flags & ~G_IO_FLAG_NONBLOCK, NULL); |
552 | |
|
553 | 0 | status = g_io_channel_flush (channel, &err); |
554 | |
|
555 | 0 | if (err) |
556 | 0 | { /* No way to return the error */ |
557 | 0 | g_warning ("Error flushing string: %s", err->message); |
558 | 0 | g_error_free (err); |
559 | 0 | } |
560 | 0 | } |
561 | | |
562 | | /* Flush these in case anyone tries to close without unrefing */ |
563 | |
|
564 | 0 | if (channel->read_buf) |
565 | 0 | g_string_truncate (channel->read_buf, 0); |
566 | 0 | if (channel->write_buf) |
567 | 0 | g_string_truncate (channel->write_buf, 0); |
568 | 0 | if (channel->encoding) |
569 | 0 | { |
570 | 0 | if (channel->encoded_read_buf) |
571 | 0 | g_string_truncate (channel->encoded_read_buf, 0); |
572 | |
|
573 | 0 | if (channel->partial_write_buf[0] != '\0') |
574 | 0 | { |
575 | 0 | g_warning ("Partial character at end of write buffer not flushed."); |
576 | 0 | channel->partial_write_buf[0] = '\0'; |
577 | 0 | } |
578 | 0 | } |
579 | 0 | } |
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 | | g_io_create_watch (GIOChannel *channel, |
605 | | GIOCondition condition) |
606 | 0 | { |
607 | 0 | g_return_val_if_fail (channel != NULL, NULL); |
608 | | |
609 | 0 | return channel->funcs->io_create_watch (channel, condition); |
610 | 0 | } |
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 | | g_io_add_watch_full (GIOChannel *channel, |
632 | | gint priority, |
633 | | GIOCondition condition, |
634 | | GIOFunc func, |
635 | | gpointer user_data, |
636 | | GDestroyNotify notify) |
637 | 0 | { |
638 | 0 | GSource *source; |
639 | 0 | guint id; |
640 | | |
641 | 0 | g_return_val_if_fail (channel != NULL, 0); |
642 | | |
643 | 0 | source = g_io_create_watch (channel, condition); |
644 | |
|
645 | 0 | if (priority != G_PRIORITY_DEFAULT) |
646 | 0 | g_source_set_priority (source, priority); |
647 | 0 | g_source_set_callback (source, (GSourceFunc)func, user_data, notify); |
648 | |
|
649 | 0 | id = g_source_attach (source, NULL); |
650 | 0 | g_source_unref (source); |
651 | |
|
652 | 0 | return id; |
653 | 0 | } |
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 | | g_io_add_watch (GIOChannel *channel, |
695 | | GIOCondition condition, |
696 | | GIOFunc func, |
697 | | gpointer user_data) |
698 | 0 | { |
699 | 0 | return g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, condition, func, user_data, NULL); |
700 | 0 | } |
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 | | g_io_channel_get_buffer_condition (GIOChannel *channel) |
714 | 0 | { |
715 | 0 | GIOCondition condition = 0; |
716 | |
|
717 | 0 | if (channel->encoding) |
718 | 0 | { |
719 | 0 | 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 | 0 | } |
722 | 0 | else |
723 | 0 | { |
724 | 0 | if (channel->read_buf && (channel->read_buf->len > 0)) |
725 | 0 | condition |= G_IO_IN; |
726 | 0 | } |
727 | |
|
728 | 0 | if (channel->write_buf && (channel->write_buf->len < channel->buf_size)) |
729 | 0 | condition |= G_IO_OUT; |
730 | |
|
731 | 0 | return condition; |
732 | 0 | } |
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 | | g_io_channel_error_from_errno (gint en) |
745 | 0 | { |
746 | 0 | #ifdef EAGAIN |
747 | 0 | g_return_val_if_fail (en != EAGAIN, G_IO_CHANNEL_ERROR_FAILED); |
748 | 0 | #endif |
749 | | |
750 | 0 | switch (en) |
751 | 0 | { |
752 | 0 | #ifdef EBADF |
753 | 0 | case EBADF: |
754 | 0 | g_warning ("Invalid file descriptor."); |
755 | 0 | return G_IO_CHANNEL_ERROR_FAILED; |
756 | 0 | #endif |
757 | | |
758 | 0 | #ifdef EFAULT |
759 | 0 | case EFAULT: |
760 | 0 | g_warning ("Buffer outside valid address space."); |
761 | 0 | return G_IO_CHANNEL_ERROR_FAILED; |
762 | 0 | #endif |
763 | | |
764 | 0 | #ifdef EFBIG |
765 | 0 | case EFBIG: |
766 | 0 | return G_IO_CHANNEL_ERROR_FBIG; |
767 | 0 | #endif |
768 | | |
769 | 0 | #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 | 0 | #endif |
780 | | |
781 | 0 | #ifdef EINVAL |
782 | 0 | case EINVAL: |
783 | 0 | return G_IO_CHANNEL_ERROR_INVAL; |
784 | 0 | #endif |
785 | | |
786 | 0 | #ifdef EIO |
787 | 0 | case EIO: |
788 | 0 | return G_IO_CHANNEL_ERROR_IO; |
789 | 0 | #endif |
790 | | |
791 | 0 | #ifdef EISDIR |
792 | 0 | case EISDIR: |
793 | 0 | return G_IO_CHANNEL_ERROR_ISDIR; |
794 | 0 | #endif |
795 | | |
796 | 0 | #ifdef ENOSPC |
797 | 0 | case ENOSPC: |
798 | 0 | return G_IO_CHANNEL_ERROR_NOSPC; |
799 | 0 | #endif |
800 | | |
801 | 0 | #ifdef ENXIO |
802 | 0 | case ENXIO: |
803 | 0 | return G_IO_CHANNEL_ERROR_NXIO; |
804 | 0 | #endif |
805 | | |
806 | 0 | #ifdef EOVERFLOW |
807 | 0 | #if EOVERFLOW != EFBIG |
808 | 0 | case EOVERFLOW: |
809 | 0 | return G_IO_CHANNEL_ERROR_OVERFLOW; |
810 | 0 | #endif |
811 | 0 | #endif |
812 | | |
813 | 0 | #ifdef EPIPE |
814 | 0 | case EPIPE: |
815 | 0 | return G_IO_CHANNEL_ERROR_PIPE; |
816 | 0 | #endif |
817 | | |
818 | 0 | default: |
819 | 0 | return G_IO_CHANNEL_ERROR_FAILED; |
820 | 0 | } |
821 | 0 | } |
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 | | g_io_channel_set_buffer_size (GIOChannel *channel, |
832 | | gsize size) |
833 | 0 | { |
834 | 0 | g_return_if_fail (channel != NULL); |
835 | | |
836 | 0 | if (size == 0) |
837 | 0 | size = G_IO_NICE_BUF_SIZE; |
838 | |
|
839 | 0 | if (size < MAX_CHAR_SIZE) |
840 | 0 | size = MAX_CHAR_SIZE; |
841 | |
|
842 | 0 | channel->buf_size = size; |
843 | 0 | } |
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 | | g_io_channel_get_buffer_size (GIOChannel *channel) |
855 | 0 | { |
856 | 0 | g_return_val_if_fail (channel != NULL, 0); |
857 | | |
858 | 0 | return channel->buf_size; |
859 | 0 | } |
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 | | g_io_channel_set_line_term (GIOChannel *channel, |
877 | | const gchar *line_term, |
878 | | gint length) |
879 | 0 | { |
880 | 0 | guint length_unsigned; |
881 | |
|
882 | 0 | g_return_if_fail (channel != NULL); |
883 | 0 | g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */ |
884 | | |
885 | 0 | if (line_term == NULL) |
886 | 0 | length_unsigned = 0; |
887 | 0 | else if (length >= 0) |
888 | 0 | length_unsigned = (guint) length; |
889 | 0 | else |
890 | 0 | { |
891 | | /* FIXME: We’re constrained by line_term_len being a guint here */ |
892 | 0 | gsize length_size = strlen (line_term); |
893 | 0 | g_return_if_fail (length_size <= G_MAXUINT); |
894 | 0 | length_unsigned = (guint) length_size; |
895 | 0 | } |
896 | | |
897 | 0 | g_free (channel->line_term); |
898 | 0 | channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL; |
899 | 0 | channel->line_term_len = length_unsigned; |
900 | 0 | } |
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 | | g_io_channel_get_line_term (GIOChannel *channel, |
916 | | gint *length) |
917 | 0 | { |
918 | 0 | g_return_val_if_fail (channel != NULL, NULL); |
919 | | |
920 | 0 | if (length) |
921 | 0 | *length = channel->line_term_len; |
922 | |
|
923 | 0 | return channel->line_term; |
924 | 0 | } |
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 | | g_io_channel_set_flags (GIOChannel *channel, |
966 | | GIOFlags flags, |
967 | | GError **error) |
968 | 0 | { |
969 | 0 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
970 | 0 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
971 | 0 | G_IO_STATUS_ERROR); |
972 | | |
973 | 0 | return (*channel->funcs->io_set_flags) (channel, |
974 | 0 | flags & G_IO_FLAG_SET_MASK, |
975 | 0 | error); |
976 | 0 | } |
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 | | g_io_channel_get_flags (GIOChannel *channel) |
996 | 0 | { |
997 | 0 | GIOFlags flags; |
998 | |
|
999 | 0 | g_return_val_if_fail (channel != NULL, 0); |
1000 | | |
1001 | 0 | flags = (* channel->funcs->io_get_flags) (channel); |
1002 | | |
1003 | | /* Cross implementation code */ |
1004 | |
|
1005 | 0 | if (channel->is_seekable) |
1006 | 0 | flags |= G_IO_FLAG_IS_SEEKABLE; |
1007 | 0 | if (channel->is_readable) |
1008 | 0 | flags |= G_IO_FLAG_IS_READABLE; |
1009 | 0 | if (channel->is_writeable) |
1010 | 0 | flags |= G_IO_FLAG_IS_WRITABLE; |
1011 | |
|
1012 | 0 | return flags; |
1013 | 0 | } |
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 | | g_io_channel_set_close_on_unref (GIOChannel *channel, |
1030 | | gboolean do_close) |
1031 | 0 | { |
1032 | 0 | g_return_if_fail (channel != NULL); |
1033 | | |
1034 | 0 | channel->close_on_unref = do_close; |
1035 | 0 | } |
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 | | g_io_channel_get_close_on_unref (GIOChannel *channel) |
1050 | 0 | { |
1051 | 0 | g_return_val_if_fail (channel != NULL, FALSE); |
1052 | | |
1053 | 0 | return channel->close_on_unref; |
1054 | 0 | } |
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 | | g_io_channel_seek_position (GIOChannel *channel, |
1081 | | gint64 offset, |
1082 | | GSeekType type, |
1083 | | GError **error) |
1084 | 0 | { |
1085 | 0 | 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 | 0 | G_IO_STATUS_ERROR); |
1094 | 0 | g_return_val_if_fail (channel->is_seekable, G_IO_STATUS_ERROR); |
1095 | | |
1096 | 0 | switch (type) |
1097 | 0 | { |
1098 | 0 | case G_SEEK_CUR: /* The user is seeking relative to the head of the buffer */ |
1099 | 0 | if (channel->use_buffer) |
1100 | 0 | { |
1101 | 0 | if (channel->do_encode && channel->encoded_read_buf |
1102 | 0 | && channel->encoded_read_buf->len > 0) |
1103 | 0 | { |
1104 | 0 | g_warning ("Seek type G_SEEK_CUR not allowed for this" |
1105 | 0 | " channel's encoding."); |
1106 | 0 | return G_IO_STATUS_ERROR; |
1107 | 0 | } |
1108 | 0 | if (channel->read_buf) |
1109 | 0 | offset -= channel->read_buf->len; |
1110 | 0 | if (channel->encoded_read_buf) |
1111 | 0 | { |
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 | 0 | } |
1121 | 0 | } |
1122 | 0 | break; |
1123 | 0 | case G_SEEK_SET: |
1124 | 0 | 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 | 0 | } |
1130 | | |
1131 | 0 | if (channel->use_buffer) |
1132 | 0 | { |
1133 | 0 | status = g_io_channel_flush (channel, error); |
1134 | 0 | if (status != G_IO_STATUS_NORMAL) |
1135 | 0 | return status; |
1136 | 0 | } |
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 | 0 | { |
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 | 0 | { |
1153 | 0 | g_assert (channel->encoded_read_buf->len == 0 || !channel->do_encode); |
1154 | 0 | g_string_truncate (channel->encoded_read_buf, 0); |
1155 | 0 | } |
1156 | | |
1157 | 0 | if (channel->partial_write_buf[0] != '\0') |
1158 | 0 | { |
1159 | 0 | g_warning ("Partial character at end of write buffer not flushed."); |
1160 | 0 | channel->partial_write_buf[0] = '\0'; |
1161 | 0 | } |
1162 | 0 | } |
1163 | | |
1164 | 0 | return status; |
1165 | 0 | } |
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 | | g_io_channel_flush (GIOChannel *channel, |
1180 | | GError **error) |
1181 | 0 | { |
1182 | 0 | GIOStatus status; |
1183 | 0 | gsize this_time = 1, bytes_written = 0; |
1184 | |
|
1185 | 0 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
1186 | 0 | g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); |
1187 | | |
1188 | 0 | if (channel->write_buf == NULL || channel->write_buf->len == 0) |
1189 | 0 | return G_IO_STATUS_NORMAL; |
1190 | | |
1191 | 0 | do |
1192 | 0 | { |
1193 | 0 | g_assert (this_time > 0); |
1194 | | |
1195 | 0 | status = channel->funcs->io_write (channel, |
1196 | 0 | channel->write_buf->str + bytes_written, |
1197 | 0 | channel->write_buf->len - bytes_written, |
1198 | 0 | &this_time, error); |
1199 | 0 | bytes_written += this_time; |
1200 | 0 | } |
1201 | 0 | while ((bytes_written < channel->write_buf->len) |
1202 | 0 | && (status == G_IO_STATUS_NORMAL)); |
1203 | | |
1204 | 0 | g_string_erase (channel->write_buf, 0, bytes_written); |
1205 | |
|
1206 | 0 | return status; |
1207 | 0 | } |
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 | | g_io_channel_set_buffered (GIOChannel *channel, |
1236 | | gboolean buffered) |
1237 | 0 | { |
1238 | 0 | g_return_if_fail (channel != NULL); |
1239 | | |
1240 | 0 | if (channel->encoding != NULL) |
1241 | 0 | { |
1242 | 0 | g_warning ("Need to have NULL encoding to set the buffering state of the " |
1243 | 0 | "channel."); |
1244 | 0 | return; |
1245 | 0 | } |
1246 | | |
1247 | 0 | g_return_if_fail (!channel->read_buf || channel->read_buf->len == 0); |
1248 | 0 | g_return_if_fail (!channel->write_buf || channel->write_buf->len == 0); |
1249 | | |
1250 | 0 | channel->use_buffer = buffered; |
1251 | 0 | } |
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 | | g_io_channel_get_buffered (GIOChannel *channel) |
1263 | 0 | { |
1264 | 0 | g_return_val_if_fail (channel != NULL, FALSE); |
1265 | | |
1266 | 0 | return channel->use_buffer; |
1267 | 0 | } |
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 | | g_io_channel_set_encoding (GIOChannel *channel, |
1314 | | const gchar *encoding, |
1315 | | GError **error) |
1316 | 0 | { |
1317 | 0 | GIConv read_cd, write_cd; |
1318 | 0 | #ifndef G_DISABLE_ASSERT |
1319 | 0 | gboolean did_encode; |
1320 | 0 | #endif |
1321 | |
|
1322 | 0 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
1323 | 0 | g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); |
1324 | | |
1325 | | /* Make sure the encoded buffers are empty */ |
1326 | | |
1327 | 0 | g_return_val_if_fail (!channel->do_encode || !channel->encoded_read_buf || |
1328 | 0 | channel->encoded_read_buf->len == 0, G_IO_STATUS_ERROR); |
1329 | | |
1330 | 0 | if (!channel->use_buffer) |
1331 | 0 | { |
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 | 0 | } |
1337 | |
|
1338 | 0 | if (channel->partial_write_buf[0] != '\0') |
1339 | 0 | { |
1340 | 0 | g_warning ("Partial character at end of write buffer not flushed."); |
1341 | 0 | channel->partial_write_buf[0] = '\0'; |
1342 | 0 | } |
1343 | |
|
1344 | 0 | #ifndef G_DISABLE_ASSERT |
1345 | 0 | did_encode = channel->do_encode; |
1346 | 0 | #endif |
1347 | |
|
1348 | 0 | if (!encoding || strcmp (encoding, "UTF8") == 0 || strcmp (encoding, "UTF-8") == 0) |
1349 | 0 | { |
1350 | 0 | channel->do_encode = FALSE; |
1351 | 0 | read_cd = write_cd = (GIConv) -1; |
1352 | 0 | } |
1353 | 0 | else |
1354 | 0 | { |
1355 | 0 | gint err = 0; |
1356 | 0 | const gchar *from_enc = NULL, *to_enc = NULL; |
1357 | |
|
1358 | 0 | if (channel->is_readable) |
1359 | 0 | { |
1360 | 0 | read_cd = g_iconv_open ("UTF-8", encoding); |
1361 | |
|
1362 | 0 | if (read_cd == (GIConv) -1) |
1363 | 0 | { |
1364 | 0 | err = errno; |
1365 | 0 | from_enc = encoding; |
1366 | 0 | to_enc = "UTF-8"; |
1367 | 0 | } |
1368 | 0 | } |
1369 | 0 | else |
1370 | 0 | read_cd = (GIConv) -1; |
1371 | |
|
1372 | 0 | if (channel->is_writeable && err == 0) |
1373 | 0 | { |
1374 | 0 | write_cd = g_iconv_open (encoding, "UTF-8"); |
1375 | |
|
1376 | 0 | if (write_cd == (GIConv) -1) |
1377 | 0 | { |
1378 | 0 | err = errno; |
1379 | 0 | from_enc = "UTF-8"; |
1380 | 0 | to_enc = encoding; |
1381 | 0 | } |
1382 | 0 | } |
1383 | 0 | else |
1384 | 0 | write_cd = (GIConv) -1; |
1385 | |
|
1386 | 0 | if (err != 0) |
1387 | 0 | { |
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 | 0 | _("Conversion from character set “%s” to “%s” is not supported"), |
1394 | 0 | from_enc, to_enc); |
1395 | 0 | else |
1396 | 0 | g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, |
1397 | 0 | _("Could not open converter from “%s” to “%s”: %s"), |
1398 | 0 | 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 | 0 | } |
1407 | | |
1408 | 0 | channel->do_encode = TRUE; |
1409 | 0 | } |
1410 | | |
1411 | | /* The encoding is ok, so set the fields in channel */ |
1412 | | |
1413 | 0 | if (channel->read_cd != (GIConv) -1) |
1414 | 0 | g_iconv_close (channel->read_cd); |
1415 | 0 | if (channel->write_cd != (GIConv) -1) |
1416 | 0 | g_iconv_close (channel->write_cd); |
1417 | |
|
1418 | 0 | if (channel->encoded_read_buf && channel->encoded_read_buf->len > 0) |
1419 | 0 | { |
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 | 0 | } |
1430 | | |
1431 | 0 | channel->read_cd = read_cd; |
1432 | 0 | channel->write_cd = write_cd; |
1433 | |
|
1434 | 0 | g_free (channel->encoding); |
1435 | 0 | channel->encoding = g_strdup (encoding); |
1436 | |
|
1437 | 0 | return G_IO_STATUS_NORMAL; |
1438 | 0 | } |
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 | | g_io_channel_get_encoding (GIOChannel *channel) |
1453 | 0 | { |
1454 | 0 | g_return_val_if_fail (channel != NULL, NULL); |
1455 | | |
1456 | 0 | return channel->encoding; |
1457 | 0 | } |
1458 | | |
1459 | | static GIOStatus |
1460 | | g_io_channel_fill_buffer (GIOChannel *channel, |
1461 | | GError **err) |
1462 | 0 | { |
1463 | 0 | gsize read_size, cur_len, oldlen; |
1464 | 0 | GIOStatus status; |
1465 | |
|
1466 | 0 | if (channel->is_seekable && channel->write_buf && channel->write_buf->len > 0) |
1467 | 0 | { |
1468 | 0 | status = g_io_channel_flush (channel, err); |
1469 | 0 | if (status != G_IO_STATUS_NORMAL) |
1470 | 0 | return status; |
1471 | 0 | } |
1472 | 0 | if (channel->is_seekable && channel->partial_write_buf[0] != '\0') |
1473 | 0 | { |
1474 | 0 | g_warning ("Partial character at end of write buffer not flushed."); |
1475 | 0 | channel->partial_write_buf[0] = '\0'; |
1476 | 0 | } |
1477 | |
|
1478 | 0 | if (!channel->read_buf) |
1479 | 0 | channel->read_buf = g_string_sized_new (channel->buf_size); |
1480 | |
|
1481 | 0 | cur_len = channel->read_buf->len; |
1482 | |
|
1483 | 0 | g_string_set_size (channel->read_buf, channel->read_buf->len + channel->buf_size); |
1484 | |
|
1485 | 0 | status = channel->funcs->io_read (channel, channel->read_buf->str + cur_len, |
1486 | 0 | channel->buf_size, &read_size, err); |
1487 | |
|
1488 | 0 | g_assert ((status == G_IO_STATUS_NORMAL) || (read_size == 0)); |
1489 | | |
1490 | 0 | g_string_truncate (channel->read_buf, read_size + cur_len); |
1491 | |
|
1492 | 0 | if ((status != G_IO_STATUS_NORMAL) && |
1493 | 0 | ((status != G_IO_STATUS_EOF) || (channel->read_buf->len == 0))) |
1494 | 0 | return status; |
1495 | | |
1496 | 0 | g_assert (channel->read_buf->len > 0); |
1497 | | |
1498 | 0 | if (channel->encoded_read_buf) |
1499 | 0 | oldlen = channel->encoded_read_buf->len; |
1500 | 0 | else |
1501 | 0 | { |
1502 | 0 | oldlen = 0; |
1503 | 0 | if (channel->encoding) |
1504 | 0 | channel->encoded_read_buf = g_string_sized_new (channel->buf_size); |
1505 | 0 | } |
1506 | |
|
1507 | 0 | if (channel->do_encode) |
1508 | 0 | { |
1509 | 0 | gsize errnum, inbytes_left, outbytes_left; |
1510 | 0 | gchar *inbuf, *outbuf; |
1511 | 0 | int errval; |
1512 | |
|
1513 | 0 | g_assert (channel->encoded_read_buf); |
1514 | | |
1515 | 0 | reencode: |
1516 | |
|
1517 | 0 | inbytes_left = channel->read_buf->len; |
1518 | 0 | outbytes_left = MAX (channel->read_buf->len, |
1519 | 0 | channel->encoded_read_buf->allocated_len |
1520 | 0 | - channel->encoded_read_buf->len - 1); /* 1 for NULL */ |
1521 | 0 | outbytes_left = MAX (outbytes_left, 6); |
1522 | |
|
1523 | 0 | inbuf = channel->read_buf->str; |
1524 | 0 | g_string_set_size (channel->encoded_read_buf, |
1525 | 0 | channel->encoded_read_buf->len + outbytes_left); |
1526 | 0 | outbuf = channel->encoded_read_buf->str + channel->encoded_read_buf->len |
1527 | 0 | - outbytes_left; |
1528 | |
|
1529 | 0 | errnum = g_iconv (channel->read_cd, &inbuf, &inbytes_left, |
1530 | 0 | &outbuf, &outbytes_left); |
1531 | 0 | errval = errno; |
1532 | |
|
1533 | 0 | g_assert (inbuf + inbytes_left == channel->read_buf->str |
1534 | 0 | + channel->read_buf->len); |
1535 | 0 | g_assert (outbuf + outbytes_left == channel->encoded_read_buf->str |
1536 | 0 | + channel->encoded_read_buf->len); |
1537 | | |
1538 | 0 | g_string_erase (channel->read_buf, 0, |
1539 | 0 | channel->read_buf->len - inbytes_left); |
1540 | 0 | g_string_truncate (channel->encoded_read_buf, |
1541 | 0 | channel->encoded_read_buf->len - outbytes_left); |
1542 | |
|
1543 | 0 | if (errnum == (gsize) -1) |
1544 | 0 | { |
1545 | 0 | switch (errval) |
1546 | 0 | { |
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 | 0 | 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 | 0 | else |
1562 | 0 | { |
1563 | 0 | g_set_error_literal (err, G_CONVERT_ERROR, |
1564 | 0 | G_CONVERT_ERROR_ILLEGAL_SEQUENCE, |
1565 | 0 | _("Invalid byte sequence in conversion input")); |
1566 | 0 | return G_IO_STATUS_ERROR; |
1567 | 0 | } |
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 | 0 | _("Error during conversion: %s"), g_strerror (errval)); |
1573 | 0 | return G_IO_STATUS_ERROR; |
1574 | 0 | } |
1575 | 0 | } |
1576 | 0 | g_assert ((status != G_IO_STATUS_NORMAL) |
1577 | 0 | || (channel->encoded_read_buf->len > 0)); |
1578 | 0 | } |
1579 | 0 | else if (channel->encoding) /* UTF-8 */ |
1580 | 0 | { |
1581 | 0 | gchar *nextchar, *lastchar; |
1582 | |
|
1583 | 0 | g_assert (channel->encoded_read_buf); |
1584 | | |
1585 | 0 | nextchar = channel->read_buf->str; |
1586 | 0 | lastchar = channel->read_buf->str + channel->read_buf->len; |
1587 | |
|
1588 | 0 | while (nextchar < lastchar) |
1589 | 0 | { |
1590 | 0 | gunichar val_char; |
1591 | |
|
1592 | 0 | val_char = g_utf8_get_char_validated (nextchar, lastchar - nextchar); |
1593 | |
|
1594 | 0 | switch (val_char) |
1595 | 0 | { |
1596 | 0 | case -2: |
1597 | | /* stop, leave partial character in buffer */ |
1598 | 0 | lastchar = nextchar; |
1599 | 0 | break; |
1600 | 0 | case -1: |
1601 | 0 | if (oldlen < channel->encoded_read_buf->len) |
1602 | 0 | status = G_IO_STATUS_NORMAL; |
1603 | 0 | else |
1604 | 0 | { |
1605 | 0 | g_set_error_literal (err, G_CONVERT_ERROR, |
1606 | 0 | G_CONVERT_ERROR_ILLEGAL_SEQUENCE, |
1607 | 0 | _("Invalid byte sequence in conversion input")); |
1608 | 0 | status = G_IO_STATUS_ERROR; |
1609 | 0 | } |
1610 | 0 | lastchar = nextchar; |
1611 | 0 | break; |
1612 | 0 | default: |
1613 | 0 | nextchar = g_utf8_next_char (nextchar); |
1614 | 0 | break; |
1615 | 0 | } |
1616 | 0 | } |
1617 | | |
1618 | 0 | if (lastchar > channel->read_buf->str) |
1619 | 0 | { |
1620 | 0 | gint copy_len = lastchar - channel->read_buf->str; |
1621 | |
|
1622 | 0 | g_string_append_len (channel->encoded_read_buf, channel->read_buf->str, |
1623 | 0 | copy_len); |
1624 | 0 | g_string_erase (channel->read_buf, 0, copy_len); |
1625 | 0 | } |
1626 | 0 | } |
1627 | | |
1628 | 0 | return status; |
1629 | 0 | } |
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 | | g_io_channel_read_line (GIOChannel *channel, |
1652 | | gchar **str_return, |
1653 | | gsize *length, |
1654 | | gsize *terminator_pos, |
1655 | | GError **error) |
1656 | 0 | { |
1657 | 0 | GIOStatus status; |
1658 | 0 | gsize got_length; |
1659 | | |
1660 | 0 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
1661 | 0 | g_return_val_if_fail (str_return != NULL, G_IO_STATUS_ERROR); |
1662 | 0 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
1663 | 0 | G_IO_STATUS_ERROR); |
1664 | 0 | g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); |
1665 | | |
1666 | 0 | status = g_io_channel_read_line_backend (channel, &got_length, terminator_pos, error); |
1667 | |
|
1668 | 0 | if (length && status != G_IO_STATUS_ERROR) |
1669 | 0 | *length = got_length; |
1670 | |
|
1671 | 0 | if (status == G_IO_STATUS_NORMAL) |
1672 | 0 | { |
1673 | 0 | 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 | 0 | g_assert (USE_BUF (channel)); |
1680 | 0 | line = g_memdup2 (USE_BUF (channel)->str, got_length + 1); |
1681 | 0 | line[got_length] = '\0'; |
1682 | 0 | *str_return = g_steal_pointer (&line); |
1683 | 0 | g_string_erase (USE_BUF (channel), 0, got_length); |
1684 | 0 | } |
1685 | 0 | else |
1686 | 0 | *str_return = NULL; |
1687 | | |
1688 | 0 | return status; |
1689 | 0 | } |
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 | | g_io_channel_read_line_string (GIOChannel *channel, |
1707 | | GString *buffer, |
1708 | | gsize *terminator_pos, |
1709 | | GError **error) |
1710 | 0 | { |
1711 | 0 | gsize length; |
1712 | 0 | GIOStatus status; |
1713 | |
|
1714 | 0 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
1715 | 0 | g_return_val_if_fail (buffer != NULL, G_IO_STATUS_ERROR); |
1716 | 0 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
1717 | 0 | G_IO_STATUS_ERROR); |
1718 | 0 | g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); |
1719 | | |
1720 | 0 | if (buffer->len > 0) |
1721 | 0 | g_string_truncate (buffer, 0); /* clear out the buffer */ |
1722 | |
|
1723 | 0 | status = g_io_channel_read_line_backend (channel, &length, terminator_pos, error); |
1724 | |
|
1725 | 0 | if (status == G_IO_STATUS_NORMAL) |
1726 | 0 | { |
1727 | 0 | g_assert (USE_BUF (channel)); |
1728 | 0 | g_string_append_len (buffer, USE_BUF (channel)->str, length); |
1729 | 0 | g_string_erase (USE_BUF (channel), 0, length); |
1730 | 0 | } |
1731 | | |
1732 | 0 | return status; |
1733 | 0 | } |
1734 | | |
1735 | | |
1736 | | static GIOStatus |
1737 | | g_io_channel_read_line_backend (GIOChannel *channel, |
1738 | | gsize *length, |
1739 | | gsize *terminator_pos, |
1740 | | GError **error) |
1741 | 0 | { |
1742 | 0 | GIOStatus status; |
1743 | 0 | gsize checked_to, line_term_len, line_length, got_term_len; |
1744 | 0 | gboolean first_time = TRUE; |
1745 | |
|
1746 | 0 | if (!channel->use_buffer) |
1747 | 0 | { |
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 | 0 | _("Can’t do a raw read in g_io_channel_read_line_string")); |
1751 | 0 | return G_IO_STATUS_ERROR; |
1752 | 0 | } |
1753 | | |
1754 | 0 | status = G_IO_STATUS_NORMAL; |
1755 | |
|
1756 | 0 | if (channel->line_term) |
1757 | 0 | line_term_len = channel->line_term_len; |
1758 | 0 | else |
1759 | 0 | 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 | 0 | checked_to = 0; |
1765 | |
|
1766 | 0 | while (TRUE) |
1767 | 0 | { |
1768 | 0 | gchar *nextchar, *lastchar; |
1769 | 0 | GString *use_buf; |
1770 | |
|
1771 | 0 | if (!first_time || (BUF_LEN (USE_BUF (channel)) == 0)) |
1772 | 0 | { |
1773 | 0 | read_again: |
1774 | 0 | status = g_io_channel_fill_buffer (channel, error); |
1775 | 0 | switch (status) |
1776 | 0 | { |
1777 | 0 | case G_IO_STATUS_NORMAL: |
1778 | 0 | if (BUF_LEN (USE_BUF (channel)) == 0) |
1779 | | /* Can happen when using conversion and only read |
1780 | | * part of a character |
1781 | | */ |
1782 | 0 | { |
1783 | 0 | first_time = FALSE; |
1784 | 0 | continue; |
1785 | 0 | } |
1786 | 0 | break; |
1787 | 0 | case G_IO_STATUS_EOF: |
1788 | 0 | if (BUF_LEN (USE_BUF (channel)) == 0) |
1789 | 0 | { |
1790 | 0 | if (length) |
1791 | 0 | *length = 0; |
1792 | |
|
1793 | 0 | if (channel->encoding && channel->read_buf->len != 0) |
1794 | 0 | { |
1795 | 0 | g_set_error_literal (error, G_CONVERT_ERROR, |
1796 | 0 | G_CONVERT_ERROR_PARTIAL_INPUT, |
1797 | 0 | _("Leftover unconverted data in " |
1798 | 0 | "read buffer")); |
1799 | 0 | return G_IO_STATUS_ERROR; |
1800 | 0 | } |
1801 | 0 | else |
1802 | 0 | return G_IO_STATUS_EOF; |
1803 | 0 | } |
1804 | 0 | break; |
1805 | 0 | default: |
1806 | 0 | if (length) |
1807 | 0 | *length = 0; |
1808 | 0 | return status; |
1809 | 0 | } |
1810 | 0 | } |
1811 | | |
1812 | 0 | g_assert (BUF_LEN (USE_BUF (channel)) != 0); |
1813 | | |
1814 | 0 | use_buf = USE_BUF (channel); /* The buffer has been created by this point */ |
1815 | |
|
1816 | 0 | first_time = FALSE; |
1817 | |
|
1818 | 0 | lastchar = use_buf->str + use_buf->len; |
1819 | |
|
1820 | 0 | for (nextchar = use_buf->str + checked_to; nextchar < lastchar; |
1821 | 0 | channel->encoding ? nextchar = g_utf8_next_char (nextchar) : nextchar++) |
1822 | 0 | { |
1823 | 0 | if (channel->line_term) |
1824 | 0 | { |
1825 | 0 | if (memcmp (channel->line_term, nextchar, line_term_len) == 0) |
1826 | 0 | { |
1827 | 0 | line_length = nextchar - use_buf->str; |
1828 | 0 | got_term_len = line_term_len; |
1829 | 0 | goto done; |
1830 | 0 | } |
1831 | 0 | } |
1832 | 0 | else /* auto detect */ |
1833 | 0 | { |
1834 | 0 | switch (*nextchar) |
1835 | 0 | { |
1836 | 0 | case '\n': /* unix */ |
1837 | 0 | line_length = nextchar - use_buf->str; |
1838 | 0 | got_term_len = 1; |
1839 | 0 | 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 | 0 | else /* mac */ |
1848 | 0 | got_term_len = 1; |
1849 | 0 | goto done; |
1850 | 0 | case '\xe2': /* Unicode paragraph separator */ |
1851 | 0 | if (strncmp ("\xe2\x80\xa9", nextchar, 3) == 0) |
1852 | 0 | { |
1853 | 0 | line_length = nextchar - use_buf->str; |
1854 | 0 | got_term_len = 3; |
1855 | 0 | goto done; |
1856 | 0 | } |
1857 | 0 | 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 | 0 | default: /* no match */ |
1863 | 0 | break; |
1864 | 0 | } |
1865 | 0 | } |
1866 | 0 | } |
1867 | | |
1868 | | /* If encoding != NULL, valid UTF-8, didn't overshoot */ |
1869 | 0 | g_assert (nextchar == lastchar); |
1870 | | |
1871 | | /* Check for EOF */ |
1872 | | |
1873 | 0 | if (status == G_IO_STATUS_EOF) |
1874 | 0 | { |
1875 | 0 | if (channel->encoding && channel->read_buf->len > 0) |
1876 | 0 | { |
1877 | 0 | g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT, |
1878 | 0 | _("Channel terminates in a partial character")); |
1879 | 0 | return G_IO_STATUS_ERROR; |
1880 | 0 | } |
1881 | 0 | line_length = use_buf->len; |
1882 | 0 | got_term_len = 0; |
1883 | 0 | break; |
1884 | 0 | } |
1885 | | |
1886 | 0 | if (use_buf->len > line_term_len - 1) |
1887 | 0 | checked_to = use_buf->len - (line_term_len - 1); |
1888 | 0 | else |
1889 | 0 | checked_to = 0; |
1890 | 0 | } |
1891 | | |
1892 | 0 | done: |
1893 | |
|
1894 | 0 | if (terminator_pos) |
1895 | 0 | *terminator_pos = line_length; |
1896 | |
|
1897 | 0 | if (length) |
1898 | 0 | *length = line_length + got_term_len; |
1899 | |
|
1900 | 0 | return G_IO_STATUS_NORMAL; |
1901 | 0 | } |
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 | | g_io_channel_read_to_end (GIOChannel *channel, |
1922 | | gchar **str_return, |
1923 | | gsize *length, |
1924 | | GError **error) |
1925 | 0 | { |
1926 | 0 | 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 | 0 | 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 | 0 | { |
1940 | 0 | g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED, |
1941 | 0 | _("Can’t do a raw read in g_io_channel_read_to_end")); |
1942 | 0 | return G_IO_STATUS_ERROR; |
1943 | 0 | } |
1944 | | |
1945 | 0 | 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 | 0 | { |
1954 | 0 | g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT, |
1955 | 0 | _("Channel terminates in a partial character")); |
1956 | 0 | return G_IO_STATUS_ERROR; |
1957 | 0 | } |
1958 | | |
1959 | 0 | if (USE_BUF (channel) == NULL) |
1960 | 0 | { |
1961 | | /* length is already set to zero */ |
1962 | 0 | if (str_return) |
1963 | 0 | *str_return = g_strdup (""); |
1964 | 0 | } |
1965 | 0 | else |
1966 | 0 | { |
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 | 0 | else |
1973 | 0 | g_string_free (USE_BUF (channel), TRUE); |
1974 | |
|
1975 | 0 | if (channel->encoding) |
1976 | 0 | channel->encoded_read_buf = NULL; |
1977 | 0 | else |
1978 | 0 | channel->read_buf = NULL; |
1979 | 0 | } |
1980 | |
|
1981 | 0 | return G_IO_STATUS_NORMAL; |
1982 | 0 | } |
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 | | g_io_channel_read_chars (GIOChannel *channel, |
2005 | | gchar *buf, |
2006 | | gsize count, |
2007 | | gsize *bytes_read, |
2008 | | GError **error) |
2009 | 0 | { |
2010 | 0 | GIOStatus status; |
2011 | 0 | gsize got_bytes; |
2012 | |
|
2013 | 0 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
2014 | 0 | g_return_val_if_fail ((error == NULL) || (*error == NULL), G_IO_STATUS_ERROR); |
2015 | 0 | g_return_val_if_fail (channel->is_readable, G_IO_STATUS_ERROR); |
2016 | | |
2017 | 0 | if (count == 0) |
2018 | 0 | { |
2019 | 0 | if (bytes_read) |
2020 | 0 | *bytes_read = 0; |
2021 | 0 | return G_IO_STATUS_NORMAL; |
2022 | 0 | } |
2023 | 0 | g_return_val_if_fail (buf != NULL, G_IO_STATUS_ERROR); |
2024 | | |
2025 | 0 | if (!channel->use_buffer) |
2026 | 0 | { |
2027 | 0 | gsize tmp_bytes; |
2028 | |
|
2029 | 0 | g_assert (!channel->read_buf || channel->read_buf->len == 0); |
2030 | | |
2031 | 0 | status = channel->funcs->io_read (channel, buf, count, &tmp_bytes, error); |
2032 | |
|
2033 | 0 | if (bytes_read) |
2034 | 0 | *bytes_read = tmp_bytes; |
2035 | |
|
2036 | 0 | return status; |
2037 | 0 | } |
2038 | | |
2039 | 0 | status = G_IO_STATUS_NORMAL; |
2040 | |
|
2041 | 0 | while (BUF_LEN (USE_BUF (channel)) < count && status == G_IO_STATUS_NORMAL) |
2042 | 0 | status = g_io_channel_fill_buffer (channel, error); |
2043 | | |
2044 | | /* Only return an error if we have no data */ |
2045 | |
|
2046 | 0 | if (BUF_LEN (USE_BUF (channel)) == 0) |
2047 | 0 | { |
2048 | 0 | g_assert (status != G_IO_STATUS_NORMAL); |
2049 | | |
2050 | 0 | if (status == G_IO_STATUS_EOF && channel->encoding |
2051 | 0 | && BUF_LEN (channel->read_buf) > 0) |
2052 | 0 | { |
2053 | 0 | g_set_error_literal (error, G_CONVERT_ERROR, |
2054 | 0 | G_CONVERT_ERROR_PARTIAL_INPUT, |
2055 | 0 | _("Leftover unconverted data in read buffer")); |
2056 | 0 | status = G_IO_STATUS_ERROR; |
2057 | 0 | } |
2058 | |
|
2059 | 0 | if (bytes_read) |
2060 | 0 | *bytes_read = 0; |
2061 | |
|
2062 | 0 | return status; |
2063 | 0 | } |
2064 | | |
2065 | 0 | if (status == G_IO_STATUS_ERROR) |
2066 | 0 | g_clear_error (error); |
2067 | |
|
2068 | 0 | got_bytes = MIN (count, BUF_LEN (USE_BUF (channel))); |
2069 | |
|
2070 | 0 | g_assert (got_bytes > 0); |
2071 | | |
2072 | 0 | if (channel->encoding) |
2073 | | /* Don't validate for NULL encoding, binary safe */ |
2074 | 0 | { |
2075 | 0 | gchar *nextchar, *prevchar; |
2076 | |
|
2077 | 0 | g_assert (USE_BUF (channel) == channel->encoded_read_buf); |
2078 | | |
2079 | 0 | nextchar = channel->encoded_read_buf->str; |
2080 | |
|
2081 | 0 | do |
2082 | 0 | { |
2083 | 0 | prevchar = nextchar; |
2084 | 0 | nextchar = g_utf8_next_char (nextchar); |
2085 | 0 | g_assert (nextchar != prevchar); /* Possible for *prevchar of -1 or -2 */ |
2086 | 0 | } |
2087 | 0 | while (nextchar < channel->encoded_read_buf->str + got_bytes); |
2088 | | |
2089 | 0 | if (nextchar > channel->encoded_read_buf->str + got_bytes) |
2090 | 0 | got_bytes = prevchar - channel->encoded_read_buf->str; |
2091 | |
|
2092 | 0 | g_assert (got_bytes > 0 || count < 6); |
2093 | 0 | } |
2094 | | |
2095 | 0 | memcpy (buf, USE_BUF (channel)->str, got_bytes); |
2096 | 0 | g_string_erase (USE_BUF (channel), 0, got_bytes); |
2097 | |
|
2098 | 0 | if (bytes_read) |
2099 | 0 | *bytes_read = got_bytes; |
2100 | |
|
2101 | 0 | return G_IO_STATUS_NORMAL; |
2102 | 0 | } |
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 | | g_io_channel_read_unichar (GIOChannel *channel, |
2118 | | gunichar *thechar, |
2119 | | GError **error) |
2120 | 0 | { |
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 | 0 | 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 | 0 | { |
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 | 0 | { |
2140 | 0 | g_set_error_literal (error, G_CONVERT_ERROR, |
2141 | 0 | G_CONVERT_ERROR_PARTIAL_INPUT, |
2142 | 0 | _("Leftover unconverted data in read buffer")); |
2143 | 0 | status = G_IO_STATUS_ERROR; |
2144 | 0 | } |
2145 | |
|
2146 | 0 | if (thechar) |
2147 | 0 | *thechar = (gunichar) -1; |
2148 | |
|
2149 | 0 | return status; |
2150 | 0 | } |
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 | 0 | } |
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 | | g_io_channel_write_chars (GIOChannel *channel, |
2190 | | const gchar *buf, |
2191 | | gssize count, |
2192 | | gsize *bytes_written, |
2193 | | GError **error) |
2194 | 0 | { |
2195 | 0 | gsize count_unsigned; |
2196 | 0 | GIOStatus status; |
2197 | 0 | gsize wrote_bytes = 0; |
2198 | |
|
2199 | 0 | g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR); |
2200 | 0 | g_return_val_if_fail (buf != NULL || count == 0, G_IO_STATUS_ERROR); |
2201 | 0 | g_return_val_if_fail ((error == NULL) || (*error == NULL), |
2202 | 0 | G_IO_STATUS_ERROR); |
2203 | 0 | g_return_val_if_fail (channel->is_writeable, G_IO_STATUS_ERROR); |
2204 | | |
2205 | 0 | if (count < 0) |
2206 | 0 | count_unsigned = strlen (buf); |
2207 | 0 | else |
2208 | 0 | count_unsigned = count; |
2209 | |
|
2210 | 0 | if (count_unsigned == 0) |
2211 | 0 | { |
2212 | 0 | if (bytes_written) |
2213 | 0 | *bytes_written = 0; |
2214 | 0 | return G_IO_STATUS_NORMAL; |
2215 | 0 | } |
2216 | | |
2217 | 0 | g_assert (count_unsigned > 0); |
2218 | | |
2219 | | /* Raw write case */ |
2220 | | |
2221 | 0 | if (!channel->use_buffer) |
2222 | 0 | { |
2223 | 0 | 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 | 0 | &tmp_bytes, error); |
2230 | |
|
2231 | 0 | if (bytes_written) |
2232 | 0 | *bytes_written = tmp_bytes; |
2233 | |
|
2234 | 0 | return status; |
2235 | 0 | } |
2236 | | |
2237 | | /* General case */ |
2238 | | |
2239 | 0 | if (channel->is_seekable && (( BUF_LEN (channel->read_buf) > 0) |
2240 | 0 | || (BUF_LEN (channel->encoded_read_buf) > 0))) |
2241 | 0 | { |
2242 | 0 | if (channel->do_encode && BUF_LEN (channel->encoded_read_buf) > 0) |
2243 | 0 | { |
2244 | 0 | g_warning ("Mixed reading and writing not allowed on encoded files"); |
2245 | 0 | return G_IO_STATUS_ERROR; |
2246 | 0 | } |
2247 | 0 | status = g_io_channel_seek_position (channel, 0, G_SEEK_CUR, error); |
2248 | 0 | if (status != G_IO_STATUS_NORMAL) |
2249 | 0 | { |
2250 | 0 | if (bytes_written) |
2251 | 0 | *bytes_written = 0; |
2252 | 0 | return status; |
2253 | 0 | } |
2254 | 0 | } |
2255 | | |
2256 | 0 | if (!channel->write_buf) |
2257 | 0 | channel->write_buf = g_string_sized_new (channel->buf_size); |
2258 | |
|
2259 | 0 | while (wrote_bytes < count_unsigned) |
2260 | 0 | { |
2261 | 0 | 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 | 0 | if (channel->write_buf->len >= channel->buf_size - MAX_CHAR_SIZE) |
2270 | 0 | { |
2271 | 0 | gsize did_write = 0, this_time; |
2272 | |
|
2273 | 0 | do |
2274 | 0 | { |
2275 | 0 | status = channel->funcs->io_write (channel, channel->write_buf->str |
2276 | 0 | + did_write, channel->write_buf->len |
2277 | 0 | - did_write, &this_time, error); |
2278 | 0 | did_write += this_time; |
2279 | 0 | } |
2280 | 0 | while (status == G_IO_STATUS_NORMAL && |
2281 | 0 | did_write < MIN (channel->write_buf->len, MAX_CHAR_SIZE)); |
2282 | |
|
2283 | 0 | g_string_erase (channel->write_buf, 0, did_write); |
2284 | |
|
2285 | 0 | if (status != G_IO_STATUS_NORMAL) |
2286 | 0 | { |
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 | 0 | } |
2293 | 0 | } |
2294 | | |
2295 | 0 | space_in_buf = MAX (channel->buf_size, channel->write_buf->allocated_len - 1) |
2296 | 0 | - 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 | 0 | g_assert (space_in_buf >= MAX_CHAR_SIZE); |
2302 | | |
2303 | 0 | if (!channel->encoding) |
2304 | 0 | { |
2305 | 0 | 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 | 0 | if (write_this > G_MAXSSIZE) |
2309 | 0 | write_this = G_MAXSSIZE; |
2310 | |
|
2311 | 0 | g_string_append_len (channel->write_buf, buf, write_this); |
2312 | 0 | buf += write_this; |
2313 | 0 | wrote_bytes += write_this; |
2314 | 0 | } |
2315 | 0 | else |
2316 | 0 | { |
2317 | 0 | const gchar *from_buf; |
2318 | 0 | gsize from_buf_len, from_buf_old_len, left_len; |
2319 | 0 | gsize err; |
2320 | 0 | gint errnum; |
2321 | |
|
2322 | 0 | if (channel->partial_write_buf[0] != '\0') |
2323 | 0 | { |
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 | 0 | from_buf_len - from_buf_old_len); |
2333 | 0 | } |
2334 | 0 | else |
2335 | 0 | { |
2336 | 0 | from_buf = buf; |
2337 | 0 | from_buf_len = count_unsigned - wrote_bytes; |
2338 | 0 | from_buf_old_len = 0; |
2339 | 0 | } |
2340 | | |
2341 | 0 | reconvert: |
2342 | |
|
2343 | 0 | if (!channel->do_encode) /* UTF-8 encoding */ |
2344 | 0 | { |
2345 | 0 | const gchar *badchar; |
2346 | 0 | gsize try_len = MIN (from_buf_len, space_in_buf); |
2347 | | |
2348 | | /* UTF-8, just validate, emulate g_iconv */ |
2349 | |
|
2350 | 0 | if (!g_utf8_validate_len (from_buf, try_len, &badchar)) |
2351 | 0 | { |
2352 | 0 | 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 | 0 | { |
2361 | 0 | case -2: |
2362 | 0 | g_assert (incomplete_len < 6); |
2363 | 0 | if (try_len == from_buf_len) |
2364 | 0 | { |
2365 | 0 | errnum = EINVAL; |
2366 | 0 | err = (gsize) -1; |
2367 | 0 | } |
2368 | 0 | else |
2369 | 0 | { |
2370 | 0 | errnum = 0; |
2371 | 0 | err = (gsize) 0; |
2372 | 0 | } |
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 | 0 | g_assert_not_reached (); |
2382 | 0 | err = (gsize) -1; |
2383 | 0 | errnum = 0; /* Don't confuse the compiler */ |
2384 | 0 | } |
2385 | 0 | } |
2386 | 0 | else |
2387 | 0 | { |
2388 | 0 | err = (gsize) 0; |
2389 | 0 | errnum = 0; |
2390 | 0 | left_len = from_buf_len - try_len; |
2391 | 0 | } |
2392 | | |
2393 | 0 | g_string_append_len (channel->write_buf, from_buf, |
2394 | 0 | from_buf_len - left_len); |
2395 | 0 | from_buf += from_buf_len - left_len; |
2396 | 0 | } |
2397 | 0 | else |
2398 | 0 | { |
2399 | 0 | gchar *outbuf; |
2400 | |
|
2401 | 0 | left_len = from_buf_len; |
2402 | 0 | g_string_set_size (channel->write_buf, channel->write_buf->len |
2403 | 0 | + 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 | 0 | &outbuf, &space_in_buf); |
2408 | 0 | errnum = errno; |
2409 | 0 | g_string_truncate (channel->write_buf, channel->write_buf->len |
2410 | 0 | - space_in_buf); |
2411 | 0 | } |
2412 | | |
2413 | 0 | if (err == (gsize) -1) |
2414 | 0 | { |
2415 | 0 | switch (errnum) |
2416 | 0 | { |
2417 | 0 | case EINVAL: |
2418 | 0 | g_assert (left_len < 6); |
2419 | | |
2420 | 0 | if (from_buf_old_len == 0) |
2421 | 0 | { |
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 | 0 | } |
2430 | | |
2431 | | /* Working in partial_write_buf */ |
2432 | | |
2433 | 0 | if (left_len == from_buf_len) |
2434 | 0 | { |
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 | 0 | } |
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 | 0 | { |
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 | 0 | } |
2463 | 0 | break; |
2464 | 0 | case EILSEQ: |
2465 | 0 | g_set_error_literal (error, G_CONVERT_ERROR, |
2466 | 0 | G_CONVERT_ERROR_ILLEGAL_SEQUENCE, |
2467 | 0 | _("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 | 0 | "at the end of a previous write."); |
2471 | 0 | else |
2472 | 0 | { |
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 | 0 | } |
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 | 0 | _("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 | 0 | } |
2490 | 0 | } |
2491 | | |
2492 | 0 | g_assert (from_buf_len - left_len >= from_buf_old_len); |
2493 | | |
2494 | 0 | wrote_bytes += from_buf_len - left_len - from_buf_old_len; |
2495 | |
|
2496 | 0 | if (from_buf_old_len > 0) |
2497 | 0 | { |
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 | 0 | } |
2503 | 0 | else |
2504 | 0 | buf = from_buf; |
2505 | 0 | } |
2506 | 0 | } |
2507 | | |
2508 | 0 | if (bytes_written) |
2509 | 0 | *bytes_written = count_unsigned; |
2510 | |
|
2511 | 0 | return G_IO_STATUS_NORMAL; |
2512 | 0 | } |
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 | | g_io_channel_write_unichar (GIOChannel *channel, |
2528 | | gunichar thechar, |
2529 | | GError **error) |
2530 | 0 | { |
2531 | 0 | GIOStatus status; |
2532 | 0 | gchar static_buf[6]; |
2533 | 0 | 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 | 0 | 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 | 0 | { |
2545 | 0 | g_warning ("Partial character written before writing unichar."); |
2546 | 0 | channel->partial_write_buf[0] = '\0'; |
2547 | 0 | } |
2548 | |
|
2549 | 0 | status = g_io_channel_write_chars (channel, static_buf, |
2550 | 0 | 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 | 0 | } |
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 | | G_DEFINE_QUARK (g-io-channel-error-quark, g_io_channel_error) |