Index: function.c
===================================================================
RCS file: /sources/make/make/function.c,v
retrieving revision 1.129
diff -u -r1.129 function.c
--- function.c	29 Jan 2012 18:12:22 -0000	1.129
+++ function.c	31 Jan 2012 17:50:16 -0000
@@ -2113,6 +2113,7 @@
     {
       FILE *fp;
       const char *mode = "w";
+      int l = strlen (argv[1]);
 
       /* We are writing a file.  */
       ++fn;
@@ -2123,19 +2124,64 @@
         }
       fn = next_token (fn);
 
-      fp = fopen (fn, mode);
-      if (fp == NULL)
-        fatal (reading_file, _("open: %s: %s"), fn, strerror (errno));
+      if (l > 0 || *mode == 'w' || access(fn, F_OK))
+	{
+	  /* normal case: write data to file */
+
+	  fp = fopen (fn, mode);
+	  if (fp == NULL)
+	    fatal (reading_file, _("open: %s: %s"), fn, strerror (errno));
+	  else
+	    {
+	      int nl = argv[1][l-1] != '\n';
+
+	      if (l > 0)
+		if (fputs (argv[1], fp) == EOF || (nl && fputc('\n', fp) == EOF))
+		  fatal (reading_file, _("write: %s: %s"), fn, strerror (errno));
+
+	      fclose (fp);
+	    }
+	}
       else
-        {
-          int l = strlen (argv[1]);
-          int nl = (l == 0 || argv[1][l-1] != '\n');
-
-          if (fputs (argv[1], fp) == EOF || (nl && fputc('\n', fp) == EOF))
-            fatal (reading_file, _("write: %s: %s"), fn, strerror (errno));
-
-          fclose (fp);
-        }
+	{
+	  struct stat statbuf;
+          int e;
+
+	  /* special case: if appending zero-length data to an existing
+	     file, force a write to ensure updated mod time */
+
+	  fp = fopen (fn, "r+");
+	  if (fp == NULL)
+	    fatal (reading_file, _("open: %s: %s"), fn, strerror (errno));
+
+          EINTRLOOP (e, fstat (fileno(fp), &statbuf));
+	  if (e < 0)
+	    fatal (reading_file, _("stat: %s: %s"), fn, strerror (errno));
+
+	  if (statbuf.st_size == 0)
+	    {
+	      fclose (fp);
+	      fp = fopen (fn, "w");
+	      if (fp == NULL)
+		fatal (reading_file, _("open: %s: %s"), fn, strerror (errno));
+	      fclose (fp);
+	    }
+	  else
+	    {
+	      int c = fgetc(fp);
+
+	      if (c == EOF)
+		fatal (reading_file, _("read: %s: %s"), fn, strerror (errno));
+
+	      if (fseek(fp, -1, SEEK_CUR) == -1)
+		fatal (reading_file, _("seek: %s: %s"), fn, strerror (errno));
+
+	      if (fputc(c, fp) == EOF)
+		fatal (reading_file, _("write: %s: %s"), fn, strerror (errno));
+
+	      fclose (fp);
+	    }
+	}
     }
   else
     fatal (reading_file, _("Invalid file operation: %s"), fn);
Index: doc/make.texi
===================================================================
RCS file: /sources/make/make/doc/make.texi,v
retrieving revision 1.78
diff -u -r1.78 make.texi
--- doc/make.texi	30 Jan 2012 00:21:58 -0000	1.78
+++ doc/make.texi	31 Jan 2012 17:50:17 -0000
@@ -7344,10 +7344,11 @@
 
 When the @code{file} function is expanded all its arguments are
 expanded first, then the file indicated by @var{filename} will be
-opened in the mode described by @var{op}.  Finally @var{text} will be
-written to the file.  If @var{text} does not already end in a newline,
-a final newline will be written.  The result of evaluating the
-@code{file} function is always the empty string.
+opened in the mode described by @var{op}.  Then, if @var{text}
+is non-empty it will be written to the file.  If @var{text} does
+not already end in a newline, a final newline will be written.
+The result of evaluating the @code{file} function is always the
+empty string.
 
 It is a fatal error if the file cannot be opened for writing, or if
 the write operation fails.
