/* * Copyright 2015 Red Hat, Inc. * * SPDX-License-Identifier: LGPL-2.1-or-later * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . * * Author: Matthias Clasen */ #include "config.h" #include #include #include #include "gio-tool.h" static char *attr_type = "string"; static gboolean nofollow_symlinks = FALSE; static gboolean delete = FALSE; static const GOptionEntry entries[] = { { "type", 't', 0, G_OPTION_ARG_STRING, &attr_type, N_("Type of the attribute"), N_("TYPE") }, { "nofollow-symlinks", 'n', 0, G_OPTION_ARG_NONE, &nofollow_symlinks, N_("Don’t follow symbolic links"), NULL }, { "delete", 'd', 0, G_OPTION_ARG_NONE, &delete, N_("Unset given attribute"), NULL }, G_OPTION_ENTRY_NULL }; static char * hex_unescape (const char *str) { size_t i; char *unescaped_str, *p; unsigned char c; size_t len; len = strlen (str); unescaped_str = g_malloc (len + 1); p = unescaped_str; for (i = 0; i < len; i++) { if (str[i] == '\\' && str[i+1] == 'x' && len - i >= 4) { c = (g_ascii_xdigit_value (str[i+2]) << 4) | g_ascii_xdigit_value (str[i+3]); *p++ = c; i += 3; } else *p++ = str[i]; } *p++ = 0; return unescaped_str; } int handle_set (int argc, char *argv[], gboolean do_help) { GOptionContext *context; GError *error = NULL; GFile *file; const char *attribute; GFileAttributeType type; gpointer value; gpointer value_allocated = NULL; gboolean b; guint32 uint32; gint32 int32; guint64 uint64; gint64 int64; gchar *param; int retval = 0; g_set_prgname ("gio set"); /* Translators: commandline placeholder */ param = g_strdup_printf ("%s %s %s…", _("LOCATION"), _("ATTRIBUTE"), _("VALUE")); context = g_option_context_new (param); g_free (param); g_option_context_set_help_enabled (context, FALSE); g_option_context_set_summary (context, _("Set a file attribute of LOCATION.")); g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); if (do_help) { show_help (context, NULL); g_option_context_free (context); return 0; } if (!g_option_context_parse (context, &argc, &argv, &error)) { show_help (context, error->message); g_error_free (error); g_option_context_free (context); return 1; } if (argc < 2) { show_help (context, _("Location not specified")); g_option_context_free (context); return 1; } if (argc < 3) { show_help (context, _("Attribute not specified")); g_option_context_free (context); return 1; } attribute = argv[2]; if (delete) { type = G_FILE_ATTRIBUTE_TYPE_INVALID; } else { type = attribute_type_from_string (attr_type); } if ((argc < 4) && (type != G_FILE_ATTRIBUTE_TYPE_INVALID)) { show_help (context, _("Value not specified")); g_option_context_free (context); return 1; } if ((argc > 4) && (type != G_FILE_ATTRIBUTE_TYPE_STRINGV)) { show_help (context, _("Too many arguments")); g_option_context_free (context); return 1; } g_option_context_free (context); switch (type) { case G_FILE_ATTRIBUTE_TYPE_STRING: value = argv[3]; break; case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING: value = value_allocated = hex_unescape (argv[3]); break; case G_FILE_ATTRIBUTE_TYPE_BOOLEAN: b = g_ascii_strcasecmp (argv[3], "true") == 0; value = &b; break; case G_FILE_ATTRIBUTE_TYPE_UINT32: uint32 = atol (argv[3]); value = &uint32; break; case G_FILE_ATTRIBUTE_TYPE_INT32: int32 = atol (argv[3]); value = &int32; break; case G_FILE_ATTRIBUTE_TYPE_UINT64: uint64 = g_ascii_strtoull (argv[3], NULL, 10); value = &uint64; break; case G_FILE_ATTRIBUTE_TYPE_INT64: int64 = g_ascii_strtoll (argv[3], NULL, 10); value = &int64; break; case G_FILE_ATTRIBUTE_TYPE_STRINGV: value = &argv[3]; break; case G_FILE_ATTRIBUTE_TYPE_INVALID: value = NULL; break; case G_FILE_ATTRIBUTE_TYPE_OBJECT: default: print_error (_("Invalid attribute type “%s”"), attr_type); return 1; } file = g_file_new_for_commandline_arg (argv[1]); if (!g_file_set_attribute (file, attribute, type, value, nofollow_symlinks ? G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS : G_FILE_QUERY_INFO_NONE, NULL, &error)) { print_error ("%s", error->message); g_error_free (error); retval = 1; } g_clear_pointer (&value_allocated, g_free); g_object_unref (file); return retval; }