retaining old file if contents are the same


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@736 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/libasn1compiler/asn1c_compat.c b/libasn1compiler/asn1c_compat.c
index ebc6d3f..2a80251 100644
--- a/libasn1compiler/asn1c_compat.c
+++ b/libasn1compiler/asn1c_compat.c
@@ -14,7 +14,7 @@
 #endif
 
 FILE *
-asn1c_open_file(const char *name, const char *ext) {
+asn1c_open_file(const char *name, const char *ext, char **opt_tmpname) {
 	int created = 1;
 #ifndef	WIN32
 	struct stat sb;
@@ -22,22 +22,35 @@
 	char *fname;
 	size_t len;
 	FILE *fp;
+	int ret;
 	int fd;
 
 	/*
 	 * Compute filenames.
 	 */
-	len = strlen(name) + strlen(ext) + 1;
+	len = strlen(name) + strlen(ext) + sizeof(".XXXXXX");
 	fname = alloca(len);
-	snprintf(fname, len, "%s%s", name, ext);
+	ret = snprintf(fname, len, "%s%s%s", name, ext,
+		opt_tmpname ? ".XXXXXX" : "");
+	assert(ret > 0 && ret < len);
 
-	/*
-	 * Create files.
-	 */
-	fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
-	if(fd == -1 && errno == EEXIST) {
-		fd = open(fname, O_WRONLY, DEFFILEMODE);
-		created = 0;
+	if(opt_tmpname) {
+		/*
+		 * Create temporary file.
+		 */
+		fd = mkstemp(fname);
+#ifndef	WIN32
+		(void)fchmod(fd, DEFFILEMODE);
+#endif
+	} else {
+		/*
+		 * Create specified file, or open the old one.
+		 */
+		fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
+		if(fd == -1 && errno == EEXIST) {
+			fd = open(fname, O_WRONLY, DEFFILEMODE);
+			created = 0;
+		}
 	}
 	if(fd == -1) {
 		perror(fname);
@@ -68,6 +81,13 @@
 		if(created) unlink(fname);
 		close(fd);
 	}
+
+	/* Return the temporary file name */
+	if(opt_tmpname) {
+		*opt_tmpname = strdup(fname);
+		assert(*opt_tmpname);
+	}
+
 	return fp;
 }