(root)/
glib-2.79.0/
gio/
tests/
filter-cat.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   *
       3   * Copyright (C) 2009 Red Hat, Inc.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General
      18   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   *
      20   * Author: Alexander Larsson <alexl@redhat.com>
      21   */
      22  
      23  #include <config.h>
      24  
      25  #include <stdio.h>
      26  #include <locale.h>
      27  #include <errno.h>
      28  
      29  #include <glib.h>
      30  #include <gio/gio.h>
      31  
      32  #ifdef G_OS_UNIX
      33  #include <unistd.h>
      34  #endif
      35  
      36  #ifdef G_OS_WIN32
      37  #include <io.h>
      38  #ifndef STDOUT_FILENO
      39  #define STDOUT_FILENO 1
      40  #endif
      41  #endif
      42  
      43  static gchar **locations = NULL;
      44  static char *from_charset = NULL;
      45  static char *to_charset = NULL;
      46  static gboolean decompress = FALSE;
      47  static gboolean compress = FALSE;
      48  static gboolean gzip = FALSE;
      49  static gboolean fallback = FALSE;
      50  
      51  static GOptionEntry entries[] = {
      52    {"decompress", 0, 0, G_OPTION_ARG_NONE, &decompress, "decompress", NULL},
      53    {"compress", 0, 0, G_OPTION_ARG_NONE, &compress, "compress", NULL},
      54    {"gzip", 0, 0, G_OPTION_ARG_NONE, &gzip, "use gzip format", NULL},
      55    {"from-charset", 0, 0, G_OPTION_ARG_STRING, &from_charset, "from charset", NULL},
      56    {"to-charset", 0, 0, G_OPTION_ARG_STRING, &to_charset, "to charset", NULL},
      57    {"fallback", 0, 0, G_OPTION_ARG_NONE, &fallback, "use fallback", NULL},
      58    {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &locations, "locations", NULL},
      59    G_OPTION_ENTRY_NULL
      60  };
      61  
      62  static void
      63  decompressor_file_info_notify_cb (GZlibDecompressor *decompressor,
      64                                    GParamSpec *pspec,
      65                                    gpointer data)
      66  {
      67    GFileInfo *file_info;
      68    const gchar *filename;
      69  
      70    file_info = g_zlib_decompressor_get_file_info (decompressor);
      71    if (file_info == NULL)
      72      return;
      73  
      74    filename = g_file_info_get_name (file_info);
      75    if (filename)
      76      g_printerr ("Decompressor filename: %s\n", filename);
      77  }
      78  
      79  static void
      80  cat (GFile * file)
      81  {
      82    GInputStream *in;
      83    char buffer[1024 * 8 + 1];
      84    char *p;
      85    gssize res;
      86    gboolean close_res;
      87    GError *error;
      88    GConverter *conv;
      89    GCharsetConverter *cconv = NULL;
      90  
      91    error = NULL;
      92    in = (GInputStream *) g_file_read (file, NULL, &error);
      93    if (in == NULL)
      94      {
      95        /* Translators: the first %s is the program name, the second one  */
      96        /* is the URI of the file, the third is the error message.        */
      97        g_printerr ("%s: %s: error opening file: %s\n",
      98  		  g_get_prgname (), g_file_get_uri (file), error->message);
      99        g_error_free (error);
     100        return;
     101      }
     102  
     103    if (decompress)
     104      {
     105        GInputStream *old;
     106        conv = (GConverter *)g_zlib_decompressor_new (gzip?G_ZLIB_COMPRESSOR_FORMAT_GZIP:G_ZLIB_COMPRESSOR_FORMAT_ZLIB);
     107        old = in;
     108        in = (GInputStream *) g_converter_input_stream_new (in, conv);
     109        g_signal_connect (conv, "notify::file-info", G_CALLBACK (decompressor_file_info_notify_cb), NULL);
     110        g_object_unref (conv);
     111        g_object_unref (old);
     112      }
     113  
     114    if (from_charset && to_charset)
     115      {
     116        cconv = g_charset_converter_new (to_charset, from_charset, &error);
     117        conv = (GConverter *)cconv;
     118        if (conv)
     119  	{
     120  	  GInputStream *old;
     121  
     122  	  g_charset_converter_set_use_fallback (cconv, fallback);
     123  
     124  	  old = in;
     125  	  in = (GInputStream *) g_converter_input_stream_new (in, conv);
     126  	  g_object_unref (conv);
     127  	  g_object_unref (old);
     128  	}
     129        else
     130  	{
     131  	  g_printerr ("%s: Can't convert between charsets: %s\n",
     132  		      g_get_prgname (), error->message);
     133  	}
     134      }
     135  
     136    if (compress)
     137      {
     138        GInputStream *old;
     139        GFileInfo *in_file_info;
     140  
     141        in_file_info = g_file_query_info (file,
     142                                          G_FILE_ATTRIBUTE_STANDARD_NAME ","
     143                                          G_FILE_ATTRIBUTE_TIME_MODIFIED,
     144                                          G_FILE_QUERY_INFO_NONE,
     145                                          NULL,
     146                                          &error);
     147        if (in_file_info == NULL)
     148          {
     149            g_printerr ("%s: %s: error reading file info: %s\n",
     150                        g_get_prgname (), g_file_get_uri (file), error->message);
     151            g_error_free (error);
     152            return;
     153          }
     154  
     155        conv = (GConverter *)g_zlib_compressor_new(gzip?G_ZLIB_COMPRESSOR_FORMAT_GZIP:G_ZLIB_COMPRESSOR_FORMAT_ZLIB, -1);
     156        g_zlib_compressor_set_file_info (G_ZLIB_COMPRESSOR (conv), in_file_info);
     157        old = in;
     158        in = (GInputStream *) g_converter_input_stream_new (in, conv);
     159        g_object_unref (conv);
     160        g_object_unref (old);
     161        g_object_unref (in_file_info);
     162      }
     163  
     164    while (1)
     165      {
     166        res =
     167  	g_input_stream_read (in, buffer, sizeof (buffer) - 1, NULL, &error);
     168        if (res > 0)
     169  	{
     170  	  gssize written;
     171  
     172  	  p = buffer;
     173  	  while (res > 0)
     174  	    {
     175  	      written = write (STDOUT_FILENO, p, res);
     176  
     177  	      if (written == -1 && errno != EINTR)
     178  		{
     179  		  /* Translators: the first %s is the program name, the */
     180  		  /* second one is the URI of the file.                 */
     181  		  g_printerr ("%s: %s, error writing to stdout",
     182  			      g_get_prgname (), g_file_get_uri (file));
     183  		  goto out;
     184  		}
     185  	      res -= written;
     186  	      p += written;
     187  	    }
     188  	}
     189        else if (res < 0)
     190  	{
     191  	  g_printerr ("%s: %s: error reading: %s\n",
     192  		      g_get_prgname (), g_file_get_uri (file),
     193  		      error->message);
     194  	  g_error_free (error);
     195  	  error = NULL;
     196  	  break;
     197  	}
     198        else if (res == 0)
     199  	break;
     200      }
     201  
     202   out:
     203  
     204    close_res = g_input_stream_close (in, NULL, &error);
     205    if (!close_res)
     206      {
     207        g_printerr ("%s: %s:error closing: %s\n",
     208  		  g_get_prgname (), g_file_get_uri (file), error->message);
     209        g_error_free (error);
     210      }
     211  
     212    if (cconv != NULL && fallback)
     213      {
     214        guint num = g_charset_converter_get_num_fallbacks (cconv);
     215        if (num > 0)
     216  	g_printerr ("Number of fallback errors: %u\n", num);
     217      }
     218  }
     219  
     220  int
     221  main (int argc, char *argv[])
     222  {
     223    GError *error = NULL;
     224    GOptionContext *context = NULL;
     225    GFile *file;
     226    int i;
     227  
     228    context =
     229      g_option_context_new ("LOCATION... - concatenate LOCATIONS "
     230  			  "to standard output.");
     231  
     232    g_option_context_set_summary (context, "filter files");
     233  
     234    g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
     235    g_option_context_parse (context, &argc, &argv, &error);
     236  
     237    g_option_context_free (context);
     238  
     239    if (error != NULL)
     240      {
     241        g_printerr ("Error parsing commandline options: %s\n", error->message);
     242        g_printerr ("\n");
     243        g_printerr ("Try \"%s --help\" for more information.",
     244  		  g_get_prgname ());
     245        g_printerr ("\n");
     246        g_error_free(error);
     247        return 1;
     248      }
     249  
     250    if (!locations)
     251      {
     252        g_printerr ("%s: missing locations", g_get_prgname ());
     253        g_printerr ("\n");
     254        g_printerr ("Try \"%s --help\" for more information.",
     255  		  g_get_prgname ());
     256        g_printerr ("\n");
     257        return 1;
     258      }
     259  
     260    i = 0;
     261  
     262    do
     263      {
     264        file = g_file_new_for_commandline_arg (locations[i]);
     265        cat (file);
     266        g_object_unref (file);
     267      }
     268    while (locations[++i] != NULL);
     269  
     270    return 0;
     271  }