Rewrite grub-install, grub-mkrescue, grub-mkstandalone and grub-mknetdir

the function of these files exceeds what can be sanely handled in shell
	in posix-comaptible way. Also writing it in C extends the functionality
	to non-UNIX-like OS and minimal environments.
This commit is contained in:
Vladimir Serbinenko 2013-11-16 20:21:16 +01:00
parent 9ef81064a3
commit cd46aa6cef
52 changed files with 5811 additions and 2101 deletions

View file

@ -428,3 +428,10 @@ efiemu64.o: efiemu64_c.o efiemu64_s.o $(TARGET_OBJ2ELEF)
platform_DATA += efiemu32.o efiemu64.o
CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o
endif
windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows
windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA)
test -d $(windowsdir)/$(target_cpu)-$(platform) || mkdir $(windowsdir)/$(target_cpu)-$(platform)
for x in $(platform_DATA); do \
cp -fp $$x $(windowsdir)/$(target_cpu)-$(platform)/$$x; \
done

View file

@ -609,3 +609,78 @@ grub_util_biosdisk_get_osdev (grub_disk_t disk)
return map[disk->id].device;
}
static char *
grub_util_path_concat_real (size_t n, int ext, va_list ap)
{
size_t totlen = 0;
char **l = xmalloc ((n + ext) * sizeof (l[0]));
char *r, *p, *pi;
size_t i;
int first = 1;
for (i = 0; i < n + ext; i++)
{
l[i] = va_arg (ap, char *);
if (l[i])
totlen += strlen (l[i]) + 1;
}
r = xmalloc (totlen + 10);
p = r;
for (i = 0; i < n; i++)
{
pi = l[i];
if (!pi)
continue;
while (*pi == '/')
pi++;
if ((p != r || (pi != l[i] && first)) && (p == r || *(p - 1) != '/'))
*p++ = '/';
first = 0;
p = grub_stpcpy (p, pi);
while (p != r && p != r + 1 && *(p - 1) == '/')
p--;
}
if (ext && l[i])
p = grub_stpcpy (p, l[i]);
*p = '\0';
free (l);
return r;
}
char *
grub_util_path_concat (size_t n, ...)
{
va_list ap;
char *r;
va_start (ap, n);
r = grub_util_path_concat_real (n, 0, ap);
va_end (ap);
return r;
}
char *
grub_util_path_concat_ext (size_t n, ...)
{
va_list ap;
char *r;
va_start (ap, n);
r = grub_util_path_concat_real (n, 1, ap);
va_end (ap);
return r;
}

View file

@ -0,0 +1,94 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,2012,2013 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 <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <config-util.h>
#include <grub/emu/hostdisk.h>
#include <grub/emu/exec.h>
#include <grub/emu/config.h>
#include <grub/util/install.h>
#include <grub/util/misc.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdlib.h>
const char *
grub_util_get_config_filename (void)
{
static char *value = NULL;
if (!value)
value = grub_util_path_concat (3, GRUB_SYSCONFDIR,
"default", "grub");
return value;
}
const char *
grub_util_get_pkgdatadir (void)
{
const char *ret = getenv ("pkgdatadir");
if (ret)
return ret;
return GRUB_DATADIR "/" PACKAGE;
}
const char *
grub_util_get_pkglibdir (void)
{
return GRUB_LIBDIR "/" PACKAGE;
}
const char *
grub_util_get_localedir (void)
{
return LOCALEDIR;
}
void
grub_util_load_config (struct grub_util_config *cfg)
{
const char *cfgfile;
FILE *f = NULL;
const char *v;
memset (cfg, 0, sizeof (*cfg));
v = getenv ("GRUB_ENABLE_CRYPTODISK");
if (v && v[0] == 'y' && v[1] == '\0')
cfg->is_cryptodisk_enabled = 1;
v = getenv ("GRUB_DISTRIBUTOR");
if (v)
cfg->grub_distributor = xstrdup (v);
cfgfile = grub_util_get_config_filename ();
if (!grub_util_is_regular (cfgfile))
return;
f = grub_util_fopen (cfgfile, "r");
if (f)
{
grub_util_parse_config (f, cfg, 0);
fclose (f);
}
else
grub_util_warn (_("cannot open config file `%s': %s"),
cfgfile, strerror (errno));
}

