enhanced sio,pio,fio to support win9x

fixed minor bugs in sio,pio,fio
This commit is contained in:
2012-02-19 14:38:22 +00:00
parent b330d2c350
commit 5cc0e408b3
62 changed files with 715 additions and 270 deletions

View File

@ -179,6 +179,7 @@ SHELL = @SHELL@
SOCKET_LIBS = @SOCKET_LIBS@
STRIP = @STRIP@
TRUE = @TRUE@
UNICOWS_LIBS = @UNICOWS_LIBS@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@

View File

@ -206,6 +206,7 @@ SHELL = @SHELL@
SOCKET_LIBS = @SOCKET_LIBS@
STRIP = @STRIP@
TRUE = @TRUE@
UNICOWS_LIBS = @UNICOWS_LIBS@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@

View File

@ -100,9 +100,9 @@ libqsecmn_la_SOURCES = \
libqsecmn_la_LDFLAGS = -L$(libdir) -version-info 1:0:0 -no-undefined
if WIN32
libqsecmn_la_LIBADD = -lpsapi
endif
#if WIN32
#libqsecmn_la_LIBADD = -lpsapi
#endif
if ENABLE_CXX

View File

@ -35,6 +35,10 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
#if WIN32
#libqsecmn_la_LIBADD = -lpsapi
#endif
@ENABLE_CXX_TRUE@am__append_1 = libqsecmnxx.la
subdir = lib/cmn
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
@ -74,7 +78,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
libqsecmn_la_DEPENDENCIES =
libqsecmn_la_LIBADD =
am_libqsecmn_la_OBJECTS = alg-rand.lo alg-search.lo alg-sort.lo \
assert.lo chr.lo dll.lo env.lo gdl.lo htb.lo lda.lo fio.lo \
fma.lo fmt.lo fs.lo fs-err.lo fs-move.lo hton.lo ipad.lo \
@ -220,6 +224,7 @@ SHELL = @SHELL@
SOCKET_LIBS = @SOCKET_LIBS@
STRIP = @STRIP@
TRUE = @TRUE@
UNICOWS_LIBS = @UNICOWS_LIBS@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
@ -373,7 +378,6 @@ libqsecmn_la_SOURCES = \
xma.c
libqsecmn_la_LDFLAGS = -L$(libdir) -version-info 1:0:0 -no-undefined
@WIN32_TRUE@libqsecmn_la_LIBADD = -lpsapi
@ENABLE_CXX_TRUE@libqsecmnxx_la_SOURCES = \
@ENABLE_CXX_TRUE@ Mmgr.cpp StdMmgr.cpp

View File

