LCOV - code coverage report
Current view: top level - glib/glib - giochannel.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 443 852 52.0 %
Date: 2024-04-23 05:16:05 Functions: 31 39 79.5 %
Branches: 238 557 42.7 %

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

Generated by: LCOV version 1.14