(root)/
glib-2.79.0/
gio/
gio-tool-cat.c
       1  /*
       2   * Copyright 2015 Red Hat, Inc.
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General Public
      17   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   *
      19   * Author: Matthias Clasen <mclasen@redhat.com>
      20   */
      21  
      22  #include "config.h"
      23  
      24  #include <gio/gio.h>
      25  #include <gi18n.h>
      26  #include <errno.h>
      27  
      28  #ifdef G_OS_WIN32
      29  #include <io.h>
      30  #endif
      31  
      32  #ifndef STDOUT_FILENO
      33  #define STDOUT_FILENO 1
      34  #endif
      35  
      36  #ifdef HAVE_UNISTD_H
      37  #include <unistd.h>
      38  #endif
      39  
      40  #include "gio-tool.h"
      41  
      42  
      43  static const GOptionEntry entries[] = {
      44    G_OPTION_ENTRY_NULL
      45  };
      46  
      47  /* 256k minus malloc overhead */
      48  #define STREAM_BUFFER_SIZE (1024*256 - 2*sizeof(gpointer))
      49  
      50  static gboolean
      51  cat (GFile *file)
      52  {
      53    GInputStream *in;
      54    char *buffer;
      55    char *p;
      56    gssize res;
      57    gboolean close_res;
      58    GError *error;
      59    gboolean success;
      60  
      61    error = NULL;
      62    in = (GInputStream *) g_file_read (file, NULL, &error);
      63    if (in == NULL)
      64      {
      65        print_file_error (file, error->message);
      66        g_error_free (error);
      67        return FALSE;
      68      }
      69  
      70    buffer = g_malloc (STREAM_BUFFER_SIZE);
      71    success = TRUE;
      72    while (1)
      73      {
      74        res = g_input_stream_read (in, buffer, STREAM_BUFFER_SIZE, NULL, &error);
      75        if (res > 0)
      76          {
      77            gssize written;
      78  
      79            p = buffer;
      80            while (res > 0)
      81              {
      82                int errsv;
      83  
      84                written = write (STDOUT_FILENO, p, res);
      85                errsv = errno;
      86  
      87                if (written == -1 && errsv != EINTR)
      88                  {
      89                    print_error ("%s", _("Error writing to stdout"));
      90                    success = FALSE;
      91                    goto out;
      92                  }
      93                res -= written;
      94                p += written;
      95              }
      96          }
      97        else if (res < 0)
      98          {
      99            print_file_error (file, error->message);
     100            g_error_free (error);
     101            error = NULL;
     102            success = FALSE;
     103            break;
     104          }
     105        else if (res == 0)
     106          break;
     107      }
     108  
     109   out:
     110   close_res = g_input_stream_close (in, NULL, &error);
     111    if (!close_res)
     112      {
     113        print_file_error (file, error->message);
     114        g_error_free (error);
     115        success = FALSE;
     116      }
     117  
     118    g_free (buffer);
     119  
     120    return success;
     121  }
     122  
     123  int
     124  handle_cat (int argc, char *argv[], gboolean do_help)
     125  {
     126    GOptionContext *context;
     127    gchar *param;
     128    GError *error = NULL;
     129    int i;
     130    gboolean res;
     131    GFile *file;
     132  
     133    g_set_prgname ("gio cat");
     134    /* Translators: commandline placeholder */
     135    param = g_strdup_printf ("%s", _("LOCATION"));
     136    context = g_option_context_new (param);
     137    g_free (param);
     138    g_option_context_set_help_enabled (context, FALSE);
     139    g_option_context_set_summary (context,
     140        _("Concatenate files and print to standard output."));
     141    g_option_context_set_description (context,
     142        _("gio cat works just like the traditional cat utility, but using GIO\n"
     143          "locations instead of local files: for example, you can use something\n"
     144          "like smb://server/resource/file.txt as location."));
     145    g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
     146  
     147    if (do_help)
     148      {
     149        show_help (context, NULL);
     150        g_option_context_free (context);
     151        return 0;
     152      }
     153  
     154    if (!g_option_context_parse (context, &argc, &argv, &error))
     155      {
     156        show_help (context, error->message);
     157        g_error_free (error);
     158        g_option_context_free (context);
     159        return 1;
     160      }
     161  
     162    if (argc < 2)
     163      {
     164        show_help (context, _("No locations given"));
     165        g_option_context_free (context);
     166        return 1;
     167      }
     168  
     169    g_option_context_free (context);
     170  
     171    res = TRUE;
     172    for (i = 1; i < argc; i++)
     173      {
     174        file = g_file_new_for_commandline_arg (argv[i]);
     175        res &= cat (file);
     176        g_object_unref (file);
     177      }
     178  
     179    return res ? 0 : 2;
     180  }