View file

@ -41,6 +41,7 @@
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <time.h>
#include <string.h>
#include <dos/dos.h>
@ -516,6 +517,17 @@ grub_util_is_directory (const char *path)
return S_ISDIR (st.st_mode);
}
int
grub_util_is_regular (const char *path)
{
struct stat st;
if (stat (path, &st) == -1)
return 0;
return S_ISREG (st.st_mode);
}
int
grub_util_is_special_file (const char *path)
{
@ -525,3 +537,53 @@ grub_util_is_special_file (const char *path)
return 1;
return (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode));
}
static char *
get_temp_name (void)
{
static int ctr = 0;
char *t;
struct stat st;
while (1)
{
t = xasprintf ("T:grub.%d.%d.%d.%d", (int) getpid (), (int) getppid (),
ctr++, time (0));
if (stat (t, &st) == -1)
return t;
free (t);
}
}
char *
grub_util_make_temporary_file (void)
{
char *ret = get_temp_name ();
FILE *f;
f = grub_util_fopen (ret, "wb");
if (f)
fclose (f);
return ret;
}
char *
grub_util_make_temporary_dir (void)
{
char *ret = get_temp_name ();
grub_util_mkdir (ret);
return ret;
}
grub_uint32_t
grub_util_get_mtime (const char *path)
{
struct stat st;
if (stat (path, &st) == -1)
return 0;
return st.st_mtime;
}

View file

@ -0,0 +1,21 @@
#include <config.h>
#include <grub/util/install.h>
#include <grub/util/misc.h>
int
grub_install_compress_gzip (const char *src, const char *dest)
{
grub_util_error ("no compression is available for your platform");
}
int
grub_install_compress_xz (const char *src, const char *dest)
{
grub_util_error ("no compression is available for your platform");
}
int
grub_install_compress_lzop (const char *src, const char *dest)
{
grub_util_error ("no compression is available for your platform");
}

View file

@ -20,6 +20,7 @@
#include <config-util.h>
#include <grub/util/misc.h>
#include <grub/i18n.h>
#include "progname.h"
@ -29,7 +30,9 @@ grub_util_host_init (int *argc __attribute__ ((unused)),
{
set_program_name ((*argv)[0]);
#ifdef GRUB_UTIL
grub_util_init_nls ();
#endif
#if (defined (GRUB_UTIL) && defined(ENABLE_NLS) && ENABLE_NLS)
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
}

View file

@ -0,0 +1,46 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/emu/misc.h>
#include <grub/util/install.h>
#include <grub/util/misc.h>
#include "platform.c"
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
int partno, const char *relpath)
{
grub_util_error ("%s", "no IEEE1275 routines are available for your platform");
}
void
grub_install_register_efi (const char *efidir_disk, int efidir_part,
const char *efifile_path,
const char *efi_distributor)
{
grub_util_error ("%s", "no EFI routines are available for your platform");
}
void
grub_install_sgi_setup (const char *install_device,
const char *imgfile, const char *destname)
{
grub_util_error ("%s", "no SGI routines are available for your platform");
}

View file

@ -0,0 +1,26 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
*/
#include <grub/util/install.h>
const char *
grub_install_get_default_x86_platform (void)
{
return "i386-pc";
}

View file

@ -0,0 +1,5 @@
#if !defined (__MINGW32__) && !defined (__CYGWIN__) && !defined (__AROS__)
#include "unix/compress.c"
#else
#include "basic/compress.c"
#endif

7
grub-core/osdep/config.c Normal file
View file

@ -0,0 +1,7 @@
#if defined (__MINGW32__) && !defined (__CYGWIN__)
#include "windows/config.c"
#elif defined (__AROS__)
#include "aros/config.c"
#else
#include "unix/config.c"
#endif

View file

