• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  *
17  * Author: Matthias Clasen <mclasen@redhat.com>
18  */
19 
20 #include "config.h"
21 
22 #include <gio/gio.h>
23 #include <gi18n.h>
24 
25 #include "gio-tool.h"
26 
27 
28 static char *attributes = NULL;
29 static gboolean show_hidden = FALSE;
30 static gboolean show_long = FALSE;
31 static gboolean nofollow_symlinks = FALSE;
32 static gboolean print_display_names = FALSE;
33 static gboolean print_uris = FALSE;
34 
35 static const GOptionEntry entries[] = {
36   { "attributes", 'a', 0, G_OPTION_ARG_STRING, &attributes, N_("The attributes to get"), N_("ATTRIBUTES") },
37   { "hidden", 'h', 0, G_OPTION_ARG_NONE, &show_hidden, N_("Show hidden files"), NULL },
38   { "long", 'l', 0, G_OPTION_ARG_NONE, &show_long, N_("Use a long listing format"), NULL },
39   { "nofollow-symlinks", 'n', 0, G_OPTION_ARG_NONE, &nofollow_symlinks, N_("Don’t follow symbolic links"), NULL},
40   { "print-display-names", 'd', 0, G_OPTION_ARG_NONE, &print_display_names, N_("Print display names"), NULL },
41   { "print-uris", 'u', 0, G_OPTION_ARG_NONE, &print_uris, N_("Print full URIs"), NULL},
42   { NULL }
43 };
44 
45 static void
show_file_listing(GFileInfo * info,GFile * parent)46 show_file_listing (GFileInfo *info, GFile *parent)
47 {
48   const char *name, *type;
49   char *uri = NULL;
50   goffset size;
51   char **attributes;
52   int i;
53   gboolean first_attr;
54   GFile *child;
55 
56   if ((g_file_info_get_is_hidden (info)) && !show_hidden)
57     return;
58 
59   if (print_display_names)
60     name = g_file_info_get_display_name (info);
61   else
62     name = g_file_info_get_name (info);
63 
64   if (name == NULL)
65     name = "";
66 
67   if (print_uris) {
68     child = g_file_get_child (parent, name);
69     uri = g_file_get_uri (child);
70     g_object_unref (child);
71   }
72 
73   size = g_file_info_get_size (info);
74   type = file_type_to_string (g_file_info_get_file_type (info));
75   if (show_long)
76     g_print ("%s\t%"G_GUINT64_FORMAT"\t(%s)", print_uris? uri: name, (guint64)size, type);
77   else
78     g_print ("%s", print_uris? uri: name);
79 
80   if (print_uris)
81     g_free (uri);
82 
83   first_attr = TRUE;
84   attributes = g_file_info_list_attributes (info, NULL);
85   for (i = 0 ; attributes[i] != NULL; i++)
86     {
87       char *val_as_string;
88 
89       if (!show_long ||
90           (!print_display_names && strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_NAME) == 0) ||
91           (print_display_names && strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME) == 0) ||
92           strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_SIZE) == 0 ||
93           strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_TYPE) == 0 ||
94           strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN) == 0)
95         continue;
96 
97       if (first_attr)
98         {
99           g_print ("\t");
100           first_attr = FALSE;
101         }
102       else
103         g_print (" ");
104       val_as_string = g_file_info_get_attribute_as_string (info, attributes[i]);
105       g_print ("%s=%s", attributes[i], val_as_string);
106       g_free (val_as_string);
107     }
108 
109   g_strfreev (attributes);
110 
111   g_print ("\n");
112 }
113 
114 static gboolean
list(GFile * file)115 list (GFile *file)
116 {
117   GFileEnumerator *enumerator;
118   GFileInfo *info;
119   GError *error;
120   gboolean res;
121 
122   error = NULL;
123   enumerator = g_file_enumerate_children (file,
124                                           attributes,
125                                           nofollow_symlinks ? G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS : 0,
126                                           NULL,
127                                           &error);
128   if (enumerator == NULL)
129     {
130       print_file_error (file, error->message);
131       g_error_free (error);
132       return FALSE;
133     }
134 
135   res = TRUE;
136   while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL)
137     {
138       show_file_listing (info, file);
139       g_object_unref (info);
140     }
141 
142   if (error)
143     {
144       print_file_error (file, error->message);
145       g_clear_error (&error);
146       res = FALSE;
147     }
148 
149   if (!g_file_enumerator_close (enumerator, NULL, &error))
150     {
151       print_file_error (file, error->message);
152       g_clear_error (&error);
153       res = FALSE;
154     }
155 
156   return res;
157 }
158 
159 int
handle_list(int argc,char * argv[],gboolean do_help)160 handle_list (int argc, char *argv[], gboolean do_help)
161 {
162   GOptionContext *context;
163   gchar *param;
164   GError *error = NULL;
165   gboolean res;
166   gint i;
167   GFile *file;
168 
169   g_set_prgname ("gio list");
170 
171   /* Translators: commandline placeholder */
172   param = g_strdup_printf ("[%s…]", _("LOCATION"));
173   context = g_option_context_new (param);
174   g_free (param);
175   g_option_context_set_help_enabled (context, FALSE);
176   g_option_context_set_summary (context,
177       _("List the contents of the locations."));
178   g_option_context_set_description (context,
179       _("gio list is similar to the traditional ls utility, but using GIO\n"
180         "locations instead of local files: for example, you can use something\n"
181         "like smb://server/resource/file.txt as location. File attributes can\n"
182         "be specified with their GIO name, e.g. standard::icon"));
183   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
184 
185   if (do_help)
186     {
187       show_help (context, NULL);
188       g_option_context_free (context);
189       return 0;
190     }
191 
192   if (!g_option_context_parse (context, &argc, &argv, &error))
193     {
194       show_help (context, error->message);
195       g_error_free (error);
196       g_option_context_free (context);
197       return 1;
198     }
199 
200   g_option_context_free (context);
201 
202   if (attributes != NULL)
203     show_long = TRUE;
204 
205   attributes = g_strconcat (!print_display_names ? G_FILE_ATTRIBUTE_STANDARD_NAME "," : "",
206                             print_display_names ? G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," : "",
207                             G_FILE_ATTRIBUTE_STANDARD_TYPE ","
208                             G_FILE_ATTRIBUTE_STANDARD_SIZE ","
209                             G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
210                             attributes != NULL ? "," : "",
211                             attributes,
212                             NULL);
213 
214   res = TRUE;
215   if (argc > 1)
216     {
217       for (i = 1; i < argc; i++)
218         {
219           file = g_file_new_for_commandline_arg (argv[i]);
220           res &= list (file);
221           g_object_unref (file);
222         }
223     }
224   else
225     {
226       char *cwd;
227 
228       cwd = g_get_current_dir ();
229       file = g_file_new_for_path (cwd);
230       res = list (file);
231       g_object_unref (file);
232       g_free (cwd);
233     }
234 
235   g_free (attributes);
236 
237   return res ? 0 : 2;
238 }
239