mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 01:37:00 +00:00
922 lines
25 KiB
C++
922 lines
25 KiB
C++
// $Id: OS_NS_unistd.cpp 94448 2011-09-08 08:20:29Z johnnyw $
|
|
|
|
#include "ace/OS_NS_unistd.h"
|
|
|
|
#if !defined (ACE_HAS_INLINED_OSCALLS)
|
|
# include "ace/OS_NS_unistd.inl"
|
|
#endif /* ACE_HAS_INLINED_OSCALLS */
|
|
|
|
#include "ace/Base_Thread_Adapter.h"
|
|
#include "ace/OS_NS_stdlib.h"
|
|
#include "ace/OS_NS_ctype.h"
|
|
#include "ace/Default_Constants.h"
|
|
#include "ace/OS_Memory.h"
|
|
#include "ace/OS_NS_Thread.h"
|
|
#include "ace/Object_Manager_Base.h"
|
|
#include "ace/Auto_Ptr.h"
|
|
#include "ace/os_include/sys/os_pstat.h"
|
|
#include "ace/os_include/sys/os_sysctl.h"
|
|
|
|
#if defined ACE_HAS_VXCPULIB
|
|
# include "vxCpuLib.h"
|
|
# include "cpuset.h"
|
|
#endif /* ACE_HAS_VXCPULIB */
|
|
|
|
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
|
|
|
int
|
|
ACE_OS::argv_to_string (ACE_TCHAR **argv,
|
|
ACE_TCHAR *&buf,
|
|
bool substitute_env_args,
|
|
bool quote_args)
|
|
{
|
|
if (argv == 0 || argv[0] == 0)
|
|
return 0;
|
|
|
|
int argc;
|
|
for (argc = 0; argv[argc] != 0; ++argc)
|
|
continue;
|
|
|
|
return argv_to_string (argc,
|
|
argv,
|
|
buf,
|
|
substitute_env_args,
|
|
quote_args);
|
|
}
|
|
|
|
int
|
|
ACE_OS::argv_to_string (int argc,
|
|
ACE_TCHAR **argv,
|
|
ACE_TCHAR *&buf,
|
|
bool substitute_env_args,
|
|
bool quote_args)
|
|
{
|
|
#if defined (ACE_LACKS_STRENVDUP)
|
|
ACE_UNUSED_ARG (substitute_env_args);
|
|
#endif /* ACE_LACKS_STRENVDUP */
|
|
|
|
if (argc <= 0 || argv == 0 || argv[0] == 0)
|
|
return 0;
|
|
|
|
size_t buf_len = 0;
|
|
|
|
// Determine the length of the buffer.
|
|
|
|
ACE_TCHAR **argv_p = argv;
|
|
|
|
for (int i = 0; i < argc; ++i)
|
|
{
|
|
#if !defined (ACE_LACKS_STRENVDUP)
|
|
// Account for environment variables.
|
|
if (substitute_env_args
|
|
&& ACE_OS::strchr (argv[i], ACE_TEXT ('$')) != 0)
|
|
{
|
|
if (argv_p == argv)
|
|
{
|
|
argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
|
|
if (argv_p == 0)
|
|
{
|
|
errno = ENOMEM;
|
|
return 0;
|
|
}
|
|
ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
|
|
}
|
|
argv_p[i] = ACE_OS::strenvdup (argv[i]);
|
|
if (argv_p[i] == 0)
|
|
{
|
|
ACE_OS::free (argv_p);
|
|
errno = ENOMEM;
|
|
return 0;
|
|
}
|
|
}
|
|
#endif /* ACE_LACKS_STRENVDUP */
|
|
// If must quote, we only do it if the arg contains spaces, or
|
|
// is empty. Perhaps a check for other c | ord(c) <= 32 is in
|
|
// order?
|
|
if (quote_args
|
|
&& (ACE_OS::strchr (argv_p[i], ACE_TEXT (' ')) != 0
|
|
|| ACE_OS::strchr (argv_p[i], ACE_TEXT ('\t')) != 0
|
|
|| ACE_OS::strchr (argv_p[i], ACE_TEXT ('\n')) != 0
|
|
|| *argv_p[i] == 0))
|
|
{
|
|
if (argv_p == argv)
|
|
{
|
|
argv_p = (ACE_TCHAR **) ACE_OS::malloc (argc * sizeof (ACE_TCHAR *));
|
|
if (argv_p == 0)
|
|
{
|
|
errno = ENOMEM;
|
|
return 0;
|
|
}
|
|
ACE_OS::memcpy (argv_p, argv, argc * sizeof (ACE_TCHAR *));
|
|
}
|
|
int quotes = 0;
|
|
ACE_TCHAR *temp = argv_p[i];
|
|
if (ACE_OS::strchr (temp, ACE_TEXT ('"')) != 0)
|
|
{
|
|
for (int j = 0; temp[j] != 0; ++j)
|
|
if (temp[j] == ACE_TEXT ('"'))
|
|
++quotes;
|
|
}
|
|
argv_p[i] =
|
|
(ACE_TCHAR *) ACE_OS::malloc ((ACE_OS::strlen (temp) + quotes + 3)
|
|
* sizeof (ACE_TCHAR));
|
|
if (argv_p[i] == 0)
|
|
{
|
|
ACE_OS::free (argv_p);
|
|
errno = ENOMEM;
|
|
return 0;
|
|
}
|
|
ACE_TCHAR *end = argv_p[i];
|
|
|
|
*end++ = ACE_TEXT ('"');
|
|
|
|
if (quotes > 0)
|
|
{
|
|
for (ACE_TCHAR *p = temp;
|
|
*p != 0;
|
|
*end++ = *p++)
|
|
if (*p == ACE_TEXT ('"'))
|
|
*end++ = ACE_TEXT ('\\');
|
|
|
|
*end++ = ACE_TEXT ('\0');
|
|
}
|
|
else
|
|
end = ACE_OS::strecpy (end, temp);
|
|
|
|
end[-1] = ACE_TEXT ('"');
|
|
|
|
*end = ACE_TEXT ('\0');
|
|
if (temp != argv[i])
|
|
ACE_OS::free (temp);
|
|
}
|
|
buf_len += ACE_OS::strlen (argv_p[i]);
|
|
|
|
// Add one for the extra space between each string.
|
|
buf_len++;
|
|
}
|
|
|
|
// Step through all argv params and copy each one into buf; separate
|
|
// each param with white space.
|
|
|
|
ACE_NEW_RETURN (buf,
|
|
ACE_TCHAR[buf_len + 1],
|
|
0);
|
|
|
|
// Initial null charater to make it a null string.
|
|
buf[0] = ACE_TEXT ('\0');
|
|
ACE_TCHAR *end = buf;
|
|
|
|
for (int i = 0; i < argc; ++i)
|
|
{
|
|
end = ACE_OS::strecpy (end, argv_p[i]);
|
|
if (argv_p[i] != argv[i])
|
|
ACE_OS::free (argv_p[i]);
|
|
|
|
// Replace the null char that strecpy put there with white
|
|
// space.
|
|
end[-1] = ACE_TEXT (' ');
|
|
}
|
|
// Null terminate the string.
|
|
*end = ACE_TEXT ('\0');
|
|
|
|
if (argv_p != argv)
|
|
ACE_OS::free (argv_p);
|
|
|
|
// The number of arguments.
|
|
return argc;
|
|
}
|
|
|
|
int
|
|
ACE_OS::execl (const char * /* path */, const char * /* arg0 */, ...)
|
|
{
|
|
ACE_OS_TRACE ("ACE_OS::execl");
|
|
ACE_NOTSUP_RETURN (-1);
|
|
// Need to write this code.
|
|
// ACE_OSCALL_RETURN (::execv (path, argv), int, -1);
|
|
}
|
|
|
|
int
|
|
ACE_OS::execle (const char * /* path */, const char * /* arg0 */, ...)
|
|
{
|
|
ACE_OS_TRACE ("ACE_OS::execle");
|
|
ACE_NOTSUP_RETURN (-1);
|
|
// Need to write this code.
|
|
// ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1);
|
|
}
|
|
|
|
int
|
|
ACE_OS::execlp (const char * /* file */, const char * /* arg0 */, ...)
|
|
{
|
|
ACE_OS_TRACE ("ACE_OS::execlp");
|
|
ACE_NOTSUP_RETURN (-1);
|
|
// Need to write this code.
|
|
// ACE_OSCALL_RETURN (::execvp (file, argv), int, -1);
|
|
}
|
|
|
|
pid_t
|
|
ACE_OS::fork (const ACE_TCHAR *program_name)
|
|
{
|
|
ACE_OS_TRACE ("ACE_OS::fork");
|
|
# if defined (ACE_LACKS_FORK)
|
|
ACE_UNUSED_ARG (program_name);
|
|
ACE_NOTSUP_RETURN (pid_t (-1));
|
|
# else
|
|
pid_t const pid =
|
|
# if defined (ACE_HAS_STHREADS)
|
|
::fork1 ();
|
|
#else
|
|
::fork ();
|
|
#endif /* ACE_HAS_STHREADS */
|
|
|
|
#if !defined (ACE_HAS_MINIMAL_ACE_OS) && !defined (ACE_HAS_THREADS)
|
|
|
|
// ACE_Base_Thread_Adapter::sync_log_msg() is used to update the
|
|
// program name and process id in ACE's log framework. However, we
|
|
// can't invoke it from (the child process of) threaded programs
|
|
// because it calls async signal unsafe functions, which will result
|
|
// in undefined behavior (only async signal safe functions can be
|
|
// called after fork() until an exec()).
|
|
//
|
|
// This is no great loss. Using the ACE log framework in the child
|
|
// process will undoubtedly call async signal unsafe functions too.
|
|
// So it doesn't really matter that the program name and process id
|
|
// will not be updated.
|
|
|
|
if (pid == 0)
|
|
ACE_Base_Thread_Adapter::sync_log_msg (program_name);
|
|
|
|
#else
|
|
|
|
ACE_UNUSED_ARG (program_name);
|
|
|
|
#endif /* ! ACE_HAS_MINIMAL_ACE_OS && !ACE_HAS_THREADS */
|
|
|
|
return pid;
|
|
# endif /* ACE_WIN32 */
|
|
}
|
|
|
|
// Create a contiguous command-line argument buffer with each arg
|
|
// separated by spaces.
|
|
|
|
pid_t
|
|
ACE_OS::fork_exec (ACE_TCHAR *argv[])
|
|
{
|
|
# if defined (ACE_WIN32)
|
|
|
|
ACE_TCHAR *buf = 0;
|
|
ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_ptr (buf);
|
|
if (ACE_OS::argv_to_string (argv, buf) != -1)
|
|
{
|
|
PROCESS_INFORMATION process_info;
|
|
# if !defined (ACE_HAS_WINCE)
|
|
ACE_TEXT_STARTUPINFO startup_info;
|
|
ACE_OS::memset ((void *) &startup_info,
|
|
0,
|
|
sizeof startup_info);
|
|
startup_info.cb = sizeof startup_info;
|
|
|
|
if (ACE_TEXT_CreateProcess (0,
|
|
buf,
|
|
0, // No process attributes.
|
|
0, // No thread attributes.
|
|
TRUE, // Allow handle inheritance.
|
|
0, // Don't create a new console window.
|
|
0, // No environment.
|
|
0, // No current directory.
|
|
&startup_info,
|
|
&process_info))
|
|
# else
|
|
if (ACE_TEXT_CreateProcess (0,
|
|
buf,
|
|
0, // No process attributes.
|
|
0, // No thread attributes.
|
|
FALSE, // Can's inherit handles on CE
|
|
0, // Don't create a new console window.
|
|
0, // No environment.
|
|
0, // No current directory.
|
|
0, // Can't use startup info on CE
|
|
&process_info))
|
|
# endif /* ! ACE_HAS_WINCE */
|
|
{
|
|
// Free resources allocated in kernel.
|
|
ACE_OS::close (process_info.hThread);
|
|
ACE_OS::close (process_info.hProcess);
|
|
// Return new process id.
|
|
return process_info.dwProcessId;
|
|
}
|
|
}
|
|
|
|
// CreateProcess failed.
|
|
return -1;
|
|
# else
|
|
pid_t const result = ACE_OS::fork ();
|
|
|
|
# if defined (ACE_USES_WCHAR)
|
|
// Wide-char builds need to convert the command-line args to
|
|
// narrow char strings for execv ().
|
|
char **cargv = 0;
|
|
int arg_count;
|
|
# endif /* ACE_HAS_WCHAR */
|
|
|
|
switch (result)
|
|
{
|
|
case -1:
|
|
// Error.
|
|
return -1;
|
|
case 0:
|
|
// Child process.
|
|
# if defined (ACE_USES_WCHAR)
|
|
for (arg_count = 0; argv[arg_count] != 0; ++arg_count)
|
|
;
|
|
++arg_count; // Need a 0-pointer end-of-array marker
|
|
ACE_NEW_NORETURN (cargv, char*[arg_count]);
|
|
if (cargv == 0)
|
|
ACE_OS::exit (errno);
|
|
--arg_count; // Back to 0-indexed
|
|
cargv[arg_count] = 0;
|
|
while (--arg_count >= 0)
|
|
cargv[arg_count] = ACE_Wide_To_Ascii::convert (argv[arg_count]);
|
|
// Don't worry about freeing the cargv or the strings it points to.
|
|
// Either the process will be replaced, or we'll exit.
|
|
if (ACE_OS::execv (cargv[0], cargv) == -1)
|
|
ACE_OS::exit (errno);
|
|
# else
|
|
if (ACE_OS::execv (argv[0], argv) == -1)
|
|
{
|
|
// The OS layer should not print stuff out
|
|
// ACE_ERROR ((LM_ERROR,
|
|
// "%p Exec failed\n"));
|
|
|
|
// If the execv fails, this child needs to exit.
|
|
ACE_OS::exit (errno);
|
|
}
|
|
# endif /* ACE_HAS_WCHAR */
|
|
|
|
default:
|
|
// Server process. The fork succeeded.
|
|
return result;
|
|
}
|
|
# endif /* ACE_WIN32 */
|
|
}
|
|
|
|
long
|
|
ACE_OS::num_processors (void)
|
|
{
|
|
ACE_OS_TRACE ("ACE_OS::num_processors");
|
|
|
|
#if defined (ACE_HAS_PHARLAP)
|
|
return 1;
|
|
#elif defined (ACE_WIN32)
|
|
SYSTEM_INFO sys_info;
|
|
::GetSystemInfo (&sys_info);
|
|
return sys_info.dwNumberOfProcessors;
|
|
#elif defined (ACE_HAS_VXCPULIB)
|
|
return vxCpuConfiguredGet();
|
|
#elif defined (_SC_NPROCESSORS_CONF)
|
|
return ::sysconf (_SC_NPROCESSORS_CONF);
|
|
#elif defined (ACE_HAS_SYSCTL)
|
|
int num_processors = 0;
|
|
int mib[2] = { CTL_HW, HW_NCPU };
|
|
size_t len = sizeof (num_processors);
|
|
if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
|
|
return num_processors;
|
|
else
|
|
return -1;
|
|
#elif defined (__hpux)
|
|
struct pst_dynamic psd;
|
|
if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
|
|
return psd.psd_max_proc_cnt;
|
|
else
|
|
return -1;
|
|
#else
|
|
ACE_NOTSUP_RETURN (-1);
|
|
#endif
|
|
}
|
|
|
|
long
|
|
ACE_OS::num_processors_online (void)
|
|
{
|
|
ACE_OS_TRACE ("ACE_OS::num_processors_online");
|
|
|
|
#if defined (ACE_HAS_PHARLAP)
|
|
return 1;
|
|
#elif defined (ACE_WIN32)
|
|
SYSTEM_INFO sys_info;
|
|
::GetSystemInfo (&sys_info);
|
|
long active_processors = 0;
|
|
DWORD_PTR mask = sys_info.dwActiveProcessorMask;
|
|
while (mask != 0)
|
|
{
|
|
if (mask & 1)
|
|
++active_processors;
|
|
mask >>= 1;
|
|
}
|
|
return active_processors;
|
|
#elif defined (ACE_HAS_VXCPULIB)
|
|
long num_cpu = 0;
|
|
cpuset_t cpuset;
|
|
CPUSET_ZERO (cpuset);
|
|
cpuset = vxCpuEnabledGet();
|
|
unsigned int const maxcpu = vxCpuConfiguredGet();
|
|
for (unsigned int i =0; i < maxcpu; i++)
|
|
{
|
|
if (CPUSET_ISSET (cpuset, i))
|
|
{
|
|
++num_cpu;
|
|
}
|
|
}
|
|
return num_cpu;
|
|
#elif defined (_SC_NPROCESSORS_ONLN)
|
|
return ::sysconf (_SC_NPROCESSORS_ONLN);
|
|
#elif defined (ACE_HAS_SYSCTL)
|
|
int num_processors;
|
|
int mib[2] = { CTL_HW, HW_NCPU };
|
|
size_t len = sizeof (num_processors);
|
|
if (::sysctl (mib, 2, &num_processors, &len, 0, 0) != -1)
|
|
return num_processors;
|
|
else
|
|
return -1;
|
|
#elif defined (__hpux)
|
|
struct pst_dynamic psd;
|
|
if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
|
|
return psd.psd_proc_cnt;
|
|
else
|
|
return -1;
|
|
#else
|
|
ACE_NOTSUP_RETURN (-1);
|
|
#endif
|
|
}
|
|
|
|
ssize_t
|
|
ACE_OS::read_n (ACE_HANDLE handle,
|
|
void *buf,
|
|
size_t len,
|
|
size_t *bt)
|
|
{
|
|
size_t temp;
|
|
size_t &bytes_transferred = bt == 0 ? temp : *bt;
|
|
ssize_t n = 0;
|
|
|
|
for (bytes_transferred = 0;
|
|
bytes_transferred < len;
|
|
bytes_transferred += n)
|
|
{
|
|
n = ACE_OS::read (handle,
|
|
(char *) buf + bytes_transferred,
|
|
len - bytes_transferred);
|
|
|
|
if (n == -1 || n == 0)
|
|
{
|
|
return n;
|
|
}
|
|
}
|
|
|
|
return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
|
|
}
|
|
|
|
ssize_t
|
|
ACE_OS::pread (ACE_HANDLE handle,
|
|
void *buf,
|
|
size_t nbytes,
|
|
ACE_OFF_T offset)
|
|
{
|
|
# if defined (ACE_HAS_P_READ_WRITE)
|
|
# if defined (ACE_WIN32)
|
|
|
|
ACE_OS_GUARD
|
|
|
|
// Remember the original file pointer position
|
|
LONG original_high_position = 0;
|
|
DWORD original_low_position = ::SetFilePointer (handle,
|
|
0,
|
|
&original_high_position,
|
|
FILE_CURRENT);
|
|
|
|
if (original_low_position == INVALID_SET_FILE_POINTER
|
|
&& GetLastError () != NO_ERROR)
|
|
{
|
|
ACE_OS::set_errno_to_last_error ();
|
|
return -1;
|
|
}
|
|
|
|
// Go to the correct position
|
|
LONG low_offset = ACE_LOW_PART (offset);
|
|
LONG high_offset = ACE_HIGH_PART (offset);
|
|
DWORD altered_position = ::SetFilePointer (handle,
|
|
low_offset,
|
|
&high_offset,
|
|
FILE_BEGIN);
|
|
if (altered_position == INVALID_SET_FILE_POINTER
|
|
&& GetLastError () != NO_ERROR)
|
|
{
|
|
ACE_OS::set_errno_to_last_error ();
|
|
return -1;
|
|
}
|
|
|
|
DWORD bytes_read;
|
|
|
|
# if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
|
|
|
|
OVERLAPPED overlapped;
|
|
overlapped.Internal = 0;
|
|
overlapped.InternalHigh = 0;
|
|
overlapped.Offset = low_offset;
|
|
overlapped.OffsetHigh = high_offset;
|
|
overlapped.hEvent = 0;
|
|
|
|
BOOL result = ::ReadFile (handle,
|
|
buf,
|
|
static_cast <DWORD> (nbytes),
|
|
&bytes_read,
|
|
&overlapped);
|
|
|
|
if (result == FALSE)
|
|
{
|
|
if (::GetLastError () != ERROR_IO_PENDING)
|
|
return -1;
|
|
|
|
else
|
|
{
|
|
result = ::GetOverlappedResult (handle,
|
|
&overlapped,
|
|
&bytes_read,
|
|
TRUE);
|
|
if (result == FALSE)
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
# else /* ACE_HAS_WIN32_OVERLAPPED_IO */
|
|
|
|
BOOL result = ::ReadFile (handle,
|
|
buf,
|
|
nbytes,
|
|
&bytes_read,
|
|
0);
|
|
if (result == FALSE)
|
|
return -1;
|
|
|
|
# endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
|
|
|
|
// Reset the original file pointer position
|
|
if (::SetFilePointer (handle,
|
|
original_low_position,
|
|
&original_high_position,
|
|
FILE_BEGIN) == INVALID_SET_FILE_POINTER
|
|
&& GetLastError () != NO_ERROR)
|
|
{
|
|
ACE_OS::set_errno_to_last_error ();
|
|
return -1;
|
|
}
|
|
|
|
return (ssize_t) bytes_read;
|
|
|
|
# else /* ACE_WIN32 */
|
|
|
|
return ::pread (handle, buf, nbytes, offset);
|
|
|
|
# endif /* ACE_WIN32 */
|
|
|
|
# else /* ACE_HAS_P_READ_WRITE */
|
|
|
|
ACE_OS_GUARD
|
|
|
|
// Remember the original file pointer position
|
|
ACE_OFF_T original_position = ACE_OS::lseek (handle,
|
|
0,
|
|
SEEK_CUR);
|
|
|
|
if (original_position == -1)
|
|
return -1;
|
|
|
|
// Go to the correct position
|
|
ACE_OFF_T altered_position = ACE_OS::lseek (handle, offset, SEEK_SET);
|
|
|
|
if (altered_position == -1)
|
|
return -1;
|
|
|
|
ssize_t const bytes_read = ACE_OS::read (handle, buf, nbytes);
|
|
|
|
if (bytes_read == -1)
|
|
return -1;
|
|
|
|
if (ACE_OS::lseek (handle,
|
|
original_position,
|
|
SEEK_SET) == -1)
|
|
return -1;
|
|
|
|
return bytes_read;
|
|
|
|
# endif /* ACE_HAD_P_READ_WRITE */
|
|
}
|
|
|
|
ssize_t
|
|
ACE_OS::pwrite (ACE_HANDLE handle,
|
|
const void *buf,
|
|
size_t nbytes,
|
|
ACE_OFF_T offset)
|
|
{
|
|
# if defined (ACE_HAS_P_READ_WRITE)
|
|
# if defined (ACE_WIN32)
|
|
|
|
ACE_OS_GUARD
|
|
|
|
// Remember the original file pointer position
|
|
LONG original_high_position = 0;
|
|
DWORD original_low_position = ::SetFilePointer (handle,
|
|
0,
|
|
&original_high_position,
|
|
FILE_CURRENT);
|
|
|
|
if (original_low_position == INVALID_SET_FILE_POINTER
|
|
&& GetLastError () != NO_ERROR)
|
|
{
|
|
ACE_OS::set_errno_to_last_error ();
|
|
return -1;
|
|
}
|
|
|
|
DWORD bytes_written;
|
|
LONG low_offset = ACE_LOW_PART (offset);
|
|
LONG high_offset = ACE_HIGH_PART (offset);
|
|
|
|
# if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
|
|
|
|
OVERLAPPED overlapped;
|
|
overlapped.Internal = 0;
|
|
overlapped.InternalHigh = 0;
|
|
overlapped.Offset = low_offset;
|
|
overlapped.OffsetHigh = high_offset;
|
|
overlapped.hEvent = 0;
|
|
|
|
BOOL result = ::WriteFile (handle,
|
|
buf,
|
|
static_cast <DWORD> (nbytes),
|
|
&bytes_written,
|
|
&overlapped);
|
|
|
|
if (result == FALSE)
|
|
{
|
|
if (::GetLastError () != ERROR_IO_PENDING)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
result = ::GetOverlappedResult (handle,
|
|
&overlapped,
|
|
&bytes_written,
|
|
TRUE);
|
|
if (result == FALSE)
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
# else /* ACE_HAS_WIN32_OVERLAPPED_IO */
|
|
|
|
if (::SetFilePointer (handle,
|
|
low_offset,
|
|
&high_offset,
|
|
FILE_BEGIN) == INVALID_SET_FILE_POINTER
|
|
&& ::GetLastError () != NO_ERROR)
|
|
{
|
|
ACE_OS::set_errno_to_last_error ();
|
|
return -1;
|
|
}
|
|
|
|
BOOL result = ::WriteFile (handle,
|
|
buf,
|
|
nbytes,
|
|
&bytes_written,
|
|
0);
|
|
if (result == FALSE)
|
|
return -1;
|
|
|
|
# endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
|
|
|
|
// Reset the original file pointer position
|
|
if (::SetFilePointer (handle,
|
|
original_low_position,
|
|
&original_high_position,
|
|
FILE_BEGIN) == INVALID_SET_FILE_POINTER
|
|
&& GetLastError () != NO_ERROR)
|
|
{
|
|
ACE_OS::set_errno_to_last_error ();
|
|
return -1;
|
|
}
|
|
|
|
return (ssize_t) bytes_written;
|
|
|
|
# else /* ACE_WIN32 */
|
|
# if defined (ACE_HAS_NON_CONST_PWRITE)
|
|
return ::pwrite (handle, const_cast<void*> (buf), nbytes, offset);
|
|
# else
|
|
return ::pwrite (handle, buf, nbytes, offset);
|
|
# endif
|
|
# endif /* ACE_WIN32 */
|
|
# else /* ACE_HAS_P_READ_WRITE */
|
|
|
|
ACE_OS_GUARD
|
|
|
|
// Remember the original file pointer position
|
|
ACE_OFF_T original_position = ACE_OS::lseek (handle,
|
|
0,
|
|
SEEK_CUR);
|
|
if (original_position == -1)
|
|
return -1;
|
|
|
|
// Go to the correct position
|
|
ACE_OFF_T altered_position = ACE_OS::lseek (handle,
|
|
offset,
|
|
SEEK_SET);
|
|
if (altered_position == -1)
|
|
return -1;
|
|
|
|
ssize_t const bytes_written = ACE_OS::write (handle,
|
|
buf,
|
|
nbytes);
|
|
if (bytes_written == -1)
|
|
return -1;
|
|
|
|
if (ACE_OS::lseek (handle,
|
|
original_position,
|
|
SEEK_SET) == -1)
|
|
return -1;
|
|
|
|
return bytes_written;
|
|
# endif /* ACE_HAS_P_READ_WRITE */
|
|
}
|
|
|
|
int
|
|
ACE_OS::string_to_argv (ACE_TCHAR *buf,
|
|
int &argc,
|
|
ACE_TCHAR **&argv,
|
|
bool substitute_env_args)
|
|
{
|
|
#if defined (ACE_LACKS_STRENVDUP)
|
|
ACE_UNUSED_ARG (substitute_env_args);
|
|
#endif /* ACE_LACKS_STRENVDUP */
|
|
|
|
// Reset the number of arguments
|
|
argc = 0;
|
|
|
|
if (buf == 0)
|
|
return -1;
|
|
|
|
ACE_TCHAR *cp = buf;
|
|
|
|
// First pass: count arguments.
|
|
|
|
// '#' is the start-comment token..
|
|
while (*cp != ACE_TEXT ('\0') && *cp != ACE_TEXT ('#'))
|
|
{
|
|
// Skip whitespace..
|
|
while (ACE_OS::ace_isspace (*cp))
|
|
++cp;
|
|
|
|
// Increment count and move to next whitespace..
|
|
if (*cp != ACE_TEXT ('\0'))
|
|
++argc;
|
|
|
|
while (*cp != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*cp))
|
|
{
|
|
// Grok quotes....
|
|
if (*cp == ACE_TEXT ('\'') || *cp == ACE_TEXT ('"'))
|
|
{
|
|
ACE_TCHAR quote = *cp;
|
|
|
|
// Scan past the string..
|
|
for (++cp; *cp != ACE_TEXT ('\0')
|
|
&& (*cp != quote || cp[-1] == ACE_TEXT ('\\')); ++cp)
|
|
continue;
|
|
|
|
// '\0' implies unmatched quote..
|
|
if (*cp == ACE_TEXT ('\0'))
|
|
{
|
|
--argc;
|
|
break;
|
|
}
|
|
else
|
|
++cp;
|
|
}
|
|
else
|
|
++cp;
|
|
}
|
|
}
|
|
|
|
// Second pass: copy arguments.
|
|
ACE_TCHAR arg[ACE_DEFAULT_ARGV_BUFSIZ];
|
|
ACE_TCHAR *argp = arg;
|
|
|
|
// Make sure that the buffer we're copying into is always large
|
|
// enough.
|
|
if (cp - buf >= ACE_DEFAULT_ARGV_BUFSIZ)
|
|
ACE_NEW_RETURN (argp,
|
|
ACE_TCHAR[cp - buf + 1],
|
|
-1);
|
|
|
|
// Make a new argv vector of argc + 1 elements.
|
|
ACE_NEW_RETURN (argv,
|
|
ACE_TCHAR *[argc + 1],
|
|
-1);
|
|
|
|
ACE_TCHAR *ptr = buf;
|
|
|
|
for (int i = 0; i < argc; ++i)
|
|
{
|
|
// Skip whitespace..
|
|
while (ACE_OS::ace_isspace (*ptr))
|
|
++ptr;
|
|
|
|
// Copy next argument and move to next whitespace..
|
|
cp = argp;
|
|
while (*ptr != ACE_TEXT ('\0') && !ACE_OS::ace_isspace (*ptr))
|
|
if (*ptr == ACE_TEXT ('\'') || *ptr == ACE_TEXT ('"'))
|
|
{
|
|
ACE_TCHAR quote = *ptr++;
|
|
|
|
while (*ptr != ACE_TEXT ('\0')
|
|
&& (*ptr != quote || ptr[-1] == ACE_TEXT ('\\')))
|
|
{
|
|
if (*ptr == quote && ptr[-1] == ACE_TEXT ('\\')) --cp;
|
|
*cp++ = *ptr++;
|
|
}
|
|
|
|
if (*ptr == quote)
|
|
++ptr;
|
|
}
|
|
else
|
|
*cp++ = *ptr++;
|
|
|
|
*cp = ACE_TEXT ('\0');
|
|
|
|
#if !defined (ACE_LACKS_STRENVDUP)
|
|
// Check for environment variable substitution here.
|
|
if (substitute_env_args) {
|
|
argv[i] = ACE_OS::strenvdup (argp);
|
|
|
|
if (argv[i] == 0)
|
|
{
|
|
if (argp != arg)
|
|
delete [] argp;
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
#endif /* ACE_LACKS_STRENVDUP */
|
|
{
|
|
argv[i] = ACE_OS::strdup (argp);
|
|
|
|
if (argv[i] == 0)
|
|
{
|
|
if (argp != arg)
|
|
{
|
|
delete [] argp;
|
|
}
|
|
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (argp != arg)
|
|
{
|
|
delete [] argp;
|
|
}
|
|
|
|
argv[argc] = 0;
|
|
return 0;
|
|
}
|
|
|
|
// Write <len> bytes from <buf> to <handle> (uses the <write>
|
|
// system call on UNIX and the <WriteFile> call on Win32).
|
|
|
|
ssize_t
|
|
ACE_OS::write_n (ACE_HANDLE handle,
|
|
const void *buf,
|
|
size_t len,
|
|
size_t *bt)
|
|
{
|
|
size_t temp;
|
|
size_t &bytes_transferred = bt == 0 ? temp : *bt;
|
|
ssize_t n;
|
|
|
|
for (bytes_transferred = 0;
|
|
bytes_transferred < len;
|
|
bytes_transferred += n)
|
|
{
|
|
n = ACE_OS::write (handle,
|
|
(char *) buf + bytes_transferred,
|
|
len - bytes_transferred);
|
|
|
|
if (n == -1 || n == 0)
|
|
{
|
|
return n;
|
|
}
|
|
}
|
|
|
|
return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
|
|
}
|
|
|
|
ACE_END_VERSIONED_NAMESPACE_DECL
|