title: mkstemp() and fdopen() in Cygwin 1.7.28
body: <p>In the course of building some C++-based code under Cygwin (1.7.28-2, 64-bit) with GNU GCC 4.8.2,  I ran into the following errors:</p>
  
  <pre><code>...
  SortDetails.cpp: In function ‘FILE* create_tmpfile(const char*, char**)’:
  SortDetails.cpp:127:20: error: ‘mkstemp’ was not declared in this scope
     fd = mkstemp(tmpl);
                      ^
  SortDetails.cpp:133:24: error: ‘fdopen’ was not declared in this scope
     fp = fdopen(fd, "wb+");
  ...
  </code></pre>
  
  <p>The specific chunk of code that fails to compile is:</p>
  
  <pre><code>FILE *
  create_tmpfile(char const* path, char** fileName)
  {
    FILE* fp;
    int fd;
    char* tmpl;
  
    if ( path == NULL )
        {
            fileName = NULL;
            return tmpfile();
        }
  
    tmpl = (char*)malloc(1 + strlen(path) + L_tmpnam);
    strcpy(tmpl, path);
    strcpy(tmpl+strlen(path), "/sb.XXXXXX");
    fd = mkstemp(tmpl);                        /* &lt;----- here... */
    if(fd == -1)
        {
            fprintf(stderr, "unable to create temp file!\n");
            return NULL;
        }
    fp = fdopen(fd, "wb+");                    /* &lt;----- ...and here */
    *fileName = (char*)malloc(strlen(tmpl) + 1);
    strcpy(*fileName, tmpl);
    free(tmpl);
    return fp;
  }
  </code></pre>
  
  <p>(The results of <code>malloc</code> are being cast because this code is within a larger C++-based project.)</p>
  
  <p><strong>Regression</strong></p>
  
  <p>This code compiles and works successfully with GNU GCC 4.8.x on Linux hosts and with Clang/++ 5.0 under OS X.</p>
  
  <p><strong>Environment</strong></p>
  
  <p>I am using the following version of Cygwin:</p>
  
  <pre><code>$ uname -a
  CYGWIN_NT-6.1 CygFoo-PC 1.7.28(0.271/5/3) 2014-02-09 21:06 x86_64 Cygwin
  </code></pre>
  
  <p>Here is the version of GCC I am using:</p>
  
  <pre><code>$ gcc -v
  Using built-in specs.
  COLLECT_GCC=gcc
  COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-cygwin/4.8.2/lto-wrapper.exe
  Target: x86_64-pc-cygwin
  Configured with: /cygdrive/i/szsz/tmpp/cygwin64/gcc/gcc-4.8.2-2/src/gcc-4.8.2/configure --srcdir=/cygdrive/i/szsz/tmpp/cygwin64/gcc/gcc-4.8.2-2/src/gcc-4.8.2 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/libexec --datadir=/usr/share --localstatedir=/var --sysconfdir=/etc --libdir=/usr/lib --datarootdir=/usr/share --docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=x86_64-pc-cygwin --host=x86_64-pc-cygwin --target=x86_64-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --enable-shared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --disable-__cxa_atexit --with-dwarf2 --with-tune=generic --enable-languages=ada,c,c++,fortran,lto,objc,obj-c++ --enable-graphite --enable-threads=posix --enable-libatomic --enable-libgomp --disable-libitm --enable-libquadmath --enable-math-support --enable-libssp --enable-libada --enable-libgcj-sublibs --disable-java-awt --disable-symvers --with-ecj-jar=/usr/share/java/ecj.jar --with-gnu-ld --with-gnu-as --with-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib
  Thread model: posix
  gcc version 4.8.2 (GCC)
  </code></pre>
  
  <p><strong>Questions</strong></p>
  
  <ol>
  <li><p>Is there support for <code>mkstemp()</code> and <code>fdopen()</code> in GCC 4.8.2 for Cygwin? </p></li>
  <li><p>If not, is there a package I can add or a library I can relatively easily compile to add support for these functions?</p></li>
  <li><p>If not, are there alternatives to <code>mkstemp()</code> and <code>fdopen()</code> that I can make use of to replicate their functionality under Cygwin?</p></li>
  </ol>
  
  <p><strong>Possible fix</strong></p>
  
  <p>Here's a modified version of this function:</p>
  
  <pre><code>FILE *
  create_tmpfile(char const* path, char** fileName)
  {
    FILE* fp;
    char* tmpl;
  
    if ( path == NULL )
        {
            fileName = NULL;
            return tmpfile();
        }
  
  #if defined(__CYGWIN__) &amp;&amp; !defined(_WIN32)
    const char *cygwinPrefix = "/sb.";
    const char *cygwinTmpDir = "/tmp";
    char *cygwinTmplSuffix = (char *)malloc(1 + L_tmpnam);
    tmpnam(cygwinTmplSuffix);
    tmpl = (char *)malloc(1 + strlen(path) + strlen(cygwinPrefix) + strlen(cygwinTmplSuffix + strlen(cygwinTmpDir) + 1));
    strcpy(tmpl, path);
    strcpy(tmpl+strlen(path), cygwinPrefix);
    strcpy(tmpl+strlen(path)+strlen(cygwinPrefix), cygwinTmplSuffix + strlen(cygwinTmpDir) + 1);
    fp = fopen(tmpl, "wbx+"); /* we add the 'x' extension to apply the O_EXCL flag, to avoid a security hole described in the GNU C library docs */
    free(cygwinTmplSuffix);
  #else
    tmpl = (char*)malloc(1 + strlen(path) + L_tmpnam);
    strcpy(tmpl, path);
    strcpy(tmpl+strlen(path), "/sb.XXXXXX");
    int fd = mkstemp(tmpl);
    if(fd == -1)
        {
            fprintf(stderr, "unable to create temp file!\n");
            return NULL;
        }
    fp = fdopen(fd, "wb+");
  #endif
    *fileName = (char*)malloc(strlen(tmpl) + 1);
    strcpy(*fileName, tmpl);
    free(tmpl);
    return fp;
  }
  </code></pre>
  
  <p>This is pretty ugly. If there is a way to use POSIX functions, I'd like to use them, if I can. Thanks for any advice.</p>