Imported Upstream version 2.66.6
[platform/upstream/glib.git] / gio / gio-tool-set.c
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 #include <stdlib.h>
25
26 #include "gio-tool.h"
27
28
29 static char *attr_type = "string";
30 static gboolean nofollow_symlinks = FALSE;
31
32 static const GOptionEntry entries[] = {
33   { "type", 't', 0, G_OPTION_ARG_STRING, &attr_type, N_("Type of the attribute"), N_("TYPE") },
34   { "nofollow-symlinks", 'n', 0, G_OPTION_ARG_NONE, &nofollow_symlinks, N_("Don’t follow symbolic links"), NULL },
35   { NULL }
36 };
37
38 static char *
39 hex_unescape (const char *str)
40 {
41   int i;
42   char *unescaped_str, *p;
43   unsigned char c;
44   int len;
45
46   len = strlen (str);
47   unescaped_str = g_malloc (len + 1);
48
49   p = unescaped_str;
50   for (i = 0; i < len; i++)
51     {
52       if (str[i] == '\\' &&
53           str[i+1] == 'x' &&
54           len - i >= 4)
55         {
56           c =
57             (g_ascii_xdigit_value (str[i+2]) << 4) |
58             g_ascii_xdigit_value (str[i+3]);
59           *p++ = c;
60           i += 3;
61         }
62       else
63         *p++ = str[i];
64     }
65   *p++ = 0;
66
67   return unescaped_str;
68 }
69
70 int
71 handle_set (int argc, char *argv[], gboolean do_help)
72 {
73   GOptionContext *context;
74   GError *error = NULL;
75   GFile *file;
76   const char *attribute;
77   GFileAttributeType type;
78   gpointer value;
79   gboolean b;
80   guint32 uint32;
81   gint32 int32;
82   guint64 uint64;
83   gint64 int64;
84   gchar *param;
85
86   g_set_prgname ("gio set");
87
88   /* Translators: commandline placeholder */
89   param = g_strdup_printf ("%s %s %s…", _("LOCATION"), _("ATTRIBUTE"), _("VALUE"));
90   context = g_option_context_new (param);
91   g_free (param);
92   g_option_context_set_help_enabled (context, FALSE);
93   g_option_context_set_summary (context, _("Set a file attribute of LOCATION."));
94   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
95
96   if (do_help)
97     {
98       show_help (context, NULL);
99       g_option_context_free (context);
100       return 0;
101     }
102
103   if (!g_option_context_parse (context, &argc, &argv, &error))
104     {
105       show_help (context, error->message);
106       g_error_free (error);
107       g_option_context_free (context);
108       return 1;
109     }
110
111   if (argc < 2)
112     {
113       show_help (context, _("Location not specified"));
114       g_option_context_free (context);
115       return 1;
116     }
117
118   if (argc < 3)
119     {
120       show_help (context, _("Attribute not specified"));
121       g_option_context_free (context);
122       return 1;
123     }
124
125   attribute = argv[2];
126
127   type = attribute_type_from_string (attr_type);
128   if ((argc < 4) && (type != G_FILE_ATTRIBUTE_TYPE_INVALID))
129     {
130       show_help (context, _("Value not specified"));
131       g_option_context_free (context);
132       return 1;
133     }
134
135   if ((argc > 4) && (type != G_FILE_ATTRIBUTE_TYPE_STRINGV))
136     {
137       show_help (context, _("Too many arguments"));
138       g_option_context_free (context);
139       return 1;
140     }
141
142   g_option_context_free (context);
143
144   switch (type)
145     {
146     case G_FILE_ATTRIBUTE_TYPE_STRING:
147       value = argv[3];
148       break;
149     case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
150       value = hex_unescape (argv[3]);
151       break;
152     case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
153       b = g_ascii_strcasecmp (argv[3], "true") == 0;
154       value = &b;
155       break;
156     case G_FILE_ATTRIBUTE_TYPE_UINT32:
157       uint32 = atol (argv[3]);
158       value = &uint32;
159       break;
160     case G_FILE_ATTRIBUTE_TYPE_INT32:
161       int32 = atol (argv[3]);
162       value = &int32;
163       break;
164     case G_FILE_ATTRIBUTE_TYPE_UINT64:
165       uint64 = g_ascii_strtoull (argv[3], NULL, 10);
166       value = &uint64;
167       break;
168     case G_FILE_ATTRIBUTE_TYPE_INT64:
169       int64 = g_ascii_strtoll (argv[3], NULL, 10);
170       value = &int64;
171       break;
172     case G_FILE_ATTRIBUTE_TYPE_STRINGV:
173       value = &argv[3];
174       break;
175     case G_FILE_ATTRIBUTE_TYPE_INVALID:
176       value = NULL;
177       break;
178     case G_FILE_ATTRIBUTE_TYPE_OBJECT:
179     default:
180       print_error (_("Invalid attribute type “%s”"), attr_type);
181       return 1;
182     }
183
184   file = g_file_new_for_commandline_arg (argv[1]);
185
186   if (!g_file_set_attribute (file,
187                              attribute,
188                              type,
189                              value,
190                              nofollow_symlinks ?
191                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS :
192                                G_FILE_QUERY_INFO_NONE,
193                              NULL, &error))
194     {
195       print_error ("%s", error->message);
196       g_error_free (error);
197       g_object_unref (file);
198       return 1;
199     }
200
201   g_object_unref (file);
202
203   return 0;
204 }