OS_NS_unistd.cpp

Go to the documentation of this file.
00001 // $Id: OS_NS_unistd.cpp 81284 2008-04-09 03:08:22Z iliyan $
00002 
00003 #include "ace/OS_NS_unistd.h"
00004 
00005 ACE_RCSID (ace, OS_NS_unistd, "$Id: OS_NS_unistd.cpp 81284 2008-04-09 03:08:22Z iliyan $")
00006 
00007 #if !defined (ACE_HAS_INLINED_OSCALLS)
00008 # include "ace/OS_NS_unistd.inl"
00009 #endif /* ACE_HAS_INLINED_OSCALLS */
00010 
00011 #include "ace/Base_Thread_Adapter.h"
00012 #include "ace/OS_NS_stdlib.h"
00013 #include "ace/OS_NS_ctype.h"
00014 #include "ace/Default_Constants.h"
00015 #include "ace/OS_Memory.h"
00016 #include "ace/OS_NS_Thread.h"
00017 #include "ace/Object_Manager_Base.h"
00018 #include "ace/Auto_Ptr.h"
00019 #include "ace/os_include/sys/os_pstat.h"
00020 #include "ace/os_include/sys/os_sysctl.h"
00021 
00022 #if defined (ACE_NEEDS_FTRUNCATE)
00023 extern "C" int
00024 ftruncate (ACE_HANDLE handle, long len)
00025 {
00026   struct flock fl;
00027   fl.l_whence = 0;
00028   fl.l_len = 0;
00029   fl.l_start = len;
00030   fl.l_type = F_WRLCK;
00031 
00032   return ACE_OS::fcntl (handle, F_FREESP, reinterpret_cast <long> (&fl));
00033 }
00034 #endif /* ACE_NEEDS_FTRUNCATE */
00035 
00036 /*****************************************************************************/
00037 
00038 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00039 
00040 int
00041 ACE_OS::argv_to_string (ACE_TCHAR **argv,
00042                         ACE_TCHAR *&buf,
00043                         bool substitute_env_args,
00044                         bool quote_args)
00045 {
00046   if (argv == 0 || argv[0] == 0)
00047     return 0;
00048 
00049   int argc;
00050   for (argc = 0; argv[argc] != 0; ++argc)
00051     continue;
00052 
00053   return argv_to_string (argc,
00054                          argv,
00055                          buf,
00056                          substitute_env_args,
00057                          quote_args);
00058 }
00059 
00060 int
00061 ACE_OS::argv_to_string (int argc,
00062                         ACE_TCHAR **argv,
00063                         ACE_TCHAR *&buf,
00064                         bool substitute_env_args,
00065                         bool quote_args)
00066 {
00067   if (argc <= 0 || argv == 0 || argv[0] == 0)
00068     return 0;
00069 
00070   size_t buf_len = 0;
00071 
00072   // Determine the length of the buffer.
00073 
00074   ACE_TCHAR **argv_p = argv;
00075 
00076   for (int i = 0; i < argc; ++i)
00077     {
00078 #if !defined (ACE_LACKS_ENV)
00079       // Account for environment variables.
00080       if (substitute_env_args
00081           && ACE_OS::strchr (argv[i], ACE_TEXT ('$')) != 0)
00082         {
00083           if (argv_p == argv)
00084             {
00085               argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
00086               if (argv_p == 0)
00087                 {
00088                   errno = ENOMEM;
00089                   return 0;
00090                 }
00091               ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
00092             }
00093           argv_p[i] = ACE_OS::strenvdup (argv[i]);
00094           if (argv_p[i] == 0)
00095             {
00096               ACE_OS::free (argv_p);
00097               errno = ENOMEM;
00098               return 0;
00099             }
00100         }
00101 #endif /* ACE_LACKS_ENV */
00102       // If must quote, we only do it if the arg contains spaces, or
00103       // is empty. Perhaps a check for other c | ord(c) <= 32 is in
00104       // order?
00105       if (quote_args
00106           && (ACE_OS::strchr (argv_p[i], ACE_TEXT (' ')) != 0
00107               || ACE_OS::strchr (argv_p[i], ACE_TEXT ('\t')) != 0
00108               || ACE_OS::strchr (argv_p[i], ACE_TEXT ('\n')) != 0
00109               || *argv_p[i] == 0))
00110         {
00111           if (argv_p == argv)
00112             {
00113               argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
00114               if (argv_p == 0)
00115                 {
00116                   errno = ENOMEM;
00117                   return 0;
00118                 }
00119               ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
00120             }
00121           int quotes = 0;
00122           ACE_TCHAR *temp = argv_p[i];
00123           if (ACE_OS::strchr (temp, ACE_TEXT ('"')) != 0)
00124             {
00125               for (int j = 0; temp[j] != 0; ++j)
00126                 if (temp[j] == ACE_TEXT ('"'))
00127                   ++quotes;
00128             }
00129           argv_p[i] =
00130             (ACE_TCHAR *) ACE_OS::malloc (ACE_OS::strlen (temp) * sizeof (ACE_TCHAR) + quotes + 3);
00131           if (argv_p[i] == 0)
00132             {
00133               ACE_OS::free (argv_p);
00134               errno = ENOMEM;
00135               return 0;
00136             }
00137           ACE_TCHAR *end = argv_p[i];
00138 
00139           *end++ = ACE_TEXT ('"');
00140 
00141           if (quotes > 0)
00142             {
00143               for (ACE_TCHAR *p = temp;
00144                    *p != 0;
00145                    *end++ = *p++)
00146                 if (*p == ACE_TEXT ('"'))
00147                   *end++ = ACE_TEXT ('\\');
00148 
00149               *end++ = ACE_TEXT ('\0');
00150             }
00151           else
00152             end = ACE_OS::strecpy (end, temp);
00153 
00154           end[-1] = ACE_TEXT ('"');
00155 
00156           *end = ACE_TEXT ('\0');
00157           if (temp != argv[i])
00158             ACE_OS::free (temp);
00159         }
00160       buf_len += ACE_OS::strlen (argv_p[i]);
00161 
00162       // Add one for the extra space between each string.
00163       buf_len++;
00164     }
00165 
00166   // Step through all argv params and copy each one into buf; separate
00167   // each param with white space.
00168 
00169   ACE_NEW_RETURN (buf,
00170                   ACE_TCHAR[buf_len + 1],
00171                   0);
00172 
00173   // Initial null charater to make it a null string.
00174   buf[0] = ACE_TEXT ('\0');
00175   ACE_TCHAR *end = buf;
00176 
00177   for (int i = 0; i < argc; ++i)
00178     {
00179       end = ACE_OS::strecpy (end, argv_p[i]);
00180       if (argv_p[i] != argv[i])
00181         ACE_OS::free (argv_p[i]);
00182 
00183       // Replace the null char that strecpy put there with white
00184       // space.
00185       end[-1] = ACE_TEXT (' ');
00186     }
00187   // Null terminate the string.
00188   *end = ACE_TEXT ('\0');
00189 
00190   if (argv_p != argv)
00191     ACE_OS::free (argv_p);
00192 
00193   // The number of arguments.
00194   return argc;
00195 }
00196 
00197 int
00198 ACE_OS::execl (const char * /* path */, const char * /* arg0 */, ...)
00199 {
00200   ACE_OS_TRACE ("ACE_OS::execl");
00201   ACE_NOTSUP_RETURN (-1);
00202   // Need to write this code.
00203   // ACE_OSCALL_RETURN (::execv (path, argv), int, -1);
00204 }
00205 
00206 int
00207 ACE_OS::execle (const char * /* path */, const char * /* arg0 */, ...)
00208 {
00209   ACE_OS_TRACE ("ACE_OS::execle");
00210   ACE_NOTSUP_RETURN (-1);
00211   // Need to write this code.
00212   //  ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1);
00213 }
00214 
00215 int
00216 ACE_OS::execlp (const char * /* file */, const char * /* arg0 */, ...)
00217 {
00218   ACE_OS_TRACE ("ACE_OS::execlp");
00219   ACE_NOTSUP_RETURN (-1);
00220   // Need to write this code.
00221   //  ACE_OSCALL_RETURN (::execvp (file, argv), int, -1);
00222 }
00223 
00224 pid_t
00225 ACE_OS::fork (const ACE_TCHAR *program_name)
00226 {
00227   ACE_OS_TRACE ("ACE_OS::fork");
00228 # if defined (ACE_LACKS_FORK)
00229   ACE_UNUSED_ARG (program_name);
00230   ACE_NOTSUP_RETURN (pid_t (-1));
00231 # else
00232   pid_t const pid =
00233 # if defined (ACE_HAS_STHREADS)
00234     ::fork1 ();
00235 #else
00236     ::fork ();
00237 #endif /* ACE_HAS_STHREADS */
00238 
00239 #if !defined (ACE_HAS_MINIMAL_ACE_OS) && !defined (ACE_HAS_THREADS)
00240 
00241   // ACE_Base_Thread_Adapter::sync_log_msg() is used to update the
00242   // program name and process id in ACE's log framework.  However, we
00243   // can't invoke it from (the child process of) threaded programs
00244   // because it calls async signal unsafe functions, which will result
00245   // in undefined behavior (only async signal safe functions can be
00246   // called after fork() until an exec()).
00247   //
00248   // This is no great loss.  Using the ACE log framework in the child
00249   // process will undoubtedly call async signal unsafe functions too.
00250   // So it doesn't really matter that the program name and process id
00251   // will not be updated.
00252 
00253   if (pid == 0)
00254     ACE_Base_Thread_Adapter::sync_log_msg (program_name);
00255 
00256 #else
00257 
00258   ACE_UNUSED_ARG (program_name);
00259 
00260 #endif /* ! ACE_HAS_MINIMAL_ACE_OS && !ACE_HAS_THREADS */
00261 
00262   return pid;
00263 # endif /* ACE_WIN32 */
00264 }
00265 
00266 // Create a contiguous command-line argument buffer with each arg
00267 // separated by spaces.
00268 
00269 pid_t
00270 ACE_OS::fork_exec (ACE_TCHAR *argv[])
00271 {
00272 # if defined (ACE_WIN32)
00273 
00274   ACE_TCHAR *buf = 0;
00275   ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_ptr (buf);
00276   if (ACE_OS::argv_to_string (argv, buf) != -1)
00277     {
00278       PROCESS_INFORMATION process_info;
00279 #   if !defined (ACE_HAS_WINCE)
00280       ACE_TEXT_STARTUPINFO startup_info;
00281       ACE_OS::memset ((void *) &startup_info,
00282                       0,
00283                       sizeof startup_info);
00284       startup_info.cb = sizeof startup_info;
00285 
00286       if (ACE_TEXT_CreateProcess (0,
00287                                   buf,
00288                                   0, // No process attributes.
00289                                   0,  // No thread attributes.
00290                                   TRUE, // Allow handle inheritance.
00291                                   0, // Don't create a new console window.
00292                                   0, // No environment.
00293                                   0, // No current directory.
00294                                   &startup_info,
00295                                   &process_info))
00296 #   else
00297       if (ACE_TEXT_CreateProcess (0,
00298                                   buf,
00299                                   0, // No process attributes.
00300                                   0,  // No thread attributes.
00301                                   FALSE, // Can's inherit handles on CE
00302                                   0, // Don't create a new console window.
00303                                   0, // No environment.
00304                                   0, // No current directory.
00305                                   0, // Can't use startup info on CE
00306                                   &process_info))
00307 #   endif /* ! ACE_HAS_WINCE */
00308         {
00309           // Free resources allocated in kernel.
00310           ACE_OS::close (process_info.hThread);
00311           ACE_OS::close (process_info.hProcess);
00312           // Return new process id.
00313           return process_info.dwProcessId;
00314         }
00315     }
00316 
00317   // CreateProcess failed.
00318   return -1;
00319 # else
00320       pid_t const result = ACE_OS::fork ();
00321 
00322 #   if defined (ACE_USES_WCHAR)
00323       // Wide-char builds need to convert the command-line args to
00324       // narrow char strings for execv ().
00325       char **cargv = 0;
00326       int arg_count;
00327 #   endif /* ACE_HAS_WCHAR */
00328 
00329       switch (result)
00330         {
00331         case -1:
00332           // Error.
00333           return -1;
00334         case 0:
00335           // Child process.
00336 #   if defined (ACE_USES_WCHAR)
00337           for (arg_count = 0; argv[arg_count] != 0; ++arg_count)
00338             ;
00339           ++arg_count;    // Need a 0-pointer end-of-array marker
00340           ACE_NEW_NORETURN (cargv, char*[arg_count]);
00341           if (cargv == 0)
00342             ACE_OS::exit (errno);
00343           --arg_count;    // Back to 0-indexed
00344           cargv[arg_count] = 0;
00345           while (--arg_count >= 0)
00346             cargv[arg_count] = ACE_Wide_To_Ascii::convert (argv[arg_count]);
00347           // Don't worry about freeing the cargv or the strings it points to.
00348           // Either the process will be replaced, or we'll exit.
00349           if (ACE_OS::execv (cargv[0], cargv) == -1)
00350             ACE_OS::exit (errno);
00351 #   else
00352           if (ACE_OS::execv (argv[0], argv) == -1)
00353             {
00354               // The OS layer should not print stuff out
00355               // ACE_ERROR ((LM_ERROR,
00356               //             "%p Exec failed\n"));
00357 
00358               // If the execv fails, this child needs to exit.
00359               ACE_OS::exit (errno);
00360             }
00361 #   endif /* ACE_HAS_WCHAR */
00362 
00363         default:
00364           // Server process.  The fork succeeded.
00365           return result;
00366         }
00367 # endif /* ACE_WIN32 */
00368 }
00369 
00370 long
00371 ACE_OS::num_processors (void)
00372 {
00373   ACE_OS_TRACE ("ACE_OS::num_processors");
00374 
00375 #if defined (ACE_HAS_PHARLAP)
00376   return 1;
00377 #elif defined (ACE_WIN32)
00378   SYSTEM_INFO sys_info;
00379   ::GetSystemInfo (&sys_info);
00380   return sys_info.dwNumberOfProcessors;
00381 #elif defined (_SC_NPROCESSORS_CONF)
00382   return ::sysconf (_SC_NPROCESSORS_CONF);
00383 #elif defined (ACE_HAS_SYSCTL)
00384   int num_processors;
00385   int mib[2] = { CTL_HW, HW_NCPU };
00386   size_t len = sizeof (num_processors);
00387   if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
00388     return num_processors;
00389   else
00390     return -1;
00391 #elif defined (__hpux)
00392   struct pst_dynamic psd;
00393   if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
00394     return psd.psd_max_proc_cnt;
00395   else
00396     return -1;
00397 #else
00398   ACE_NOTSUP_RETURN (-1);
00399 #endif
00400 }
00401 
00402 long
00403 ACE_OS::num_processors_online (void)
00404 {
00405   ACE_OS_TRACE ("ACE_OS::num_processors_online");
00406 
00407 #if defined (ACE_HAS_PHARLAP)
00408   return 1;
00409 #elif defined (ACE_WIN32)
00410   SYSTEM_INFO sys_info;
00411   ::GetSystemInfo (&sys_info);
00412   long active_processors = 0;
00413   DWORD_PTR mask = sys_info.dwActiveProcessorMask;
00414   while (mask != 0)
00415     {
00416       if (mask & 1)
00417         ++active_processors;
00418       mask >>= 1;
00419     }
00420   return active_processors;
00421 #elif defined (_SC_NPROCESSORS_ONLN)
00422   return ::sysconf (_SC_NPROCESSORS_ONLN);
00423 #elif defined (ACE_HAS_SYSCTL)
00424   int num_processors;
00425   int mib[2] = { CTL_HW, HW_NCPU };
00426   size_t len = sizeof (num_processors);
00427   if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
00428     return num_processors;
00429   else
00430     return -1;
00431 #elif defined (__hpux)
00432   struct pst_dynamic psd;
00433   if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
00434     return psd.psd_proc_cnt;
00435   else
00436     return -1;
00437 #else
00438   ACE_NOTSUP_RETURN (-1);
00439 #endif
00440 }
00441 
00442 ssize_t
00443 ACE_OS::read_n (ACE_HANDLE handle,
00444                 void *buf,
00445                 size_t len,
00446                 size_t *bt)
00447 {
00448   size_t temp;
00449   size_t &bytes_transferred = bt == 0 ? temp : *bt;
00450   ssize_t n = 0;
00451 
00452   for (bytes_transferred = 0;
00453        bytes_transferred < len;
00454        bytes_transferred += n)
00455     {
00456       n = ACE_OS::read (handle,
00457                         (char *) buf + bytes_transferred,
00458                         len - bytes_transferred);
00459 
00460       if (n == -1 || n == 0)
00461         return n;
00462     }
00463 
00464   return bytes_transferred;
00465 }
00466 
00467 ssize_t
00468 ACE_OS::pread (ACE_HANDLE handle,
00469                void *buf,
00470                size_t nbytes,
00471                ACE_OFF_T offset)
00472 {
00473 # if defined (ACE_HAS_P_READ_WRITE)
00474 #   if defined (ACE_WIN32)
00475 
00476   ACE_OS_GUARD
00477 
00478   // Remember the original file pointer position
00479   LONG original_high_position = 0;
00480   DWORD original_low_position = ::SetFilePointer (handle,
00481                                                   0,
00482                                                   &original_high_position,
00483                                                   FILE_CURRENT);
00484 
00485   if (original_low_position == INVALID_SET_FILE_POINTER
00486       && GetLastError () != NO_ERROR)
00487     return -1;
00488 
00489   // Go to the correct position
00490   LONG low_offset = ACE_LOW_PART (offset);
00491   LONG high_offset = ACE_HIGH_PART (offset);
00492   DWORD altered_position = ::SetFilePointer (handle,
00493                                              low_offset,
00494                                              &high_offset,
00495                                              FILE_BEGIN);
00496   if (altered_position == INVALID_SET_FILE_POINTER
00497       && GetLastError () != NO_ERROR)
00498     return -1;
00499 
00500   DWORD bytes_read;
00501 
00502 #     if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
00503 
00504   OVERLAPPED overlapped;
00505   overlapped.Internal = 0;
00506   overlapped.InternalHigh = 0;
00507   overlapped.Offset = low_offset;
00508   overlapped.OffsetHigh = high_offset;
00509   overlapped.hEvent = 0;
00510 
00511   BOOL result = ::ReadFile (handle,
00512                             buf,
00513                             static_cast <DWORD> (nbytes),
00514                             &bytes_read,
00515                             &overlapped);
00516 
00517   if (result == FALSE)
00518     {
00519       if (::GetLastError () != ERROR_IO_PENDING)
00520         return -1;
00521 
00522       else
00523         {
00524           result = ::GetOverlappedResult (handle,
00525                                           &overlapped,
00526                                           &bytes_read,
00527                                           TRUE);
00528           if (result == FALSE)
00529             return -1;
00530         }
00531     }
00532 
00533 #     else /* ACE_HAS_WIN32_OVERLAPPED_IO */
00534 
00535   BOOL result = ::ReadFile (handle,
00536                             buf,
00537                             nbytes,
00538                             &bytes_read,
00539                             0);
00540   if (result == FALSE)
00541     return -1;
00542 
00543 #     endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
00544 
00545   // Reset the original file pointer position
00546   if (::SetFilePointer (handle,
00547                         original_low_position,
00548                         &original_high_position,
00549                         FILE_BEGIN) == INVALID_SET_FILE_POINTER
00550       && GetLastError () != NO_ERROR)
00551     return -1;
00552 
00553   return (ssize_t) bytes_read;
00554 
00555 #   else /* ACE_WIN32 */
00556 
00557   return ::pread (handle, buf, nbytes, offset);
00558 
00559 #   endif /* ACE_WIN32 */
00560 
00561 # else /* ACE_HAS_P_READ_WRITE */
00562 
00563   ACE_OS_GUARD
00564 
00565   // Remember the original file pointer position
00566   ACE_OFF_T original_position = ACE_OS::lseek (handle,
00567                                                0,
00568                                                SEEK_CUR);
00569 
00570   if (original_position == -1)
00571     return -1;
00572 
00573   // Go to the correct position
00574   ACE_OFF_T altered_position = ACE_OS::lseek (handle, offset, SEEK_SET);
00575 
00576   if (altered_position == -1)
00577     return -1;
00578 
00579   ssize_t const bytes_read = ACE_OS::read (handle, buf, nbytes);
00580 
00581   if (bytes_read == -1)
00582     return -1;
00583 
00584   if (ACE_OS::lseek (handle,
00585                      original_position,
00586                      SEEK_SET) == -1)
00587     return -1;
00588 
00589   return bytes_read;
00590 
00591 # endif /* ACE_HAD_P_READ_WRITE */
00592 }
00593 
00594 ssize_t
00595 ACE_OS::pwrite (ACE_HANDLE handle,
00596                 const void *buf,
00597                 size_t nbytes,
00598                 ACE_OFF_T offset)
00599 {
00600 # if defined (ACE_HAS_P_READ_WRITE)
00601 #   if defined (ACE_WIN32)
00602 
00603   ACE_OS_GUARD
00604 
00605   // Remember the original file pointer position
00606   LARGE_INTEGER orig_position;
00607   orig_position.QuadPart = 0;
00608   orig_position.LowPart = ::SetFilePointer (handle,
00609                                             0,
00610                                             &orig_position.HighPart,
00611                                             FILE_CURRENT);
00612   if (orig_position.LowPart == INVALID_SET_FILE_POINTER
00613       && GetLastError () != NO_ERROR)
00614     return -1;
00615 
00616   DWORD bytes_written;
00617   LARGE_INTEGER loffset;
00618   loffset.QuadPart = offset;
00619 
00620 #     if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
00621 
00622   OVERLAPPED overlapped;
00623   overlapped.Internal = 0;
00624   overlapped.InternalHigh = 0;
00625   overlapped.Offset = loffset.LowPart;
00626   overlapped.OffsetHigh = loffset.HighPart;
00627   overlapped.hEvent = 0;
00628 
00629   BOOL result = ::WriteFile (handle,
00630                              buf,
00631                              static_cast <DWORD> (nbytes),
00632                              &bytes_written,
00633                              &overlapped);
00634 
00635   if (result == FALSE)
00636     {
00637       if (::GetLastError () != ERROR_IO_PENDING)
00638         return -1;
00639 
00640       result = ::GetOverlappedResult (handle,
00641                                       &overlapped,
00642                                       &bytes_written,
00643                                       TRUE);
00644       if (result == FALSE)
00645         return -1;
00646     }
00647 
00648 #     else /* ACE_HAS_WIN32_OVERLAPPED_IO */
00649 
00650   // Go to the correct position; if this is a Windows variant without
00651   // overlapped I/O, it probably doesn't have SetFilePointerEx either,
00652   // so manage this with SetFilePointer, changing calls based on the use
00653   // of 64 bit offsets.
00654   DWORD newpos;
00655 #       if defined (_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
00656   newpos = ::SetFilePointer (handle,
00657                              loffset.LowPart,
00658                              &loffset.HighPart,
00659                              FILE_BEGIN);
00660 #       else
00661   newpos = ::SetFilePointer (handle,
00662                              loffset.LowPart,
00663                              0,
00664                              FILE_BEGIN);
00665 #       endif /* 64-bit file offsets */
00666   if (newpos == 0xFFFFFFFF && ::GetLastError () != NO_ERROR)
00667     {
00668       ACE_OS::set_errno_to_last_error ();
00669       return -1;
00670     }
00671 
00672   BOOL result = ::WriteFile (handle,
00673                              buf,
00674                              nbytes,
00675                              &bytes_written,
00676                              0);
00677   if (result == FALSE)
00678     return -1;
00679 
00680 #     endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
00681 
00682   // Reset the original file pointer position
00683   if (::SetFilePointer (handle,
00684                         orig_position.LowPart,
00685                         &orig_position.HighPart,
00686                         FILE_BEGIN) == INVALID_SET_FILE_POINTER
00687       && GetLastError () != NO_ERROR)
00688     return -1;
00689 
00690   return (ssize_t) bytes_written;
00691 
00692 #   else /* ACE_WIN32 */
00693 
00694   return ::pwrite (handle, buf, nbytes, offset);
00695 #   endif /* ACE_WIN32 */
00696 # else /* ACE_HAS_P_READ_WRITE */
00697 
00698   ACE_OS_GUARD
00699 
00700   // Remember the original file pointer position
00701   ACE_OFF_T original_position = ACE_OS::lseek (handle,
00702                                                0,
00703                                                SEEK_CUR);
00704   if (original_position == -1)
00705     return -1;
00706 
00707   // Go to the correct position
00708   ACE_OFF_T altered_position = ACE_OS::lseek (handle,
00709                                               offset,
00710                                               SEEK_SET);
00711   if (altered_position == -1)
00712     return -1;
00713 
00714   ssize_t const bytes_written = ACE_OS::write (handle,
00715                                                buf,
00716                                                nbytes);
00717   if (bytes_written == -1)
00718     return -1;
00719 
00720   if (ACE_OS::lseek (handle,
00721                      original_position,
00722                      SEEK_SET) == -1)
00723     return -1;
00724 
00725   return bytes_written;
00726 # endif /* ACE_HAS_P_READ_WRITE */
00727 }
00728 
00729 int
00730 ACE_OS::string_to_argv (ACE_TCHAR *buf,
00731                         int &argc,
00732                         ACE_TCHAR **&argv,
00733                         bool substitute_env_args)
00734 {
00735   // Reset the number of arguments
00736   argc = 0;
00737 
00738   if (buf == 0)
00739     return -1;
00740 
00741   ACE_TCHAR *cp = buf;
00742 
00743   // First pass: count arguments.
00744 
00745   // '#' is the start-comment token..
00746   while (*cp != ACE_TEXT ('\0') && *cp != ACE_TEXT ('#'))
00747     {
00748       // Skip whitespace..
00749       while (ACE_OS::ace_isspace (*cp))
00750         ++cp;
00751 
00752       // Increment count and move to next whitespace..
00753       if (*cp != ACE_TEXT ('\0'))
00754         ++argc;
00755 
00756       while (*cp != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*cp))
00757         {
00758           // Grok quotes....
00759           if (*cp == ACE_TEXT ('\'') || *cp == ACE_TEXT ('"'))
00760             {
00761               ACE_TCHAR quote = *cp;
00762 
00763               // Scan past the string..
00764               for (++cp; *cp != ACE_TEXT ('\0')
00765                    && (*cp != quote || cp[-1] == ACE_TEXT ('\\')); ++cp)
00766                 continue;
00767 
00768               // '\0' implies unmatched quote..
00769               if (*cp == ACE_TEXT ('\0'))
00770                 {
00771                   --argc;
00772                   break;
00773                 }
00774               else
00775                 ++cp;
00776             }
00777           else
00778             ++cp;
00779         }
00780     }
00781 
00782   // Second pass: copy arguments.
00783   ACE_TCHAR arg[ACE_DEFAULT_ARGV_BUFSIZ];
00784   ACE_TCHAR *argp = arg;
00785 
00786   // Make sure that the buffer we're copying into is always large
00787   // enough.
00788   if (cp - buf >= ACE_DEFAULT_ARGV_BUFSIZ)
00789     ACE_NEW_RETURN (argp,
00790                     ACE_TCHAR[cp - buf + 1],
00791                     -1);
00792 
00793   // Make a new argv vector of argc + 1 elements.
00794   ACE_NEW_RETURN (argv,
00795                   ACE_TCHAR *[argc + 1],
00796                   -1);
00797 
00798   ACE_TCHAR *ptr = buf;
00799 
00800   for (int i = 0; i < argc; ++i)
00801     {
00802       // Skip whitespace..
00803       while (ACE_OS::ace_isspace (*ptr))
00804         ++ptr;
00805 
00806       // Copy next argument and move to next whitespace..
00807       cp = argp;
00808       while (*ptr != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*ptr))
00809         if (*ptr == ACE_TEXT ('\'') || *ptr == ACE_TEXT ('"'))
00810           {
00811             ACE_TCHAR quote = *ptr++;
00812 
00813             while (*ptr != ACE_TEXT ('\0')
00814                    && (*ptr != quote || ptr[-1] == ACE_TEXT ('\\')))
00815               {
00816                 if (*ptr == quote && ptr[-1] == ACE_TEXT ('\\')) --cp;
00817                 *cp++ = *ptr++;
00818               }
00819 
00820             if (*ptr == quote)
00821               ++ptr;
00822           }
00823         else
00824           *cp++ = *ptr++;
00825 
00826       *cp = ACE_TEXT ('\0');
00827 
00828 #if !defined (ACE_LACKS_ENV)
00829       // Check for environment variable substitution here.
00830       if (substitute_env_args) {
00831           argv[i] = ACE_OS::strenvdup (argp);
00832 
00833           if (argv[i] == 0)
00834             {
00835               if (argp != arg)
00836                 delete [] argp;
00837               errno = ENOMEM;
00838               return -1;
00839             }
00840       }
00841       else
00842 #endif /* ACE_LACKS_ENV */
00843         {
00844           argv[i] = ACE_OS::strdup (argp);
00845 
00846           if (argv[i] == 0)
00847             {
00848               if (argp != arg)
00849                 delete [] argp;
00850               errno = ENOMEM;
00851               return -1;
00852             }
00853         }
00854     }
00855 
00856   if (argp != arg)
00857     delete [] argp;
00858 
00859   argv[argc] = 0;
00860   return 0;
00861 }
00862 
00863 // Write <len> bytes from <buf> to <handle> (uses the <write>
00864 // system call on UNIX and the <WriteFile> call on Win32).
00865 
00866 ssize_t
00867 ACE_OS::write_n (ACE_HANDLE handle,
00868                  const void *buf,
00869                  size_t len,
00870                  size_t *bt)
00871 {
00872   size_t temp;
00873   size_t &bytes_transferred = bt == 0 ? temp : *bt;
00874   ssize_t n;
00875 
00876   for (bytes_transferred = 0;
00877        bytes_transferred < len;
00878        bytes_transferred += n)
00879     {
00880       n = ACE_OS::write (handle,
00881                          (char *) buf + bytes_transferred,
00882                          len - bytes_transferred);
00883 
00884       if (n == -1 || n == 0)
00885         return n;
00886     }
00887 
00888   return bytes_transferred;
00889 }
00890 
00891 ACE_END_VERSIONED_NAMESPACE_DECL

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