Factor out xtempfile()
diff --git a/lib/lib.c b/lib/lib.c
index 83e4db4..ea67801 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -700,18 +700,14 @@
 int copy_tempfile(int fdin, char *name, char **tempname)
 {
   struct stat statbuf;
-  int fd;
-  int ignored __attribute__((__unused__));
+  int fd = xtempfile(name, tempname), ignored __attribute__((__unused__));
 
-  *tempname = xmprintf("%s%s", name, "XXXXXX");
-  if(-1 == (fd = mkstemp(*tempname))) error_exit("no temp file");
+  // Record tempfile for exit cleanup if interrupted
   if (!tempfile2zap) sigatexit(tempfile_handler);
   tempfile2zap = *tempname;
 
-  // Set permissions of output file (ignoring errors, usually due to nonroot)
-
-  fstat(fdin, &statbuf);
-  fchmod(fd, statbuf.st_mode);
+  // Set permissions of output file.
+  if (!fstat(fdin, &statbuf)) fchmod(fd, statbuf.st_mode);
 
   // We chmod before chown, which strips the suid bit. Caller has to explicitly
   // switch it back on if they want to keep suid.
diff --git a/lib/lib.h b/lib/lib.h
index 609210a..676c47b 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -138,6 +138,7 @@
 int xpspawn(char **argv, int*pipes);
 void xaccess(char *path, int flags);
 void xunlink(char *path);
+int xtempfile(char *name, char **tempname);
 int xcreate(char *path, int flags, int mode);
 int xopen(char *path, int flags);
 int xcreate_stdio(char *path, int flags, int mode);
diff --git a/lib/xwrap.c b/lib/xwrap.c
index 74da0ed..562cbaf 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -377,6 +377,16 @@
   return fd;
 }
 
+int xtempfile(char *name, char **tempname)
+{
+  int fd;
+
+   *tempname = xmprintf("%s%s", name, "XXXXXX");
+  if(-1 == (fd = mkstemp(*tempname))) error_exit("no temp file");
+
+  return fd;
+}
+
 // Create a file but don't return stdin/stdout/stderr
 int xcreate(char *path, int flags, int mode)
 {