@ -0,0 +1,85 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/util/install.h>
#include <grub/emu/exec.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <sys/utsname.h>
static int
is_not_empty_directory (const char *dir)
{
DIR *d;
struct dirent *de;
d = opendir (dir);
if (!d)
return 0;
while ((de = readdir (d)))
{
if (strcmp (de->d_name, ".") == 0
|| strcmp (de->d_name, "..") == 0)
continue;
closedir (d);
return 1;
}
closedir (d);
return 0;
}
static int
is_64_kernel (void)
{
struct utsname un;
if (uname (&un) < 0)
return 0;
return strcmp (un.machine, "x86_64") == 0;
}
const char *
grub_install_get_default_x86_platform (void)
{
/*
On Linux, we need the efivars kernel modules.
If no EFI is available this module just does nothing
besides a small hello and if we detect efi we'll load it
anyway later. So it should be safe to
try to load it here.
*/
grub_util_exec ((const char * []){ "modprobe", "-q",
"efivars", NULL });
if (is_not_empty_directory ("/sys/firmware/efi"))
{
if (is_64_kernel ())
return "x86_64-efi";
else
return "i386-efi";
}
else if (is_not_empty_directory ("/proc/device-tree"))
return "i386-ieee1275";
else
return "i386-pc";
}

View file

@ -0,0 +1,7 @@
#ifdef __linux__
#include "linux/platform.c"
#elif defined (__MINGW32__) || defined (__CYGWIN__) || defined (__AROS__)
#include "basic/no_platform.c"
#else
#include "basic/platform.c"
#endif

View file

@ -0,0 +1,3 @@
#if !defined (__MINGW32__) && !defined (__CYGWIN__) && !defined (__AROS__)
#include "unix/platform.c"
#endif

View file

@ -0,0 +1,41 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
*/
#include <grub/emu/exec.h>
#include <grub/util/install.h>
int
grub_install_compress_gzip (const char *src, const char *dest)
{
return grub_util_exec_redirect ((const char * []) { "gzip", "--best",
"--stdout", NULL }, src, dest);
}
int
grub_install_compress_xz (const char *src, const char *dest)
{
return grub_util_exec_redirect ((const char * []) { "xz",
"--lzma2=dict=128KiB", "--check=none", "--stdout", NULL }, src, dest);
}
int
grub_install_compress_lzop (const char *src, const char *dest)
{
return grub_util_exec_redirect ((const char * []) { "lzop", "-9", "-c",
NULL }, src, dest);
}

View file

@ -0,0 +1,139 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,2012,2013 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 <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <config-util.h>
#include <grub/emu/hostdisk.h>
#include <grub/emu/exec.h>
#include <grub/emu/config.h>
#include <grub/util/install.h>
#include <grub/util/misc.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdlib.h>
const char *
grub_util_get_config_filename (void)
{
static char *value = NULL;
if (!value)
value = grub_util_path_concat (3, GRUB_SYSCONFDIR,
"default", "grub");
return value;
}
const char *
grub_util_get_pkgdatadir (void)
{
const char *ret = getenv ("pkgdatadir");
if (ret)
return ret;
return GRUB_DATADIR "/" PACKAGE;
}
const char *
grub_util_get_pkglibdir (void)
{
return GRUB_LIBDIR "/" PACKAGE;
}
const char *
grub_util_get_localedir (void)
{
return LOCALEDIR;
}
void
grub_util_load_config (struct grub_util_config *cfg)
{
pid_t pid;
const char *argv[4];
char *script, *ptr;
const char *cfgfile, *iptr;
FILE *f = NULL;
int fd;
const char *v;
memset (cfg, 0, sizeof (*cfg));
v = getenv ("GRUB_ENABLE_CRYPTODISK");
if (v && v[0] == 'y' && v[1] == '\0')
cfg->is_cryptodisk_enabled = 1;
v = getenv ("GRUB_DISTRIBUTOR");
if (v)
cfg->grub_distributor = xstrdup (v);
cfgfile = grub_util_get_config_filename ();
if (!grub_util_is_regular (cfgfile))
return;
argv[0] = "sh";
argv[1] = "-c";
script = xmalloc (4 * strlen (cfgfile) + 300);
ptr = script;
memcpy (ptr, ". '", 3);
ptr += 3;
for (iptr = cfgfile; *iptr; iptr++)
{
if (*iptr == '\\')
{
memcpy (ptr, "'\\''", 4);
ptr += 4;
continue;
}
*ptr++ = *iptr;
}
strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\n\", "
"\"$GRUB_ENABLE_CRYPTODISK\", \"$GRUB_DISTRIBUTOR\"");
argv[2] = script;
argv[3] = '\0';
pid = grub_util_exec_pipe (argv, &fd);
if (pid)
f = fdopen (fd, "r");
if (f)
{
grub_util_parse_config (f, cfg, 1);
fclose (f);
}
if (pid)
{
close (fd);
waitpid (pid, NULL, 0);
}
if (f)
return;
f = grub_util_fopen (cfgfile, "r");
if (f)
{
grub_util_parse_config (f, cfg, 0);
fclose (f);
}
else
grub_util_warn (_("cannot open config file `%s': %s"),
cfgfile, strerror (errno));
}

