From 041d1ea37802bf7178a31a53f96c26efa6b8fb7b Mon Sep 17 00:00:00 2001 From: James Date: Fri, 16 Nov 2012 10:41:01 +0000 Subject: fish --- util/grub-editenv.c | 313 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 util/grub-editenv.c (limited to 'util/grub-editenv.c') diff --git a/util/grub-editenv.c b/util/grub-editenv.c new file mode 100644 index 0000000..5199454 --- /dev/null +++ b/util/grub-editenv.c @@ -0,0 +1,313 @@ +/* grub-editenv.c - tool to edit environment block. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "progname.h" + +#define DEFAULT_ENVBLK_SIZE 1024 +#define DEFAULT_ENVBLK_PATH DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG + +static struct argp_option options[] = { + {0, 0, 0, OPTION_DOC, N_("Commands:"), 1}, + {"create", 0, 0, OPTION_DOC|OPTION_NO_USAGE, + N_("Create a blank environment block file."), 0}, + {"list", 0, 0, OPTION_DOC|OPTION_NO_USAGE, + N_("List the current variables."), 0}, + {"set [name=value ...]", 0, 0, OPTION_DOC|OPTION_NO_USAGE, + N_("Set variables."), 0}, + {"unset [name ....]", 0, 0, OPTION_DOC|OPTION_NO_USAGE, + N_("Delete variables."), 0}, + + {0, 0, 0, OPTION_DOC, N_("Options:"), -1}, + {"verbose", 'v', 0, 0, N_("Print verbose messages."), 0}, + + { 0, 0, 0, 0, 0, 0 } +}; + +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) +{ + fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); +} +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +/* Set the bug report address */ +const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">"; + +error_t argp_parser (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case 'v': + verbosity++; + break; + + case ARGP_KEY_NO_ARGS: + fprintf (stderr, "%s", + _("You need to specify at least one command.\n")); + argp_usage (state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static char * +help_filter (int key, const char *text, void *input __attribute__ ((unused))) +{ + switch (key) + { + case ARGP_KEY_HELP_POST_DOC: + return xasprintf(text, DEFAULT_ENVBLK_PATH); + + default: + return (char *) text; + } +} + +struct argp argp = { + options, argp_parser, N_("FILENAME COMMAND"), + "\n"N_("\ +Tool to edit environment block.") +"\v"N_("\ +If FILENAME is '-', the default value %s is used."), + NULL, help_filter, NULL +}; + +static void +create_envblk_file (const char *name) +{ + FILE *fp; + char *buf; + char *namenew; + + buf = malloc (DEFAULT_ENVBLK_SIZE); + if (! buf) + grub_util_error ("out of memory"); + + namenew = xasprintf ("%s.new", name); + fp = fopen (namenew, "wb"); + if (! fp) + grub_util_error ("cannot open the file %s", namenew); + + memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1); + memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', + DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1); + + if (fwrite (buf, 1, DEFAULT_ENVBLK_SIZE, fp) != DEFAULT_ENVBLK_SIZE) + grub_util_error ("cannot write to the file %s", namenew); + + fsync (fileno (fp)); + free (buf); + fclose (fp); + + if (rename (namenew, name) < 0) + grub_util_error ("cannot rename the file %s to %s", namenew, name); + free (namenew); +} + +static grub_envblk_t +open_envblk_file (const char *name) +{ + FILE *fp; + char *buf; + size_t size; + grub_envblk_t envblk; + + fp = fopen (name, "rb"); + if (! fp) + { + /* Create the file implicitly. */ + create_envblk_file (name); + fp = fopen (name, "rb"); + if (! fp) + grub_util_error ("cannot open the file %s", name); + } + + if (fseek (fp, 0, SEEK_END) < 0) + grub_util_error ("cannot seek the file %s", name); + + size = (size_t) ftell (fp); + + if (fseek (fp, 0, SEEK_SET) < 0) + grub_util_error ("cannot seek the file %s", name); + + buf = malloc (size); + if (! buf) + grub_util_error ("out of memory"); + + if (fread (buf, 1, size, fp) != size) + grub_util_error ("cannot read the file %s", name); + + fclose (fp); + + envblk = grub_envblk_open (buf, size); + if (! envblk) + grub_util_error ("invalid environment block"); + + return envblk; +} + +static void +list_variables (const char *name) +{ + grub_envblk_t envblk; + + auto int print_var (const char *name, const char *value); + int print_var (const char *name, const char *value) + { + printf ("%s=%s\n", name, value); + return 0; + } + + envblk = open_envblk_file (name); + grub_envblk_iterate (envblk, print_var); + grub_envblk_close (envblk); +} + +static void +write_envblk (const char *name, grub_envblk_t envblk) +{ + FILE *fp; + + fp = fopen (name, "wb"); + if (! fp) + grub_util_error ("cannot open the file %s", name); + + if (fwrite (grub_envblk_buffer (envblk), 1, grub_envblk_size (envblk), fp) + != grub_envblk_size (envblk)) + grub_util_error ("cannot write to the file %s", name); + + fsync (fileno (fp)); + fclose (fp); +} + +static void +set_variables (const char *name, int argc, char *argv[]) +{ + grub_envblk_t envblk; + + envblk = open_envblk_file (name); + while (argc) + { + char *p; + + p = strchr (argv[0], '='); + if (! p) + grub_util_error ("invalid parameter %s", argv[0]); + + *(p++) = 0; + + if (! grub_envblk_set (envblk, argv[0], p)) + grub_util_error ("environment block too small"); + + argc--; + argv++; + } + + write_envblk (name, envblk); + grub_envblk_close (envblk); +} + +static void +unset_variables (const char *name, int argc, char *argv[]) +{ + grub_envblk_t envblk; + + envblk = open_envblk_file (name); + while (argc) + { + grub_envblk_delete (envblk, argv[0]); + + argc--; + argv++; + } + + write_envblk (name, envblk); + grub_envblk_close (envblk); +} + +int +main (int argc, char *argv[]) +{ + char *filename; + char *command; + int index, arg_count; + + set_program_name (argv[0]); + + grub_util_init_nls (); + + /* Parse our arguments */ + if (argp_parse (&argp, argc, argv, 0, &index, 0) != 0) + { + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); + } + + arg_count = argc - index; + + if (arg_count == 1) + { + filename = DEFAULT_ENVBLK_PATH; + command = argv[index++]; + } + else + { + filename = argv[index++]; + if (strcmp (filename, "-") == 0) + filename = DEFAULT_ENVBLK_PATH; + command = argv[index++]; + } + + if (strcmp (command, "create") == 0) + create_envblk_file (filename); + else if (strcmp (command, "list") == 0) + list_variables (filename); + else if (strcmp (command, "set") == 0) + set_variables (filename, argc - index, argv + index); + else if (strcmp (command, "unset") == 0) + unset_variables (filename, argc - index, argv + index); + else + { + char *program = xstrdup(program_name); + fprintf (stderr, _("Unknown command `%s'.\n"), command); + argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program); + free(program); + exit(1); + } + + return 0; +} -- cgit v1.2.3