@ -28,7 +28,7 @@
#if defined(_WIN32)
# include <windows.h>
# include <psapi.h> /* for GetMappedFileName() */
/*# include <psapi.h>*/ /* for GetMappedFileName(). but dynamically loaded */
# include <tchar.h>
#elif defined(__OS2__)
# define INCL_DOSFILEMGR
@ -41,6 +41,12 @@
# include "syscall.h"
#endif
/* internal status codes */
enum
{
STATUS_APPEND = (1 << 0),
STATUS_NOCLOSE = (1 << 1)
};
QSE_IMPLEMENT_COMMON_FUNCTIONS (fio)
@ -188,21 +194,35 @@ int qse_fio_init (
qse_char_t* temp_ptr;
qse_size_t temp_tries;
#if defined(_WIN32)
int fellback = 0;
#endif
QSE_MEMSET (fio, 0, QSE_SIZEOF(*fio));
fio->mmgr = mmgr;
/* Store the flags for later use though only OS/2 needs
* this at this moment */
fio->flags = flags;
if (!(flags & (QSE_FIO_READ | QSE_FIO_WRITE | QSE_FIO_APPEND | QSE_FIO_HANDLE)))
{
/* one of QSE_FIO_READ, QSE_FIO_WRITE, QSE_FIO_APPEND,
* and QSE_FIO_HANDLE must be specified */
fio->errnum = QSE_FIO_EINVAL;
return -1;
}
/* Store some flags for later use */
if (flags & QSE_FIO_NOCLOSE)
fio->status |= STATUS_NOCLOSE;
if (flags & QSE_FIO_TEMPORARY)
{
qse_ntime_t now;
QSE_ASSERTX (
(flags & QSE_FIO_HANDLE) == 0,
"QSE_FIO_TEMPORARY and QSE_FIO_HANDLE are mutually exclusive"
);
if (flags & QSE_FIO_HANDLE)
{
/* QSE_FIO_TEMPORARY and QSE_FIO_HANDLE are mutually exclusive */
fio->errnum = QSE_FIO_EINVAL;
return -1;
}
temp_no = 0;
/* if QSE_FIO_TEMPORARY is used, the path name must
@ -258,6 +278,10 @@ int qse_fio_init (
if (flags & QSE_FIO_HANDLE)
{
handle = *(qse_fio_hnd_t*)path;
QSE_ASSERTX (
handle != INVALID_HANDLE_VALUE,
"Do not specify an invalid handle value"
);
}
else
{
@ -266,11 +290,21 @@ int qse_fio_init (
DWORD creation_disposition = 0;
DWORD flag_and_attr = FILE_ATTRIBUTE_NORMAL;
if (fellback) share_mode &= ~FILE_SHARE_DELETE;
if (flags & QSE_FIO_APPEND)
{
/* this is not officially documented for CreateFile.
* ZwCreateFile (kernel) seems to document it */
desired_access |= FILE_APPEND_DATA;
if (fellback)
{
desired_access |= GENERIC_WRITE;
}
else
{
/* this is not officially documented for CreateFile.
* ZwCreateFile (kernel) seems to document it */
fio->status &= ~STATUS_APPEND;
desired_access |= FILE_APPEND_DATA;
}
}
else if (flags & QSE_FIO_WRITE)
{
@ -318,12 +352,44 @@ int qse_fio_init (
QSE_NULL, /* set noinherit by setting no secattr */
creation_disposition, flag_and_attr, 0
);
}
if (handle == INVALID_HANDLE_VALUE)
{
if (flags & QSE_FIO_TEMPORARY) goto retry_temporary;
fio->errnum = syserr_to_errnum(GetLastError());
return -1;
if (handle == INVALID_HANDLE_VALUE)
{
DWORD e = GetLastError();
if (!fellback && e == ERROR_INVALID_PARAMETER &&
((share_mode & FILE_SHARE_DELETE) || (flags & QSE_FIO_APPEND)))
{
/* old windows fails with ERROR_INVALID_PARAMETER
* when some advanced flags are used. so try again
* with fallback flags */
fellback = 1;
share_mode &= ~FILE_SHARE_DELETE;
if (flags & QSE_FIO_APPEND)
{
fio->status |= STATUS_APPEND;
desired_access &= ~FILE_APPEND_DATA;
desired_access |= GENERIC_WRITE;
}
handle = CreateFile (
path, desired_access, share_mode,
QSE_NULL, /* set noinherit by setting no secattr */
creation_disposition, flag_and_attr, 0
);
if (handle == INVALID_HANDLE_VALUE)
{
if (flags & QSE_FIO_TEMPORARY) goto retry_temporary;
fio->errnum = syserr_to_errnum(GetLastError());
return -1;
}
}
else
{
if (flags & QSE_FIO_TEMPORARY) goto retry_temporary;
fio->errnum = syserr_to_errnum(e);
return -1;
}
}
}
/* some special check */
@ -383,6 +449,9 @@ int qse_fio_init (
zero.ulLo = 0;
zero.ulHi = 0;
if (flags & QSE_FIO_APPEND)
fio->stats |= STATUS_APPEND;
if (flags & QSE_FIO_CREATE)
{
if (flags & QSE_FIO_EXCLUSIVE)
@ -463,6 +532,10 @@ int qse_fio_init (
if (flags & QSE_FIO_HANDLE)
{
handle = *(qse_fio_hnd_t*)path;
QSE_ASSERTX (
handle >= 0,
"Do not specify an invalid handle value"
);
}
else
{
@ -544,6 +617,10 @@ int qse_fio_init (
if (flags & QSE_FIO_HANDLE)
{
handle = *(qse_fio_hnd_t*)path;
QSE_ASSERTX (
handle >= 0,
"Do not specify an invalid handle value"
);
}
else
{
@ -620,25 +697,23 @@ int qse_fio_init (
#else
if (path_mb != path_mb_buf) QSE_MMGR_FREE (mmgr, path_mb);
#endif
if (handle == -1)
{
if (flags & QSE_FIO_TEMPORARY) goto retry_temporary;
fio->errnum = syserr_to_errnum (errno);
return -1;
}
/* set some file access hints */
#if defined(POSIX_FADV_RANDOM)
if (flags & QSE_FIO_RANDOM)
posix_fadvise (handle, 0, 0, POSIX_FADV_RANDOM);
#endif
#if defined(POSIX_FADV_SEQUENTIAL)
if (flags & QSE_FIO_SEQUENTIAL)
posix_fadvise (handle, 0, 0, POSIX_FADV_SEQUENTIAL);
#endif
}
if (handle == -1)
{
if (flags & QSE_FIO_TEMPORARY) goto retry_temporary;
fio->errnum = syserr_to_errnum (errno);
return -1;
}
/* set some file access hints */
#if defined(POSIX_FADV_RANDOM)
if (flags & QSE_FIO_RANDOM)
posix_fadvise (handle, 0, 0, POSIX_FADV_RANDOM);
#endif
#if defined(POSIX_FADV_SEQUENTIAL)
if (flags & QSE_FIO_SEQUENTIAL)
posix_fadvise (handle, 0, 0, POSIX_FADV_SEQUENTIAL);
#endif
#endif
fio->handle = handle;
@ -647,7 +722,7 @@ int qse_fio_init (
void qse_fio_fini (qse_fio_t* fio)
{
if (!(fio->flags & QSE_FIO_NOCLOSE))
if (!(fio->status & STATUS_NOCLOSE))
{
#if defined(_WIN32)
CloseHandle (fio->handle);
@ -701,7 +776,7 @@ qse_fio_off_t qse_fio_seek (
QSE_ASSERT (QSE_SIZEOF(offset) <= QSE_SIZEOF(x.QuadPart));
/* SetFilePointerEx is not available on Windows NT 4.
* So let's use SetFilePointerEx */
* So let's use SetFilePointer */
#if 0
x.QuadPart = offset;
if (SetFilePointerEx (fio->handle, x, &y, seek_map[origin]) == FALSE)
@ -887,6 +962,14 @@ qse_ssize_t qse_fio_write (qse_fio_t* fio, const void* data, qse_size_t size)
#if defined(_WIN32)
DWORD count;
if (fio->status & STATUS_APPEND)
{
/* TODO: only when FILE_APPEND_DATA failed??? how do i know this??? */
/* i do this on a best-effort basis */
SetFilePointer (fio->handle, 0, QSE_NULL, FILE_END);
}
if (size > (QSE_TYPE_MAX(qse_ssize_t) & QSE_TYPE_MAX(DWORD)))
size = QSE_TYPE_MAX(qse_ssize_t) & QSE_TYPE_MAX(DWORD);
if (WriteFile (fio->handle,
@ -902,7 +985,7 @@ qse_ssize_t qse_fio_write (qse_fio_t* fio, const void* data, qse_size_t size)
APIRET ret;
ULONG count;
if (fio->flags & QSE_FIO_APPEND)
if (fio->status & STATUS_APPEND)
{
/* i do this on a best-effort basis */
LONGLONG pos, newpos;
@ -950,6 +1033,36 @@ static int get_devname_from_handle (
HANDLE map = NULL;
void* mem = NULL;
DWORD olen;
HINSTANCE psapi;
typedef DWORD (WINAPI*getmappedfilename_t) (
HANDLE hProcess,
LPVOID lpv,
LPTSTR lpFilename,
DWORD nSize
);
getmappedfilename_t getmappedfilename;
/* try to load psapi.dll dynamially for
* systems without it. direct linking to the library
* may end up with dependency failure on such systems.
* this way, the worst case is that this function simply
* fails. */
psapi = LoadLibrary (QSE_T("PSAPI.DLL"));
if (!psapi)
{
fio->errnum = syserr_to_errnum (GetLastError());
return -1;
}
getmappedfilename = (getmappedfilename_t)
GetProcAddress (psapi, QSE_T("GetMappedFileName"));
if (!getmappedfilename)
{
fio->errnum = syserr_to_errnum (GetLastError());
FreeLibrary (psapi);
return -1;
}
/* create a file mapping object */
map = CreateFileMapping (
@ -962,7 +1075,8 @@ static int get_devname_from_handle (
);
if (map == NULL)
{
mem = MapViewOfFile (map, FILE_MAP_READ, 0, 0, 1);
fio->errnum = syserr_to_errnum (GetLastError());
FreeLibrary (psapi);
return -1;
}
@ -972,20 +1086,23 @@ static int get_devname_from_handle (
{
fio->errnum = syserr_to_errnum (GetLastError());
CloseHandle (map);
FreeLibrary (psapi);
return -1;
}
olen = GetMappedFileName (GetCurrentProcess(), mem, buf, len);
olen = getmappedfilename (GetCurrentProcess(), mem, buf, len);
if (olen == 0)
{
fio->errnum = syserr_to_errnum (GetLastError());
UnmapViewOfFile (mem);
CloseHandle (map);
FreeLibrary (psapi);
return -1;
}
UnmapViewOfFile (mem);
CloseHandle (map);
FreeLibrary (psapi);
return 0;
}

View File

@ -27,9 +27,9 @@ int qse_runmain (
{
#if (defined(QSE_ACHAR_IS_MCHAR) && defined(QSE_CHAR_IS_MCHAR)) || \
(defined(QSE_ACHAR_IS_WCHAR) && defined(QSE_CHAR_IS_WCHAR))
{
return handler (argc, (qse_char_t**)argv);
}
return handler (argc, (qse_char_t**)argv);
#else
{
int i, ret;

View File

@ -221,7 +221,7 @@ struct param_t
qse_mchar_t** argv;
#if defined(QSE_CHAR_IS_MCHAR)
/* nothign extra */
/* nothing extra */
#else
qse_mchar_t fixed_mbuf[64];
#endif
@ -528,6 +528,9 @@ int qse_pio_init (
PROCESS_INFORMATION procinfo;
STARTUPINFO startup;
HANDLE windevnul = INVALID_HANDLE_VALUE;
BOOL apiret;
qse_char_t* dupcmd;
int create_retried;
#elif defined(__OS2__)
APIRET rc;
@ -549,7 +552,7 @@ int qse_pio_init (
#elif defined(HAVE_POSIX_SPAWN)
posix_spawn_file_actions_t fa;
int fa_inited = 0;
int spawn_ret;
int pserr;
qse_pio_pid_t pid;
param_t param;
extern char** environ;
@ -581,8 +584,14 @@ int qse_pio_init (
/* don't inherit write handle */
if (SetHandleInformation (handle[1], HANDLE_FLAG_INHERIT, 0) == FALSE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
DWORD e = GetLastError();
if (e != ERROR_CALL_NOT_IMPLEMENTED)
{
/* SetHandleInformation() is not implemented on win9x.
* so let's care only if it is implemented */
pio->errnum = syserr_to_errnum (e);
goto oops;
}
}
minidx = 0; maxidx = 1;
@ -600,8 +609,14 @@ int qse_pio_init (
/* don't inherit read handle */
if (SetHandleInformation (handle[2], HANDLE_FLAG_INHERIT, 0) == FALSE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
DWORD e = GetLastError();
if (e != ERROR_CALL_NOT_IMPLEMENTED)
{
/* SetHandleInformation() is not implemented on win9x.
* so let's care only if it is implemented */
pio->errnum = syserr_to_errnum (e);
goto oops;
}
}
if (minidx == -1) minidx = 2;
@ -620,8 +635,14 @@ int qse_pio_init (
/* don't inherit read handle */
if (SetHandleInformation (handle[4], HANDLE_FLAG_INHERIT, 0) == FALSE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
DWORD e = GetLastError();
if (e != ERROR_CALL_NOT_IMPLEMENTED)
{
/* SetHandleInformation() is not implemented on win9x.
* so let's care only if it is implemented */
pio->errnum = syserr_to_errnum (e);
goto oops;
}
}
if (minidx == -1) minidx = 4;
@ -664,12 +685,18 @@ int qse_pio_init (
startup.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
startup.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
startup.hStdOutput = GetStdHandle (STD_ERROR_HANDLE);
if (startup.hStdInput == INVALID_HANDLE_VALUE ||
startup.hStdOutput == INVALID_HANDLE_VALUE ||
startup.hStdError == INVALID_HANDLE_VALUE) goto oops;
startup.hStdError == INVALID_HANDLE_VALUE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
}
if (flags & QSE_PIO_WRITEIN) startup.hStdInput = handle[0];
if (flags & QSE_PIO_WRITEIN)
{
startup.hStdInput = handle[0];
}
if (flags & QSE_PIO_READOUT)
{
@ -696,72 +723,95 @@ int qse_pio_init (
/* there is nothing to do for QSE_PIO_SHELL as CreateProcess
* takes the entire command line */
create_retried = 0;
create_process:
if (flags & QSE_PIO_SHELL)
{
qse_char_t* dupcmd;
BOOL x;
static const qse_char_t* cmdname[] =
{
QSE_T("cmd.exe /c "),
QSE_T("command.com /c ")
};
static const qse_mchar_t* mcmdname[] =
{
QSE_MT("cmd.exe /c "),
QSE_MT("command.com /c ")
};
if (flags & QSE_PIO_SHELL)
#if defined(QSE_CHAR_IS_WCHAR)
if (flags & QSE_PIO_MBSCMD)
{
#if defined(QSE_CHAR_IS_WCHAR)
if (flags & QSE_PIO_MBSCMD)
{
const qse_mchar_t* x[3];
x[0] = QSE_MT("cmd.exe /c ");
x[1] = (const qse_mchar_t*)cmd;
x[2] = QSE_NULL;
dupcmd = qse_mbsatowcsdup (x, mmgr);
}
else
{
#endif
dupcmd = qse_strdup2 (QSE_T("cmd.exe /c "), cmd, mmgr);
#if defined(QSE_CHAR_IS_WCHAR)
}
#endif
const qse_mchar_t* x[3];
x[0] = mcmdname[create_retried];
x[1] = (const qse_mchar_t*)cmd;
x[2] = QSE_NULL;
dupcmd = qse_mbsatowcsdup (x, mmgr);
}
else
else
{
#if defined(QSE_CHAR_IS_WCHAR)
if (flags & QSE_PIO_MBSCMD)
{
dupcmd = qse_mbstowcsdup ((const qse_mchar_t*)cmd, mmgr);
}
else
{
#endif
/* CreateProcess requires command buffer to be read-write. */
dupcmd = qse_strdup (cmd, mmgr);
#if defined(QSE_CHAR_IS_WCHAR)
}
#endif
#endif
dupcmd = qse_strdup2 (cmdname[create_retried], cmd, mmgr);
#if defined(QSE_CHAR_IS_WCHAR)
}
#endif
}
else
{
#if defined(QSE_CHAR_IS_WCHAR)
if (flags & QSE_PIO_MBSCMD)
{
dupcmd = qse_mbstowcsdup ((const qse_mchar_t*)cmd, mmgr);
}
else
{
#endif
/* CreateProcess requires command buffer to be read-write. */
dupcmd = qse_strdup (cmd, mmgr);
#if defined(QSE_CHAR_IS_WCHAR)
}
#endif
}
if (dupcmd == QSE_NULL)
{
pio->errnum = QSE_PIO_ENOMEM;
goto oops;
}
apiret = CreateProcess (
QSE_NULL, /* LPCTSTR lpApplicationName */
dupcmd, /* LPTSTR lpCommandLine */
QSE_NULL, /* LPSECURITY_ATTRIBUTES lpProcessAttributes */
QSE_NULL, /* LPSECURITY_ATTRIBUTES lpThreadAttributes */
TRUE, /* BOOL bInheritHandles */
#ifdef QSE_CHAR_IS_MCHAR
0, /* DWORD dwCreationFlags */
#else
CREATE_UNICODE_ENVIRONMENT, /* DWORD dwCreationFlags */
#endif
(env? qse_env_getstr(env): QSE_NULL), /* LPVOID lpEnvironment */
QSE_NULL, /* LPCTSTR lpCurrentDirectory */
&startup, /* LPSTARTUPINFO lpStartupInfo */
&procinfo /* LPPROCESS_INFORMATION lpProcessInformation */
);
QSE_MMGR_FREE (mmgr, dupcmd);
if (apiret == FALSE)
{
DWORD e = GetLastError();
if (create_retried == 0 && (flags & QSE_PIO_SHELL) &&
e == ERROR_FILE_NOT_FOUND)
{
/* if it failed to exeucte cmd.exe,
* attempt to execute command.com.
* this is provision for old windows platforms */
create_retried = 1;
goto create_process;
}
if (dupcmd == QSE_NULL)
{
pio->errnum = QSE_PIO_ENOMEM;
goto oops;
}
x = CreateProcess (
QSE_NULL, /* LPCTSTR lpApplicationName */
dupcmd, /* LPTSTR lpCommandLine */
QSE_NULL, /* LPSECURITY_ATTRIBUTES lpProcessAttributes */
QSE_NULL, /* LPSECURITY_ATTRIBUTES lpThreadAttributes */
TRUE, /* BOOL bInheritHandles */
#ifdef QSE_CHAR_IS_MCHAR
0, /* DWORD dwCreationFlags */
#else
CREATE_UNICODE_ENVIRONMENT, /* DWORD dwCreationFlags */
#endif
(env? qse_env_getstr(env): QSE_NULL), /* LPVOID lpEnvironment */
QSE_NULL, /* LPCTSTR lpCurrentDirectory */
&startup, /* LPSTARTUPINFO lpStartupInfo */
&procinfo /* LPPROCESS_INFORMATION lpProcessInformation */
);
QSE_MMGR_FREE (mmgr, dupcmd);
if (x == FALSE)
pio->errnum = syserr_to_errnum (GetLastError());
pio->errnum = syserr_to_errnum (e);
goto oops;
}
if (windevnul != INVALID_HANDLE_VALUE)
@ -1124,6 +1174,7 @@ int qse_pio_init (
#elif defined(__DOS__)
/* DOS not multi-processed. can't support pio */
pio->errnum = QSE_PIO_ENOIMPL;
return -1;
#elif defined(HAVE_POSIX_SPAWN)
@ -1165,35 +1216,83 @@ int qse_pio_init (
goto oops;
}
if (posix_spawn_file_actions_init (&fa) != 0) goto oops;
if ((pserr = posix_spawn_file_actions_init (&fa)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
fa_inited = 1;
if (flags & QSE_PIO_WRITEIN)
{
/* child should read */
if (posix_spawn_file_actions_addclose (&fa, handle[1]) != 0) goto oops;
if (posix_spawn_file_actions_adddup2 (&fa, handle[0], 0) != 0) goto oops;
if (posix_spawn_file_actions_addclose (&fa, handle[0]) != 0) goto oops;
if ((pserr = posix_spawn_file_actions_addclose (&fa, handle[1])) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((pserr = posix_spawn_file_actions_adddup2 (&fa, handle[0]), 0) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((pserr = posix_spawn_file_actions_addclose (&fa, handle[0])) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
}
if (flags & QSE_PIO_READOUT)
{
/* child should write */
if (posix_spawn_file_actions_addclose (&fa, handle[2]) != 0) goto oops;
if (posix_spawn_file_actions_adddup2 (&fa, handle[3], 1) != 0) goto oops;
if ((pserr = posix_spawn_file_actions_addclose (&fa, handle[2])) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((pserr = posix_spawn_file_actions_adddup2 (&fa, handle[3], 1)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((flags & QSE_PIO_ERRTOOUT) &&
posix_spawn_file_actions_adddup2 (&fa, handle[3], 2) != 0) goto oops;
if (posix_spawn_file_actions_addclose (&fa, handle[3]) != 0) goto oops;
(pserr = posix_spawn_file_actions_adddup2 (&fa, handle[3], 2)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((pserr = posix_spawn_file_actions_addclose (&fa, handle[3])) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
}
if (flags & QSE_PIO_READERR)
{
/* child should write */
if (posix_spawn_file_actions_addclose (&fa, handle[4]) != 0) goto oops;
if (posix_spawn_file_actions_adddup2 (&fa, handle[5], 2) != 0) goto oops;
if ((pserr = posix_spawn_file_actions_addclose (&fa, handle[4])) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((pserr = posix_spawn_file_actions_adddup2 (&fa, handle[5], 2)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((flags & QSE_PIO_OUTTOERR) &&
posix_spawn_file_actions_adddup2 (&fa, handle[5], 1) != 0) goto oops;
if (posix_spawn_file_actions_addclose (&fa, handle[5]) != 0) goto oops;
(pserr = posix_spawn_file_actions_adddup2 (&fa, handle[5], 1)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((pserr = posix_spawn_file_actions_addclose (&fa, handle[5])) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
}
{
@ -1203,11 +1302,23 @@ int qse_pio_init (
#endif
if ((flags & QSE_PIO_INTONUL) &&
posix_spawn_file_actions_addopen (&fa, 0, QSE_MT("/dev/null"), oflags, 0) != 0) goto oops;
(pserr = posix_spawn_file_actions_addopen (&fa, 0, QSE_MT("/dev/null"), oflags, 0)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((flags & QSE_PIO_OUTTONUL) &&
posix_spawn_file_actions_addopen (&fa, 1, QSE_MT("/dev/null"), oflags, 0) != 0) goto oops;
(pserr = posix_spawn_file_actions_addopen (&fa, 1, QSE_MT("/dev/null"), oflags, 0)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((flags & QSE_PIO_ERRTONUL) &&
posix_spawn_file_actions_addopen (&fa, 2, QSE_MT("/dev/null"), oflags, 0) != 0) goto oops;
(pserr = posix_spawn_file_actions_addopen (&fa, 2, QSE_MT("/dev/null"), oflags, 0)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
}
/* there remains the chance of race condition that
@ -1216,11 +1327,23 @@ int qse_pio_init (
* just on the best-effort basis.
*/
if ((flags & QSE_PIO_DROPIN) && is_fd_valid(0) &&
posix_spawn_file_actions_addclose (&fa, 0) != 0) goto oops;
(pserr = posix_spawn_file_actions_addclose (&fa, 0)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((flags & QSE_PIO_DROPOUT) && is_fd_valid(1) &&
posix_spawn_file_actions_addclose (&fa, 1) != 0) goto oops;
(pserr = posix_spawn_file_actions_addclose (&fa, 1)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if ((flags & QSE_PIO_DROPERR) && is_fd_valid(2) &&
posix_spawn_file_actions_addclose (&fa, 2) != 0) goto oops;
(pserr = posix_spawn_file_actions_addclose (&fa, 2)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
if (!(flags & QSE_PIO_NOCLOEXEC))
{
@ -1236,7 +1359,11 @@ int qse_pio_init (
* with addclose() is closed before posix_spawn().
* addclose() if no FD_CLOEXEC is set or it's unknown. */
if (is_fd_valid_and_nocloexec(fd) &&
posix_spawn_file_actions_addclose (&fa, fd) != 0) goto oops;
(pserr = posix_spawn_file_actions_addclose (&fa, fd)) != 0)
{
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
}
}
@ -1251,7 +1378,7 @@ int qse_pio_init (
goto oops;
}
spawn_ret = posix_spawn(
pserr = posix_spawn(
&pid, param.argv[0], &fa, QSE_NULL, param.argv,
(env? qse_env_getarr(env): environ));
free_param (pio, &param);
@ -1260,9 +1387,9 @@ int qse_pio_init (
posix_spawn_file_actions_destroy (&fa);
fa_inited = 0;
}
if (spawn_ret != 0)
if (pserr != 0)
{
pio->errnum = syserr_to_errnum (errno);
pio->errnum = syserr_to_errnum (pserr);
goto oops;
}
@ -1287,20 +1414,32 @@ int qse_pio_init (
if (flags & QSE_PIO_WRITEIN)
{
if (QSE_PIPE(&handle[0]) <= -1) goto oops;
if (QSE_PIPE(&handle[0]) <= -1)
{
pio->errnum = syserr_to_errnum (errno);
goto oops;
}
minidx = 0; maxidx = 1;
}
if (flags & QSE_PIO_READOUT)
{
if (QSE_PIPE(&handle[2]) <= -1) goto oops;
if (QSE_PIPE(&handle[2]) <= -1)
{
pio->errnum = syserr_to_errnum (errno);
goto oops;
}
if (minidx == -1) minidx = 2;
maxidx = 3;
}
if (flags & QSE_PIO_READERR)
{
if (QSE_PIPE(&handle[4]) <= -1) goto oops;
if (QSE_PIPE(&handle[4]) <= -1)
{
pio->errnum = syserr_to_errnum (errno);
goto oops;
}
if (minidx == -1) minidx = 4;
maxidx = 5;
}
@ -1325,6 +1464,7 @@ int qse_pio_init (
pid = QSE_FORK();
if (pid <= -1)
{
pio->errnum = QSE_PIO_EINVAL;
free_param (pio, &param);
goto oops;
}
@ -1979,7 +2119,8 @@ int qse_pio_wait (qse_pio_t* pio)
child_rc.codeResult: (255 + 1 + child_rc.codeTerminate);
#elif defined(__DOS__)
/* TOOD: implement this */
pio->errnum = QSE_PIO_ENOIMPL;
return -1;
#else
@ -2099,7 +2240,8 @@ int qse_pio_kill (qse_pio_t* pio)
return 0;
#elif defined(__DOS__)
/* TODO: implement this*/
pio->errnum = QSE_PIO_ENOIMPL;
return -1;
#else

View File

@ -43,7 +43,6 @@ static qse_ssize_t socket_output (
static qse_sio_errnum_t fio_errnum_to_sio_errnum (qse_fio_t* fio)
{
/* TODO: finish this after adding fio->errnum */
switch (fio->errnum)
{
case QSE_FIO_ENOMEM:
@ -60,6 +59,8 @@ static qse_sio_errnum_t fio_errnum_to_sio_errnum (qse_fio_t* fio)
return QSE_SIO_EINTR;
case QSE_FIO_ESUBSYS:
return QSE_SIO_ESUBSYS;
case QSE_FIO_ENOIMPL:
return QSE_SIO_ENOIMPL;
default:
return QSE_SIO_EOTHER;
}
@ -422,42 +423,43 @@ qse_ssize_t qse_sio_putwcs (qse_sio_t* sio, const qse_wchar_t* str)
{
qse_ssize_t n;
sio->errnum = QSE_SIO_ENOERR;
#if defined(_WIN32)
/* DAMN UGLY: See comment in qse_sio_putwcsn() */
if (sio->status)
{
DWORD mode;
if (GetConsoleMode (sio->u.file.handle, &mode) == FALSE)
{
n = qse_tio_writewcs (&sio->tio.io, str, (qse_size_t)-1);
if (n <= -1 && sio->errnum == QSE_SIO_ENOERR)
sio->errnum = tio_errnum_to_sio_errnum (&sio->tio.io);
return n;
}
else
if (GetConsoleMode (sio->u.file.handle, &mode) == TRUE &&
GetConsoleOutputCP() == CP_UTF8)
{
DWORD count, left;
const qse_wchar_t* cur;
if (qse_sio_flush (sio) <= -1) return -1; /* can't do buffering */
for (cur = str, left = qse_wcslen(str); left > 0; cur += count, left -= count)
{
if (WriteConsoleW (
sio->u.file.handle, cur, left,
&count, QSE_NULL) == FALSE)
{
sio->errnum = QSE_SIO_EOTHER;
sio->errnum = QSE_SIO_ESUBSYS;
return -1;
}
if (count == 0) break;
if (count > left)
{
sio->errnum = QSE_SIO_ESUBSYS;
return -1;
}
}
return cur - str;
}
}
#endif
sio->errnum = QSE_SIO_ENOERR;
n = qse_tio_writewcs (&sio->tio.io, str, (qse_size_t)-1);
if (n <= -1 && sio->errnum == QSE_SIO_ENOERR)
sio->errnum = tio_errnum_to_sio_errnum (&sio->tio.io);
@ -469,8 +471,6 @@ qse_ssize_t qse_sio_putwcsn (
{
qse_ssize_t n;
sio->errnum = QSE_SIO_ENOERR;
#if defined(_WIN32)
/* DAMN UGLY:
* WriteFile returns wrong number of bytes written if it is
@ -488,31 +488,46 @@ qse_ssize_t qse_sio_putwcsn (
{
DWORD mode;
if (GetConsoleMode (sio->u.file.handle, &mode) == FALSE)
{
n = qse_tio_writewcs (&sio->tio.io, str, size);
if (n <= -1 && sio->errnum == QSE_SIO_ENOERR)
sio->errnum = tio_errnum_to_sio_errnum (&sio->tio.io);
return n;
}
else
if (GetConsoleMode (sio->u.file.handle, &mode) == TRUE &&
GetConsoleOutputCP() == CP_UTF8)
{
DWORD count, left;
const qse_wchar_t* cur;
if (qse_sio_flush (sio) <= -1) return -1; /* can't do buffering */
for (cur = str, left = size; left > 0; cur += count, left -= count)
{
if (WriteConsoleW (
sio->u.file.handle, cur, left,
&count, QSE_NULL) == FALSE) return -1;
&count, QSE_NULL) == FALSE)
{
sio->errnum = QSE_SIO_ESUBSYS;
return -1;
}
if (count == 0) break;
/* Note:
* WriteConsoleW() in unicosw.dll on win 9x/me returns
* the number of bytes via 'count'. If a double byte
* string is given, 'count' can be greater than 'left'.
* this case is a miserable failure. however, i don't
* think there is CP_UTF8 codepage for console on win9x/me.
* so let me make this function fail if that ever happens.
*/
if (count > left)
{
sio->errnum = QSE_SIO_ESUBSYS;
return -1;
}
}
return cur - str;
}
}
#endif
sio->errnum = QSE_SIO_ENOERR;
n = qse_tio_writewcs (&sio->tio.io, str, size);
if (n <= -1 && sio->errnum == QSE_SIO_ENOERR)
sio->errnum = tio_errnum_to_sio_errnum (&sio->tio.io);

View File

@ -48,8 +48,10 @@ qse_size_t qse_slwcrtoslmb (
#if defined(_WIN32)
int n;
/* CP_THREAD_ACP results in ERROR_INVALID_PARAMETER
* on an old windows os like win95 */
n = WideCharToMultiByte (
CP_THREAD_ACP, 0 /*WC_ERR_INVALID_CHARS*/,
CP_ACP/*CP_THREAD_ACP*/, 0 /*WC_ERR_INVALID_CHARS*/,
&wc, 1, mb, mbl, NULL, NULL);
if (n == 0)
{
@ -106,11 +108,11 @@ qse_size_t qse_slmbrtoslwc (
QSE_ASSERT (mb != QSE_NULL);
QSE_ASSERT (mbl > 0);
dbcslen = IsDBCSLeadByteEx(CP_THREAD_ACP, *mb)? 2: 1;
dbcslen = IsDBCSLeadByteEx(CP_ACP/*CP_THREAD_ACP*/, *mb)? 2: 1;
if (mbl < dbcslen) return mbl + 1; /* incomplete sequence */
n = MultiByteToWideChar (
CP_THREAD_ACP, MB_ERR_INVALID_CHARS, mb, dbcslen, wc, 1);
CP_ACP/*CP_THREAD_ACP*/, MB_ERR_INVALID_CHARS, mb, dbcslen, wc, 1);
if (n == 0)
{
/*DWORD e = GetLastError();*/
@ -184,7 +186,7 @@ qse_size_t qse_slmbrlen (
* the actual sequence. So it can't actually detect an invalid
* sequence. Thus, qse_slmbrtowc() may return a different length
* for an invalid sequence form qse_slmbrlen(). */
dbcslen = IsDBCSLeadByteEx(CP_THREAD_ACP, *mb)? 2: 1;
dbcslen = IsDBCSLeadByteEx(CP_ACP/*CP_THREAD_ACP*/, *mb)? 2: 1;
if (mbl < dbcslen) return mbl + 1; /* incomplete sequence */
return dbcslen;

View File

@ -204,6 +204,7 @@ SHELL = @SHELL@
SOCKET_LIBS = @SOCKET_LIBS@
STRIP = @STRIP@
TRUE = @TRUE@
UNICOWS_LIBS = @UNICOWS_LIBS@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@

View File

@ -186,6 +186,7 @@ SHELL = @SHELL@
SOCKET_LIBS = @SOCKET_LIBS@
STRIP = @STRIP@
TRUE = @TRUE@
UNICOWS_LIBS = @UNICOWS_LIBS@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@

View File

@ -381,10 +381,10 @@ static qse_httpd_task_t* entask_error (
return qse_httpd_entaskformat (
httpd, client, task,
QSE_MT("HTTP/%d.%d %d %s\r\nConnection: %s\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
QSE_MT("HTTP/%d.%d %d %s\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"),
version->major, version->minor, code, smsg,
(keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(int)qse_mbslen(lmsg) + 4, lmsg
(unsigned long)qse_mbslen(lmsg) + 4, lmsg
);
}
@ -415,12 +415,18 @@ qse_httpd_task_t* qse_httpd_entaskauth (
qse_httpd_t* httpd, qse_httpd_client_t* client,
const qse_httpd_task_t* task, const qse_mchar_t* realm, qse_htre_t* req)
{
const qse_http_version_t* version = qse_htre_getversion(req);
/* TODO: */
const qse_http_version_t* version;
const qse_mchar_t* lmsg;
version = qse_htre_getversion(req);
lmsg = QSE_MT("<html><head><title>Unauthorized</title></head><body><b>UNAUTHORIZED<b></body></html>");
return qse_httpd_entaskformat (
httpd, client, task,
QSE_MT("HTTP/%d.%d 401 Unauthorized\r\nContent-Length: 0\r\nWWW-Authenticate: Digest realm=\"%s\", qop=\"auth\", nonce=\"%s\""),
version->major, version->minor);
QSE_MT("HTTP/%d.%d 401 Unauthorized\r\nConnection: %s\r\nWWW-Authenticate: Basic realm=\"%s\"\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"),
version->major, version->minor,
(req->attr.keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
realm, (unsigned long)qse_mbslen(lmsg) + 4, lmsg);
}
/*------------------------------------------------------------------------*/
@ -816,7 +822,7 @@ static QSE_INLINE int task_main_path_dir (
{
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: keep-alive\r\nContent-Type: text/html;charset=utf-8\r\nTransfer-Encoding: chunked\r\n\r\n"),
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: keep-alive\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\n\r\n"),
data->version.major, data->version.minor
);
if (x) x = qse_httpd_entaskdir (httpd, client, x, handle, data->keepalive);
@ -825,7 +831,7 @@ static QSE_INLINE int task_main_path_dir (
{
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: close\r\nContent-Type: text/html;charset=utf-8\r\n\r\n"),
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n"),
data->version.major, data->version.minor
);

View File

@ -204,6 +204,7 @@ SHELL = @SHELL@
SOCKET_LIBS = @SOCKET_LIBS@
STRIP = @STRIP@
TRUE = @TRUE@
UNICOWS_LIBS = @UNICOWS_LIBS@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@

View File

@ -186,6 +186,7 @@ SHELL = @SHELL@
SOCKET_LIBS = @SOCKET_LIBS@
STRIP = @STRIP@
TRUE = @TRUE@
UNICOWS_LIBS = @UNICOWS_LIBS@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@