View file

@ -38,6 +38,23 @@ grub_util_exec (const char *const *argv)
{
pid_t pid;
int status = -1;
char *str, *pstr;
const char *const *ptr;
grub_size_t strl = 0;
for (ptr = argv; *ptr; ptr++)
strl += grub_strlen (*ptr) + 1;
pstr = str = xmalloc (strl);
for (ptr = argv; *ptr; ptr++)
{
pstr = grub_stpcpy (pstr, *ptr);
*pstr++ = ' ';
}
if (pstr > str)
pstr--;
*pstr = '\0';
grub_util_info ("executing %s", str);
grub_free (str);
pid = fork ();
if (pid < 0)
@ -71,6 +88,29 @@ grub_util_exec_redirect (const char *const *argv, const char *stdin_file,
{
pid_t mdadm_pid;
int status = -1;
char *str, *pstr;
const char *const *ptr;
grub_size_t strl = 0;
for (ptr = argv; *ptr; ptr++)
strl += grub_strlen (*ptr) + 1;
strl += grub_strlen (stdin_file) + 2;
strl += grub_strlen (stdout_file) + 2;
pstr = str = xmalloc (strl);
for (ptr = argv; *ptr; ptr++)
{
pstr = grub_stpcpy (pstr, *ptr);
*pstr++ = ' ';
}
*pstr++ = '<';
pstr = grub_stpcpy (pstr, stdin_file);
*pstr++ = ' ';
*pstr++ = '>';
pstr = grub_stpcpy (pstr, stdout_file);
*pstr = '\0';
grub_util_info ("executing %s", str);
grub_free (str);
mdadm_pid = fork ();
if (mdadm_pid < 0)
@ -87,6 +127,8 @@ grub_util_exec_redirect (const char *const *argv, const char *stdin_file,
#endif
in = open (stdin_file, O_RDONLY);
if (in < 0)
exit (127);
dup2 (in, STDIN_FILENO);
close (in);
@ -94,6 +136,9 @@ grub_util_exec_redirect (const char *const *argv, const char *stdin_file,
dup2 (out, STDOUT_FILENO);
close (out);
if (out < 0)
exit (127);
/* Ensure child is not localised. */
setenv ("LC_ALL", "C", 1);

View file

@ -246,6 +246,17 @@ grub_util_is_regular (const char *path)
return S_ISREG (st.st_mode);
}
grub_uint32_t
grub_util_get_mtime (const char *path)
{
struct stat st;
if (stat (path, &st) == -1)
return 0;
return st.st_mtime;
}
int
grub_util_is_special_file (const char *path)
{
@ -256,4 +267,39 @@ grub_util_is_special_file (const char *path)
return (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode));
}
char *
grub_util_make_temporary_file (void)
{
const char *t = getenv ("TMPDIR");
size_t tl;
char *tmp;
if (!t)
t = "/tmp";
tl = strlen (t);
tmp = xmalloc (tl + sizeof ("/grub.XXXXXX"));
memcpy (tmp, t, tl);
memcpy (tmp + tl, "/grub.XXXXXX",
sizeof ("/grub.XXXXXX"));
mkstemp (tmp);
return tmp;
}
char *
grub_util_make_temporary_dir (void)
{
const char *t = getenv ("TMPDIR");
size_t tl;
char *tmp;
if (!t)
t = "/tmp";
tl = strlen (t);
tmp = xmalloc (tl + sizeof ("/grub.XXXXXX"));
memcpy (tmp, t, tl);
memcpy (tmp + tl, "/grub.XXXXXX",
sizeof ("/grub.XXXXXX"));
mkdtemp (tmp);
return tmp;
}
#endif

View file

@ -0,0 +1,213 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/util/install.h>
#include <grub/util/misc.h>
#include <grub/misc.h>
#include <grub/i18n.h>
#include <grub/emu/exec.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
static char *
get_ofpathname (const char *dev)
{
char *ret = xmalloc (2 * PATH_MAX);
char *end = ret + 2 * PATH_MAX - 1;
int fd;
pid_t pid;
char *ptr = ret;
pid = grub_util_exec_pipe ((const char * []){ "ofpathname", dev, NULL }, &fd);
if (!pid)
goto fail;
FILE *fp = fdopen (fd, "r");
if (!fp)
goto fail;
while (!feof (fp) && ptr < end)
{
size_t r;
r = fread (ptr, 1, end - ptr, fp);
ptr += r;
}
fclose (fp);
return ret;
fail:
grub_util_error (_("couldn't find IEEE1275 device tree path for %s.\nYou will have to set `boot-device' variable manually"),
dev);
}
static void
grub_install_remove_efi_entries_by_distributor (const char *efi_distributor)
{
int fd;
pid_t pid = grub_util_exec_pipe ((const char * []){ "efibootmgr", NULL }, &fd);
char *line = NULL;
size_t len = 0;
if (!pid)
{
grub_util_warn (_("Unable to open stream from %s: %s"),
"efibootmgr", strerror (errno));
return;
}
FILE *fp = fdopen (fd, "r");
if (!fp)
{
grub_util_warn (_("Unable to open stream from %s: %s"),
"efibootmgr", strerror (errno));
return;
}
line = xmalloc (80);
len = 80;
while (1)
{
int ret;
char *bootnum;
ret = getline (&line, &len, fp);
if (ret == -1)
break;
if (grub_memcmp (line, "Boot", sizeof ("Boot") - 1) != 0
|| line[sizeof ("Boot") - 1] < '0'
|| line[sizeof ("Boot") - 1] > '9')
continue;
if (!strcasestr (line, efi_distributor))
continue;
bootnum = line + sizeof ("Boot") - 1;
bootnum[4] = '\0';
if (!verbosity)
grub_util_exec ((const char * []){ "efibootmgr", "-q",
"-b", bootnum, "-B", NULL });
else
grub_util_exec ((const char * []){ "efibootmgr",
"-b", bootnum, "-B", NULL });
}
free (line);
}
void
grub_install_register_efi (const char *efidir_disk, int efidir_part,
const char *efifile_path,
const char *efi_distributor)
{
if (grub_util_exec_redirect_null ((const char * []){ "efibootmgr", "--version", NULL }))
{
/* TRANSLATORS: This message is shown when required executable `%s'
isn't found. */
grub_util_error (_("%s: not found"), "efibootmgr");
}
/* On Linux, we need the efivars kernel modules. */
#ifdef __linux__
grub_util_exec ((const char * []){ "modprobe", "-q", "efivars", NULL });
#endif
/* Delete old entries from the same distributor. */
grub_install_remove_efi_entries_by_distributor (efi_distributor);
char *efidir_part_str = xasprintf ("%d", efidir_part);
if (!verbosity)
grub_util_exec ((const char * []){ "efibootmgr", "-q",
"-c", "-d", efidir_disk,
"-p", efidir_part_str, "-w",
"-L", efi_distributor, "-l",
efifile_path, NULL });
else
grub_util_exec ((const char * []){ "efibootmgr",
"-c", "-d", efidir_disk,
"-p", efidir_part_str, "-w",
"-L", efi_distributor, "-l",
efifile_path, NULL });
free (efidir_part_str);
}
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
int partno, const char *relpath)
{
char *boot_device;
if (grub_util_exec_redirect_null ((const char * []){ "ofpathname", "--version", NULL }))
{
/* TRANSLATORS: This message is shown when required executable `%s'
isn't found. */
grub_util_error (_("%s: not found"), "ofpathname");
}
/* Get the Open Firmware device tree path translation. */
if (!is_prep)
{
char *ptr;
char *ofpath;
const char *iptr;
ofpath = get_ofpathname (install_device);
boot_device = xmalloc (strlen (ofpath) + 1
+ sizeof ("XXXXXXXXXXXXXXXXXXXX")
+ 1 + strlen (relpath) + 1);
ptr = grub_stpcpy (boot_device, ofpath);
*ptr++ = ':';
grub_snprintf (ptr, sizeof ("XXXXXXXXXXXXXXXXXXXX"), "%d",
partno);
ptr += strlen (ptr);
*ptr++ = ',';
for (iptr = relpath; *iptr; iptr++, ptr++)
{
if (*iptr == '/')
*ptr = '\\';
else
*ptr = *iptr;
}
*ptr = '\0';
}
else
boot_device = get_ofpathname (install_device);
if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
boot_device, NULL }))
{
char *cmd = xasprintf ("setenv boot-device %s", boot_device);
grub_util_error ("`nvsetenv' failed. \nYou will have to set `boot-device' variable manually. At the IEEE1275 prompt, type:\n %s\n",
cmd);
free (cmd);
}
free (boot_device);
}
void
grub_install_sgi_setup (const char *install_device,
const char *imgfile, const char *destname)
{
grub_util_exec ((const char * []){ "dvhtool", "-d",
install_device, "--unix-to-vh",
imgfile, destname, NULL });
grub_util_warn ("%s", _("You will have to set `SystemPartition' and `OSLoader' manually."));
}

