-fskeletons-copy

diff --git a/ChangeLog b/ChangeLog
index 684b0ac..f59da17 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,5 @@
 
-0.9.19:	2005-Oct-05
+0.9.19:	2005-Oct-06
 
 	* A proper solution to circular references. No kludge flags
 	  should be necessary anymore to produce reference-free code:
@@ -10,6 +10,7 @@
 	* New feature for unber(1): -s <skip> bytes.
 	* Mandatory elements map for SET was not getting generated properly.
 	  (Test case 94) (Severity: high; Security impact: low)
+	* asn1c: new command line option: -fskeletons-copy.
 
 0.9.18:	2005-Aug-14
 
diff --git a/asn1c/asn1c.1 b/asn1c/asn1c.1
index 893d599..a428935 100644
--- a/asn1c/asn1c.1
+++ b/asn1c/asn1c.1
@@ -25,7 +25,7 @@
 .br
 \fB\-fall-defs-global \-fbless-SIZE \-fcompound-names \-findirect-choice
 .BI "\-fknown-extern-type="<name>
-\fB\-fnative-types \-fno-constraints \-fno-include-deps \-funnamed-unions \-ftypes88\fR
+\fB\-fnative-types \-fno-constraints \-fno-include-deps \-funnamed-unions \-fskeletons-copy \-ftypes88\fR
 .TP
 \fIOutput Options\fR
 .br
@@ -115,6 +115,9 @@
 .B \-funnamed-unions
 Enable unnamed unions in the definitions of target language's structures.
 .TP
+.B \-fskeletons-copy
+Copy support files (skeletons) rather than symlink them.
+.TP
 .B \-ftypes88
 Pretend to support only ASN.1:1988 embedded types. Certain reserved words,
 such as UniversalString and BMPString, become ordinary type references
