summaryrefslogtreecommitdiff
path: root/ace/OS_NS_stdlib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ace/OS_NS_stdlib.cpp')
-rw-r--r--ace/OS_NS_stdlib.cpp199
1 files changed, 154 insertions, 45 deletions
diff --git a/ace/OS_NS_stdlib.cpp b/ace/OS_NS_stdlib.cpp
index 882057e6380..de0c9c305b0 100644
--- a/ace/OS_NS_stdlib.cpp
+++ b/ace/OS_NS_stdlib.cpp
@@ -1,9 +1,10 @@
-// -*- C++ -*-
// $Id$
#include "ace/OS_NS_stdlib.h"
-ACE_RCSID(ace, OS_NS_stdlib, "$Id$")
+ACE_RCSID (ace,
+ OS_NS_stdlib,
+ "$Id$")
#if !defined (ACE_HAS_INLINED_OSCALLS)
# include "ace/OS_NS_stdlib.inl"
@@ -13,10 +14,21 @@ ACE_RCSID(ace, OS_NS_stdlib, "$Id$")
#include "ace/OS_NS_unistd.h"
-#if defined (ACE_LACKS_MKTEMP) || defined (ACE_LACKS_REALPATH)
+#if defined (ACE_LACKS_MKTEMP) \
+ || defined (ACE_LACKS_MKSTEMP) \
+ || defined (ACE_LACKS_REALPATH)
# include "ace/OS_NS_stdio.h"
# include "ace/OS_NS_sys_stat.h"
-#endif /* ACE_LACKS_MKTEMP || ACE_LACKS_REALPATH */
+#endif /* ACE_LACKS_MKTEMP || ACE_LACKS_MKSTEMP || ACE_LACKS_REALPATH */
+
+#if defined (ACE_LACKS_MKSTEMP)
+# include "ace/OS_NS_fcntl.h"
+# include "ace/OS_NS_ctype.h"
+# include "ace/OS_NS_sys_time.h"
+# if !defined (ACE_HAS_WINCE) && !defined (ACE_VXWORKS)
+# include /**/ <limits>
+# endif
+#endif /* ACE_LACKS_MKSTEMP */
ACE_EXIT_HOOK ACE_OS::exit_hook_ = 0;
@@ -262,10 +274,10 @@ ACE_OS::realloc (void *ptr, size_t nbytes)
#if defined (ACE_LACKS_REALPATH) && !defined (ACE_HAS_WINCE)
char *
ACE_OS::realpath (const char *file_name,
- char *resolved_name)
+ char *resolved_name)
{
ACE_OS_TRACE ("ACE_OS::realpath");
-
+
if (file_name == 0)
{
// Single Unix Specification V3:
@@ -366,6 +378,7 @@ ACE_OS::realpath (const char *file_name,
while (*--dest != '/')
;
}
+# if !defined (ACE_LACKS_SYMLINKS)
else
{
ACE_stat st;
@@ -378,49 +391,50 @@ ACE_OS::realpath (const char *file_name,
return 0;
}
- // Check if current path is a link
- if (S_ISLNK (st.st_mode))
- {
- if (++nlinks > MAXSYMLINKS)
- {
- errno = ELOOP;
- if (resolved_name == 0)
- ACE_OS::free (rpath);
- return 0;
- }
+ // Check if current path is a link
+ if (S_ISLNK (st.st_mode))
+ {
+ if (++nlinks > MAXSYMLINKS)
+ {
+ errno = ELOOP;
+ if (resolved_name == 0)
+ ACE_OS::free (rpath);
+ return 0;
+ }
- char link_buf[PATH_MAX];
+ char link_buf[PATH_MAX];
- int link_len = ACE_OS::readlink (rpath, link_buf, PATH_MAX);
- int tail_len = ACE_OS::strlen (file_name) + 1;
+ int link_len = ACE_OS::readlink (rpath, link_buf, PATH_MAX);
+ int tail_len = ACE_OS::strlen (file_name) + 1;
- // Check if there is room to expand link?
- if (link_len + tail_len > PATH_MAX)
- {
- errno = ENAMETOOLONG;
- if (resolved_name == 0)
- ACE_OS::free (rpath);
- return 0;
- }
-
- // Move tail and prefix it with expanded link
- ACE_OS::memmove (expand_buf + link_len, file_name, tail_len);
- ACE_OS::memcpy (expand_buf, link_buf, link_len);
-
- if (*link_buf == '/') // Absolute link?
- {
- dest = rpath;
- }
- else // Relative link, remove expanded link component
- {
- --dest;
- while (*--dest != '/')
- ;
- }
- file_name = expand_buf; // Source path is now in expand_buf
- }
+ // Check if there is room to expand link?
+ if (link_len + tail_len > PATH_MAX)
+ {
+ errno = ENAMETOOLONG;
+ if (resolved_name == 0)
+ ACE_OS::free (rpath);
+ return 0;
+ }
+
+ // Move tail and prefix it with expanded link
+ ACE_OS::memmove (expand_buf + link_len, file_name, tail_len);
+ ACE_OS::memcpy (expand_buf, link_buf, link_len);
+
+ if (*link_buf == '/') // Absolute link?
+ {
+ dest = rpath;
+ }
+ else // Relative link, remove expanded link component
+ {
+ --dest;
+ while (*--dest != '/')
+ ;
+ }
+ file_name = expand_buf; // Source path is now in expand_buf
+ }
+ }
+# endif /* ACE_LACKS_SYMLINKS */
}
- }
*dest = '\0';
@@ -576,3 +590,98 @@ ACE_OS::strtoul_emulation (const char *nptr,
}
#endif /* ACE_LACKS_STRTOUL */
+
+#if defined (ACE_LACKS_MKSTEMP)
+ACE_HANDLE
+ACE_OS::mkstemp_emulation (ACE_TCHAR * s)
+{
+ if (s == 0)
+ {
+ errno = EINVAL;
+ return ACE_INVALID_HANDLE;
+ }
+
+ // The "XXXXXX" template to be filled in.
+ ACE_TCHAR * const t = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX"));
+
+ if (t == 0)
+ {
+ errno = EINVAL;
+ return ACE_INVALID_HANDLE;
+ }
+
+ static unsigned int const NUM_RETRIES = 50;
+ static unsigned int const NUM_CHARS = 6; // Do not change!
+
+ ACE_RANDR_TYPE seed =
+ static_cast<ACE_RANDR_TYPE> (ACE_OS::gettimeofday ().msec ());
+
+ // We only care about UTF-8 / ASCII characters in generated
+ // filenames. A UTF-16 or UTF-32 character could potentially cause
+ // a very large space to be searched in the below do/while() loop,
+ // greatly slowing down this mkstemp() implementation. It is more
+ // practical to limit the search space to UTF-8 / ASCII characters
+ // (i.e. 127 characters).
+# if defined (ACE_HAS_WINCE) || defined (ACE_VXWORKS) || defined (max)
+ static float const MAX_VAL = static_cast<float> (127);
+#else
+ static float const MAX_VAL =
+ static_cast<float> (std::numeric_limits<char>::max ());
+#endif /* ACE_HAS_WINCE */
+
+ // Use high-order bits rather than low-order ones (e.g. rand() %
+ // MAX_VAL). See Numerical Recipes in C: The Art of Scientific
+ // Computing (William H. Press, Brian P. Flannery, Saul
+ // A. Teukolsky, William T. Vetterling; New York: Cambridge
+ // University Press, 1992 (2nd ed., p. 277).
+ //
+ // e.g.: MAX_VAL * rand() / (RAND_MAX + 1.0)
+
+ // Factor out the constant coefficient.
+ static float const coefficient =
+ static_cast<float> (MAX_VAL / (RAND_MAX + 1.0f));
+
+ // @@ These nested loops may be ineffecient. Improvements are
+ // welcome.
+ for (unsigned int i = 0; i < NUM_RETRIES; ++i)
+ {
+ for (unsigned int n = 0; n < NUM_CHARS; ++n)
+ {
+ ACE_TCHAR r;
+
+ // This do/while() loop allows this alphanumeric character
+ // selection to work for EBCDIC, as well.
+ do
+ {
+ r =
+ static_cast<ACE_TCHAR> (coefficient * ACE_OS::rand_r (seed));
+ }
+ while (!ACE_OS::ace_isalnum (r));
+
+ t[n] = r;
+ }
+
+ static int const perms =
+#if defined (ACE_WIN32)
+ 0; /* Do not share while open. */
+#else
+ 0600; /* S_IRUSR | S_IWUSR */
+#endif /* ACE_WIN32 */
+
+ // Create the file with the O_EXCL bit set to ensure that we're
+ // not subject to a symbolic link attack.
+ //
+ // Note that O_EXCL is subject to a race condition over NFS
+ // filesystems.
+ ACE_HANDLE const handle = ACE_OS::open (s,
+ O_RDWR | O_CREAT | O_EXCL,
+ perms);
+
+ if (handle != ACE_INVALID_HANDLE)
+ return handle;
+ }
+
+ errno = EEXIST; // Couldn't create a unique temporary file.
+ return ACE_INVALID_HANDLE;
+}
+#endif /* ACE_LACKS_MKSTEMP */