You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@stdcxx.apache.org by Martin Sebor <ms...@gmail.com> on 2008/11/01 23:03:15 UTC

test for STDCXX-1019 ([Fwd: svn commit: r709784 - /stdcxx/branches/4.2.x/src/file.cpp])

Scott, as an FYI, the change below adds support for TMPDIR to
std::filebuf::open() (in __rw_mkstemp()). I resolved the issue
but I won't close it until we've added a test for it to the test
suite. The test needs to verify that the function considers the
TMPDIR variable and behaves reasonably when TMPDIR is invalid
(either too long refers to a non-existent or inaccessible
directory). Now that I think of it, I'm not sure the solution
I implemented quite meets that goal: the function fails with an
error in the edge case. I wonder if falling back on P_tmpdir
instead of failing would be more robust. We should check to see
what other implementations (e.g., tmpnam()) do. Let me know if
you're interested in working on it.

Martin

-------- Original Message --------
Subject: svn commit: r709784 - /stdcxx/branches/4.2.x/src/file.cpp
Date: Sat, 01 Nov 2008 21:49:58 -0000
From: sebor@apache.org
Reply-To: dev@stdcxx.apache.org
To: commits@stdcxx.apache.org

Author: sebor
Date: Sat Nov  1 14:49:58 2008
New Revision: 709784

URL: http://svn.apache.org/viewvc?rev=709784&view=rev
Log:
2008-11-01  Scott Zhong  <sc...@gmail.com>
	    Martin Sebor  <se...@roguewave.com>

	STDCXX-1019
	* src/file.cpp (ENAMETOOLONG, PATH_MAX): Defined macro to a known
	value when not #defined by system headers.
	(__rw_mkstemp): Used the value of TMPDIR when set and not empty.
	Replaced calls to the POSIX unlink() function with the standard
	C function remove().

Modified:
     stdcxx/branches/4.2.x/src/file.cpp

Modified: stdcxx/branches/4.2.x/src/file.cpp
URL: 
http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/src/file.cpp?rev=709784&r1=709783&r2=709784&view=diff
==============================================================================
--- stdcxx/branches/4.2.x/src/file.cpp (original)
+++ stdcxx/branches/4.2.x/src/file.cpp Sat Nov  1 14:49:58 2008
@@ -37,11 +37,12 @@
  #  define _RWSTD_NO_DEPRECATED_C_HEADERS
  #endif   // _RWSTD_NO_DEPRECATED_C_HEADERS

-#include <errno.h>    // for ERANGE, errno
+#include <errno.h>    // for ENAMETOOLONG, ERANGE, errno
  #include <stddef.h>   // for ptrdiff_t
-#include <stdio.h>    // for P_tmpdir, std{err,in,out}, tmpnam()
+#include <stdio.h>    // for P_tmpdir, std{err,in,out}, remove(), tmpnam()
  #include <stdlib.h>   // for mkstemp(), strtoul(), size_t
  #include <ctype.h>    // for isalpha(), isspace(), toupper()
+#include <string.h>   // for memcpy()


  #if defined (_WIN32) && !defined (__CYGWIN__)
@@ -58,6 +59,24 @@
  #  define _BINARY 0
  #endif

+#ifndef ENAMETOOLONG
+   // hardcode based on the known value on each platform
+#  ifdef _RWSTD_OS_AIX
+#    define ENAMETOOLONG    86
+#  elif defined _RWSTD_OS_FREEBSD
+#    define ENAMETOOLONG    63
+#  elif defined _RWSTD_OS_HP_UX
+#    define ENAMETOOLONG   248
+#  elif defined _RWSTD_OS_LINUX
+#    define ENAMETOOLONG    36
+#  elif defined _RWSTD_OS_SUN_OS
+#    define ENAMETOOLONG    78
+#  endif
+#endif   // ENAMETOOLONG
+
+#ifndef PATH_MAX
+#  define PATH_MAX   1024
+#endif

  #include <rw/_file.h>
  #include <rw/_defs.h>
@@ -257,18 +276,48 @@
  #    define P_tmpdir "/tmp"
  #  endif   // P_tmpdir

-    char fnamebuf[] = P_tmpdir "/.rwtmpXXXXXX";
+    // use TMPDIR and fall back on P_tmpdir as per POSIX
+    const char *tmpdir = getenv ("TMPDIR");
+    if (0 == tmpdir || '\0' == *tmpdir)
+        tmpdir = P_tmpdir;
+
+    // template for temporary file name
+    static const char rwtmpXXXXXX[] = "/.rwtmpXXXXXX";
+
+    // buffer for temporary pathname
+    char pathbuf [PATH_MAX];
+
+    // check to see if the buffer is large enough
+    const size_t len = strlen (tmpdir) - 1;
+    if (sizeof pathbuf < len + sizeof rwtmpXXXXXX) {
+
+#  ifdef ENAMETOOLONG
+        // fail according to POSIX rules
+        errno = ENAMETOOLONG;
+#  endif   // ENAMETOOLONG

-    fd = mkstemp (fnamebuf);
+        return -1;
+    }

+    // construct a template for temporary pathname
+    memcpy (pathbuf, tmpdir, len);
+    memcpy (pathbuf + len, rwtmpXXXXXX, sizeof rwtmpXXXXXX);
+
+    // call mkstemp() to create a temporary file and fill
+    // pathbuf with its pathname
+    fd = mkstemp (pathbuf);
+
+    // immediately delete the temporary file on success
+    // the open descriptor will refer to the file until
+    // it's explicitly closed or until the process exits
      if (fd >= 0)
-        unlink (fnamebuf);
+        remove (pathbuf);

  #else   // if defined (_RWSTD_NO_MKSTEMP)

      modebits |= _RWSTD_O_EXCL | _RWSTD_O_CREAT;

-#ifdef _WIN32
+#  ifdef _WIN32

      // tempnam(const char *dir, const char *prefix) will generate
      // a unique file name for a directory chosen by the following rules:
@@ -286,7 +335,7 @@
      //    exist, tempnam will use the current working directory to
      //    generate unique names. Currently, if both TMP and dir specify
      //    names of directories that do not exist, the tempnam function
-    // call will fail.
+    //    call will fail.
      //
      // The name returned by tempnam will be a concatenation of prefix
      // and a sequential number, which will combine to create a unique
@@ -294,7 +343,7 @@
      // names that have no extension. tempnam uses malloc to allocate
      // space for the filename; the program is responsible for freeing
      // this space when it is no longer needed.
-    char* const fname = tempnam (P_tmpdir, ".rwtmp");
+    char* const fname = tempnam (tmpdir, ".rwtmp");

      if (!fname)
          return -1;
@@ -317,10 +366,10 @@

      fd = open (fname, modebits, prot);

-    // unlink the file, forcing the OS to delete it when
+    // remove the file, forcing the OS to delete it when
      // the last file descriptor that refers to it is closed
      if (fd >= 0)
-        unlink (fname);
+        remove (fname);

  #  endif   // _WIN32
  #endif   // _RWSTD_NO_MKSTEMP