Branch data Line data Source code
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 : 0 : print_error (const gchar *format, ...)
37 : : {
38 : : gchar *message;
39 : : va_list args;
40 : :
41 : 0 : va_start (args, format);
42 : 0 : message = g_strdup_vprintf (format, args);
43 : 0 : va_end (args);
44 : :
45 : 0 : g_printerr ("gio: %s\n", message);
46 : 0 : g_free (message);
47 : 0 : }
48 : :
49 : : void
50 : 0 : print_file_error (GFile *file, const gchar *message)
51 : : {
52 : : gchar *uri;
53 : :
54 : 0 : uri = g_file_get_uri (file);
55 : 0 : print_error ("%s: %s", uri, message);
56 : 0 : g_free (uri);
57 : 0 : }
58 : :
59 : : void
60 : 0 : show_help (GOptionContext *context, const char *message)
61 : : {
62 : : char *help;
63 : :
64 : 0 : if (message)
65 : 0 : g_printerr ("gio: %s\n\n", message);
66 : :
67 : 0 : help = g_option_context_get_help (context, TRUE, NULL);
68 : 0 : g_printerr ("%s", help);
69 : 0 : g_free (help);
70 : 0 : }
71 : :
72 : : const char *
73 : 0 : file_type_to_string (GFileType type)
74 : : {
75 : 0 : switch (type)
76 : : {
77 : 0 : case G_FILE_TYPE_UNKNOWN:
78 : 0 : return "unknown";
79 : 0 : case G_FILE_TYPE_REGULAR:
80 : 0 : return "regular";
81 : 0 : case G_FILE_TYPE_DIRECTORY:
82 : 0 : return "directory";
83 : 0 : case G_FILE_TYPE_SYMBOLIC_LINK:
84 : 0 : return "symlink";
85 : 0 : case G_FILE_TYPE_SPECIAL:
86 : 0 : return "special";
87 : 0 : case G_FILE_TYPE_SHORTCUT:
88 : 0 : return "shortcut";
89 : 0 : case G_FILE_TYPE_MOUNTABLE:
90 : 0 : return "mountable";
91 : 0 : default:
92 : 0 : return "invalid type";
93 : : }
94 : : }
95 : :
96 : : const char *
97 : 0 : attribute_type_to_string (GFileAttributeType type)
98 : : {
99 : 0 : switch (type)
100 : : {
101 : 0 : case G_FILE_ATTRIBUTE_TYPE_INVALID:
102 : 0 : return "invalid";
103 : 0 : case G_FILE_ATTRIBUTE_TYPE_STRING:
104 : 0 : return "string";
105 : 0 : case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
106 : 0 : return "bytestring";
107 : 0 : case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
108 : 0 : return "boolean";
109 : 0 : case G_FILE_ATTRIBUTE_TYPE_UINT32:
110 : 0 : return "uint32";
111 : 0 : case G_FILE_ATTRIBUTE_TYPE_INT32:
112 : 0 : return "int32";
113 : 0 : case G_FILE_ATTRIBUTE_TYPE_UINT64:
114 : 0 : return "uint64";
115 : 0 : case G_FILE_ATTRIBUTE_TYPE_INT64:
116 : 0 : return "int64";
117 : 0 : case G_FILE_ATTRIBUTE_TYPE_OBJECT:
118 : 0 : return "object";
119 : 0 : default:
120 : 0 : return "unknown type";
121 : : }
122 : : }
123 : :
124 : : GFileAttributeType
125 : 0 : attribute_type_from_string (const char *str)
126 : : {
127 : 0 : if (strcmp (str, "string") == 0)
128 : 0 : return G_FILE_ATTRIBUTE_TYPE_STRING;
129 : 0 : if (strcmp (str, "stringv") == 0)
130 : 0 : return G_FILE_ATTRIBUTE_TYPE_STRINGV;
131 : 0 : if (strcmp (str, "bytestring") == 0)
132 : 0 : return G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
133 : 0 : if (strcmp (str, "boolean") == 0)
134 : 0 : return G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
135 : 0 : if (strcmp (str, "uint32") == 0)
136 : 0 : return G_FILE_ATTRIBUTE_TYPE_UINT32;
137 : 0 : if (strcmp (str, "int32") == 0)
138 : 0 : return G_FILE_ATTRIBUTE_TYPE_INT32;
139 : 0 : if (strcmp (str, "uint64") == 0)
140 : 0 : return G_FILE_ATTRIBUTE_TYPE_UINT64;
141 : 0 : if (strcmp (str, "int64") == 0)
142 : 0 : return G_FILE_ATTRIBUTE_TYPE_INT64;
143 : 0 : if (strcmp (str, "object") == 0)
144 : 0 : return G_FILE_ATTRIBUTE_TYPE_OBJECT;
145 : 0 : if (strcmp (str, "unset") == 0)
146 : 0 : return G_FILE_ATTRIBUTE_TYPE_INVALID;
147 : 0 : return -1;
148 : : }
149 : :
150 : : char *
151 : 0 : 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 : 0 : } 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 : 0 : first = TRUE;
171 : :
172 : 0 : s = g_string_new ("");
173 : 0 : for (i = 0; i < G_N_ELEMENTS (flag_descr); i++)
174 : : {
175 : 0 : if (flags & flag_descr[i].mask)
176 : : {
177 : 0 : if (!first)
178 : 0 : g_string_append (s, ", ");
179 : 0 : g_string_append (s, gettext (flag_descr[i].descr));
180 : 0 : first = FALSE;
181 : : }
182 : : }
183 : :
184 : 0 : return g_string_free (s, FALSE);
185 : : }
186 : :
187 : : gboolean
188 : 0 : file_is_dir (GFile *file)
189 : : {
190 : : GFileInfo *info;
191 : : gboolean res;
192 : :
193 : 0 : info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL);
194 : 0 : res = info && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
195 : 0 : if (info)
196 : 0 : g_object_unref (info);
197 : 0 : return res;
198 : : }
199 : :
200 : :
201 : : static int
202 : 0 : handle_version (int argc, char *argv[], gboolean do_help)
203 : : {
204 : 0 : if (do_help || argc > 1)
205 : : {
206 : 0 : if (!do_help)
207 : 0 : g_printerr ("gio: %s\n\n", _("“version” takes no arguments"));
208 : :
209 : 0 : g_printerr ("%s\n", _("Usage:"));
210 : 0 : g_printerr (" gio version\n");
211 : 0 : g_printerr ("\n");
212 : 0 : g_printerr ("%s\n", _("Print version information and exit."));
213 : :
214 : 0 : return do_help ? 0 : 2;
215 : : }
216 : :
217 : 0 : g_print ("%d.%d.%d\n", glib_major_version, glib_minor_version, glib_micro_version);
218 : :
219 : 0 : 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 : 3 : usage (gboolean is_error)
253 : : {
254 : 3 : GString *out = NULL;
255 : 3 : size_t name_width = 0;
256 : :
257 : 3 : out = g_string_new ("");
258 : 3 : g_string_append_printf (out, "%s\n", _("Usage:"));
259 : 3 : g_string_append_printf (out, " gio %s %s\n", _("COMMAND"), _("[ARGS…]"));
260 : : g_string_append_c (out, '\n');
261 : 3 : g_string_append_printf (out, "%s\n", _("Commands:"));
262 : :
263 : : /* Work out the maximum name length for column alignment. */
264 : 60 : for (size_t i = 0; i < G_N_ELEMENTS (gio_subcommands); i++)
265 : 57 : name_width = MAX (name_width, strlen (gio_subcommands[i].name));
266 : :
267 : 60 : for (size_t i = 0; i < G_N_ELEMENTS (gio_subcommands); i++)
268 : : {
269 : 57 : g_string_append_printf (out, " %-*s %s\n",
270 : 57 : (int) name_width, gio_subcommands[i].name,
271 : 57 : _(gio_subcommands[i].description));
272 : : }
273 : :
274 : : g_string_append_c (out, '\n');
275 : 3 : g_string_append_printf (out, _("Use %s to get detailed help.\n"), "“gio help COMMAND”");
276 : :
277 : 3 : if (is_error)
278 : 1 : g_printerr ("%s", out->str);
279 : : else
280 : 2 : g_print ("%s", out->str);
281 : :
282 : 3 : g_string_free (out, TRUE);
283 : 3 : }
284 : :
285 : : int
286 : 4 : 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 : 4 : setlocale (LC_ALL, GLIB_DEFAULT_LOCALE);
296 : 4 : 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 : 4 : bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
304 : : #endif
305 : :
306 : : #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
307 : 4 : bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
308 : : #endif
309 : :
310 : 4 : if (argc < 2)
311 : : {
312 : 1 : usage (TRUE);
313 : 1 : return 1;
314 : : }
315 : :
316 : 3 : command = argv[1];
317 : 3 : argc -= 1;
318 : 3 : argv += 1;
319 : :
320 : 3 : do_help = FALSE;
321 : 3 : if (g_str_equal (command, "help"))
322 : : {
323 : 1 : if (argc == 1)
324 : : {
325 : 1 : usage (FALSE);
326 : 1 : return 0;
327 : : }
328 : : else
329 : : {
330 : 0 : command = argv[1];
331 : 0 : do_help = TRUE;
332 : : }
333 : : }
334 : 2 : else if (g_str_equal (command, "--help"))
335 : : {
336 : 1 : usage (FALSE);
337 : 1 : return 0;
338 : : }
339 : 1 : else if (g_str_equal (command, "--version"))
340 : 0 : command = "version";
341 : :
342 : : /* Work out which subcommand it is. */
343 : 5 : for (size_t i = 0; i < G_N_ELEMENTS (gio_subcommands); i++)
344 : : {
345 : 5 : if (g_str_equal (command, gio_subcommands[i].name))
346 : : {
347 : 1 : g_assert (gio_subcommands[i].handle_func != NULL);
348 : 1 : return gio_subcommands[i].handle_func (argc, argv, do_help);
349 : : }
350 : : }
351 : :
352 : : /* Unknown subcommand. */
353 : 0 : usage (TRUE);
354 : :
355 : 0 : return 1;
356 : : }
|