View file

@ -0,0 +1,57 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,2012,2013 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 <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <config-util.h>
#include <grub/emu/hostfile.h>
#include <grub/emu/config.h>
#include <grub/util/install.h>
#include <grub/util/misc.h>
void
grub_util_load_config (struct grub_util_config *cfg)
{
const char *cfgfile;
FILE *f = NULL;
const char *v;
cfgfile = grub_util_get_config_filename ();
if (!grub_util_is_regular (cfgfile))
return;
memset (cfg, 0, sizeof (*cfg));
v = getenv ("GRUB_ENABLE_CRYPTODISK");
if (v && v[0] == 'y' && v[1] == '\0')
cfg->is_cryptodisk_enabled = 1;
v = getenv ("GRUB_DISTRIBUTOR");
if (v)
cfg->grub_distributor = xstrdup (v);
f = grub_util_fopen (cfgfile, "r");
if (f)
{
grub_util_parse_config (f, cfg, 0);
fclose (f);
}
else
grub_util_warn (_("cannot open config file `%s': %s"),
cfgfile, strerror (errno));
}

View file

@ -46,6 +46,7 @@
#include <windows.h>
#include <winioctl.h>
#include <wincrypt.h>
#if SIZEOF_TCHAR == 1
@ -411,6 +412,89 @@ grub_util_unlink (const char *name)
return ret;
}
int
grub_util_rmdir (const char *name)
{
LPTSTR name_windows;
int ret;
name_windows = grub_util_get_windows_path (name);
ret = !RemoveDirectory (name_windows);
free (name_windows);
return ret;
}
static char *
get_temp_name (void)
{
TCHAR rt[1024];
TCHAR *ptr;
HCRYPTPROV hCryptProv;
grub_uint8_t rnd[5];
const size_t sz = sizeof (rnd) * GRUB_CHAR_BIT / 5;
int i;
GetTempPath (ARRAY_SIZE (rt) - 100, rt);
if (!CryptAcquireContext (&hCryptProv,
NULL,
MS_DEF_PROV,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)
|| !CryptGenRandom (hCryptProv, 5, rnd))
grub_util_error ("%s", _("couldn't retrieve random data"));
CryptReleaseContext (hCryptProv, 0);
for (ptr = rt; *ptr; ptr++);
memcpy (ptr, TEXT("\\GRUB."), sizeof (TEXT("\\GRUB.")));
ptr += sizeof ("\\GRUB.") - 1;
for (i = 0; i < 8; i++)
{
grub_size_t b = i * 5;
grub_uint8_t r;
grub_size_t f1 = GRUB_CHAR_BIT - b % GRUB_CHAR_BIT;
grub_size_t f2;
if (f1 > 5)
f1 = 5;
f2 = 5 - f1;
r = (rnd[b / GRUB_CHAR_BIT] >> (b % GRUB_CHAR_BIT)) & ((1 << f1) - 1);
if (f2)
r |= (rnd[b / GRUB_CHAR_BIT + 1] & ((1 << f2) - 1)) << f1;
if (r < 10)
*ptr++ = '0' + r;
else
*ptr++ = 'a' + (r - 10);
}
*ptr = '\0';
return grub_util_tchar_to_utf8 (rt);
}
char *
grub_util_make_temporary_file (void)
{
char *ret = get_temp_name ();
FILE *f;
f = grub_util_fopen (ret, "wb");
if (f)
fclose (f);
return ret;
}
char *
grub_util_make_temporary_dir (void)
{
char *ret = get_temp_name ();
grub_util_mkdir (ret);
return ret;
}
int
grub_util_is_directory (const char *name)
{
@ -444,6 +528,33 @@ grub_util_is_regular (const char *name)
&& !(attr & FILE_ATTRIBUTE_REPARSE_POINT) && attr;
}
grub_uint32_t
grub_util_get_mtime (const char *path)
{
LPTSTR name_windows;
BOOL b;
WIN32_FILE_ATTRIBUTE_DATA attr;
ULARGE_INTEGER us_ul;
name_windows = grub_util_get_windows_path (path);
if (!name_windows)
return 0;
b = GetFileAttributesEx (name_windows, GetFileExInfoStandard, &attr);
grub_free (name_windows);
if (!b)
return 0;
us_ul.LowPart = attr.ftLastWriteTime.dwLowDateTime;
us_ul.HighPart = attr.ftLastWriteTime.dwHighDateTime;
return (us_ul.QuadPart / 10000000)
- 86400ULL * 365 * (1970 - 1601)
- 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
}
#ifdef __MINGW32__
FILE *

