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
29static char *attr_type = "string";
30static gboolean nofollow_symlinks = FALSE;
31
32static 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
38static char *
39hex_unescape (const char *str)
40{
41 int i;
42 char *unescaped_str, *p;
43 unsigned char c;
44 int len;
45
46 len = strlen (s: str);
47 unescaped_str = g_malloc (n_bytes: 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 (c: str[i+2]) << 4) |
58 g_ascii_xdigit_value (c: 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
70int
71handle_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 (prgname: "gio set");
87
88 /* Translators: commandline placeholder */
89 param = g_strdup_printf (format: "%s %s %s…", _("LOCATION"), _("ATTRIBUTE"), _("VALUE"));
90 context = g_option_context_new (parameter_string: param);
91 g_free (mem: 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: &argc, argv: &argv, error: &error))
104 {
105 show_help (context, message: 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 (str: 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 (str: argv[3]);
151 break;
152 case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
153 b = g_ascii_strcasecmp (s1: argv[3], s2: "true") == 0;
154 value = &b;
155 break;
156 case G_FILE_ATTRIBUTE_TYPE_UINT32:
157 uint32 = atol (nptr: argv[3]);
158 value = &uint32;
159 break;
160 case G_FILE_ATTRIBUTE_TYPE_INT32:
161 int32 = atol (nptr: argv[3]);
162 value = &int32;
163 break;
164 case G_FILE_ATTRIBUTE_TYPE_UINT64:
165 uint64 = g_ascii_strtoull (nptr: argv[3], NULL, base: 10);
166 value = &uint64;
167 break;
168 case G_FILE_ATTRIBUTE_TYPE_INT64:
169 int64 = g_ascii_strtoll (nptr: argv[3], NULL, base: 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 (arg: argv[1]);
185
186 if (!g_file_set_attribute (file,
187 attribute,
188 type,
189 value_p: value,
190 flags: nofollow_symlinks ?
191 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS :
192 G_FILE_QUERY_INFO_NONE,
193 NULL, error: &error))
194 {
195 print_error (format: "%s", error->message);
196 g_error_free (error);
197 g_object_unref (object: file);
198 return 1;
199 }
200
201 g_object_unref (object: file);
202
203 return 0;
204}
205

source code of gtk/subprojects/glib/gio/gio-tool-set.c