+/* Mark FILE as close-on-exec. Return FILE. FILE may be NULL, in
+ which case nothing is done. */
+static FILE *
+close_on_exec (FILE *file)
+{
+#if defined (HAVE_FILENO) && defined (F_GETFD)
+ if (file)
+ {
+ int fd = fileno (file);
+ int old = fcntl (fd, F_GETFD, 0);
+ if (old >= 0)
+ fcntl (fd, F_SETFD, old | FD_CLOEXEC);
+ }
+#endif
+ return file;
+}
+
+FILE *
+_bfd_real_fopen (const char *filename, const char *modes)
+{
+#ifdef VMS
+ char *vms_attr;
+
+ /* On VMS, fopen allows file attributes as optional arguments.
+ We need to use them but we'd better to use the common prototype.
+ In fopen-vms.h, they are separated from the mode with a comma.
+ Split here. */
+ vms_attr = strchr (modes, ',');
+ if (vms_attr != NULL)
+ {
+ /* Attributes found. Split. */
+ size_t modes_len = strlen (modes) + 1;
+ char attrs[modes_len + 1];
+ char *at[3];
+ int i;
+
+ memcpy (attrs, modes, modes_len);
+ at[0] = attrs;
+ for (i = 0; i < 2; i++)
+ {
+ at[i + 1] = strchr (at[i], ',');
+ BFD_ASSERT (at[i + 1] != NULL);
+ *(at[i + 1]++) = 0; /* Replace ',' with a nul, and skip it. */
+ }
+ return close_on_exec (fopen (filename, at[0], at[1], at[2]));
+ }
+
+#elif defined (_WIN32)
+ size_t filelen = strlen (filename) + 1;
+
+ if (filelen > MAX_PATH - 1)
+ {
+ FILE * file;
+ char * fullpath = (char *) malloc (filelen + 8);
+ int i;
+
+ /* Add a Microsoft recommended prefix that
+ will allow the extra-long path to work. */
+ strcpy (fullpath, "\\\\?\\");
+ strcat (fullpath, filename);
+
+ /* Convert any UNIX style path separators into the DOS form. */
+ for (i = 0; fullpath[i]; i++)
+ {
+ if (IS_UNIX_DIR_SEPARATOR (fullpath[i]))
+ fullpath[i] = '\\';
+ }
+
+ file = close_on_exec (fopen (fullpath, modes));
+ free (fullpath);
+ return file;
+ }
+
+#elif defined (HAVE_FOPEN64)
+ return close_on_exec (fopen64 (filename, modes));
+#endif
+
+ return close_on_exec (fopen (filename, modes));
+}
+