From: Peter Jones <pjo...@redhat.com> The grub-editenv create command will wrongly overwrite /boot/grub2/grubenv with a regular file if grubenv is a symbolic link. But instead, it should create a new file in the path the symlink points to.
This lets /boot/grub2/grubenv be a symlink to /boot/efi/EFI/fedora/grubenv even when they're different mount points, which allows grub2-editenv to be the same across platforms (i.e. UEFI vs BIOS). For example, in Fedora the GRUB EFI builds have prefix set to /EFI/fedora (on the EFI System Partition), but for BIOS machine it'll be /boot/grub2 (which may or may not be its own mountpoint). With this patch, on EFI machines we can make /boot/grub2/grubenv a symlink to /boot/efi/EFI/fedora/grubenv, and the same copy of grub-set-default will work on both kinds of systems. Windows doesn't implement a readlink primitive, so the current behaviour is maintained for this operating system. Signed-off-by: Peter Jones <pjo...@redhat.com> Signed-off-by: Jonathan Lebon <jle...@redhat.com> Reviewed-by: Adam Jackson <a...@redhat.com> Signed-off-by: Javier Martinez Canillas <javi...@redhat.com> --- Changes in v4: - Only attempt following symlinks in operating sytems other than Windows. Changes in v3: - A couple of style cleanups. Changes in v2: - Address issues pointed out by Daniel Kiper in the previous version. Makefile.util.def | 11 ++++++++ util/editenv.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/Makefile.util.def b/Makefile.util.def index 969d32f0097..733a397cb2b 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -240,8 +240,19 @@ program = { common = util/grub-editenv.c; common = util/editenv.c; + common = util/grub-install-common.c; common = grub-core/osdep/init.c; + common = grub-core/osdep/compress.c; + extra_dist = grub-core/osdep/unix/compress.c; + extra_dist = grub-core/osdep/basic/compress.c; + common = util/mkimage.c; + common = util/grub-mkimage32.c; + common = util/grub-mkimage64.c; + common = grub-core/osdep/config.c; + common = util/config.c; + common = util/resolve.c; + ldadd = '$(LIBLZMA)'; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; diff --git a/util/editenv.c b/util/editenv.c index eb2d0c03a98..d53d4d6c68e 100644 --- a/util/editenv.c +++ b/util/editenv.c @@ -28,6 +28,9 @@ #include <errno.h> #include <string.h> +#if !defined(_WIN32) +#include <libgen.h> +#endif #define DEFAULT_ENVBLK_SIZE 1024 @@ -37,6 +40,11 @@ grub_util_create_envblk_file (const char *name) FILE *fp; char *buf; char *namenew; +#if !defined(_WIN32) + ssize_t size = 1; + char *rename_target = xstrdup (name); + int rc; +#endif buf = xmalloc (DEFAULT_ENVBLK_SIZE); @@ -60,7 +68,64 @@ grub_util_create_envblk_file (const char *name) free (buf); fclose (fp); +#if defined(_WIN32) if (grub_util_rename (namenew, name) < 0) grub_util_error (_("cannot rename the file %s to %s"), namenew, name); +#else + while (1) + { + char *linkbuf; + ssize_t retsize; + + linkbuf = xmalloc (size + 1); + retsize = grub_util_readlink (rename_target, linkbuf, size); + if (retsize < 0 && (errno == ENOENT || errno == EINVAL)) + { + free (linkbuf); + break; + } + else if (retsize < 0) + { + free (linkbuf); + grub_util_error (_("cannot rename the file %s to %s: %m"), namenew, name); + } + else if (retsize == size) + { + free (linkbuf); + size += 128; + continue; + } + + linkbuf[retsize] = '\0'; + if (linkbuf[0] == '/') + { + free (rename_target); + rename_target = linkbuf; + } + else + { + char *dbuf = xstrdup (rename_target); + const char *dir = dirname (dbuf); + + free (rename_target); + rename_target = xasprintf ("%s/%s", dir, linkbuf); + free (dbuf); + free (linkbuf); + } + } + + rc = grub_util_rename (namenew, rename_target); + if (rc < 0 && errno == EXDEV) + { + rc = grub_install_copy_file (namenew, rename_target, 1); + grub_util_unlink (namenew); + } + + free (rename_target); + + if (rc < 0) + grub_util_error (_("cannot rename the file %s to %s: %m"), namenew, name); +#endif + free (namenew); } -- 2.23.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel