aboutsummaryrefslogtreecommitdiff
path: root/dep/acelite/ace/Lib_Find.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/acelite/ace/Lib_Find.cpp')
-rw-r--r--dep/acelite/ace/Lib_Find.cpp768
1 files changed, 768 insertions, 0 deletions
diff --git a/dep/acelite/ace/Lib_Find.cpp b/dep/acelite/ace/Lib_Find.cpp
new file mode 100644
index 00000000000..b1a2f6a4160
--- /dev/null
+++ b/dep/acelite/ace/Lib_Find.cpp
@@ -0,0 +1,768 @@
+// $Id: Lib_Find.cpp 85473 2009-06-01 08:09:31Z johnnyw $
+
+#include "ace/Lib_Find.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_fcntl.h"
+
+#if defined (ACE_WIN32)
+# include "ace/OS_NS_strings.h"
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_OPENVMS)
+#include "ace/RB_Tree.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Singleton.h"
+
+#include /**/ "descrip.h"
+#include /**/ "chfdef.h"
+#include /**/ "stsdef.h"
+#include /**/ "libdef.h"
+
+extern "C" int LIB$FIND_IMAGE_SYMBOL(...);
+
+/**
+ * @internal
+ *
+ * Implements a class to register symbols and addresses for use with DLL
+ * symbol retrieval.
+ *
+ * OpenVMS restricts symbol length to 31 characters encoding any symbols
+ * longer than that. In these cases dlsym() only works with the encoded
+ * names.
+ * This creates serious problems for the service configurator framework
+ * where the factory method names often exceed 31 chars and where loading
+ * is based on retrieval of method pointers using the *full* name.
+ * For OpenVMS we therefor added this singleton class and the
+ * ACE_Dynamic_Svc_Registrar class which registers full names and function
+ * pointers with this singleton at the time the static ACE_Dynamic_Svc_Registrar
+ * object is created in a (service) DLL.
+ * By forcing the DLL to load using a common symbol ("NULL") we trigger static
+ * object creation *before* the full names are referenced.
+ * Symbol references will be resolved as follows on OpenVMS:
+ * - first try directly from DLL using the RTL dlsym() function and if that fails;
+ * - try to find symbol in singleton registry.
+ */
+class ACE_LD_Symbol_Registry
+{
+public:
+
+ typedef ACE_RB_Tree<const ACE_TCHAR*,
+ void*,
+ ACE_Less_Than<const ACE_TCHAR*>,
+ ACE_Thread_Mutex>
+ TREE;
+
+ void register_symbol (const ACE_TCHAR* symname, void* symaddr);
+
+ void* find_symbol (const ACE_TCHAR* symname);
+
+ ACE_LD_Symbol_Registry () {}
+private:
+
+ TREE symbol_registry_;
+};
+
+void
+ACE_LD_Symbol_Registry::register_symbol (const ACE_TCHAR* symname,
+ void* symaddr)
+{
+ int const result = symbol_registry_.bind (symname, symaddr);
+ if (result == 1)
+ {
+ ACE_DEBUG((LM_INFO, ACE_TEXT ("ACE_LD_Symbol_Registry:")
+ ACE_TEXT (" duplicate symbol %s registered\n"),
+ ACE_TEXT_ALWAYS_CHAR (symname)));
+ }
+ else if (result == -1)
+ {
+ ACE_ERROR((LM_ERROR, ACE_TEXT ("ACE_LD_Symbol_Registry:")
+ ACE_TEXT (" failed to register symbol %s\n"),
+ ACE_TEXT_ALWAYS_CHAR (symname)));
+ }
+}
+
+void*
+ACE_LD_Symbol_Registry::find_symbol (const ACE_TCHAR* symname)
+{
+ void* symaddr = 0;
+ int const result = symbol_registry_.find (symname, symaddr);
+
+ return (result == 0 ? symaddr : 0);
+}
+
+/// Declare a process wide singleton
+ACE_SINGLETON_DECLARE (ACE_Singleton,
+ ACE_LD_Symbol_Registry,
+ ACE_Thread_Mutex)
+
+typedef ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex>
+ ACE_LD_SYMBOL_REGISTRY;
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex> *
+ ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+#endif
+
+ACE_RCSID(ace, Lib_Find, "$Id: Lib_Find.cpp 85473 2009-06-01 08:09:31Z johnnyw $")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+int
+ACE::ldfind (const ACE_TCHAR* filename,
+ ACE_TCHAR pathname[],
+ size_t maxpathnamelen)
+{
+ ACE_TRACE ("ACE::ldfind");
+#if defined (ACE_OPENVMS)
+ if (ACE_OS::strlen(filename) >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ dsc$descriptor nameDsc;
+ nameDsc.dsc$b_class = DSC$K_CLASS_S;
+ nameDsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ nameDsc.dsc$w_length = ACE_OS::strlen(filename);
+ nameDsc.dsc$a_pointer = (char*)filename;
+
+ char symbol[] = "NULL";
+ dsc$descriptor symbolDsc;
+ symbolDsc.dsc$b_class = DSC$K_CLASS_S;
+ symbolDsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ symbolDsc.dsc$w_length = ACE_OS::strlen(symbol);
+ symbolDsc.dsc$a_pointer = symbol;
+
+ int symbolValue;
+ int result;
+ try
+ {
+ result = LIB$FIND_IMAGE_SYMBOL(&nameDsc, &symbolDsc, &symbolValue, 0, 0);
+ }
+ catch (chf$signal_array& sig)
+ {
+ result = sig.chf$l_sig_name;
+ }
+
+ int severity = result & STS$M_SEVERITY;
+ int conditionId = result & STS$M_COND_ID;
+ if (severity == STS$K_SUCCESS || severity == STS$K_WARNING || severity == STS$K_INFO ||
+ (severity == STS$K_ERROR && conditionId == (LIB$_KEYNOTFOU & STS$M_COND_ID)))
+ {
+ ACE_OS::strcpy(pathname, filename);
+ return 0;
+ }
+
+ if (ACE_OS::strlen(filename) + ACE_OS::strlen(ACE_DLL_PREFIX) >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+
+ ACE_OS::strcpy(pathname, ACE_DLL_PREFIX);
+ ACE_OS::strcat(pathname, filename);
+ nameDsc.dsc$w_length = ACE_OS::strlen(pathname);
+ nameDsc.dsc$a_pointer = pathname;
+ try
+ {
+ result = LIB$FIND_IMAGE_SYMBOL(&nameDsc, &symbolDsc, &symbolValue, 0, 0);
+ }
+ catch (chf$signal_array& sig)
+ {
+ result = sig.chf$l_sig_name;
+ }
+
+ severity = result & STS$M_SEVERITY;
+ conditionId = result & STS$M_COND_ID;
+ if (severity == STS$K_SUCCESS || severity == STS$K_WARNING || severity == STS$K_INFO ||
+ (severity == STS$K_ERROR && conditionId == (LIB$_KEYNOTFOU & STS$M_COND_ID)))
+ {
+ return 0;
+ }
+ errno = ENOENT;
+ return -1;
+#endif /* ACE_OPENVMS */
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) && \
+ !defined (ACE_HAS_PHARLAP)
+ ACE_TCHAR expanded_filename[MAXPATHLEN];
+ if (ACE_TEXT_ExpandEnvironmentStrings (filename,
+ expanded_filename,
+ sizeof expanded_filename
+ / sizeof (ACE_TCHAR)))
+ filename = expanded_filename;
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE && !ACE_HAS_PHARLAP */
+
+ ACE_TCHAR tempcopy[MAXPATHLEN + 1];
+ ACE_TCHAR searchpathname[MAXPATHLEN + 1];
+#if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ ACE_TCHAR decorator[] = ACE_LD_DECORATOR_STR;
+ ACE_TCHAR searchfilename[MAXPATHLEN + sizeof(decorator) / sizeof (ACE_TCHAR)];
+#else
+ ACE_TCHAR searchfilename[MAXPATHLEN + 1];
+#endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
+
+ // Create a copy of filename to work with.
+ if (ACE_OS::strlen (filename) + 1
+ > (sizeof tempcopy / sizeof (ACE_TCHAR)))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else
+ ACE_OS::strcpy (tempcopy, filename);
+
+ // Insert canonical directory separators.
+ ACE_TCHAR *separator_ptr;
+
+#if (ACE_DIRECTORY_SEPARATOR_CHAR != '/')
+ // Make all the directory separators "canonical" to simplify
+ // subsequent code.
+ ACE::strrepl (tempcopy, ACE_DIRECTORY_SEPARATOR_CHAR, '/');
+#endif /* ACE_DIRECTORY_SEPARATOR_CHAR */
+
+ // Separate filename from pathname.
+ separator_ptr = ACE_OS::strrchr (tempcopy, '/');
+
+ // This is a relative path.
+ if (separator_ptr == 0)
+ {
+ searchpathname[0] = '\0';
+ ACE_OS::strcpy (searchfilename, tempcopy);
+ }
+ else // This is an absolute path.
+ {
+ ACE_OS::strcpy (searchfilename, separator_ptr + 1);
+ separator_ptr[1] = '\0';
+ ACE_OS::strcpy (searchpathname, tempcopy);
+ }
+
+ bool has_suffix = false;
+
+ // Check to see if this has an appropriate DLL suffix for the OS
+ // platform.
+ ACE_TCHAR *s = ACE_OS::strrchr (searchfilename, '.');
+
+ const ACE_TCHAR *dll_suffix = ACE_DLL_SUFFIX;
+
+ if (s != 0)
+ {
+ // If we have a dot, we have a suffix
+ has_suffix = true;
+
+ // Check whether this matches the appropriate platform-specific
+ // suffix.
+#if defined (ACE_WIN32)
+ // Use <ACE_OS::strcasecmp> on any platform with
+ // case-insensitive filenames.
+ if (ACE_OS::strcasecmp (s, dll_suffix) != 0)
+#else
+ if (ACE_OS::strcmp (s, dll_suffix) != 0)
+#endif /* ACE_WIN32 */
+ {
+ ACE_ERROR ((LM_WARNING,
+ ACE_TEXT ("Warning: improper suffix for a ")
+ ACE_TEXT ("shared library on this platform: %s\n"),
+ s));
+ }
+ }
+
+ // Make sure we've got enough space in searchfilename.
+ if (ACE_OS::strlen (searchfilename)
+ + ACE_OS::strlen (ACE_DLL_PREFIX)
+ + (has_suffix ? 0 : ACE_OS::strlen (dll_suffix))
+ >= (sizeof searchfilename / sizeof (ACE_TCHAR)))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+#if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ size_t const len_searchfilename = ACE_OS::strlen (searchfilename);
+ if (!has_suffix)
+ ACE_OS::strcpy (searchfilename + len_searchfilename, decorator);
+
+ for (int tag = 1; tag >= 0; tag --)
+ {
+ if (tag == 0)
+ searchfilename [len_searchfilename] = 0;
+
+#endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
+ // Use absolute pathname if there is one.
+ if (ACE_OS::strlen (searchpathname) > 0)
+ {
+ if (ACE_OS::strlen (searchfilename)
+ + ACE_OS::strlen (searchpathname) >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else
+ {
+#if (ACE_DIRECTORY_SEPARATOR_CHAR != '/')
+ // Revert to native path name separators.
+ ACE::strrepl (searchpathname,
+ '/',
+ ACE_DIRECTORY_SEPARATOR_CHAR);
+#endif /* ACE_DIRECTORY_SEPARATOR_CHAR */
+ // First, try matching the filename *without* adding a
+ // prefix.
+ ACE_OS::sprintf (pathname,
+ ACE_TEXT ("%s%s%s"),
+ searchpathname,
+ searchfilename,
+ has_suffix ? ACE_TEXT ("") : dll_suffix);
+ if (ACE_OS::access (pathname, F_OK) == 0)
+ return 0;
+
+ // Second, try matching the filename *with* adding a prefix.
+ ACE_OS::sprintf (pathname,
+ ACE_TEXT ("%s%s%s%s"),
+ searchpathname,
+ ACE_DLL_PREFIX,
+ searchfilename,
+ has_suffix ? ACE_TEXT ("") : dll_suffix);
+ if (ACE_OS::access (pathname, F_OK) == 0)
+ return 0;
+ }
+ }
+
+ // Use relative filenames via LD_LIBRARY_PATH or PATH (depending on
+ // OS platform).
+ else
+ {
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ ACE_TCHAR *file_component = 0;
+ DWORD pathlen =
+ ACE_TEXT_SearchPath (0,
+ searchfilename,
+ dll_suffix,
+ static_cast<DWORD> (maxpathnamelen),
+ pathname,
+ &file_component);
+ if (pathlen >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else if (pathlen > 0)
+ return 0;
+
+ // In case not found we should try again with the ACE_DLL_PREFIX
+ // prefixed
+ ACE_OS::strcpy (searchfilename, ACE_DLL_PREFIX);
+ ACE_OS::strcat (searchfilename, tempcopy);
+ pathlen =
+ ACE_TEXT_SearchPath (0,
+ searchfilename,
+ dll_suffix,
+ static_cast<DWORD> (maxpathnamelen),
+ pathname,
+ &file_component);
+ if (pathlen >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else if (pathlen > 0)
+ return 0;
+#else
+ ACE_TCHAR *ld_path = 0;
+# if defined ACE_DEFAULT_LD_SEARCH_PATH
+ ld_path = const_cast <ACE_TCHAR*> (ACE_DEFAULT_LD_SEARCH_PATH);
+# else
+# if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
+ ld_path = ACE_OS::getenv (ACE_LD_SEARCH_PATH);
+# else
+ // Wide-char, non-Windows only offers char * getenv. So capture
+ // it, translate to wide-char, and continue.
+ ACE_Ascii_To_Wide wide_ldpath
+ (ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (ACE_LD_SEARCH_PATH)));
+ ld_path = wide_ldpath.wchar_rep ();
+# endif /* ACE_WIN32 || !ACE_USES_WCHAR */
+# endif /* ACE_DEFAULT_LD_SEARCH_PATH */
+
+#if defined (ACE_HAS_WINCE)
+ ACE_TCHAR *ld_path_temp = 0;
+ if (ld_path != 0)
+ {
+ ld_path_temp = (ACE_TCHAR *)
+ ACE_OS::malloc ((ACE_OS::strlen (ld_path) + 2)
+ * sizeof (ACE_TCHAR));
+ if (ld_path_temp != 0)
+ {
+ ACE_OS::strcpy (ld_path_temp,
+ ACE_LD_SEARCH_PATH_SEPARATOR_STR);
+
+ ACE_OS::strcat (ld_path_temp, ld_path);
+ ld_path = ld_path_temp;
+ }
+ else
+ {
+ ACE_OS::free ((void *) ld_path_temp);
+ ld_path = ld_path_temp = 0;
+ }
+ }
+#endif /* ACE_HAS_WINCE */
+
+ if (ld_path != 0
+ && (ld_path = ACE_OS::strdup (ld_path)) != 0)
+ {
+ // strtok has the strange behavior of not separating the
+ // string ":/foo:/bar" into THREE tokens. One would expect
+ // that the first iteration the token would be an empty
+ // string, the second iteration would be "/foo", and the
+ // third iteration would be "/bar". However, this is not
+ // the case; one only gets two iterations: "/foo" followed
+ // by "/bar".
+
+ // This is especially a problem in parsing Unix paths
+ // because it is permissible to specify 'the current
+ // directory' as an empty entry. So, we introduce the
+ // following special code to cope with this:
+
+ // Look at each dynamic lib directory in the search path.
+
+ ACE_TCHAR *nextholder = 0;
+ const ACE_TCHAR *path_entry =
+ ACE::strsplit_r (ld_path,
+ ACE_LD_SEARCH_PATH_SEPARATOR_STR,
+ nextholder);
+ int result = 0;
+
+ for (;;)
+ {
+ // Check if at end of search path.
+ if (path_entry == 0)
+ {
+ errno = ENOENT;
+ result = -1;
+ break;
+ }
+ else if (ACE_OS::strlen (path_entry)
+ + 1
+ + ACE_OS::strlen (searchfilename)
+ >= maxpathnamelen)
+ {
+ errno = ENOMEM;
+ result = -1;
+ break;
+ }
+ // This works around the issue where a path might have
+ // an empty component indicating 'current directory'.
+ // We need to do it here rather than anywhere else so
+ // that the loop condition will still work.
+ else if (path_entry[0] == '\0')
+ path_entry = ACE_TEXT (".");
+
+ // First, try matching the filename *without* adding a
+ // prefix.
+ ACE_OS::sprintf (pathname,
+ ACE_TEXT ("%s%c%s%s"),
+ path_entry,
+ ACE_DIRECTORY_SEPARATOR_CHAR,
+ searchfilename,
+ has_suffix ? ACE_TEXT ("") : dll_suffix);
+ if (ACE_OS::access (pathname, F_OK) == 0)
+ break;
+
+ // Second, try matching the filename *with* adding a
+ // prefix.
+ ACE_OS::sprintf (pathname,
+ ACE_TEXT ("%s%c%s%s%s"),
+ path_entry,
+ ACE_DIRECTORY_SEPARATOR_CHAR,
+ ACE_DLL_PREFIX,
+ searchfilename,
+ has_suffix ? ACE_TEXT ("") : dll_suffix);
+ if (ACE_OS::access (pathname, F_OK) == 0)
+ break;
+
+ // Fetch the next item in the path
+ path_entry =
+ ACE::strsplit_r (0,
+ ACE_LD_SEARCH_PATH_SEPARATOR_STR,
+ nextholder);
+ }
+
+#if defined (ACE_HAS_WINCE)
+ if (ld_path_temp != 0)
+ ACE_OS::free (ld_path_temp);
+#endif /* ACE_HAS_WINCE */
+ ACE_OS::free ((void *) ld_path);
+#if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ if (result == 0 || tag == 0)
+#endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
+ return result;
+ }
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
+ }
+#if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ }
+#endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
+
+ errno = ENOENT;
+ return -1;
+}
+
+FILE *
+ACE::ldopen (const ACE_TCHAR *filename,
+ const ACE_TCHAR *type)
+{
+ ACE_TRACE ("ACE::ldopen");
+
+ ACE_TCHAR buf[MAXPATHLEN + 1];
+ if (ACE::ldfind (filename,
+ buf,
+ sizeof (buf) /sizeof (ACE_TCHAR)) == -1)
+ return 0;
+ else
+ return ACE_OS::fopen (buf, type);
+}
+
+ACE_TCHAR *
+ACE::ldname (const ACE_TCHAR *entry_point)
+{
+ ACE_TRACE ("ACE::ldname");
+
+#if defined(ACE_NEEDS_DL_UNDERSCORE)
+ size_t size =
+ 1 // leading '_'
+ + ACE_OS::strlen (entry_point)
+ + 1;
+
+ ACE_TCHAR *new_name;
+ ACE_NEW_RETURN (new_name,
+ ACE_TCHAR[size],
+ 0);
+
+ ACE_OS::strcpy (new_name, ACE_TEXT ("_"));
+ ACE_OS::strcat (new_name, entry_point);
+
+ return new_name;
+#else /* ACE_NEEDS_DL_UNDERSCORE */
+ size_t size =
+ ACE_OS::strlen (entry_point)
+ + 1;
+
+ ACE_TCHAR *new_name;
+ ACE_NEW_RETURN (new_name,
+ ACE_TCHAR[size],
+ 0);
+
+ ACE_OS::strcpy (new_name, entry_point);
+ return new_name;
+#endif /* ACE_NEEDS_DL_UNDERSCORE */
+}
+
+#if defined (ACE_OPENVMS)
+void
+ACE::ldregister (const ACE_TCHAR *entry_point,
+ void* entry_addr)
+{
+ ACE_LD_SYMBOL_REGISTRY::instance ()->register_symbol (entry_point,
+ entry_addr);
+}
+
+void *
+ACE::ldsymbol (ACE_SHLIB_HANDLE sh, const ACE_TCHAR *entry_point)
+{
+ void* symaddr = ACE_OS::dlsym (sh, entry_point);
+ // if not found through dlsym() try registry
+ if (symaddr == 0)
+ symaddr = ACE_LD_SYMBOL_REGISTRY::instance ()->find_symbol (entry_point);
+
+ return symaddr;
+}
+#endif
+
+int
+ACE::get_temp_dir (ACE_TCHAR *buffer, size_t buffer_len)
+{
+ int result;
+#if defined (ACE_WIN32)
+ result = ACE_TEXT_GetTempPath (static_cast<DWORD> (buffer_len),
+ buffer);
+
+ // Make sure to return -1 if there is an error
+ if ((result == 0 && ::GetLastError () != ERROR_SUCCESS)
+ || (result > static_cast<int> (buffer_len)))
+ result = -1;
+
+#else /* ACE_WIN32 */
+
+ // NOTE! Non-Windows platforms don't deal with wide chars for env.
+ // variables, so do this narrow-char and convert to wide for the
+ // caller if necessary.
+
+ // On non-win32 platforms, check to see what the TMPDIR environment
+ // variable is defined to be. If it doesn't exist, just use /tmp
+ const char *tmpdir = ACE_OS::getenv ("TMPDIR");
+
+ if (tmpdir == 0)
+ tmpdir = "/tmp";
+
+ size_t len = ACE_OS::strlen (tmpdir);
+
+ // Check to see if the buffer is large enough for the string,
+ // another /, and its null character (hence the + 2)
+ if ((len + 2) > buffer_len)
+ {
+ result = -1;
+ }
+ else
+ {
+ ACE_OS::strcpy (buffer, ACE_TEXT_CHAR_TO_TCHAR (tmpdir));
+
+ // Add a trailing slash because we cannot assume there is already one
+ // at the end. And having an extra one should not cause problems.
+ buffer[len] = ACE_TEXT ('/');
+ buffer[len + 1] = 0;
+ result = 0;
+ }
+#endif /* ACE_WIN32 */
+ return result;
+}
+
+ACE_HANDLE
+ACE::open_temp_file (const ACE_TCHAR *name, int mode, int perm)
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (perm);
+ ACE_HANDLE handle = ACE_OS::open (name,
+ mode,
+ FILE_SHARE_READ
+ | FILE_SHARE_WRITE
+ | FILE_SHARE_DELETE);
+#else
+ // Open it.
+ ACE_HANDLE handle = ACE_OS::open (name, mode, perm);
+#endif /* ACE_WIN32 */
+
+ if (handle == ACE_INVALID_HANDLE)
+ return ACE_INVALID_HANDLE;
+
+ // Unlink it so that the file will be removed automatically when the
+ // process goes away.
+ if (ACE_OS::unlink (name) == -1)
+ return ACE_INVALID_HANDLE;
+ else
+ // Return the handle.
+ return handle;
+}
+
+size_t
+ACE::strrepl (char *s, char search, char replace)
+{
+ ACE_TRACE ("ACE::strrepl");
+
+ size_t replaced = 0;
+
+ for (size_t i = 0; s[i] != '\0'; i++)
+ if (s[i] == search)
+ {
+ s[i] = replace;
+ ++replaced;
+ }
+
+ return replaced;
+}
+
+
+// Split a string up into 'token'-delimited pieces, ala Perl's
+// "split".
+
+char *
+ACE::strsplit_r (char *str,
+ const char *token,
+ char *&next_start)
+{
+ char *result = 0;
+
+ if (str != 0)
+ next_start = str;
+
+ if (next_start != 0)
+ {
+ char *tok_loc = ACE_OS::strstr (next_start, token);
+
+ if (tok_loc != 0)
+ {
+ // Return the beginning of the string.
+ result = next_start;
+
+ // Insure it's terminated.
+ *tok_loc = '\0';
+ next_start = tok_loc + ACE_OS::strlen (token);
+ }
+ else
+ {
+ result = next_start;
+ next_start = (char *) 0;
+ }
+ }
+
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+wchar_t *
+ACE::strsplit_r (wchar_t *str,
+ const wchar_t *token,
+ wchar_t *&next_start)
+{
+ wchar_t *result = 0;
+
+ if (str != 0)
+ next_start = str;
+
+ if (next_start != 0)
+ {
+ wchar_t *tok_loc = ACE_OS::strstr (next_start, token);
+
+ if (tok_loc != 0)
+ {
+ // Return the beginning of the string.
+ result = next_start;
+
+ // Insure it's terminated.
+ *tok_loc = '\0';
+ next_start = tok_loc + ACE_OS::strlen (token);
+ }
+ else
+ {
+ result = next_start;
+ next_start = (wchar_t *) 0;
+ }
+ }
+
+ return result;
+}
+
+size_t
+ACE::strrepl (wchar_t *s, wchar_t search, wchar_t replace)
+{
+ ACE_TRACE ("ACE::strrepl");
+
+ size_t replaced = 0;
+
+ for (size_t i = 0; s[i] != '\0'; i++)
+ if (s[i] == search)
+ {
+ s[i] = replace;
+ ++replaced;
+ }
+
+ return replaced;
+}
+#endif /* ACE_HAS_WCHAR */
+
+ACE_END_VERSIONED_NAMESPACE_DECL