From ac977d6fea7e51c0a3ae61403dcfd5219aa2d8c2 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 6 Jul 2026 14:36:56 -0700
Subject: [PROPOSED] zic now reports cleanup failures

Problem reported by Tom Lane in:
https://lists.iana.org/hyperkitty/list/tz@iana.org/message/4X6S4DIEGQW6WSX3MVPMOP3SFH75L6MX/
* NEWS: Mention this.
* zic.c (remove_temp): New function.
(close_file, rename_dest): Use it.
---
 NEWS  |  4 ++++
 zic.c | 14 ++++++++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index c767e7b0..cb493fc2 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,10 @@ Unreleased, experimental changes
     reverts to the more-permissive 2025b behavior, as the stricter
     behavior did not catch on in FreeBSD.
 
+    zic now reports any failure to remove a temporary file when
+    cleaning up after a previous failure.  (Problem reported by Tom
+    Lane.)
+
   Changes to commentary
 
     Northwest Territories is expected to move to permanent -06 prior to
diff --git a/zic.c b/zic.c
index a2c2dec8..0b9dc37f 100644
--- a/zic.c
+++ b/zic.c
@@ -279,6 +279,7 @@ static void	mkdirs(char const *, bool);
 static zic_t	oadd(zic_t t1, zic_t t2);
 static zic_t	omul(zic_t, zic_t);
 static void	outzone(const struct zone * zp, ptrdiff_t ntzones);
+static void	remove_temp(char const *);
 static zic_t	rpytime(const struct rule * rp, zic_t wantedy);
 static bool	rulesub(struct rule * rp,
 			const char * loyearp, const char * hiyearp,
@@ -840,7 +841,7 @@ close_file(FILE *stream, char const *dir, char const *name,
 	    name ? name : "", name ? ": " : "",
 	    e);
     if (tempname)
-      remove(tempname);
+      remove_temp(tempname);
     exit(EXIT_FAILURE);
   }
 }
@@ -1657,16 +1658,25 @@ rename_dest(char *tempname, char const *name)
   if (tempname) {
     if (rename(tempname, name) != 0) {
       int rename_errno = errno;
-      remove(tempname);
       fprintf(stderr, _("%s: rename to %s%s%s: %s\n"),
 	      progname, diagdir(name), diagslash(name), name,
 	      strerror(rename_errno));
+      remove_temp(tempname);
       exit(EXIT_FAILURE);
     }
     free(tempname);
   }
 }
 
+/* Remove the temporary file TEMP, diagnosing any failure.  */
+static void
+remove_temp(char const *temp)
+{
+  if (remove(temp) < 0)
+    fprintf(stderr, _("%s: Can't remove temporary file %s%s%s: %s\n"),
+	    progname, diagdir(temp), diagslash(temp), temp, strerror(errno));
+}
+
 /* Create symlink contents suitable for symlinking TARGET to LINKNAME, as a
    freshly allocated string.  TARGET should be a relative file name, and
    is relative to the global variable DIRECTORY.  LINKNAME can be either
-- 
2.55.0

