1 #include "ace/OS_NS_stdlib.h"
3 #include "ace/Default_Constants.h"
5 #if !defined (ACE_HAS_INLINED_OSCALLS)
6 # include "ace/OS_NS_stdlib.inl"
7 #endif /* ACE_HAS_INLINED_OSCALLS */
9 #include "ace/OS_Memory.h"
11 #include "ace/OS_NS_unistd.h"
12 #include "ace/OS_NS_ctype.h"
14 #if defined (ACE_LACKS_MKTEMP) \
15 || defined (ACE_LACKS_MKSTEMP) \
16 || defined (ACE_LACKS_REALPATH)
17 # include "ace/OS_NS_stdio.h"
18 # include "ace/OS_NS_sys_stat.h"
19 #endif /* ACE_LACKS_MKTEMP || ACE_LACKS_MKSTEMP || ACE_LACKS_REALPATH */
21 #if defined (ACE_LACKS_MKSTEMP)
22 # include "ace/OS_NS_fcntl.h"
23 # include "ace/OS_NS_ctype.h"
24 # include "ace/OS_NS_sys_time.h"
25 # include "ace/OS_NS_Thread.h"
26 # include "ace/Numeric_Limits.h"
27 #endif /* ACE_LACKS_MKSTEMP */
29 #if defined (ACE_HAS_ALLOC_HOOKS)
30 # include "ace/Malloc_Base.h"
31 #endif /* ACE_HAS_ALLOC_HOOKS */
33 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
35 ACE_EXIT_HOOK
ACE_OS::exit_hook_
= 0;
38 ACE_OS::calloc (size_t elements
, size_t sizeof_elements
)
40 return ACE_CALLOC_FUNC (elements
, sizeof_elements
);
44 ACE_OS::exit (int status
)
46 ACE_OS_TRACE ("ACE_OS::exit");
48 #if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
49 // Shut down the ACE_Object_Manager, if it had registered its exit_hook.
50 // With ACE_HAS_NONSTATIC_OBJECT_MANAGER, the ACE_Object_Manager is
51 // instantiated on the main's stack. ::exit () doesn't destroy it.
54 #endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */
56 #if defined (ACE_WIN32)
57 ::ExitProcess ((UINT
) status
);
58 #elif !defined ACE_LACKS_EXIT
61 ACE_UNUSED_ARG (status
);
62 #endif /* ACE_WIN32 */
66 ACE_OS::free (void *ptr
)
68 #if defined (ACE_LACKS_FREE)
71 ACE_FREE_FUNC (ACE_MALLOC_T (ptr
));
75 // You may be asking yourself, why are we doing this? Well, in winbase.h,
76 // MS didn't follow their normal Api_FunctionA and Api_FunctionW style,
77 // so we have to #undef their define to get access to the unicode version.
78 // And because we don't want to #undef this for the users code, we keep
79 // this method in the .cpp file.
80 #if defined (ACE_WIN32) && defined (UNICODE) && !defined (ACE_USES_TCHAR)
81 #undef GetEnvironmentStrings
82 #endif /* ACE_WIN32 && UNICODE !ACE_USES_TCHAR */
85 ACE_OS::getenvstrings ()
87 #if defined (ACE_WIN32)
88 # if defined (ACE_USES_WCHAR)
89 return ::GetEnvironmentStringsW ();
90 # else /* ACE_USES_WCHAR */
91 return ::GetEnvironmentStrings ();
92 # endif /* ACE_USES_WCHAR */
94 ACE_NOTSUP_RETURN (0);
95 #endif /* ACE_WIN32 */
98 // Return a dynamically allocated duplicate of <str>, substituting the
99 // environment variables of form $VAR_NAME. Note that the pointer is
100 // allocated with <ACE_OS::malloc> and must be freed by
103 ACE_OS::strenvdup (const ACE_TCHAR
*str
)
105 const ACE_TCHAR
* start
= 0;
106 if ((start
= ACE_OS::strchr (str
, ACE_TEXT ('$'))) != 0)
108 ACE_TCHAR buf
[ACE_DEFAULT_ARGV_BUFSIZ
];
109 size_t var_len
= ACE_OS::strcspn (&start
[1],
110 ACE_TEXT ("$~!#%^&*()-+=\\|/?,.;:'\"`[]{} \t\n\r"));
111 ACE_OS::strncpy (buf
, &start
[1], var_len
);
112 buf
[var_len
++] = ACE_TEXT ('\0');
113 # if defined (ACE_WIN32)
114 // Always use the ACE_TCHAR for Windows.
115 ACE_TCHAR
*temp
= ACE_OS::getenv (buf
);
117 // Use char * for environment on non-Windows.
118 char *temp
= ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (buf
));
119 # endif /* ACE_WIN32 */
120 size_t buf_len
= ACE_OS::strlen (str
) + 1;
122 buf_len
+= ACE_OS::strlen (temp
) - var_len
;
124 #if defined (ACE_HAS_ALLOC_HOOKS)
125 (ACE_TCHAR
*) ACE_Allocator::instance()->malloc (buf_len
* sizeof (ACE_TCHAR
));
127 (ACE_TCHAR
*) ACE_OS::malloc (buf_len
* sizeof (ACE_TCHAR
));
128 #endif /* ACE_HAS_ALLOC_HOOKS */
135 ACE_TCHAR
* p
= buf_p
;
136 size_t const len
= start
- str
;
137 ACE_OS::strncpy (p
, str
, len
);
141 # if defined (ACE_WIN32)
142 p
= ACE_OS::strecpy (p
, temp
) - 1;
144 p
= ACE_OS::strecpy (p
, ACE_TEXT_CHAR_TO_TCHAR (temp
)) - 1;
145 # endif /* ACE_WIN32 */
149 ACE_OS::strncpy (p
, start
, var_len
);
151 *p
= ACE_TEXT ('\0');
153 ACE_OS::strcpy (p
, &start
[var_len
]);
157 return ACE_OS::strdup (str
);
160 #if !defined (ACE_HAS_ITOA)
162 ACE_OS::itoa_emulation (int value
, char *string
, int radix
)
167 // Short circuit if 0
175 // If negative and base 10, print a - and then do the
177 if (value
< 0 && radix
== 10)
181 ++e
; // Don't overwrite the negative sign.
182 value
= -value
; // Drop negative sign so character selection is correct.
185 // Convert to base <radix>, but in reverse order
188 int const mod
= value
% radix
;
189 value
= value
/ radix
;
191 *e
++ = (mod
< 10) ? '0' + mod
: 'a' + mod
- 10;
196 // Now reverse the string to get the correct result
209 #endif /* !ACE_HAS_ITOA */
211 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_ITOW)
213 ACE_OS::itow_emulation (int value
, wchar_t *string
, int radix
)
218 // Short circuit if 0
227 // If negative and base 10, print a - and then do the
230 if (value
< 0 && radix
== 10)
236 // Convert to base <radix>, but in reverse order
240 int mod
= value
% radix
;
241 value
= value
/ radix
;
243 *e
++ = (mod
< 10) ? '0' + mod
: 'a' + mod
- 10;
248 // Now reverse the string to get the correct result
261 #endif /* ACE_HAS_WCHAR && ACE_LACKS_ITOW */
264 ACE_OS::malloc (size_t nbytes
)
266 return ACE_MALLOC_FUNC (nbytes
);
269 #if defined (ACE_LACKS_MKTEMP) && !defined (ACE_DISABLE_MKTEMP)
271 ACE_OS::mktemp (ACE_TCHAR
*s
)
273 ACE_OS_TRACE ("ACE_OS::mktemp");
275 // check for null template string failed!
278 ACE_TCHAR
*xxxxxx
= ACE_OS::strstr (s
, ACE_TEXT ("XXXXXX"));
280 // the template string doesn't contain "XXXXXX"!
283 // Find an unused filename for this process. It is assumed
284 // that the user will open the file immediately after
285 // getting this filename back (so, yes, there is a race
286 // condition if multiple threads in a process use the same
287 // template). This appears to match the behavior of the
288 // SunOS 5.5 mktemp().
290 for (ACE_TCHAR letter
= ACE_TEXT ('a');
291 letter
<= ACE_TEXT ('z');
295 ACE_OS::snprintf (xxxxxx
, 7,
297 (int)ACE_OS::getpid () % 100000,
299 if (ACE_OS::stat (s
, &sb
) < 0)
306 // maximum of 26 unique files per template, per process
307 xxxxxx
[0] = ACE_TEXT ('\0');
310 #endif /* ACE_LACKS_MKTEMP && !ACE_DISABLE_MKTEMP */
313 ACE_OS::realloc (void *ptr
, size_t nbytes
)
315 #ifdef ACE_LACKS_REALLOC
316 ACE_UNUSED_ARG (ptr
);
317 ACE_UNUSED_ARG (nbytes
);
318 ACE_NOTSUP_RETURN (0);
320 return ACE_REALLOC_FUNC (ACE_MALLOC_T (ptr
), nbytes
);
324 #if defined (ACE_LACKS_REALPATH)
326 ACE_OS::realpath (const char *file_name
,
329 ACE_OS_TRACE ("ACE_OS::realpath");
333 // Single Unix Specification V3:
334 // Return an error if parameter is a null pointer.
339 if (*file_name
== '\0')
341 // Single Unix Specification V3:
342 // Return an error if the file_name argument points
343 // to an empty string.
350 if (resolved_name
== 0)
352 // Single Unix Specification V3:
353 // Return an error if parameter is a null pointer.
355 // To match glibc realpath() and Win32 _fullpath() behavior,
356 // allocate room for the return value if resolved_name is
358 #if defined (ACE_HAS_ALLOC_HOOKS)
359 rpath
= static_cast<char*>(ACE_Allocator::instance()->malloc (PATH_MAX
));
361 rpath
= static_cast<char*>(ACE_OS::malloc (PATH_MAX
));
362 #endif /* ACE_HAS_ALLOC_HOOKS */
371 rpath
= resolved_name
;
376 if (*file_name
!= '/')
378 // file_name is relative path so CWD needs to be added
379 if (ACE_OS::getcwd (rpath
, PATH_MAX
) == 0)
381 if (resolved_name
== 0)
382 #if defined (ACE_HAS_ALLOC_HOOKS)
383 ACE_Allocator::instance()->free (rpath
);
385 ACE_OS::free (rpath
);
386 #endif /* ACE_HAS_ALLOC_HOOKS */
389 dest
= ACE_OS::strchr (rpath
, '\0');
396 #if !defined (ACE_LACKS_SYMLINKS)
397 char expand_buf
[PATH_MAX
]; // Extra buffer needed to expand symbolic links
405 // Skip multiple separators
406 while (*file_name
== '/')
411 // Process one path component
412 while (*file_name
&& *file_name
!= '/')
414 *dest
++ = *file_name
++;
415 if (dest
- rpath
> PATH_MAX
)
417 errno
= ENAMETOOLONG
;
418 if (resolved_name
== 0)
419 #if defined (ACE_HAS_ALLOC_HOOKS)
420 ACE_Allocator::instance()->free (rpath
);
422 ACE_OS::free (rpath
);
423 #endif /* ACE_HAS_ALLOC_HOOKS */
428 if (start
== dest
) // Are we done?
430 if (dest
- rpath
> 1)
431 --dest
; // Remove trailing separator if not at root
434 else if (dest
- start
== 1 && *start
== '.')
436 dest
-= 2; // Remove "./"
438 else if (dest
- start
== 2 && *start
== '.' && *(start
+1) == '.')
440 dest
-= 3; // Remove "../"
441 if (dest
> rpath
) // Remove the last path component if not at root
442 while (*--dest
!= '/')
445 # if !defined (ACE_LACKS_SYMLINKS)
451 if (ACE_OS::lstat(rpath
, &st
) < 0)
453 if (resolved_name
== 0)
454 #if defined (ACE_HAS_ALLOC_HOOKS)
455 ACE_Allocator::instance()->free (rpath
);
457 ACE_OS::free (rpath
);
458 #endif /* ACE_HAS_ALLOC_HOOKS */
462 // Check if current path is a link
463 if (S_ISLNK (st
.st_mode
))
465 if (++nlinks
> MAXSYMLINKS
)
468 if (resolved_name
== 0)
469 #if defined (ACE_HAS_ALLOC_HOOKS)
470 ACE_Allocator::instance()->free (rpath
);
472 ACE_OS::free (rpath
);
473 #endif /* ACE_HAS_ALLOC_HOOKS */
477 char link_buf
[PATH_MAX
];
479 ssize_t link_len
= ACE_OS::readlink (rpath
, link_buf
, PATH_MAX
);
480 int tail_len
= ACE_OS::strlen (file_name
) + 1;
482 // Check if there is room to expand link?
483 if (link_len
+ tail_len
> PATH_MAX
)
485 errno
= ENAMETOOLONG
;
486 if (resolved_name
== 0)
487 #if defined (ACE_HAS_ALLOC_HOOKS)
488 ACE_Allocator::instance()->free (rpath
);
490 ACE_OS::free (rpath
);
491 #endif /* ACE_HAS_ALLOC_HOOKS */
495 // Move tail and prefix it with expanded link
496 ACE_OS::memmove (expand_buf
+ link_len
, file_name
, tail_len
);
497 ACE_OS::memcpy (expand_buf
, link_buf
, link_len
);
499 if (*link_buf
== '/') // Absolute link?
503 else // Relative link, remove expanded link component
506 while (*--dest
!= '/')
509 file_name
= expand_buf
; // Source path is now in expand_buf
512 # endif /* ACE_LACKS_SYMLINKS */
519 #endif /* ACE_LACKS_REALPATH */
521 #if defined (ACE_LACKS_STRTOL)
523 ACE_OS::strtol_emulation (const char *nptr
, char **endptr
, int base
)
525 const char *s
= nptr
;
528 unsigned long cutoff
;
529 int neg
= 0, any
, cutlim
;
532 * Skip white space and pick up leading +/- sign if any.
533 * If base is 0, allow 0x for hex and 0 for octal, else
534 * assume decimal; if base is already 16, allow 0x.
538 } while (ACE_OS::ace_isspace(c
));
544 if ((base
== 0 || base
== 16) &&
545 c
== '0' && (*s
== 'x' || *s
== 'X')) {
551 base
= c
== '0' ? 8 : 10;
554 * Compute the cutoff value between legal numbers and illegal
555 * numbers. That is the largest legal value, divided by the
556 * base. An input number that is greater than this value, if
557 * followed by a legal input character, is too big. One that
558 * is equal to this value may be valid or not; the limit
559 * between valid and invalid numbers is then based on the last
560 * digit. For instance, if the range for longs is
561 * [-2147483648..2147483647] and the input base is 10,
562 * cutoff will be set to 214748364 and cutlim to either
563 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
564 * a value > 214748364, or equal but the next digit is > 7 (or 8),
565 * the number is too big, and we will return a range error.
567 * Set any if any `digits' consumed; make it negative to indicate
570 cutoff
= neg
? -(unsigned long)LONG_MIN
: LONG_MAX
;
571 cutlim
= cutoff
% (unsigned long)base
;
572 cutoff
/= (unsigned long)base
;
573 for (acc
= 0, any
= 0;; c
= *s
++) {
574 if (ACE_OS::ace_isdigit(c
))
576 else if (ACE_OS::ace_isalpha(c
))
577 c
-= ACE_OS::ace_isupper(c
) ? 'A' - 10 : 'a' - 10;
582 if (any
< 0 || acc
> cutoff
|| acc
== cutoff
&& c
> cutlim
)
591 acc
= neg
? LONG_MIN
: LONG_MAX
;
596 *endptr
= any
? (char *)s
- 1 : (char *)nptr
;
599 #endif /* ACE_LACKS_STRTOL */
601 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSTOL)
603 ACE_OS::wcstol_emulation (const wchar_t *nptr
,
607 const wchar_t *s
= nptr
;
610 unsigned long cutoff
;
611 int neg
= 0, any
, cutlim
;
614 * Skip white space and pick up leading +/- sign if any.
615 * If base is 0, allow 0x for hex and 0 for octal, else
616 * assume decimal; if base is already 16, allow 0x.
620 } while (ACE_OS::ace_isspace(c
));
624 } else if (c
== L
'+')
626 if ((base
== 0 || base
== 16) &&
627 c
== '0' && (*s
== L
'x' || *s
== L
'X')) {
633 base
= c
== L
'0' ? 8 : 10;
636 * See strtol for comments as to the logic used.
638 cutoff
= neg
? -(unsigned long)LONG_MIN
: LONG_MAX
;
639 cutlim
= cutoff
% (unsigned long)base
;
640 cutoff
/= (unsigned long)base
;
641 for (acc
= 0, any
= 0;; c
= *s
++) {
642 if (ACE_OS::ace_isdigit(c
))
644 else if (ACE_OS::ace_isalpha(c
))
645 c
-= ACE_OS::ace_isupper(c
) ? L
'A' - 10 : L
'a' - 10;
650 if (any
< 0 || acc
> cutoff
|| acc
== cutoff
&& c
> cutlim
)
659 acc
= neg
? LONG_MIN
: LONG_MAX
;
664 *endptr
= any
? (wchar_t *)s
- 1 : (wchar_t *)nptr
;
667 #endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSTOL */
669 #if defined (ACE_LACKS_STRTOUL)
671 ACE_OS::strtoul_emulation (const char *nptr
,
675 const char *s
= nptr
;
678 unsigned long cutoff
;
679 int neg
= 0, any
, cutlim
;
682 * See strtol for comments as to the logic used.
686 while (ACE_OS::ace_isspace(c
));
694 if ((base
== 0 || base
== 16) &&
695 c
== '0' && (*s
== 'x' || *s
== 'X'))
702 base
= c
== '0' ? 8 : 10;
703 cutoff
= (unsigned long) ULONG_MAX
/ (unsigned long) base
;
704 cutlim
= (unsigned long) ULONG_MAX
% (unsigned long) base
;
706 for (acc
= 0, any
= 0;; c
= *s
++)
708 if (ACE_OS::ace_isdigit(c
))
710 else if (ACE_OS::ace_isalpha(c
))
711 c
-= ACE_OS::ace_isupper(c
) ? 'A' - 10 : 'a' - 10;
716 if (any
< 0 || acc
> cutoff
|| acc
== cutoff
&& c
> cutlim
)
733 *endptr
= any
? (char *) s
- 1 : (char *) nptr
;
736 #endif /* ACE_LACKS_STRTOUL */
739 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSTOUL)
741 ACE_OS::wcstoul_emulation (const wchar_t *nptr
,
745 const wchar_t *s
= nptr
;
748 unsigned long cutoff
;
749 int neg
= 0, any
, cutlim
;
752 * See strtol for comments as to the logic used.
756 while (ACE_OS::ace_isspace(c
));
764 if ((base
== 0 || base
== 16) &&
765 c
== L
'0' && (*s
== L
'x' || *s
== L
'X'))
772 base
= c
== L
'0' ? 8 : 10;
773 cutoff
= (unsigned long) ULONG_MAX
/ (unsigned long) base
;
774 cutlim
= (unsigned long) ULONG_MAX
% (unsigned long) base
;
776 for (acc
= 0, any
= 0;; c
= *s
++)
778 if (ACE_OS::ace_isdigit(c
))
780 else if (ACE_OS::ace_isalpha(c
))
781 c
-= ACE_OS::ace_isupper(c
) ? L
'A' - 10 : L
'a' - 10;
786 if (any
< 0 || acc
> cutoff
|| acc
== cutoff
&& c
> cutlim
)
803 *endptr
= any
? (wchar_t *) s
- 1 : (wchar_t *) nptr
;
806 #endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSTOUL */
808 #if defined (ACE_LACKS_STRTOLL)
810 ACE_OS::strtoll_emulation (const char *nptr
,
814 const char *s
= nptr
;
818 int neg
= 0, any
, cutlim
;
821 * Skip white space and pick up leading +/- sign if any.
822 * If base is 0, allow 0x for hex and 0 for octal, else
823 * assume decimal; if base is already 16, allow 0x.
827 } while (ACE_OS::ace_isspace(c
));
833 if ((base
== 0 || base
== 16) &&
834 c
== '0' && (*s
== 'x' || *s
== 'X')) {
840 base
= c
== '0' ? 8 : 10;
843 * See strtol for comments as to the logic used.
845 cutoff
= neg
? -(ACE_UINT64
)ACE_INT64_MIN
: ACE_INT64_MAX
;
846 cutlim
= cutoff
% (ACE_UINT64
)base
;
847 cutoff
/= (ACE_UINT64
)base
;
848 for (acc
= 0, any
= 0;; c
= *s
++) {
849 if (ACE_OS::ace_isdigit(c
))
851 else if (ACE_OS::ace_isalpha(c
))
852 c
-= ACE_OS::ace_isupper(c
) ? 'A' - 10 : 'a' - 10;
857 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
866 acc
= neg
? ACE_INT64_MIN
: ACE_INT64_MAX
;
871 *endptr
= any
? (char *)s
- 1 : (char *)nptr
;
874 #endif /* ACE_LACKS_STRTOLL */
876 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSTOLL)
878 ACE_OS::wcstoll_emulation (const wchar_t *nptr
,
882 const wchar_t *s
= nptr
;
886 int neg
= 0, any
, cutlim
;
889 * Skip white space and pick up leading +/- sign if any.
890 * If base is 0, allow 0x for hex and 0 for octal, else
891 * assume decimal; if base is already 16, allow 0x.
895 } while (ACE_OS::ace_isspace(c
));
899 } else if (c
== L
'+')
901 if ((base
== 0 || base
== 16) &&
902 c
== L
'0' && (*s
== L
'x' || *s
== L
'X')) {
908 base
= c
== L
'0' ? 8 : 10;
911 * See strtol for comments as to the logic used.
913 cutoff
= neg
? -(ACE_UINT64
)ACE_INT64_MIN
: ACE_INT64_MAX
;
914 cutlim
= cutoff
% (ACE_UINT64
)base
;
915 cutoff
/= (ACE_UINT64
)base
;
916 for (acc
= 0, any
= 0;; c
= *s
++) {
917 if (ACE_OS::ace_isdigit(c
))
919 else if (ACE_OS::ace_isalpha(c
))
920 c
-= ACE_OS::ace_isupper(c
) ? L
'A' - 10 : L
'a' - 10;
925 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
934 acc
= neg
? ACE_INT64_MIN
: ACE_INT64_MAX
;
939 *endptr
= any
? (wchar_t *)s
- 1 : (wchar_t *)nptr
;
942 #endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSTOLL */
945 #if defined (ACE_LACKS_STRTOULL)
947 ACE_OS::strtoull_emulation (const char *nptr
,
951 const char *s
= nptr
;
955 int neg
= 0, any
, cutlim
;
958 * See strtol for comments as to the logic used.
962 while (ACE_OS::ace_isspace(c
));
970 if ((base
== 0 || base
== 16) &&
971 c
== '0' && (*s
== 'x' || *s
== 'X'))
978 base
= c
== '0' ? 8 : 10;
980 cutoff
= (ACE_UINT64
) ACE_UINT64_MAX
/ (ACE_UINT64
) base
;
981 cutlim
= (ACE_UINT64
) ACE_UINT64_MAX
% (ACE_UINT64
) base
;
983 for (acc
= 0, any
= 0;; c
= *s
++)
985 if (ACE_OS::ace_isdigit(c
))
987 else if (ACE_OS::ace_isalpha(c
))
988 c
-= ACE_OS::ace_isupper(c
) ? 'A' - 10 : 'a' - 10;
993 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
1004 acc
= ACE_UINT64_MAX
;
1010 *endptr
= any
? (char *) s
- 1 : (char *) nptr
;
1013 #endif /* ACE_LACKS_STRTOULL */
1015 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSTOULL)
1017 ACE_OS::wcstoull_emulation (const wchar_t *nptr
,
1021 const wchar_t *s
= nptr
;
1025 int neg
= 0, any
, cutlim
;
1028 * See strtol for comments as to the logic used.
1032 while (ACE_OS::ace_isspace(c
));
1040 if ((base
== 0 || base
== 16) &&
1041 c
== L
'0' && (*s
== L
'x' || *s
== L
'X'))
1048 base
= c
== L
'0' ? 8 : 10;
1050 cutoff
= (ACE_UINT64
) ACE_UINT64_MAX
/ (ACE_UINT64
) base
;
1051 cutlim
= (ACE_UINT64
) ACE_UINT64_MAX
% (ACE_UINT64
) base
;
1053 for (acc
= 0, any
= 0;; c
= *s
++)
1055 if (ACE_OS::ace_isdigit(c
))
1057 else if (ACE_OS::ace_isalpha(c
))
1058 c
-= ACE_OS::ace_isupper(c
) ? L
'A' - 10 : L
'a' - 10;
1063 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
1074 acc
= ACE_UINT64_MAX
;
1080 *endptr
= any
? (wchar_t *) s
- 1 : (wchar_t *) nptr
;
1083 #endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSTOULL */
1085 #if defined (ACE_LACKS_MKSTEMP)
1087 ACE_OS::mkstemp_emulation (ACE_TCHAR
* s
)
1092 return ACE_INVALID_HANDLE
;
1095 // The "XXXXXX" template to be filled in.
1096 ACE_TCHAR
* const t
= ACE_OS::strstr (s
, ACE_TEXT ("XXXXXX"));
1101 return ACE_INVALID_HANDLE
;
1104 static unsigned int const NUM_RETRIES
= 50;
1105 static unsigned int const NUM_CHARS
= 6; // Do not change!
1107 // Use ACE_Time_Value::msec(ACE_UINT64&) as opposed to
1108 // ACE_Time_Value::msec() to avoid truncation.
1111 // Use a const ACE_Time_Value to resolve ambiguity between
1112 // ACE_Time_Value::msec (long) and ACE_Time_Value::msec(ACE_UINT64&) const.
1113 ACE_Time_Value
const now
= ACE_OS::gettimeofday();
1116 // Add the process and thread ids to ensure uniqueness.
1117 msec
+= ACE_OS::getpid();
1119 #ifndef ACE_THREAD_T_IS_A_STRUCT
1120 msec
+= (size_t) ACE_OS::thr_self();
1123 // ACE_thread_t may be a char* (returned by ACE_OS::thr_self()) so
1124 // we need to use a C-style cast as a catch-all in order to use a
1125 // static_cast<> to an integral type.
1126 unsigned int seed
= static_cast<unsigned int> (msec
);
1128 // We only care about UTF-8 / ASCII characters in generated
1129 // filenames. A UTF-16 or UTF-32 character could potentially cause
1130 // a very large space to be searched in the below do/while() loop,
1131 // greatly slowing down this mkstemp() implementation. It is more
1132 // practical to limit the search space to UTF-8 / ASCII characters
1133 // (i.e. 127 characters).
1135 // Note that we can't make this constant static since the compiler
1136 // may not inline the return value of ACE_Numeric_Limits::max(),
1137 // meaning multiple threads could potentially initialize this value
1139 float const MAX_VAL
=
1140 static_cast<float> (ACE_Numeric_Limits
<char>::max ());
1142 // Use high-order bits rather than low-order ones (e.g. rand() %
1143 // MAX_VAL). See Numerical Recipes in C: The Art of Scientific
1144 // Computing (William H. Press, Brian P. Flannery, Saul
1145 // A. Teukolsky, William T. Vetterling; New York: Cambridge
1146 // University Press, 1992 (2nd ed., p. 277).
1148 // e.g.: MAX_VAL * rand() / (RAND_MAX + 1.0)
1150 // Factor out the constant coefficient.
1151 float const coefficient
=
1152 static_cast<float> (MAX_VAL
/ (RAND_MAX
+ 1.0f
));
1154 // @@ These nested loops may be ineffecient. Improvements are
1156 for (unsigned int i
= 0; i
< NUM_RETRIES
; ++i
)
1158 for (unsigned int n
= 0; n
< NUM_CHARS
; ++n
)
1162 // This do/while() loop allows this alphanumeric character
1163 // selection to work for EBCDIC, as well.
1166 r
= static_cast<ACE_TCHAR
> (coefficient
* ACE_OS::rand_r (&seed
));
1168 while (!ACE_OS::ace_isalnum (r
));
1173 static int const perms
=
1174 #if defined (ACE_WIN32)
1175 0; /* Do not share while open. */
1177 0600; /* S_IRUSR | S_IWUSR */
1178 #endif /* ACE_WIN32 */
1180 // Create the file with the O_EXCL bit set to ensure that we're
1181 // not subject to a symbolic link attack.
1183 // Note that O_EXCL is subject to a race condition over NFS
1185 ACE_HANDLE
const handle
= ACE_OS::open (s
,
1186 O_RDWR
| O_CREAT
| O_EXCL
,
1189 if (handle
!= ACE_INVALID_HANDLE
)
1193 errno
= EEXIST
; // Couldn't create a unique temporary file.
1194 return ACE_INVALID_HANDLE
;
1196 #endif /* ACE_LACKS_MKSTEMP */
1198 #if !defined (ACE_HAS_GETPROGNAME) && !defined (ACE_HAS_SETPROGNAME)
1199 static const char *__progname
= "";
1200 #endif /* !ACE_HAS_GETPROGNAME && !ACE_HAS_SETPROGNAME */
1202 #if !defined (ACE_HAS_GETPROGNAME)
1204 ACE_OS::getprogname_emulation ()
1208 #endif /* !ACE_HAS_GETPROGNAME */
1210 #if !defined (ACE_HAS_SETPROGNAME)
1212 ACE_OS::setprogname_emulation (const char* progname
)
1214 const char *p
= ACE_OS::strrchr (progname
, '/');
1218 __progname
= progname
;
1220 #endif /* !ACE_HAS_SETPROGNAME */
1222 ACE_END_VERSIONED_NAMESPACE_DECL