]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
msgfmt: Supersede, not overwrite, the output file of type '.mo'.
authorBruno Haible <bruno@clisp.org>
Sun, 5 Jul 2020 21:44:41 +0000 (23:44 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 5 Jul 2020 22:40:01 +0000 (00:40 +0200)
* 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
autogen.sh
gettext-tools/src/write-mo.c

diff --git a/NEWS b/NEWS
index 5e5156dbbdcc1dc90c568db4b87d6d162ce714b1..e036a0b387b3dc69d25426898c7e948923bde974 100644 (file)
--- 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.
index ca17cd952c8358fcc843f7141d12c4aef3c95da9..c7225d941b5bfd4b46f271fb0ebcc7378abe7acc 100755 (executable)
@@ -199,6 +199,7 @@ if ! $skip_gnulib; then
     strpbrk
     strtol
     strtoul
+    supersede
     sys_select
     sys_stat
     sys_time
index fe93b708b71fea37267bbf6c692ae116bde0a436..9317ac9c6a4f1c503f960a7be273a23e21798588 100644 (file)
@@ -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;