Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Lib_Find.cpp
blobca7decd224b22bb9f3d3a9148cbaff6fb4b44010
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
21 int
22 ACE::ldfind (const ACE_TCHAR* filename,
23 ACE_TCHAR pathname[],
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,
31 expanded_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)];
42 #else
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)))
50 errno = ENOMEM;
51 return -1;
53 else
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
61 // subsequent code.
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
84 // platform.
85 ACE_TCHAR *s = ACE_OS::strrchr (searchfilename, '.');
87 const ACE_TCHAR *dll_suffix = ACE_DLL_SUFFIX;
89 if (s != 0)
91 // If we have a dot, we have a suffix
92 has_suffix = true;
94 // Check whether this matches the appropriate platform-specific
95 // suffix.
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)
100 #else
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"),
107 s));
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)))
117 errno = ENOMEM;
118 return -1;
121 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
122 size_t const len_searchfilename = ACE_OS::strlen (searchfilename);
123 if (!has_suffix)
124 ACE_OS::strcpy (searchfilename + len_searchfilename, decorator);
126 for (int tag = 1; tag >= 0; tag --)
128 if (tag == 0)
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)
138 errno = ENOMEM;
139 return -1;
141 else
143 #if (ACE_DIRECTORY_SEPARATOR_CHAR != '/')
144 // Revert to native path name separators.
145 ACE::strrepl (searchpathname,
146 '/',
147 ACE_DIRECTORY_SEPARATOR_CHAR);
148 #endif /* ACE_DIRECTORY_SEPARATOR_CHAR */
149 // First, try matching the filename *without* adding a
150 // prefix.
151 ACE_OS::snprintf (pathname, maxpathnamelen,
152 ACE_TEXT ("%s%s%s"),
153 searchpathname,
154 searchfilename,
155 has_suffix ? ACE_TEXT ("") : dll_suffix);
156 if (ACE_OS::access (pathname, F_OK) == 0)
157 return 0;
159 // Second, try matching the filename *with* adding a prefix.
160 ACE_OS::snprintf (pathname, maxpathnamelen,
161 ACE_TEXT ("%s%s%s%s"),
162 searchpathname,
163 ACE_DLL_PREFIX,
164 searchfilename,
165 has_suffix ? ACE_TEXT ("") : dll_suffix);
166 if (ACE_OS::access (pathname, F_OK) == 0)
167 return 0;
171 // Use relative filenames via LD_LIBRARY_PATH or PATH (depending on
172 // OS platform).
173 else
175 #if defined (ACE_WIN32)
176 ACE_TCHAR *file_component = 0;
177 DWORD pathlen =
178 ACE_TEXT_SearchPath (0,
179 searchfilename,
180 dll_suffix,
181 static_cast<DWORD> (maxpathnamelen),
182 pathname,
183 &file_component);
184 if (pathlen >= maxpathnamelen)
186 errno = ENOMEM;
187 return -1;
189 else if (pathlen > 0)
190 return 0;
192 // In case not found we should try again with the ACE_DLL_PREFIX
193 // prefixed
194 ACE_OS::strcpy (searchfilename, ACE_DLL_PREFIX);
195 ACE_OS::strcat (searchfilename, tempcopy);
196 pathlen =
197 ACE_TEXT_SearchPath (0,
198 searchfilename,
199 dll_suffix,
200 static_cast<DWORD> (maxpathnamelen),
201 pathname,
202 &file_component);
203 if (pathlen >= maxpathnamelen)
205 errno = ENOMEM;
206 return -1;
208 else if (pathlen > 0)
209 return 0;
210 #else
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);
214 # else
215 # if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
216 ld_path = ACE_OS::getenv (ACE_LD_SEARCH_PATH);
217 # else
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 */
226 if (ld_path != 0
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
235 // by "/bar".
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,
248 nextholder);
249 int result = 0;
251 for (;;)
253 // Check if at end of search path.
254 if (path_entry == 0)
256 errno = ENOENT;
257 result = -1;
258 break;
260 else if (ACE_OS::strlen (path_entry)
262 + ACE_OS::strlen (searchfilename)
263 >= maxpathnamelen)
265 errno = ENOMEM;
266 result = -1;
267 break;
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
277 // prefix.
278 ACE_OS::snprintf (pathname, maxpathnamelen,
279 ACE_TEXT ("%s%c%s%s"),
280 path_entry,
281 ACE_DIRECTORY_SEPARATOR_CHAR,
282 searchfilename,
283 has_suffix ? ACE_TEXT ("") : dll_suffix);
284 if (ACE_OS::access (pathname, F_OK) == 0)
285 break;
287 // Second, try matching the filename *with* adding a
288 // prefix.
289 ACE_OS::snprintf (pathname, maxpathnamelen,
290 ACE_TEXT ("%s%c%s%s%s"),
291 path_entry,
292 ACE_DIRECTORY_SEPARATOR_CHAR,
293 ACE_DLL_PREFIX,
294 searchfilename,
295 has_suffix ? ACE_TEXT ("") : dll_suffix);
296 if (ACE_OS::access (pathname, F_OK) == 0)
297 break;
299 // Fetch the next item in the path
300 path_entry =
301 ACE::strsplit_r (0,
302 ACE_LD_SEARCH_PATH_SEPARATOR_STR,
303 nextholder);
306 #if defined (ACE_HAS_ALLOC_HOOKS)
307 ACE_Allocator::instance()->free ((void *) ld_path);
308 #else
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 */
314 return result;
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 */
322 errno = ENOENT;
323 return -1;
326 FILE *
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,
334 buf,
335 sizeof (buf) /sizeof (ACE_TCHAR)) == -1)
336 return 0;
337 else
338 return ACE_OS::fopen (buf, type);
341 ACE_TCHAR *
342 ACE::ldname (const ACE_TCHAR *entry_point)
344 ACE_TRACE ("ACE::ldname");
346 #if defined(ACE_NEEDS_DL_UNDERSCORE)
347 size_t size =
348 1 // leading '_'
349 + ACE_OS::strlen (entry_point)
350 + 1;
352 ACE_TCHAR *new_name;
353 ACE_NEW_RETURN (new_name,
354 ACE_TCHAR[size],
357 ACE_OS::strcpy (new_name, ACE_TEXT ("_"));
358 ACE_OS::strcat (new_name, entry_point);
360 return new_name;
361 #else /* ACE_NEEDS_DL_UNDERSCORE */
362 size_t size =
363 ACE_OS::strlen (entry_point)
364 + 1;
366 ACE_TCHAR *new_name;
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)),
371 #else
372 ACE_NEW_RETURN (new_name,
373 ACE_TCHAR[size],
375 #endif /* ACE_HAS_ALLOC_HOOKS */
377 ACE_OS::strcpy (new_name, entry_point);
378 return new_name;
379 #endif /* ACE_NEEDS_DL_UNDERSCORE */
383 ACE::get_temp_dir (ACE_TCHAR *buffer, size_t buffer_len)
385 int result;
386 #if defined (ACE_WIN32)
387 result = ACE_TEXT_GetTempPath (static_cast<DWORD> (buffer_len),
388 buffer);
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)))
393 result = -1;
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");
405 if (tmpdir == 0)
407 #if defined (ACE_DEFAULT_TEMP_DIR)
408 tmpdir = ACE_DEFAULT_TEMP_DIR;
409 #else
410 tmpdir = "/tmp";
411 #endif
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)
420 result = -1;
422 else
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 ('/');
429 buffer[len + 1] = 0;
430 result = 0;
432 #endif /* ACE_WIN32 */
433 return result;
436 ACE_HANDLE
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,
442 mode,
443 FILE_SHARE_READ
444 | FILE_SHARE_WRITE
445 | FILE_SHARE_DELETE);
446 #else
447 // Open it.
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;
461 else
462 // Return the handle.
463 return handle;
466 size_t
467 ACE::strrepl (char *s, char search, char replace)
469 ACE_TRACE ("ACE::strrepl");
471 size_t replaced = 0;
473 for (size_t i = 0; s[i] != '\0'; i++)
474 if (s[i] == search)
476 s[i] = replace;
477 ++replaced;
480 return replaced;
484 // Split a string up into 'token'-delimited pieces, ala Perl's
485 // "split".
487 char *
488 ACE::strsplit_r (char *str,
489 const char *token,
490 char *&next_start)
492 char *result = 0;
494 if (str != 0)
495 next_start = str;
497 if (next_start != 0)
499 char *tok_loc = ACE_OS::strstr (next_start, token);
501 if (tok_loc != 0)
503 // Return the beginning of the string.
504 result = next_start;
506 // Insure it's terminated.
507 *tok_loc = '\0';
508 next_start = tok_loc + ACE_OS::strlen (token);
510 else
512 result = next_start;
513 next_start = (char *) 0;
517 return result;
520 #if defined (ACE_HAS_WCHAR)
521 wchar_t *
522 ACE::strsplit_r (wchar_t *str,
523 const wchar_t *token,
524 wchar_t *&next_start)
526 wchar_t *result = 0;
528 if (str != 0)
529 next_start = str;
531 if (next_start != 0)
533 wchar_t *tok_loc = ACE_OS::strstr (next_start, token);
535 if (tok_loc != 0)
537 // Return the beginning of the string.
538 result = next_start;
540 // Insure it's terminated.
541 *tok_loc = '\0';
542 next_start = tok_loc + ACE_OS::strlen (token);
544 else
546 result = next_start;
547 next_start = (wchar_t *) 0;
551 return result;
554 size_t
555 ACE::strrepl (wchar_t *s, wchar_t search, wchar_t replace)
557 ACE_TRACE ("ACE::strrepl");
559 size_t replaced = 0;
561 for (size_t i = 0; s[i] != '\0'; i++)
562 if (s[i] == search)
564 s[i] = replace;
565 ++replaced;
568 return replaced;
570 #endif /* ACE_HAS_WCHAR */
572 ACE_END_VERSIONED_NAMESPACE_DECL