diff --git a/asn1c/asn1c.c b/asn1c/asn1c.c
index 11559de..e009c38 100644
--- a/asn1c/asn1c.c
+++ b/asn1c/asn1c.c
@@ -93,6 +93,8 @@
 			asn1_compiler_flags |= A1C_NO_INCLUDE_DEPS;
 		} else if(strcmp(optarg, "unnamed-unions") == 0) {
 			asn1_compiler_flags |= A1C_UNNAMED_UNIONS;
+		} else if(strcmp(optarg, "skeletons-copy") == 0) {
+			asn1_compiler_flags |= A1C_SKELETONS_COPY;
 		} else if(strcmp(optarg, "types88") == 0) {
 			asn1_parser_flags |= A1P_TYPES_RESTRICT_TO_1988;
 		} else {
@@ -321,6 +323,7 @@
 "  -fno-constraints      Do not generate constraint checking code\n"
 "  -fno-include-deps     Do not generate courtesy #includes for dependencies\n"
 "  -funnamed-unions      Enable unnamed unions in structures\n"
+"  -fskeletons-copy      Force copying the support files\n"
 "  -ftypes88             Pretend to support only ASN.1:1988 embedded types\n"
 "\n"
 
diff --git a/doc/asn1c-usage.html b/doc/asn1c-usage.html
index 106ebba..239e77f 100644
--- a/doc/asn1c-usage.html
+++ b/doc/asn1c-usage.html
@@ -430,11 +430,15 @@
 <FONT SIZE="-1">Enable  unnamed  unions  in the definitions of target language's
 structures.</FONT></TD></TR>
 </TBODY><TBODY>
+<TR><TD VALIGN=BASELINE ALIGN=LEFT NOWRAP><FONT SIZE="-1">-fskeletons-copy</FONT></TD><TD VALIGN=BASELINE ALIGN=LEFT WIDTH="216">
+<FONT SIZE="-1">Copy support files rather than symlink them.</FONT></TD></TR>
+</TBODY><TBODY>
 <TR><TD VALIGN=BASELINE ALIGN=LEFT NOWRAP><FONT SIZE="-1">-ftypes88</FONT></TD><TD VALIGN=BASELINE ALIGN=LEFT WIDTH="216">
 <FONT SIZE="-1">Pretend to support only ASN.1:1988 embedded types. Certain
 reserved words, such as UniversalString and BMPString, become ordinary
 type references and may be redefined by the specification.</FONT></TD></TR>
 </TBODY><TBODY>
+
 <TR><TD VALIGN=BASELINE ALIGN=LEFT NOWRAP><B><FONT SIZE="-1">Output Options</FONT></B></TD><TD VALIGN=BASELINE ALIGN=LEFT WIDTH="216">
 <B><FONT SIZE="-1">Description</FONT></B></TD></TR>
 <TR><TD VALIGN=BASELINE ALIGN=LEFT NOWRAP>
diff --git a/doc/asn1c-usage.lyx b/doc/asn1c-usage.lyx
index 3c6ed97..205b9dc 100644
--- a/doc/asn1c-usage.lyx
+++ b/doc/asn1c-usage.lyx
@@ -71,7 +71,7 @@
 \backslash 
 lhead{This document describes 
 \backslash 
-href{http://lionet.info/asn1c}{asn1c-0.9.18}}
+href{http://lionet.info/asn1c}{asn1c-0.9.19}}
 \layout Standard
 
 \backslash 
@@ -451,7 +451,7 @@
 
 
 \begin_inset  Tabular
-<lyxtabular version="3" rows="26" columns="2">
+<lyxtabular version="3" rows="27" columns="2">
 <features islongtable="true">
 <column alignment="left" valignment="top" leftline="true" width="0">
 <column alignment="block" valignment="top" leftline="true" rightline="true" width="3in">
@@ -836,6 +836,8 @@
 
 \layout Standard
 
+
+\size small 
 -findirect-choice
 \end_inset 
 </cell>
@@ -844,6 +846,8 @@
 
 \layout Standard
 
+
+\size small 
 When generating code for a CHOICE type, compile the CHOICE members as indirect
  pointers instead of declaring them inline.
  Consider using this option together with 
@@ -861,6 +865,8 @@
 
 \layout Standard
 
+
+\size small 
 -fknown-extern-type=
 \emph on 
 <name>
@@ -871,6 +877,8 @@
 
 \layout Standard
 
+
+\size small 
 Pretend the specified type is known.
  The compiler will assume the target language source files for the given
  type have been provided manually.
@@ -969,6 +977,28 @@
 \end_inset 
 </cell>
 </row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+
+\size small 
+-fskeletons-copy
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+
+\size small 
+Copy support files rather than symlink them.
+\end_inset 
+</cell>
+</row>
 <row topline="true" bottomline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
diff --git a/doc/asn1c-usage.pdf b/doc/asn1c-usage.pdf
index 6efd7e2..3d188cf 100644
--- a/doc/asn1c-usage.pdf
+++ b/doc/asn1c-usage.pdf
Binary files differ
diff --git a/libasn1compiler/asn1c_compat.c b/libasn1compiler/asn1c_compat.c
index 2a80251..b393d6d 100644
--- a/libasn1compiler/asn1c_compat.c
+++ b/libasn1compiler/asn1c_compat.c
@@ -80,12 +80,19 @@
 	if(fp == NULL) {
 		if(created) unlink(fname);
 		close(fd);
+		return NULL;
 	}
 
 	/* Return the temporary file name */
 	if(opt_tmpname) {
 		*opt_tmpname = strdup(fname);
-		assert(*opt_tmpname);
+		if(*opt_tmpname) {
+			/* Successfull */
+		} else {
+			if(created) unlink(fname);
+			fclose(fp);
+			return NULL;
+		}
 	}
 
 	return fp;
diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c
index e0a2f67..d35db94 100644
--- a/libasn1compiler/asn1c_save.c
+++ b/libasn1compiler/asn1c_save.c
@@ -280,6 +280,8 @@
 		if(rename(tmpname_c, name_buf)) {
 			unlink(tmpname_c);
 			perror(tmpname_c);
+			free(tmpname_c);
+			free(tmpname_h);
 			return -1;
 		}
 	}
@@ -292,6 +294,8 @@
 		if(rename(tmpname_h, name_buf)) {
 			unlink(tmpname_h);
 			perror(tmpname_h);
+			free(tmpname_c);
+			free(tmpname_h);
 			return -1;
 		}
 	}
@@ -308,11 +312,20 @@
 
 static int
 identical_files(const char *fname1, const char *fname2) {
-	char buf[2][8192];
+	char buf[2][4096];
 	FILE *fp1, *fp2;
 	size_t olen, nlen;
 	int retval = 1;	/* Files are identical */
 
+#ifndef	WIN32
+	struct stat sb;
+
+	if(lstat(fname1, &sb) || !S_ISREG(sb.st_mode)
+	|| lstat(fname2, &sb) || !S_ISREG(sb.st_mode)) {
+		return 0;	/* Files are not identical */
+	}
+#endif
+
 	fp1 = fopen(fname1, "r");
 	if(!fp1) { return 0; }
 	fp2 = fopen(fname2, "r");
@@ -338,7 +351,8 @@
  */
 static int
 real_copy(const char *src, const char *dst) {
-	unsigned char buf[8192];
+	unsigned char buf[4096];
+	char *tmpname;
 	FILE *fpsrc, *fpdst;
 	size_t len;
 	int retval = 0;
@@ -348,36 +362,45 @@
 
 	fpsrc = fopen(src, "r");
 	if(!fpsrc) { errno = EIO; return -1; }
-	fpdst = asn1c_open_file(dst, "", 0);
+	fpdst = asn1c_open_file(dst, "", &tmpname);
 	if(!fpdst) { fclose(fpsrc); errno = EIO; return -1; }
 
 	while(!feof(fpsrc)) {
 		len = fread(buf, 1, sizeof(buf), fpsrc);
 		if(fwrite(buf, 1, len, fpdst) != len) {
+			perror(tmpname);
 			errno = EIO;
 			retval = -1;
 			break;
 		}
 	}
-
 	fclose(fpsrc);
 	fclose(fpdst);
+
+	/* Check if copied correctly, and rename into a permanent name */
+	if(retval) {
+		unlink(tmpname);
+	} else if(rename(tmpname, dst)) {
+		unlink(tmpname);
+		perror(tmpname);
+		retval = -1;
+	}
+	free(tmpname);
 	return retval;
 }
 
 static int
 asn1c_copy_over(arg_t *arg, char *path) {
 	char *fname;
-
-	(void)arg;	/* Unused argument */
+#ifdef	WIN32
+	int use_real_copy = 1;
+#else
+	int use_real_copy = (arg->flags & A1C_SKELETONS_COPY);
+#endif
 
 	fname = a1c_basename(path);
 	if(!fname
-#ifdef	WIN32
-		|| real_copy(path, fname)
-#else
-		|| (1 ? symlink(path, fname) : real_copy(path, fname))
-#endif
+	|| (use_real_copy ? real_copy(path, fname) : symlink(path, fname))
 	) {
 		if(errno == EEXIST) {
 			struct stat sb1, sb2;
@@ -402,13 +425,15 @@
 			/* Ignore this */
 			return 0;
 		} else {
-			fprintf(stderr, "Symlink %s -> %s failed: %s\n",
+			fprintf(stderr, "%s %s -> %s failed: %s\n",
+				use_real_copy ? "Copy" : "Symlink",
 				path, fname, strerror(errno));
 			return -1;
 		}
 	}
 
-	fprintf(stderr, "Symlinked %s\t-> %s\n", path, fname);
+	fprintf(stderr, "%s %s\t-> %s\n",
+		use_real_copy ? "Copied" : "Symlinked", path, fname);
 
 	return 1;
 }
diff --git a/libasn1compiler/asn1compiler.h b/libasn1compiler/asn1compiler.h
index e688018..847300f 100644
--- a/libasn1compiler/asn1compiler.h
+++ b/libasn1compiler/asn1compiler.h
@@ -51,6 +51,11 @@
 	 * Compile members of CHOICE as indirect pointers.
 	 */
 	A1C_INDIRECT_CHOICE	= 0x0400,
+	/*
+	 * -fskeletons-copy
+	 * Copy support files rather than symlink them.
+	 */
+	A1C_SKELETONS_COPY	= 0x0800,
 };
 
 /*