(root)/
glib-2.79.0/
gio/
gio-tool.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 <locale.h>
      27  #include <stdio.h>
      28  #include <string.h>
      29  #include <stdlib.h>
      30  #include <errno.h>
      31  
      32  #include "gio-tool.h"
      33  #include "glib/glib-private.h"
      34  
      35  void
      36  print_error (const gchar *format, ...)
      37  {
      38    gchar *message;
      39    va_list args;
      40  
      41    va_start (args, format);
      42    message = g_strdup_vprintf (format, args);
      43    va_end (args);
      44  
      45    g_printerr ("gio: %s\n", message);
      46    g_free (message);
      47  }
      48  
      49  void
      50  print_file_error (GFile *file, const gchar *message)
      51  {
      52    gchar *uri;
      53  
      54    uri = g_file_get_uri (file);
      55    print_error ("%s: %s", uri, message);
      56    g_free (uri);
      57  }
      58  
      59  void
      60  show_help (GOptionContext *context, const char *message)
      61  {
      62    char *help;
      63  
      64    if (message)
      65      g_printerr ("gio: %s\n\n", message);
      66  
      67    help = g_option_context_get_help (context, TRUE, NULL);
      68    g_printerr ("%s", help);
      69    g_free (help);
      70  }
      71  
      72  const char *
      73  file_type_to_string (GFileType type)
      74  {
      75    switch (type)
      76      {
      77      case G_FILE_TYPE_UNKNOWN:
      78        return "unknown";
      79      case G_FILE_TYPE_REGULAR:
      80        return "regular";
      81      case G_FILE_TYPE_DIRECTORY:
      82        return "directory";
      83      case G_FILE_TYPE_SYMBOLIC_LINK:
      84        return "symlink";
      85      case G_FILE_TYPE_SPECIAL:
      86        return "special";
      87      case G_FILE_TYPE_SHORTCUT:
      88        return "shortcut";
      89      case G_FILE_TYPE_MOUNTABLE:
      90        return "mountable";
      91      default:
      92        return "invalid type";
      93      }
      94  }
      95  
      96  const char *
      97  attribute_type_to_string (GFileAttributeType type)
      98  {
      99    switch (type)
     100      {
     101      case G_FILE_ATTRIBUTE_TYPE_INVALID:
     102        return "invalid";
     103      case G_FILE_ATTRIBUTE_TYPE_STRING:
     104        return "string";
     105      case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
     106        return "bytestring";
     107      case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
     108        return "boolean";
     109      case G_FILE_ATTRIBUTE_TYPE_UINT32:
     110        return "uint32";
     111      case G_FILE_ATTRIBUTE_TYPE_INT32:
     112        return "int32";
     113      case G_FILE_ATTRIBUTE_TYPE_UINT64:
     114        return "uint64";
     115      case G_FILE_ATTRIBUTE_TYPE_INT64:
     116        return "int64";
     117      case G_FILE_ATTRIBUTE_TYPE_OBJECT:
     118        return "object";
     119      default:
     120        return "unknown type";
     121      }
     122  }
     123  
     124  GFileAttributeType
     125  attribute_type_from_string (const char *str)
     126  {
     127    if (strcmp (str, "string") == 0)
     128      return G_FILE_ATTRIBUTE_TYPE_STRING;
     129    if (strcmp (str, "stringv") == 0)
     130      return G_FILE_ATTRIBUTE_TYPE_STRINGV;
     131    if (strcmp (str, "bytestring") == 0)
     132      return G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
     133    if (strcmp (str, "boolean") == 0)
     134      return G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
     135    if (strcmp (str, "uint32") == 0)
     136      return G_FILE_ATTRIBUTE_TYPE_UINT32;
     137    if (strcmp (str, "int32") == 0)
     138      return G_FILE_ATTRIBUTE_TYPE_INT32;
     139    if (strcmp (str, "uint64") == 0)
     140      return G_FILE_ATTRIBUTE_TYPE_UINT64;
     141    if (strcmp (str, "int64") == 0)
     142      return G_FILE_ATTRIBUTE_TYPE_INT64;
     143    if (strcmp (str, "object") == 0)
     144      return G_FILE_ATTRIBUTE_TYPE_OBJECT;
     145    if (strcmp (str, "unset") == 0)
     146      return G_FILE_ATTRIBUTE_TYPE_INVALID;
     147    return -1;
     148  }
     149  
     150  char *
     151  attribute_flags_to_string (GFileAttributeInfoFlags flags)
     152  {
     153    GString *s;
     154    gsize i;
     155    gboolean first;
     156    struct {
     157      guint32 mask;
     158      char *descr;
     159    } flag_descr[] = {
     160      {
     161        G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE,
     162        N_("Copy with file")
     163      },
     164      {
     165        G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED,
     166        N_("Keep with file when moved")
     167      }
     168    };
     169  
     170    first = TRUE;
     171  
     172    s = g_string_new ("");
     173    for (i = 0; i < G_N_ELEMENTS (flag_descr); i++)
     174      {
     175        if (flags & flag_descr[i].mask)
     176          {
     177            if (!first)
     178              g_string_append (s, ", ");
     179            g_string_append (s, gettext (flag_descr[i].descr));
     180            first = FALSE;
     181          }
     182      }
     183  
     184    return g_string_free (s, FALSE);
     185  }
     186  
     187  gboolean
     188  file_is_dir (GFile *file)
     189  {
     190    GFileInfo *info;
     191    gboolean res;
     192  
     193    info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL);
     194    res = info && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
     195    if (info)
     196      g_object_unref (info);
     197    return res;
     198  }
     199  
     200  
     201  static int
     202  handle_version (int argc, char *argv[], gboolean do_help)
     203  {
     204    if (do_help || argc > 1)
     205      {
     206        if (!do_help)
     207          g_printerr ("gio: %s\n\n", _("“version” takes no arguments"));
     208  
     209        g_printerr ("%s\n", _("Usage:"));
     210        g_printerr ("  gio version\n");
     211        g_printerr ("\n");
     212        g_printerr ("%s\n", _("Print version information and exit."));
     213  
     214        return do_help ? 0 : 2;
     215      }
     216  
     217    g_print ("%d.%d.%d\n", glib_major_version, glib_minor_version, glib_micro_version);
     218  
     219    return 0;
     220  }
     221  
     222  typedef int (*HandleSubcommand) (int argc, char *argv[], gboolean do_help);
     223  
     224  static const struct
     225  {
     226    const char *name;  /* as used on the command line */
     227    HandleSubcommand handle_func;  /* (nullable) for "help" only */
     228    const char *description;  /* translatable */
     229  } gio_subcommands[] = {
     230    { "help", NULL, N_("Print help") },
     231    { "version", handle_version, N_("Print version") },
     232    { "cat", handle_cat, N_("Concatenate files to standard output") },
     233    { "copy", handle_copy, N_("Copy one or more files") },
     234    { "info", handle_info, N_("Show information about locations") },
     235    { "launch", handle_launch, N_("Launch an application from a desktop file") },
     236    { "list", handle_list, N_("List the contents of locations") },
     237    { "mime", handle_mime, N_("Get or set the handler for a mimetype") },
     238    { "mkdir", handle_mkdir, N_("Create directories") },
     239    { "monitor", handle_monitor, N_("Monitor files and directories for changes") },
     240    { "mount", handle_mount, N_("Mount or unmount the locations") },
     241    { "move", handle_move, N_("Move one or more files") },
     242    { "open", handle_open, N_("Open files with the default application") },
     243    { "rename", handle_rename, N_("Rename a file") },
     244    { "remove", handle_remove, N_("Delete one or more files") },
     245    { "save", handle_save, N_("Read from standard input and save") },
     246    { "set", handle_set, N_("Set a file attribute") },
     247    { "trash", handle_trash, N_("Move files or directories to the trash") },
     248    { "tree", handle_tree, N_("Lists the contents of locations in a tree") },
     249  };
     250  
     251  static void
     252  usage (gboolean is_error)
     253  {
     254    GString *out = NULL;
     255    size_t name_width = 0;
     256  
     257    out = g_string_new ("");
     258    g_string_append_printf (out, "%s\n", _("Usage:"));
     259    g_string_append_printf (out, "  gio %s %s\n", _("COMMAND"), _("[ARGS…]"));
     260    g_string_append_c (out, '\n');
     261    g_string_append_printf (out, "%s\n", _("Commands:"));
     262  
     263    /* Work out the maximum name length for column alignment. */
     264    for (size_t i = 0; i < G_N_ELEMENTS (gio_subcommands); i++)
     265      name_width = MAX (name_width, strlen (gio_subcommands[i].name));
     266  
     267    for (size_t i = 0; i < G_N_ELEMENTS (gio_subcommands); i++)
     268      {
     269        g_string_append_printf (out, "  %-*s  %s\n",
     270                                (int) name_width, gio_subcommands[i].name,
     271                                _(gio_subcommands[i].description));
     272      }
     273  
     274    g_string_append_c (out, '\n');
     275    g_string_append_printf (out, _("Use %s to get detailed help.\n"), "“gio help COMMAND”");
     276  
     277    if (is_error)
     278      g_printerr ("%s", out->str);
     279    else
     280      g_print ("%s", out->str);
     281  
     282    g_string_free (out, TRUE);
     283  }
     284  
     285  int
     286  main (int argc, char **argv)
     287  {
     288    const char *command;
     289    gboolean do_help;
     290  
     291  #ifdef G_OS_WIN32
     292    gchar *localedir;
     293  #endif
     294  
     295    setlocale (LC_ALL, GLIB_DEFAULT_LOCALE);
     296    textdomain (GETTEXT_PACKAGE);
     297  
     298  #ifdef G_OS_WIN32
     299    localedir = _glib_get_locale_dir ();
     300    bindtextdomain (GETTEXT_PACKAGE, localedir);
     301    g_free (localedir);
     302  #else
     303    bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
     304  #endif
     305  
     306  #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
     307    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
     308  #endif
     309  
     310    if (argc < 2)
     311      {
     312        usage (TRUE);
     313        return 1;
     314      }
     315  
     316    command = argv[1];
     317    argc -= 1;
     318    argv += 1;
     319  
     320    do_help = FALSE;
     321    if (g_str_equal (command, "help"))
     322      {
     323        if (argc == 1)
     324          {
     325            usage (FALSE);
     326            return 0;
     327          }
     328        else
     329          {
     330            command = argv[1];
     331            do_help = TRUE;
     332          }
     333      }
     334    else if (g_str_equal (command, "--help"))
     335      {
     336        usage (FALSE);
     337        return 0;
     338      }
     339    else if (g_str_equal (command, "--version"))
     340      command = "version";
     341  
     342    /* Work out which subcommand it is. */
     343    for (size_t i = 0; i < G_N_ELEMENTS (gio_subcommands); i++)
     344      {
     345        if (g_str_equal (command, gio_subcommands[i].name))
     346          {
     347            g_assert (gio_subcommands[i].handle_func != NULL);
     348            return gio_subcommands[i].handle_func (argc, argv, do_help);
     349          }
     350      }
     351  
     352    /* Unknown subcommand. */
     353    usage (TRUE);
     354  
     355    return 1;
     356  }