View file

@ -21,6 +21,7 @@
#include <grub/util/misc.h>
#include <grub/osdep/hostfile.h>
#include <grub/util/windows.h>
#include <grub/emu/config.h>
#include <wincon.h>
#include <windows.h>
@ -111,10 +112,42 @@ set_console_unicode_font (void)
}
}
static char *grub_util_base_directory;
static char *locale_dir;
const char *
grub_util_get_config_filename (void)
{
static char *value = NULL;
if (!value)
value = grub_util_path_concat (2, grub_util_base_directory, "grub.cfg");
return value;
}
const char *
grub_util_get_pkgdatadir (void)
{
return grub_util_base_directory;
}
const char *
grub_util_get_localedir (void)
{
return locale_dir;
}
const char *
grub_util_get_pkglibdir (void)
{
return grub_util_base_directory;
}
void
grub_util_host_init (int *argc __attribute__ ((unused)),
char ***argv)
{
char *ptr;
SetConsoleOutputCP (CP_UTF8);
SetConsoleCP (CP_UTF8);
@ -137,9 +170,21 @@ grub_util_host_init (int *argc __attribute__ ((unused)),
#error "Unsupported TCHAR size"
#endif
grub_util_base_directory = canonicalize_file_name ((*argv)[0]);
if (!grub_util_base_directory)
grub_util_base_directory = xstrdup ((*argv)[0]);
for (ptr = grub_util_base_directory + strlen (grub_util_base_directory) - 1;
ptr >= grub_util_base_directory && *ptr != '/' && *ptr != '\\'; ptr--);
if (ptr >= grub_util_base_directory)
*ptr = '\0';
locale_dir = grub_util_path_concat (2, grub_util_base_directory, "locale");
set_program_name ((*argv)[0]);
#ifdef GRUB_UTIL
grub_util_init_nls ();
#endif
#if (defined (GRUB_UTIL) && defined(ENABLE_NLS) && ENABLE_NLS)
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, locale_dir);
textdomain (PACKAGE);
#endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
}