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