OS_NS_stdlib.cpp

Go to the documentation of this file.
00001 // $Id: OS_NS_stdlib.cpp 80826 2008-03-04 14:51:23Z wotte $
00002 
00003 #include "ace/OS_NS_stdlib.h"
00004 
00005 ACE_RCSID (ace,
00006            OS_NS_stdlib,
00007            "$Id: OS_NS_stdlib.cpp 80826 2008-03-04 14:51:23Z wotte $")
00008 
00009 #include "ace/Default_Constants.h"
00010 
00011 #if !defined (ACE_HAS_INLINED_OSCALLS)
00012 # include "ace/OS_NS_stdlib.inl"
00013 #endif /* ACE_HAS_INLINED_OSCALLS */
00014 
00015 #include "ace/OS_Memory.h"
00016 
00017 #include "ace/OS_NS_unistd.h"
00018 
00019 #if defined (ACE_LACKS_MKTEMP) \
00020     || defined (ACE_LACKS_MKSTEMP) \
00021     || defined (ACE_LACKS_REALPATH)
00022 #  include "ace/OS_NS_stdio.h"
00023 #  include "ace/OS_NS_sys_stat.h"
00024 #endif /* ACE_LACKS_MKTEMP || ACE_LACKS_MKSTEMP || ACE_LACKS_REALPATH */
00025 
00026 #if defined (ACE_LACKS_MKSTEMP)
00027 # include "ace/OS_NS_fcntl.h"
00028 # include "ace/OS_NS_ctype.h"
00029 # include "ace/OS_NS_sys_time.h"
00030 # include "ace/OS_NS_Thread.h"
00031 # include "ace/Numeric_Limits.h"
00032 #endif  /* ACE_LACKS_MKSTEMP */
00033 
00034 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00035 
00036 ACE_EXIT_HOOK ACE_OS::exit_hook_ = 0;
00037 
00038 void *
00039 ACE_OS::calloc (size_t elements, size_t sizeof_elements)
00040 {
00041 #if !defined (ACE_HAS_WINCE)
00042   return ACE_CALLOC_FUNC (elements, sizeof_elements);
00043 #else
00044   // @@ This will probably not work since it doesn't consider
00045   // alignment properly.
00046   return ACE_MALLOC_FUNC (elements * sizeof_elements);
00047 #endif /* ACE_HAS_WINCE */
00048 }
00049 
00050 void
00051 ACE_OS::exit (int status)
00052 {
00053   ACE_OS_TRACE ("ACE_OS::exit");
00054 
00055 #if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_HAS_WINCE) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
00056   // Shut down the ACE_Object_Manager, if it had registered its exit_hook.
00057   // With ACE_HAS_NONSTATIC_OBJECT_MANAGER, the ACE_Object_Manager is
00058   // instantiated on the main's stack.  ::exit () doesn't destroy it.
00059   if (exit_hook_)
00060     (*exit_hook_) ();
00061 #endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */
00062 
00063 #if !defined (ACE_HAS_WINCE)
00064 # if defined (ACE_WIN32)
00065   ::ExitProcess ((UINT) status);
00066 # else
00067   ::exit (status);
00068 # endif /* ACE_WIN32 */
00069 #else
00070   // @@ This is not exactly the same as ExitProcess.  But this is the
00071   // closest one I can get.
00072   ::TerminateProcess (::GetCurrentProcess (), status);
00073 #endif /* ACE_HAS_WINCE */
00074 }
00075 
00076 void
00077 ACE_OS::free (void *ptr)
00078 {
00079   ACE_FREE_FUNC (ACE_MALLOC_T (ptr));
00080 }
00081 
00082 // You may be asking yourself, why are we doing this?  Well, in winbase.h,
00083 // MS didn't follow their normal Api_FunctionA and Api_FunctionW style,
00084 // so we have to #undef their define to get access to the unicode version.
00085 // And because we don't want to #undef this for the users code, we keep
00086 // this method in the .cpp file.
00087 #if defined (ACE_WIN32) && defined (UNICODE) && !defined (ACE_USES_TCHAR)
00088 #undef GetEnvironmentStrings
00089 #endif /* ACE_WIN32 && UNICODE !ACE_USES_TCHAR */
00090 
00091 ACE_TCHAR *
00092 ACE_OS::getenvstrings (void)
00093 {
00094 #if defined (ACE_LACKS_ENV)
00095   ACE_NOTSUP_RETURN (0);
00096 #elif defined (ACE_WIN32)
00097 # if defined (ACE_USES_WCHAR)
00098   return ::GetEnvironmentStringsW ();
00099 # else /* ACE_USES_WCHAR */
00100   return ::GetEnvironmentStrings ();
00101 # endif /* ACE_USES_WCHAR */
00102 #else /* ACE_WIN32 */
00103   ACE_NOTSUP_RETURN (0);
00104 #endif /* ACE_WIN32 */
00105 }
00106 
00107 // Return a dynamically allocated duplicate of <str>, substituting the
00108 // environment variables of form $VAR_NAME.  Note that the pointer is
00109 // allocated with <ACE_OS::malloc> and must be freed by
00110 // <ACE_OS::free>.
00111 
00112 ACE_TCHAR *
00113 ACE_OS::strenvdup (const ACE_TCHAR *str)
00114 {
00115 #if defined (ACE_HAS_WINCE)
00116   // WinCE doesn't have environment variables so we just skip it.
00117   return ACE_OS::strdup (str);
00118 #elif defined (ACE_LACKS_ENV)
00119   ACE_UNUSED_ARG (str);
00120   ACE_NOTSUP_RETURN (0);
00121 #else
00122   const ACE_TCHAR * start = 0;
00123   if ((start = ACE_OS::strchr (str, ACE_TEXT ('$'))) != 0)
00124     {
00125       ACE_TCHAR buf[ACE_DEFAULT_ARGV_BUFSIZ];
00126       size_t var_len = ACE_OS::strcspn (&start[1],
00127         ACE_TEXT ("$~!#%^&*()-+=\\|/?,.;:'\"`[]{} \t\n\r"));
00128       ACE_OS::strncpy (buf, &start[1], var_len);
00129       buf[var_len++] = ACE_TEXT ('\0');
00130 #  if defined (ACE_WIN32)
00131       // Always use the ACE_TCHAR for Windows.
00132       ACE_TCHAR *temp = ACE_OS::getenv (buf);
00133 #  else
00134       // Use char * for environment on non-Windows.
00135       char *temp = ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (buf));
00136 #  endif /* ACE_WIN32 */
00137       size_t buf_len = ACE_OS::strlen (str) + 1;
00138       if (temp != 0)
00139         buf_len += ACE_OS::strlen (temp) - var_len;
00140       ACE_TCHAR * buf_p = buf;
00141       if (buf_len > ACE_DEFAULT_ARGV_BUFSIZ)
00142         {
00143           buf_p =
00144             (ACE_TCHAR *) ACE_OS::malloc (buf_len * sizeof (ACE_TCHAR));
00145           if (buf_p == 0)
00146             {
00147               errno = ENOMEM;
00148               return 0;
00149             }
00150         }
00151       ACE_TCHAR * p = buf_p;
00152       size_t len = start - str;
00153       ACE_OS::strncpy (p, str, len);
00154       p += len;
00155       if (temp != 0)
00156         {
00157 #  if defined (ACE_WIN32)
00158           p = ACE_OS::strecpy (p, temp) - 1;
00159 #  else
00160           p = ACE_OS::strecpy (p, ACE_TEXT_CHAR_TO_TCHAR (temp)) - 1;
00161 #  endif /* ACE_WIN32 */
00162         }
00163       else
00164         {
00165           ACE_OS::strncpy (p, start, var_len);
00166           p += var_len;
00167           *p = ACE_TEXT ('\0');
00168         }
00169       ACE_OS::strcpy (p, &start[var_len]);
00170       return (buf_p == buf) ? ACE_OS::strdup (buf) : buf_p;
00171     }
00172   else
00173     return ACE_OS::strdup (str);
00174 #endif /* ACE_HAS_WINCE */
00175 }
00176 
00177 #if !defined (ACE_HAS_ITOA)
00178 char *
00179 ACE_OS::itoa_emulation (int value, char *string, int radix)
00180 {
00181   char *e = string;
00182   char *b = string;
00183 
00184   // Short circuit if 0
00185 
00186   if (value == 0)
00187     {
00188       string[0] = '0';
00189       string[1] = 0;
00190       return string;
00191     }
00192 
00193   // If negative and base 10, print a - and then do the
00194   // number.
00195 
00196   if (value < 0 && radix == 10)
00197     {
00198       string[0] = '-';
00199       ++b;
00200       ++e; // Don't overwrite the negative sign.
00201       value = -value; // Drop negative sign so character selection is correct.
00202     }
00203 
00204   // Convert to base <radix>, but in reverse order
00205 
00206   while (value != 0)
00207     {
00208       int mod = value % radix;
00209       value = value / radix;
00210 
00211       *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10;
00212     }
00213 
00214   *e-- = 0;
00215 
00216   // Now reverse the string to get the correct result
00217 
00218   while (e > b)
00219     {
00220       char temp = *e;
00221       *e = *b;
00222       *b = temp;
00223       ++b;
00224       --e;
00225     }
00226 
00227   return string;
00228 }
00229 #endif /* !ACE_HAS_ITOA */
00230 
00231 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_ITOW)
00232 wchar_t *
00233 ACE_OS::itow_emulation (int value, wchar_t *string, int radix)
00234 {
00235   wchar_t *e = string;
00236   wchar_t *b = string;
00237 
00238   // Short circuit if 0
00239 
00240   if (value == 0)
00241     {
00242       string[0] = '0';
00243       string[1] = 0;
00244       return string;
00245     }
00246 
00247   // If negative and base 10, print a - and then do the
00248   // number.
00249 
00250   if (value < 0 && radix == 10)
00251     {
00252       string[0] = '-';
00253       b++;
00254     }
00255 
00256   // Convert to base <radix>, but in reverse order
00257 
00258   while (value != 0)
00259     {
00260       int mod = value % radix;
00261       value = value / radix;
00262 
00263       *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10;
00264     }
00265 
00266   *e-- = 0;
00267 
00268   // Now reverse the string to get the correct result
00269 
00270   while (e > b)
00271   {
00272     wchar_t temp = *e;
00273     *e = *b;
00274     *b = temp;
00275     ++b;
00276     --e;
00277   }
00278 
00279   return string;
00280 }
00281 #endif /* ACE_HAS_WCHAR && ACE_LACKS_ITOW */
00282 
00283 void *
00284 ACE_OS::malloc (size_t nbytes)
00285 {
00286   return ACE_MALLOC_FUNC (nbytes);
00287 }
00288 
00289 #if defined (ACE_LACKS_MKTEMP)
00290 ACE_TCHAR *
00291 ACE_OS::mktemp (ACE_TCHAR *s)
00292 {
00293   ACE_OS_TRACE ("ACE_OS::mktemp");
00294   if (s == 0)
00295     // check for null template string failed!
00296     return 0;
00297   else
00298     {
00299       ACE_TCHAR *xxxxxx = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX"));
00300 
00301       if (xxxxxx == 0)
00302         // the template string doesn't contain "XXXXXX"!
00303         return s;
00304       else
00305         {
00306           ACE_TCHAR unique_letter = ACE_TEXT ('a');
00307           ACE_stat sb;
00308 
00309           // Find an unused filename for this process.  It is assumed
00310           // that the user will open the file immediately after
00311           // getting this filename back (so, yes, there is a race
00312           // condition if multiple threads in a process use the same
00313           // template).  This appears to match the behavior of the
00314           // SunOS 5.5 mktemp().
00315           ACE_OS::sprintf (xxxxxx,
00316                            ACE_TEXT ("%05d%c"),
00317                            ACE_OS::getpid (),
00318                            unique_letter);
00319           while (ACE_OS::stat (s, &sb) >= 0)
00320             {
00321               if (++unique_letter <= ACE_TEXT ('z'))
00322                 ACE_OS::sprintf (xxxxxx,
00323                                  ACE_TEXT ("%05d%c"),
00324                                  ACE_OS::getpid (),
00325                                  unique_letter);
00326               else
00327                 {
00328                   // maximum of 26 unique files per template, per process
00329                   ACE_OS::sprintf (xxxxxx, ACE_TEXT ("%s"), ACE_TEXT (""));
00330                   return s;
00331                 }
00332             }
00333         }
00334       return s;
00335     }
00336 }
00337 #endif /* ACE_LACKS_MKTEMP */
00338 
00339 void *
00340 ACE_OS::realloc (void *ptr, size_t nbytes)
00341 {
00342   return ACE_REALLOC_FUNC (ACE_MALLOC_T (ptr), nbytes);
00343 }
00344 
00345 #if defined (ACE_LACKS_REALPATH) && !defined (ACE_HAS_WINCE)
00346 char *
00347 ACE_OS::realpath (const char *file_name,
00348                   char *resolved_name)
00349 {
00350   ACE_OS_TRACE ("ACE_OS::realpath");
00351 
00352   if (file_name == 0)
00353     {
00354       // Single Unix Specification V3:
00355       //   Return an error if parameter is a null pointer.
00356       errno = EINVAL;
00357       return 0;
00358     }
00359 
00360   if (*file_name == '\0')
00361     {
00362       // Single Unix Specification V3:
00363       //   Return an error if the file_name argument points
00364       //   to an empty string.
00365       errno = ENOENT;
00366       return 0;
00367     }
00368 
00369   char* rpath;
00370 
00371   if (resolved_name == 0)
00372     {
00373       // Single Unix Specification V3:
00374       //   Return an error if parameter is a null pointer.
00375       //
00376       // To match glibc realpath() and Win32 _fullpath() behavior,
00377       // allocate room for the return value if resolved_name is
00378       // a null pointer.
00379       rpath = static_cast<char*>(ACE_OS::malloc (PATH_MAX));
00380       if (rpath == 0)
00381         {
00382           errno = ENOMEM;
00383           return 0;
00384         }
00385     }
00386   else
00387     {
00388       rpath = resolved_name;
00389     }
00390 
00391   char* dest;
00392 
00393   if (*file_name != '/')
00394     {
00395       // file_name is relative path so CWD needs to be added
00396       if (ACE_OS::getcwd (rpath, PATH_MAX) == 0)
00397         {
00398           if (resolved_name == 0)
00399             ACE_OS::free (rpath);
00400           return 0;
00401         }
00402       dest = ACE_OS::strchr (rpath, '\0');
00403     }
00404   else
00405     {
00406       dest = rpath;
00407     }
00408 
00409 #if !defined (ACE_LACKS_SYMLINKS)
00410   char expand_buf[PATH_MAX]; // Extra buffer needed to expand symbolic links
00411   int nlinks = 0;
00412 #endif
00413 
00414   while (*file_name)
00415     {
00416       *dest++ = '/';
00417 
00418       // Skip multiple separators
00419       while (*file_name == '/')
00420         ++file_name;
00421 
00422       char* start = dest;
00423 
00424       // Process one path component
00425       while (*file_name && *file_name != '/')
00426         {
00427           *dest++ = *file_name++;
00428           if (dest - rpath > PATH_MAX)
00429             {
00430               errno = ENAMETOOLONG;
00431               if (resolved_name == 0)
00432                 ACE_OS::free (rpath);
00433               return 0;
00434             }
00435         }
00436 
00437       if (start == dest) // Are we done?
00438         {
00439           if (dest - rpath > 1)
00440             --dest; // Remove trailing separator if not at root
00441           break;
00442         }
00443       else if (dest - start == 1 && *start == '.')
00444         {
00445           dest -= 2; // Remove "./"
00446         }
00447       else if (dest - start == 2 && *start == '.' && *(start +1) == '.')
00448         {
00449           dest -= 3; // Remove "../"
00450           if (dest > rpath) // Remove the last path component if not at root
00451             while (*--dest != '/')
00452               ;
00453         }
00454 #  if !defined (ACE_LACKS_SYMLINKS)
00455       else
00456         {
00457           ACE_stat st;
00458 
00459           *dest = '\0';
00460           if (ACE_OS::lstat(rpath, &st) < 0)
00461             {
00462               if (resolved_name == 0)
00463               ACE_OS::free (rpath);
00464                 return 0;
00465             }
00466 
00467           // Check if current path is a link
00468           if (S_ISLNK (st.st_mode))
00469             {
00470               if (++nlinks > MAXSYMLINKS)
00471                 {
00472                   errno = ELOOP;
00473                   if (resolved_name == 0)
00474                     ACE_OS::free (rpath);
00475                   return 0;
00476                 }
00477 
00478               char link_buf[PATH_MAX];
00479 
00480               ssize_t link_len = ACE_OS::readlink (rpath, link_buf, PATH_MAX);
00481               int tail_len = ACE_OS::strlen (file_name) + 1;
00482 
00483               // Check if there is room to expand link?
00484               if (link_len + tail_len > PATH_MAX)
00485                 {
00486                   errno = ENAMETOOLONG;
00487                   if (resolved_name == 0)
00488                     ACE_OS::free (rpath);
00489                   return 0;
00490                 }
00491 
00492               // Move tail and prefix it with expanded link
00493               ACE_OS::memmove (expand_buf + link_len, file_name, tail_len);
00494               ACE_OS::memcpy (expand_buf, link_buf, link_len);
00495 
00496               if (*link_buf == '/') // Absolute link?
00497                 {
00498                   dest = rpath;
00499                 }
00500               else // Relative link, remove expanded link component
00501                 {
00502                   --dest;
00503                   while (*--dest != '/')
00504                     ;
00505                 }
00506               file_name = expand_buf; // Source path is now in expand_buf
00507             }
00508         }
00509 #  endif /* ACE_LACKS_SYMLINKS */
00510     }
00511 
00512   *dest = '\0';
00513 
00514   return rpath;
00515 }
00516 #endif /* ACE_LACKS_REALPATH && !ACE_HAS_WINCE */
00517 
00518 #if defined (ACE_LACKS_STRTOL)
00519 long
00520 ACE_OS::strtol_emulation (const char *nptr, char **endptr, int base)
00521 {
00522   register const char *s = nptr;
00523   register unsigned long acc;
00524   register int c;
00525   register unsigned long cutoff;
00526   register int neg = 0, any, cutlim;
00527 
00528   /*
00529    * Skip white space and pick up leading +/- sign if any.
00530    * If base is 0, allow 0x for hex and 0 for octal, else
00531    * assume decimal; if base is already 16, allow 0x.
00532    */
00533   do {
00534     c = *s++;
00535   } while (isspace(c));
00536   if (c == '-') {
00537     neg = 1;
00538     c = *s++;
00539   } else if (c == '+')
00540     c = *s++;
00541   if ((base == 0 || base == 16) &&
00542     c == '0' && (*s == 'x' || *s == 'X')) {
00543     c = s[1];
00544     s += 2;
00545     base = 16;
00546   }
00547   if (base == 0)
00548     base = c == '0' ? 8 : 10;
00549 
00550   /*
00551    * Compute the cutoff value between legal numbers and illegal
00552    * numbers.  That is the largest legal value, divided by the
00553    * base.  An input number that is greater than this value, if
00554    * followed by a legal input character, is too big.  One that
00555    * is equal to this value may be valid or not; the limit
00556    * between valid and invalid numbers is then based on the last
00557    * digit.  For instance, if the range for longs is
00558    * [-2147483648..2147483647] and the input base is 10,
00559    * cutoff will be set to 214748364 and cutlim to either
00560    * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
00561    * a value > 214748364, or equal but the next digit is > 7 (or 8),
00562    * the number is too big, and we will return a range error.
00563    *
00564    * Set any if any `digits' consumed; make it negative to indicate
00565    * overflow.
00566    */
00567   cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
00568   cutlim = cutoff % (unsigned long)base;
00569   cutoff /= (unsigned long)base;
00570   for (acc = 0, any = 0;; c = *s++) {
00571     if (isdigit(c))
00572       c -= '0';
00573     else if (isalpha(c))
00574       c -= isupper(c) ? 'A' - 10 : 'a' - 10;
00575     else
00576       break;
00577     if (c >= base)
00578       break;
00579     if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
00580       any = -1;
00581     else {
00582       any = 1;
00583       acc *= base;
00584       acc += c;
00585     }
00586   }
00587   if (any < 0) {
00588     acc = neg ? LONG_MIN : LONG_MAX;
00589     errno = ERANGE;
00590   } else if (neg)
00591     acc = -acc;
00592   if (endptr != 0)
00593     *endptr = any ? (char *)s - 1 : (char *)nptr;
00594   return (acc);
00595 }
00596 #endif /* ACE_LACKS_STRTOL */
00597 
00598 #if defined (ACE_LACKS_STRTOUL)
00599 unsigned long
00600 ACE_OS::strtoul_emulation (const char *nptr,
00601                            char **endptr,
00602                            register int base)
00603 {
00604   register const char *s = nptr;
00605   register unsigned long acc;
00606   register int c;
00607   register unsigned long cutoff;
00608   register int neg = 0, any, cutlim;
00609 
00610   /*
00611    * See strtol for comments as to the logic used.
00612    */
00613   do
00614     c = *s++;
00615   while (isspace(c));
00616   if (c == '-')
00617     {
00618       neg = 1;
00619       c = *s++;
00620     }
00621   else if (c == '+')
00622     c = *s++;
00623   if ((base == 0 || base == 16) &&
00624       c == '0' && (*s == 'x' || *s == 'X'))
00625     {
00626       c = s[1];
00627       s += 2;
00628       base = 16;
00629     }
00630   if (base == 0)
00631     base = c == '0' ? 8 : 10;
00632   cutoff = (unsigned long) ULONG_MAX / (unsigned long) base;
00633   cutlim = (unsigned long) ULONG_MAX % (unsigned long) base;
00634 
00635   for (acc = 0, any = 0;; c = *s++)
00636     {
00637       if (isdigit(c))
00638         c -= '0';
00639       else if (isalpha(c))
00640         c -= isupper(c) ? 'A' - 10 : 'a' - 10;
00641       else
00642         break;
00643       if (c >= base)
00644         break;
00645       if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
00646         any = -1;
00647       else
00648         {
00649           any = 1;
00650           acc *= base;
00651           acc += c;
00652         }
00653     }
00654   if (any < 0)
00655     {
00656       acc = ULONG_MAX;
00657       errno = ERANGE;
00658     } else if (neg)
00659     acc = -acc;
00660   if (endptr != 0)
00661     *endptr = any ? (char *) s - 1 : (char *) nptr;
00662   return (acc);
00663 }
00664 #endif /* ACE_LACKS_STRTOUL */
00665 
00666 
00667 #if defined (ACE_LACKS_MKSTEMP)
00668 ACE_HANDLE
00669 ACE_OS::mkstemp_emulation (ACE_TCHAR * s)
00670 {
00671   if (s == 0)
00672     {
00673       errno = EINVAL;
00674       return ACE_INVALID_HANDLE;
00675     }
00676 
00677   // The "XXXXXX" template to be filled in.
00678   ACE_TCHAR * const t  = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX"));
00679 
00680   if (t == 0)
00681     {
00682       errno = EINVAL;
00683       return ACE_INVALID_HANDLE;
00684     }
00685 
00686   static unsigned int const NUM_RETRIES = 50;
00687   static unsigned int const NUM_CHARS   = 6;  // Do not change!
00688 
00689   // Use ACE_Time_Value::msec(ACE_UINT64&) as opposed to
00690   // ACE_Time_Value::msec(void) to avoid truncation.
00691   ACE_UINT64 msec;
00692 
00693   // Use a const ACE_Time_Value to resolve ambiguity between
00694   // ACE_Time_Value::msec (long) and ACE_Time_Value::msec(ACE_UINT64&) const.
00695   ACE_Time_Value const now = ACE_OS::gettimeofday();
00696   now.msec (msec);
00697 
00698   // Add the process and thread ids to ensure uniqueness.
00699   msec += ACE_OS::getpid();
00700   msec += (size_t) ACE_OS::thr_self();
00701 
00702   // ACE_thread_t may be a char* (returned by ACE_OS::thr_self()) so
00703   // we need to use a C-style cast as a catch-all in order to use a
00704   // static_cast<> to an integral type.
00705   ACE_RANDR_TYPE seed = static_cast<ACE_RANDR_TYPE> (msec);
00706 
00707   // We only care about UTF-8 / ASCII characters in generated
00708   // filenames.  A UTF-16 or UTF-32 character could potentially cause
00709   // a very large space to be searched in the below do/while() loop,
00710   // greatly slowing down this mkstemp() implementation.  It is more
00711   // practical to limit the search space to UTF-8 / ASCII characters
00712   // (i.e. 127 characters).
00713   //
00714   // Note that we can't make this constant static since the compiler
00715   // may not inline the return value of ACE_Numeric_Limits::max(),
00716   // meaning multiple threads could potentially initialize this value
00717   // in parallel.
00718   float const MAX_VAL =
00719     static_cast<float> (ACE_Numeric_Limits<char>::max ());
00720 
00721   // Use high-order bits rather than low-order ones (e.g. rand() %
00722   // MAX_VAL).  See Numerical Recipes in C: The Art of Scientific
00723   // Computing (William  H. Press, Brian P. Flannery, Saul
00724   // A. Teukolsky, William T. Vetterling; New York: Cambridge
00725   // University Press, 1992 (2nd ed., p. 277).
00726   //
00727   // e.g.: MAX_VAL * rand() / (RAND_MAX + 1.0)
00728 
00729   // Factor out the constant coefficient.
00730   float const coefficient =
00731     static_cast<float> (MAX_VAL / (RAND_MAX + 1.0f));
00732 
00733   // @@ These nested loops may be ineffecient.  Improvements are
00734   //    welcome.
00735   for (unsigned int i = 0; i < NUM_RETRIES; ++i)
00736     {
00737       for (unsigned int n = 0; n < NUM_CHARS; ++n)
00738         {
00739           ACE_TCHAR r;
00740 
00741           // This do/while() loop allows this alphanumeric character
00742           // selection to work for EBCDIC, as well.
00743           do
00744             {
00745               r = static_cast<ACE_TCHAR> (coefficient * ACE_OS::rand_r (seed));
00746             }
00747           while (!ACE_OS::ace_isalnum (r));
00748 
00749           t[n] = r;
00750         }
00751 
00752       static int const perms =
00753 #if defined (ACE_WIN32)
00754         0;      /* Do not share while open. */
00755 #else
00756         0600;   /* S_IRUSR | S_IWUSR */
00757 #endif  /* ACE_WIN32 */
00758 
00759       // Create the file with the O_EXCL bit set to ensure that we're
00760       // not subject to a symbolic link attack.
00761       //
00762       // Note that O_EXCL is subject to a race condition over NFS
00763       // filesystems.
00764       ACE_HANDLE const handle = ACE_OS::open (s,
00765                                               O_RDWR | O_CREAT | O_EXCL,
00766                                               perms);
00767 
00768       if (handle != ACE_INVALID_HANDLE)
00769         return handle;
00770     }
00771 
00772   errno = EEXIST;  // Couldn't create a unique temporary file.
00773   return ACE_INVALID_HANDLE;
00774 }
00775 #endif /* ACE_LACKS_MKSTEMP */
00776 
00777 #if !defined (ACE_HAS_GETPROGNAME) && !defined (ACE_HAS_SETPROGNAME)
00778 static const char *__progname = "";
00779 #endif /* !ACE_HAS_GETPROGNAME && !ACE_HAS_SETPROGNAME */
00780 
00781 #if !defined (ACE_HAS_GETPROGNAME)
00782 const char*
00783 ACE_OS::getprogname_emulation ()
00784 {
00785     return __progname;
00786 }
00787 #endif /* !ACE_HAS_GETPROGNAME */
00788 
00789 #if !defined (ACE_HAS_SETPROGNAME)
00790 void
00791 ACE_OS::setprogname_emulation (const char* progname) 
00792 {
00793   const char *p = ACE_OS::strrchr (progname, '/');
00794   if (p != 0)
00795     __progname = p + 1;
00796   else
00797     __progname = progname;
00798 }
00799 #endif /* !ACE_HAS_SETPROGNAME */
00800 
00801 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:18:41 2010 for ACE by  doxygen 1.4.7