From: Bruno Haible Date: Sun, 5 Jul 2020 21:44:41 +0000 (+0200) Subject: msgfmt: Supersede, not overwrite, the output file of type '.mo'. X-Git-Tag: v0.21~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a361def05435e95d22725faf49d1bf5aa7c85414;p=thirdparty%2Fgettext.git 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. --- 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;