1 #include "ace/Lib_Find.h"
2 #include "ace/Log_Category.h"
3 #include "ace/OS_NS_string.h"
4 #include "ace/OS_NS_errno.h"
5 #include "ace/OS_NS_stdio.h"
6 #include "ace/OS_NS_unistd.h"
7 #include "ace/OS_NS_stdlib.h"
8 #include "ace/OS_Memory.h"
9 #include "ace/OS_NS_fcntl.h"
11 #if defined (ACE_HAS_ALLOC_HOOKS)
12 # include "ace/Malloc_Base.h"
13 #endif /* ACE_HAS_ALLOC_HOOKS */
15 #if defined (ACE_WIN32)
16 # include "ace/OS_NS_strings.h"
17 #endif /* ACE_WIN32 */
19 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
22 ACE::ldfind (const ACE_TCHAR
* filename
,
24 size_t maxpathnamelen
)
26 ACE_TRACE ("ACE::ldfind");
28 #if defined (ACE_WIN32)
29 ACE_TCHAR expanded_filename
[MAXPATHLEN
];
30 if (ACE_TEXT_ExpandEnvironmentStrings (filename
,
32 sizeof expanded_filename
33 / sizeof (ACE_TCHAR
)))
34 filename
= expanded_filename
;
35 #endif /* ACE_WIN32 */
37 ACE_TCHAR tempcopy
[MAXPATHLEN
+ 1];
38 ACE_TCHAR searchpathname
[MAXPATHLEN
+ 1];
39 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
40 ACE_TCHAR decorator
[] = ACE_LD_DECORATOR_STR
;
41 ACE_TCHAR searchfilename
[MAXPATHLEN
+ sizeof(decorator
) / sizeof (ACE_TCHAR
)];
43 ACE_TCHAR searchfilename
[MAXPATHLEN
+ 1];
44 #endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
46 // Create a copy of filename to work with.
47 if (ACE_OS::strlen (filename
) + 1
48 > (sizeof tempcopy
/ sizeof (ACE_TCHAR
)))
54 ACE_OS::strcpy (tempcopy
, filename
);
56 // Insert canonical directory separators.
57 ACE_TCHAR
*separator_ptr
;
59 #if (ACE_DIRECTORY_SEPARATOR_CHAR != '/')
60 // Make all the directory separators "canonical" to simplify
62 ACE::strrepl (tempcopy
, ACE_DIRECTORY_SEPARATOR_CHAR
, '/');
63 #endif /* ACE_DIRECTORY_SEPARATOR_CHAR */
65 // Separate filename from pathname.
66 separator_ptr
= ACE_OS::strrchr (tempcopy
, '/');
68 // This is a relative path.
69 if (separator_ptr
== 0)
71 searchpathname
[0] = '\0';
72 ACE_OS::strcpy (searchfilename
, tempcopy
);
74 else // This is an absolute path.
76 ACE_OS::strcpy (searchfilename
, separator_ptr
+ 1);
77 separator_ptr
[1] = '\0';
78 ACE_OS::strcpy (searchpathname
, tempcopy
);
81 bool has_suffix
= false;
83 // Check to see if this has an appropriate DLL suffix for the OS
85 ACE_TCHAR
*s
= ACE_OS::strrchr (searchfilename
, '.');
87 const ACE_TCHAR
*dll_suffix
= ACE_DLL_SUFFIX
;
91 // If we have a dot, we have a suffix
94 // Check whether this matches the appropriate platform-specific
96 #if defined (ACE_WIN32)
97 // Use <ACE_OS::strcasecmp> on any platform with
98 // case-insensitive filenames.
99 if (ACE_OS::strcasecmp (s
, dll_suffix
) != 0)
101 if (ACE_OS::strcmp (s
, dll_suffix
) != 0)
102 #endif /* ACE_WIN32 */
104 ACELIB_ERROR ((LM_WARNING
,
105 ACE_TEXT ("Warning: improper suffix for a ")
106 ACE_TEXT ("shared library on this platform: %s\n"),
111 // Make sure we've got enough space in searchfilename.
112 if (ACE_OS::strlen (searchfilename
)
113 + ACE_OS::strlen (ACE_DLL_PREFIX
)
114 + (has_suffix
? 0 : ACE_OS::strlen (dll_suffix
))
115 >= (sizeof searchfilename
/ sizeof (ACE_TCHAR
)))
121 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
122 size_t const len_searchfilename
= ACE_OS::strlen (searchfilename
);
124 ACE_OS::strcpy (searchfilename
+ len_searchfilename
, decorator
);
126 for (int tag
= 1; tag
>= 0; tag
--)
129 searchfilename
[len_searchfilename
] = 0;
131 #endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
132 // Use absolute pathname if there is one.
133 if (ACE_OS::strlen (searchpathname
) > 0)
135 if (ACE_OS::strlen (searchfilename
)
136 + ACE_OS::strlen (searchpathname
) >= maxpathnamelen
)
143 #if (ACE_DIRECTORY_SEPARATOR_CHAR != '/')
144 // Revert to native path name separators.
145 ACE::strrepl (searchpathname
,
147 ACE_DIRECTORY_SEPARATOR_CHAR
);
148 #endif /* ACE_DIRECTORY_SEPARATOR_CHAR */
149 // First, try matching the filename *without* adding a
151 ACE_OS::snprintf (pathname
, maxpathnamelen
,
155 has_suffix
? ACE_TEXT ("") : dll_suffix
);
156 if (ACE_OS::access (pathname
, F_OK
) == 0)
159 // Second, try matching the filename *with* adding a prefix.
160 ACE_OS::snprintf (pathname
, maxpathnamelen
,
161 ACE_TEXT ("%s%s%s%s"),
165 has_suffix
? ACE_TEXT ("") : dll_suffix
);
166 if (ACE_OS::access (pathname
, F_OK
) == 0)
171 // Use relative filenames via LD_LIBRARY_PATH or PATH (depending on
175 #if defined (ACE_WIN32)
176 ACE_TCHAR
*file_component
= 0;
178 ACE_TEXT_SearchPath (0,
181 static_cast<DWORD
> (maxpathnamelen
),
184 if (pathlen
>= maxpathnamelen
)
189 else if (pathlen
> 0)
192 // In case not found we should try again with the ACE_DLL_PREFIX
194 ACE_OS::strcpy (searchfilename
, ACE_DLL_PREFIX
);
195 ACE_OS::strcat (searchfilename
, tempcopy
);
197 ACE_TEXT_SearchPath (0,
200 static_cast<DWORD
> (maxpathnamelen
),
203 if (pathlen
>= maxpathnamelen
)
208 else if (pathlen
> 0)
211 ACE_TCHAR
*ld_path
= 0;
212 # if defined ACE_DEFAULT_LD_SEARCH_PATH
213 ld_path
= const_cast<ACE_TCHAR
*> (ACE_DEFAULT_LD_SEARCH_PATH
);
215 # if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
216 ld_path
= ACE_OS::getenv (ACE_LD_SEARCH_PATH
);
218 // Wide-char, non-Windows only offers char * getenv. So capture
219 // it, translate to wide-char, and continue.
220 ACE_Ascii_To_Wide wide_ldpath
221 (ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (ACE_LD_SEARCH_PATH
)));
222 ld_path
= wide_ldpath
.wchar_rep ();
223 # endif /* ACE_WIN32 || !ACE_USES_WCHAR */
224 # endif /* ACE_DEFAULT_LD_SEARCH_PATH */
227 && (ld_path
= ACE_OS::strdup (ld_path
)) != 0)
229 // strtok has the strange behavior of not separating the
230 // string ":/foo:/bar" into THREE tokens. One would expect
231 // that the first iteration the token would be an empty
232 // string, the second iteration would be "/foo", and the
233 // third iteration would be "/bar". However, this is not
234 // the case; one only gets two iterations: "/foo" followed
237 // This is especially a problem in parsing Unix paths
238 // because it is permissible to specify 'the current
239 // directory' as an empty entry. So, we introduce the
240 // following special code to cope with this:
242 // Look at each dynamic lib directory in the search path.
244 ACE_TCHAR
*nextholder
= 0;
245 const ACE_TCHAR
*path_entry
=
246 ACE::strsplit_r (ld_path
,
247 ACE_LD_SEARCH_PATH_SEPARATOR_STR
,
253 // Check if at end of search path.
260 else if (ACE_OS::strlen (path_entry
)
262 + ACE_OS::strlen (searchfilename
)
269 // This works around the issue where a path might have
270 // an empty component indicating 'current directory'.
271 // We need to do it here rather than anywhere else so
272 // that the loop condition will still work.
273 else if (path_entry
[0] == '\0')
274 path_entry
= ACE_TEXT (".");
276 // First, try matching the filename *without* adding a
278 ACE_OS::snprintf (pathname
, maxpathnamelen
,
279 ACE_TEXT ("%s%c%s%s"),
281 ACE_DIRECTORY_SEPARATOR_CHAR
,
283 has_suffix
? ACE_TEXT ("") : dll_suffix
);
284 if (ACE_OS::access (pathname
, F_OK
) == 0)
287 // Second, try matching the filename *with* adding a
289 ACE_OS::snprintf (pathname
, maxpathnamelen
,
290 ACE_TEXT ("%s%c%s%s%s"),
292 ACE_DIRECTORY_SEPARATOR_CHAR
,
295 has_suffix
? ACE_TEXT ("") : dll_suffix
);
296 if (ACE_OS::access (pathname
, F_OK
) == 0)
299 // Fetch the next item in the path
302 ACE_LD_SEARCH_PATH_SEPARATOR_STR
,
306 #if defined (ACE_HAS_ALLOC_HOOKS)
307 ACE_Allocator::instance()->free ((void *) ld_path
);
309 ACE_OS::free ((void *) ld_path
);
310 #endif /* ACE_HAS_ALLOC_HOOKS */
311 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
312 if (result
== 0 || tag
== 0)
313 #endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
316 #endif /* ACE_WIN32 */
318 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
320 #endif /* ACE_LD_DECORATOR_STR && !ACE_DISABLE_DEBUG_DLL_CHECK */
327 ACE::ldopen (const ACE_TCHAR
*filename
,
328 const ACE_TCHAR
*type
)
330 ACE_TRACE ("ACE::ldopen");
332 ACE_TCHAR buf
[MAXPATHLEN
+ 1];
333 if (ACE::ldfind (filename
,
335 sizeof (buf
) /sizeof (ACE_TCHAR
)) == -1)
338 return ACE_OS::fopen (buf
, type
);
342 ACE::ldname (const ACE_TCHAR
*entry_point
)
344 ACE_TRACE ("ACE::ldname");
346 #if defined(ACE_NEEDS_DL_UNDERSCORE)
349 + ACE_OS::strlen (entry_point
)
353 ACE_NEW_RETURN (new_name
,
357 ACE_OS::strcpy (new_name
, ACE_TEXT ("_"));
358 ACE_OS::strcat (new_name
, entry_point
);
361 #else /* ACE_NEEDS_DL_UNDERSCORE */
363 ACE_OS::strlen (entry_point
)
367 #if defined (ACE_HAS_ALLOC_HOOKS)
368 ACE_ALLOCATOR_RETURN (new_name
,
369 static_cast<ACE_TCHAR
*>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR
) * size
)),
372 ACE_NEW_RETURN (new_name
,
375 #endif /* ACE_HAS_ALLOC_HOOKS */
377 ACE_OS::strcpy (new_name
, entry_point
);
379 #endif /* ACE_NEEDS_DL_UNDERSCORE */
383 ACE::get_temp_dir (ACE_TCHAR
*buffer
, size_t buffer_len
)
386 #if defined (ACE_WIN32)
387 result
= ACE_TEXT_GetTempPath (static_cast<DWORD
> (buffer_len
),
390 // Make sure to return -1 if there is an error
391 if ((result
== 0 && ::GetLastError () != ERROR_SUCCESS
)
392 || (result
> static_cast<int> (buffer_len
)))
395 #else /* ACE_WIN32 */
397 // NOTE! Non-Windows platforms don't deal with wide chars for env.
398 // variables, so do this narrow-char and convert to wide for the
399 // caller if necessary.
401 // On non-win32 platforms, check to see what the TMPDIR environment
402 // variable is defined to be. If it doesn't exist, just use /tmp
403 const char *tmpdir
= ACE_OS::getenv ("TMPDIR");
407 #if defined (ACE_DEFAULT_TEMP_DIR)
408 tmpdir
= ACE_DEFAULT_TEMP_DIR
;
414 size_t len
= ACE_OS::strlen (tmpdir
);
416 // Check to see if the buffer is large enough for the string,
417 // another /, and its null character (hence the + 2)
418 if ((len
+ 2) > buffer_len
)
424 ACE_OS::strcpy (buffer
, ACE_TEXT_CHAR_TO_TCHAR (tmpdir
));
426 // Add a trailing slash because we cannot assume there is already one
427 // at the end. And having an extra one should not cause problems.
428 buffer
[len
] = ACE_TEXT ('/');
432 #endif /* ACE_WIN32 */
437 ACE::open_temp_file (const ACE_TCHAR
*name
, int mode
, int perm
)
439 #if defined (ACE_WIN32)
440 ACE_UNUSED_ARG (perm
);
441 ACE_HANDLE handle
= ACE_OS::open (name
,
445 | FILE_SHARE_DELETE
);
448 ACE_HANDLE handle
= ACE_OS::open (name
, mode
, perm
);
449 #endif /* ACE_WIN32 */
451 if (handle
== ACE_INVALID_HANDLE
)
452 return ACE_INVALID_HANDLE
;
454 // Unlink it so that the file will be removed automatically when the
455 // process goes away.
456 if (ACE_OS::unlink (name
) == -1)
458 ACE_OS::close (handle
);
459 return ACE_INVALID_HANDLE
;
462 // Return the handle.
467 ACE::strrepl (char *s
, char search
, char replace
)
469 ACE_TRACE ("ACE::strrepl");
473 for (size_t i
= 0; s
[i
] != '\0'; i
++)
484 // Split a string up into 'token'-delimited pieces, ala Perl's
488 ACE::strsplit_r (char *str
,
499 char *tok_loc
= ACE_OS::strstr (next_start
, token
);
503 // Return the beginning of the string.
506 // Insure it's terminated.
508 next_start
= tok_loc
+ ACE_OS::strlen (token
);
513 next_start
= (char *) 0;
520 #if defined (ACE_HAS_WCHAR)
522 ACE::strsplit_r (wchar_t *str
,
523 const wchar_t *token
,
524 wchar_t *&next_start
)
533 wchar_t *tok_loc
= ACE_OS::strstr (next_start
, token
);
537 // Return the beginning of the string.
540 // Insure it's terminated.
542 next_start
= tok_loc
+ ACE_OS::strlen (token
);
547 next_start
= (wchar_t *) 0;
555 ACE::strrepl (wchar_t *s
, wchar_t search
, wchar_t replace
)
557 ACE_TRACE ("ACE::strrepl");
561 for (size_t i
= 0; s
[i
] != '\0'; i
++)
570 #endif /* ACE_HAS_WCHAR */
572 ACE_END_VERSIONED_NAMESPACE_DECL