From a361def05435e95d22725faf49d1bf5aa7c85414 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 5 Jul 2020 23:44:41 +0200 Subject: [PATCH] msgfmt: Supersede, not overwrite, the output file of type '.mo'. * autogen.sh (GNULIB_MODULES_TOOLS_FOR_SRC): Add 'supersede'. * gettext-tools/src/write-mo.c: Include supersede.h. (msgdomain_write_mo): When writing to a file, use fopen_supersede and fwriteerror_supersede. * NEWS: Mention the change. --- NEWS | 4 ++++ autogen.sh | 1 + gettext-tools/src/write-mo.c | 31 +++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 5e5156dbb..e036a0b38 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,10 @@ Version 0.21 - April 2020 'bindtextdomain'. It allows to pass a directory name in wchar_t[] encoding. Note: 'wbindtextdomain' exists only on native Windows platforms. +* Improvements for translators: + - When msgfmt writes a MO file, it now does so in such a way that processes + that are currently using an older copy of the MO file will not crash. + * Libtextstyle: - Added support for emitting hyperlinks. - New API for doing formatted output. diff --git a/autogen.sh b/autogen.sh index ca17cd952..c7225d941 100755 --- a/autogen.sh +++ b/autogen.sh @@ -199,6 +199,7 @@ if ! $skip_gnulib; then strpbrk strtol strtoul + supersede sys_select sys_stat sys_time diff --git a/gettext-tools/src/write-mo.c b/gettext-tools/src/write-mo.c index fe93b708b..9317ac9c6 100644 --- a/gettext-tools/src/write-mo.c +++ b/gettext-tools/src/write-mo.c @@ -47,6 +47,7 @@ #include "xmalloca.h" #include "msgl-header.h" #include "binary-io.h" +#include "supersede.h" #include "fwriteerror.h" #include "gettext.h" @@ -785,34 +786,44 @@ msgdomain_write_mo (message_list_ty *mlp, /* If no entry for this domain don't even create the file. */ if (mlp->nitems != 0) { - FILE *output_file; - /* Support for "reproducible builds": Delete information that may vary between builds in the same conditions. */ message_list_delete_header_field (mlp, "POT-Creation-Date:"); if (strcmp (domain_name, "-") == 0) { - output_file = stdout; + FILE *output_file = stdout; SET_BINARY (fileno (output_file)); + + write_table (output_file, mlp); + + /* Make sure nothing went wrong. */ + if (fwriteerror (output_file)) + error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"), + file_name); } else { - output_file = fopen (file_name, "wb"); + /* Supersede, don't overwrite, the output file. Otherwise, processes + that are currently using (via mmap!) the output file could crash + (through SIGSEGV or SIGBUS). */ + struct supersede_final_action action; + FILE *output_file = + fopen_supersede (file_name, "wb", true, true, &action); if (output_file == NULL) { error (0, errno, _("error while opening \"%s\" for writing"), file_name); return 1; } - } - write_table (output_file, mlp); + write_table (output_file, mlp); - /* Make sure nothing went wrong. */ - if (fwriteerror (output_file)) - error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"), - file_name); + /* Make sure nothing went wrong. */ + if (fwriteerror_supersede (output_file, &action)) + error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"), + file_name); + } } return 0; -- 2.47.3