Hi,
Adam Purkrt wrote:
> tried stracing grub-mkrescue:
> renergy ~ # grep de.mo~ gentoo-grub-mkrescue.strace
> rename("/tmp/grub.Y1wajm/boot/grub/locale/de.mo",
> "/tmp/grub.Y1wajm/boot/grub/locale/de.mo~") = 0
> unlink("/tmp/grub.Y1wajm/boot/grub/locale/de.mo~") = 0
> rename("/tmp/grub.Y1wajm/boot/grub/locale/de.mo",
> "/tmp/grub.Y1wajm/boot/grub/locale/de.mo~") = 0
> newfstatat(AT_FDCWD, "/tmp/grub.Y1wajm/boot/grub/locale/de.mo~",
> {st_mode=S_IFREG|0644, st_size=150650, ...}, AT_SYMLINK_NOFOLLOW) = 0
> newfstatat(AT_FDCWD, "/tmp/grub.Y1wajm/boot/grub/locale/de.mo~",
> {st_mode=S_IFREG|0644, st_size=150650, ...}, 0) = 0
> unlink("/tmp/grub.Y1wajm/boot/grub/locale/de.mo~") = 0
>
> So it is grub-mkrescue that is creating the .mo~ files, but then deletes
> them; this cycle (which I do not like, but should be ok) repeats twice, or
> rather should repeat twice - but the actual result is the file is there,
> despite last syscall regarding it being "unlink"
Really puzzling.
It is explainable to see two occasions were "de.mo" already existed.
This probably happens because copy_locales() is called three times for
I386_PC (legacy BIOS), I386_EFI, and X86_64_EFI.
But i lack of ideas why unlink(2) should leave "de.mo~" existing
without error indication.
And why did the ".mo~" files not exist when you looked in /tmp after
the intentionally failed xorriso run ?
Can it be a race condition ?
What happens if you let xorriso fail and look immediately ?
# First remove or rename all /tmp/grub.* directories
grub-mkrescue -o /does_not_exist/output.iso ; ls -a
/tmp/grub.*/boot/grub/locale
xorriso will fail early. So the time until ls can look might be short
enough, compared with the time which xorriso would need to assess the
files in /tmp/grub.XYZXYZ and to copy their content into the ISO.
-----------------------------------------------------------------------
The only workaround i can propose for now is a xorriso wrapper script
which would wait a few seconds before starting xorriso and/or actively
remove /tmp/grub.XYZXYZ/boot/grub/locale/*.mo~ .
Such a script would be submitted to grub-mkrescue by the --xorriso=
option:
grub-mkrescue -o /does_not_exist/output.iso \
--xorriso="$HOME"/my_xorriso_wrapper.sh
It has to give answer to the assessment run of grub-mkrescue:
# grub-mkrescue inquires features by running these arguments
if test "$*" = "-as mkisofs -help"
then
"$xorriso" "$@"
exit $?
fi
Then it would do its extra activities and finally run
xorriso "$@"
The extra activity could be to just sleep 5 seconds or to examine the
arguments "$@" for the /tmp/grub.XYZXYZ path and to compose the path
pattern for a run of rm.
The following code snippet is from
https://dev.lovelyhq.com/libburnia/libisoburn/raw/branch/master/frontend/grub-mkrescue-sed.sh
I guess it can be made more simple and elegant. Nevertheless, this has
already been tested with grub-mkrescue.
# Look for the name of the /tmp directory with the GRUB2 files.
# It is the next argument after -r. But as default accept any /tmp/grub.*
next_is_dir=0
dir="."
for i in "$@"
do
if test x"$i" = x"-r"
then
next_is_dir=1
elif test $next_is_dir = 1
then
next_is_dir=0
if echo "$i" | grep '^/tmp/grub.' >/dev/null 2>&1
then
test -d "$i" && dir="$i"
fi
elif test "$dir" = "."
then
if echo "$i" | grep '^/tmp/grub.' >/dev/null 2>&1
then
test -d "$i" && dir="$i"
fi
fi
done
-----------------------------------------------------------------------
Source code musings:
I guess the rename(2) and unlink(2) calls come from
util/grub-install-common.c function clean_grub_dir_real(), which has
modes CREATE_BACKUP and RESTORE_BACKUP calling grub_util_rename(),
mode CLEAN_BACKUP which calls grub_util_unlink() with the ~-name,
and mode CLEAN_NEW which calls grub_util_unlink() with the original
name.
It seems that CREATE_BACKUP and CLEAN_BACKUP are effectively used
in the run which you straced.
grub_unlink() is probably the version from
include/grub/osdep/hostfile_unix.h
which calls unlink(2).
Well, grub-mkrescue does not need backups of its freshly installed
files. But in the case of overwriting an existing GRUB installation
the backup is a valuable feature.
So before we could make plans to avoid backups in the special case
of grub-mkrescue we would need to discover a strong motivation by
explaining the ineffectiveness of unlink().
Another remaining riddle:
The calls to newfstatat() probably stem from calls to fstatat(2)
or a macro mock-up of it.
But i fail to find the GRUB function which would call it.
Have a nice day :)
Thomas