added qse_dir_t.

added qse_mux_t.
added dir::xxx() for awk
This commit is contained in:
2012-11-09 17:31:33 +00:00
parent a3ee069804
commit 7e509d4daa
40 changed files with 3448 additions and 1167 deletions

View File

@ -412,11 +412,6 @@ int qse_awk_clear (qse_awk_t* awk)
return 0;
}
void qse_awk_setmmgr (qse_awk_t* awk, qse_mmgr_t* mmgr)
{
awk->mmgr = mmgr;
}
qse_mmgr_t* qse_awk_getmmgr (qse_awk_t* awk)
{
return awk->mmgr;

View File

@ -28,6 +28,7 @@ libqsecmn_la_SOURCES = \
alg-sort.c \
assert.c \
chr.c \
dir.c \
dll.c \
env.c \
gdl.c \
@ -46,6 +47,7 @@ libqsecmn_la_SOURCES = \
mbwc.c \
mbwc-str.c \
mem.c \
mux.c \
nwad.c \
nwif.c \
nwio.c \

View File

@ -88,11 +88,11 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libqsecmn_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \
alg-sort.c assert.c chr.c dll.c env.c gdl.c htb.c fio.c fma.c \
fmt.c fs.c fs-err.c fs-move.c glob.c hton.c ipad.c lda.c \
main.c mbwc.c mbwc-str.c mem.c nwad.c nwif.c nwio.c oht.c \
opt.c path-basename.c path-canon.c pio.c pma.c rbt.c rex.c \
sio.c sll.c slmb.c stdio.c str-beg.c str-cat.c str-chr.c \
alg-sort.c assert.c chr.c dir.c dll.c env.c gdl.c htb.c fio.c \
fma.c fmt.c fs.c fs-err.c fs-move.c glob.c hton.c ipad.c lda.c \
main.c mbwc.c mbwc-str.c mem.c mux.c nwad.c nwif.c nwio.c \
oht.c opt.c path-basename.c path-canon.c pio.c pma.c rbt.c \
rex.c sio.c sll.c slmb.c stdio.c str-beg.c str-cat.c str-chr.c \
str-cnv.c str-cmp.c str-cpy.c str-del.c str-dup.c str-dynm.c \
str-dynw.c str-end.c str-excl.c str-fcpy.c str-fnmat.c \
str-incl.c str-len.c str-pac.c str-pbrk.c str-put.c str-rev.c \
@ -103,10 +103,10 @@ am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \
xma.c cp949.c cp950.c
@INCLUDE_MORE_CMGRS_TRUE@am__objects_1 = cp949.lo cp950.lo
am_libqsecmn_la_OBJECTS = alg-base64.lo alg-rand.lo alg-search.lo \
alg-sort.lo assert.lo chr.lo dll.lo env.lo gdl.lo htb.lo \
fio.lo fma.lo fmt.lo fs.lo fs-err.lo fs-move.lo glob.lo \
alg-sort.lo assert.lo chr.lo dir.lo dll.lo env.lo gdl.lo \
htb.lo fio.lo fma.lo fmt.lo fs.lo fs-err.lo fs-move.lo glob.lo \
hton.lo ipad.lo lda.lo main.lo mbwc.lo mbwc-str.lo mem.lo \
nwad.lo nwif.lo nwio.lo oht.lo opt.lo path-basename.lo \
mux.lo nwad.lo nwif.lo nwio.lo oht.lo opt.lo path-basename.lo \
path-canon.lo pio.lo pma.lo rbt.lo rex.lo sio.lo sll.lo \
slmb.lo stdio.lo str-beg.lo str-cat.lo str-chr.lo str-cnv.lo \
str-cmp.lo str-cpy.lo str-del.lo str-dup.lo str-dynm.lo \
@ -350,9 +350,9 @@ noinst_HEADERS = \
tre-stack.h
libqsecmn_la_SOURCES = alg-base64.c alg-rand.c alg-search.c alg-sort.c \
assert.c chr.c dll.c env.c gdl.c htb.c fio.c fma.c fmt.c fs.c \
fs-err.c fs-move.c glob.c hton.c ipad.c lda.c main.c mbwc.c \
mbwc-str.c mem.c nwad.c nwif.c nwio.c oht.c opt.c \
assert.c chr.c dir.c dll.c env.c gdl.c htb.c fio.c fma.c fmt.c \
fs.c fs-err.c fs-move.c glob.c hton.c ipad.c lda.c main.c \
mbwc.c mbwc-str.c mem.c mux.c nwad.c nwif.c nwio.c oht.c opt.c \
path-basename.c path-canon.c pio.c pma.c rbt.c rex.c sio.c \
sll.c slmb.c stdio.c str-beg.c str-cat.c str-chr.c str-cnv.c \
str-cmp.c str-cpy.c str-del.c str-dup.c str-dynm.c str-dynw.c \
@ -455,6 +455,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp949.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp950.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dir.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dll.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fio.Plo@am__quote@
@ -473,6 +474,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbwc-str.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbwc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mux.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nwad.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nwif.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nwio.Plo@am__quote@

536
qse/lib/cmn/dir.c Normal file
View File

@ -0,0 +1,536 @@
/*
* $Id$
*
Copyright 2006-2012 Chung, Hyung-Hwan.
This file is part of QSE.
QSE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
QSE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/
#include <qse/cmn/dir.h>
#include <qse/cmn/str.h>
#include <qse/cmn/mbwc.h>
#include <qse/cmn/path.h>
#include "mem.h"
#if defined(_WIN32)
# include <windows.h>
#elif defined(__OS2__)
# define INCL_DOSFILEMGR
# define INCL_ERRORS
# include <os2.h>
#elif defined(__DOS__)
# include <dos.h>
# include <errno.h>
#else
# include "syscall.h"
#endif
struct qse_dir_t
{
qse_mmgr_t* mmgr;
int flags;
qse_str_t tbuf;
qse_mbs_t mbuf;
#if defined(_WIN32)
HANDLE h;
WIN32_FIND_DATA wfd;
int done;
#elif defined(__OS2__)
HDIR h;
FILEFINDBUF3L ffb;
ULONG count;
int opened;
#elif defined(__DOS__)
struct find_t f;
int done;
int opened;
#else
DIR* dp;
#endif
};
int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* path, int flags);
void qse_dir_fini (qse_dir_t* dir);
static int reset_to_path (qse_dir_t* dir, const qse_char_t* path);
qse_dir_t* qse_dir_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, const qse_char_t* path, int flags)
{
qse_dir_t* dir;
dir = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(*dir) + xtnsize);
if (dir)
{
if (qse_dir_init (dir, mmgr, path, flags) <= -1)
{
QSE_MMGR_FREE (mmgr, dir);
dir = QSE_NULL;
}
else QSE_MEMSET (dir + 1, 0, xtnsize);
}
return dir;
}
void qse_dir_close (qse_dir_t* dir)
{
qse_dir_fini (dir);
QSE_MMGR_FREE (dir->mmgr, dir);
}
qse_mmgr_t* qse_dir_getmmgr (qse_dir_t* dir)
{
return dir->mmgr;
}
void* qse_dir_getxtn (qse_dir_t* dir)
{
return QSE_XTN (dir);
}
int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* path, int flags)
{
QSE_MEMSET (dir, 0, QSE_SIZEOF(*dir));
dir->mmgr = mmgr;
dir->flags = flags;
if (qse_str_init (&dir->tbuf, mmgr, 256) <= -1) return -1;
if (qse_mbs_init (&dir->mbuf, mmgr, 256) <= -1)
{
qse_str_fini (&dir->tbuf);
return -1;
}
#if defined(_WIN32)
dir->h = INVALID_HANDLE_VALUE;
#endif
return reset_to_path (dir, path);
}
static void close_dir_safely (qse_dir_t* dir)
{
#if defined(_WIN32)
if (dir->h != INVALID_HANDLE_VALUE)
{
FindClose (dir->h);
dir->h = INVALID_HANDLE_VALUE;
}
#elif defined(__OS2__)
if (dir->opened)
{
DosFindClose (dir->h);
dir->opened = 0;
}
#elif defined(__DOS__)
if (dir->opened)
{
_dos_findclose (&dir->f);
dir->opened = 0;
}
#else
if (dir->dp)
{
QSE_CLOSEDIR (dir->dp);
dir->dp = QSE_NULL;
}
#endif
}
void qse_dir_fini (qse_dir_t* dir)
{
close_dir_safely (dir);
qse_mbs_fini (&dir->mbuf);
qse_str_fini (&dir->tbuf);
}
static qse_mchar_t* wcs_to_mbuf (qse_dir_t* dir, const qse_wchar_t* wcs, qse_mbs_t* mbs)
{
qse_size_t ml, wl;
if (qse_wcstombs (wcs, &wl, QSE_NULL, &ml) <= -1 ||
qse_mbs_setlen (mbs, ml) == (qse_size_t)-1) return QSE_NULL;
qse_wcstombs (wcs, &wl, QSE_MBS_PTR(mbs), &ml);
return QSE_MBS_PTR(mbs);
}
static qse_wchar_t* mbs_to_wbuf (qse_dir_t* dir, const qse_mchar_t* mbs, qse_wcs_t* wcs)
{
qse_size_t ml, wl;
if (qse_mbstowcs (mbs, &ml, QSE_NULL, &wl) <= -1 ||
qse_wcs_setlen (wcs, wl) == (qse_size_t)-1) return QSE_NULL;
qse_mbstowcs (mbs, &ml, QSE_WCS_PTR(wcs), &wl);
return QSE_WCS_PTR(wcs);
}
static qse_mchar_t* make_mbsdos_path (qse_dir_t* dir, const qse_mchar_t* mpath)
{
if (mpath[0] == QSE_MT('\0'))
{
if (qse_mbs_cpy (&dir->mbuf, QSE_MT("*.*")) == (qse_size_t)-1) return QSE_NULL;
}
else
{
qse_size_t len;
if ((len = qse_mbs_cpy (&dir->mbuf, mpath)) == (qse_size_t)-1 ||
(!QSE_ISPATHMBSEP(mpath[len - 1]) &&
!qse_ismbsdrivecurpath(mpath) &&
qse_mbs_ccat (&dir->mbuf, QSE_MT('\\')) == (qse_size_t)-1) ||
qse_mbs_cat (&dir->mbuf, QSE_MT("*.*")) == (qse_size_t)-1)
{
return QSE_NULL;
}
}
return QSE_MBS_PTR(&dir->mbuf);
}
static qse_char_t* make_dos_path (qse_dir_t* dir, const qse_char_t* path)
{
if (path[0] == QSE_T('\0'))
{
if (qse_str_cpy (&dir->tbuf, QSE_T("*.*")) == (qse_size_t)-1) return QSE_NULL;
}
else
{
qse_size_t len;
if ((len = qse_str_cpy (&dir->tbuf, path)) == (qse_size_t)-1 ||
(!QSE_ISPATHSEP(path[len - 1]) &&
!qse_isdrivecurpath(path) &&
qse_str_ccat (&dir->tbuf, QSE_T('\\')) == (qse_size_t)-1) ||
qse_str_cat (&dir->tbuf, QSE_T("*.*")) == (qse_size_t)-1)
{
return QSE_NULL;
}
}
return QSE_STR_PTR(&dir->tbuf);
}
static qse_mchar_t* mkdospath (qse_dir_t* dir, const qse_char_t* path)
{
#if defined(QSE_CHAR_IS_MCHAR)
return make_dos_path (dir, path);
#else
if (dir->flags & QSE_DIR_MBSPATH)
{
return make_mbsdos_path (dir, (const qse_mchar_t*) path);
}
else
{
qse_char_t* tptr;
qse_mchar_t* mptr;
tptr = make_dos_path (dir, path);
if (tptr == QSE_NULL) return QSE_NULL;
mptr = wcs_to_mbuf (dir, QSE_STR_PTR(&dir->tbuf), &dir->mbuf);
if (mptr == QSE_NULL) return QSE_NULL;
return mptr;
}
#endif
}
static int reset_to_path (qse_dir_t* dir, const qse_char_t* path)
{
#if defined(_WIN32)
/* ------------------------------------------------------------------- */
qse_char_t* tptr;
dir->done = 0;
#if defined(QSE_CHAR_IS_MCHAR)
tptr = make_dos_path (dir, path);
#else
if (dir->flags & QSE_DIR_MBSPATH)
{
qse_mchar_t* mptr = make_mbsdos_path (dir, (const qse_mchar_t*) path);
if (mptr == QSE_NULL) return -1;
tptr = mbs_to_wbuf (dir, mptr, &dir->tbuf);
}
else
{
tptr = make_dos_path (dir, path);
if (tptr == QSE_NULL) return -1;
}
#endif
if (tptr == QSE_NULL) return -1;
dir->h = FindFirstFile (tptr, &dir->wfd);
if (dir->h == INVALID_HANDLE_VALUE) return -1;
return 0;
/* ------------------------------------------------------------------- */
#elif defined(__OS2__)
/* ------------------------------------------------------------------- */
APIRET rc;
qse_mchar_t* mptr;
dir->h = HDIR_CREATE;
dir->count = 1;
#if defined(QSE_CHAR_IS_MCHAR)
mptr = make_dos_path (dir, path);
#else
if (dir->flags & QSE_DIR_MBSPATH)
{
mptr = make_mbsdos_path (dir, (const qse_mchar_t*) path);
}
else
{
qse_char_t* tptr = make_dos_path (dir, path);
if (tptr == QSE_NULL) return -1;
mptr = wcs_to_mbuf (dir, tptr, &dir->mbuf);
}
#endif
if (mptr == QSE_NULL) return -1;
rc = DosFindFirst (
mptr,
&dir->h,
FILE_DIRECTORY | FILE_READONLY,
&dir->ffb,
QSE_SIZEOF(dir->ffb),
&dir->count,
FIL_STANDARDL);
if (rc != NO_ERROR) return -1;
dir->opened = 1;
return 0;
/* ------------------------------------------------------------------- */
#elif defined(__DOS__)
/* ------------------------------------------------------------------- */
unsigned int rc;
qse_mchar_t* mptr;
dir->done = 0;
#if defined(QSE_CHAR_IS_MCHAR)
mptr = make_dos_path (dir, path);
#else
if (dir->flags & QSE_DIR_MBSPATH)
{
mptr = make_mbsdos_path (dir, (const qse_mchar_t*) path);
}
else
{
qse_char_t* tptr = make_dos_path (dir, path);
if (tptr == QSE_NULL) return -1;
mptr = wcs_to_mbuf (dir, tptr, &dir->mbuf);
}
#endif
if (mptr == QSE_NULL) return -1;
rc = _dos_findfirst (mptr, _A_NORMAL | _A_SUBDIR, &dir->f);
if (rc != 0) return -1;
dir->opened = 1;
return 0;
/* ------------------------------------------------------------------- */
#else
DIR* dp;
#if defined(QSE_CHAR_IS_MCHAR)
dp = QSE_OPENDIR (path[0] == QSE_MT('\0')? QSE_T("."): path);
#else
if (dir->flags & QSE_DIR_MBSPATH)
{
const qse_mchar_t* mpath = (const qse_mchar_t*)path;
dp = QSE_OPENDIR (mpath == QSE_MT('\0')? QSE_MT("."): mpath);
}
else
{
if (path[0] == QSE_T('\0'))
{
dp = QSE_OPENDIR (QSE_MT("."));
}
else
{
qse_mchar_t* mptr;
mptr = wcs_to_mbuf (dir, path, &dir->mbuf);
if (mptr == QSE_NULL) return -1;
dp = QSE_OPENDIR (mptr);
}
}
#endif
dir->dp = dp;
return 0;
#endif
}
int qse_dir_reset (qse_dir_t* dir, const qse_char_t* path)
{
close_dir_safely (dir);
return reset_to_path (dir, path);
}
static int read_dir_to_tbuf (qse_dir_t* dir, void** name)
{
#if defined(_WIN32)
/* ------------------------------------------------------------------- */
if (dir->done) return (dir->done > 0)? 0: -1;
#if defined(QSE_CHAR_IS_MCHAR)
if (qse_str_cpy (&dir->tbuf, dir->wfd.cFileName) == (qse_size_t)-1) return -1;
*name = QSE_STR_PTR(&dir->tbuf);
#else
if (dir->flags & QSE_DIR_MBSPATH)
{
if (wcs_to_mbuf (dir, dir->wfd.cFileName, &dir->mbuf) == QSE_NULL) return -1;
*name = QSE_STR_PTR(&dir->mbuf);
}
else
{
if (qse_str_cpy (&dir->tbuf, dir->wfd.cFileName) == (qse_size_t)-1) return -1;
*name = QSE_STR_PTR(&dir->tbuf);
}
#endif
if (FindNextFile (dir->h, &dir->wfd) == FALSE)
dir->done = (GetLastError() == ERROR_NO_MORE_FILES)? 1: -1;
return 1;
/* ------------------------------------------------------------------- */
#elif defined(__OS2__)
/* ------------------------------------------------------------------- */
APIRET rc;
if (dir->count <= 0) return 0;
#if defined(QSE_CHAR_IS_MCHAR)
if (qse_str_cpy (&dir->tbuf, dir->ffb.achName) == (qse_size_t)-1) return -1;
*name = QSE_STR_PTR(&dir->tbuf);
#else
if (dir->flags & QSE_DIR_MBSPATH)
{
if (qse_mbs_cpy (&dir->mbuf, dir->ffb.achName) == (qse_size_t)-1) return -1;
*name = QSE_MBS_PTR(&dir->mbuf);
}
else
{
if (mbs_to_wbuf (dir, dir->ffb.achName, &dir->tbuf) == QSE_NULL) return -1;
*name = QSE_STR_PTR(&dir->tbuf);
}
#endif
rc = DosFindNext (dir->h, &dir->ffb, QSE_SIZEOF(dir->ffb), &dir->count);
if (rc == ERROR_NO_MORE_FILES) dir->count = 0;
else if (rc != NO_ERROR) return -1;
return 1;
/* ------------------------------------------------------------------- */
#elif defined(__DOS__)
/* ------------------------------------------------------------------- */
unsigned int rc;
if (dir->done) return (dir->done > 0)? 0: -1;
#if defined(QSE_CHAR_IS_MCHAR)
if (qse_str_cpy (&dir->tbuf, dir->f.name) == (qse_size_t)-1) return -1;
*name = QSE_STR_PTR(&dir->tbuf);
#else
if (dir->flags & QSE_DIR_MBSPATH)
{
if (qse_mbs_cpy (&dir->mbuf, dir->f.name) == (qse_size_t)-1) return -1;
*name = QSE_MBS_PTR(&dir->mbuf);
}
else
{
if (mbs_to_wbuf (dir, dir->f.name, &dir->tbuf) == QSE_NULL) return -1;
*name = QSE_STR_PTR(&dir->tbuf);
}
#endif
rc = _dos_findnext (&dir->f);
if (rc != 0) dir->done = (errno == ENOENT)? 1: -1;
return 1;
/* ------------------------------------------------------------------- */
#else
/* ------------------------------------------------------------------- */
qse_dirent_t* de;
errno = 0;
de = QSE_READDIR (dir->dp);
if (de == NULL) return (errno == 0)? 0: -1;
#if defined(QSE_CHAR_IS_MCHAR)
if (qse_str_cpy (&dir->tbuf, de->d_name) == (qse_size_t)-1) return -1;
*name = QSE_STR_PTR(&dir->tbuf);
#else
if (dir->flags & QSE_DIR_MBSPATH)
{
if (qse_mbs_cpy (&dir->mbuf, de->d_name) == (qse_size_t)-1) return -1;
*name = QSE_MBS_PTR(&dir->mbuf);
}
else
{
if (mbs_to_wbuf (dir, de->d_name, &dir->tbuf) == QSE_NULL) return -1;
*name = QSE_STR_PTR(&dir->tbuf);
}
#endif
return 1;
/* ------------------------------------------------------------------- */
#endif
}
int qse_dir_read (qse_dir_t* dir, qse_dir_ent_t* ent)
{
int x;
void* name;
x = read_dir_to_tbuf (dir, &name);
if (x >= 1)
{
QSE_MEMSET (ent, 0, QSE_SIZEOF(ent));
ent->name = name;
if (dir->flags & QSE_DIR_STAT)
{
/* TODO: more information */
}
}
return x;
}

View File

@ -22,6 +22,7 @@
#include <qse/cmn/str.h>
#include <qse/cmn/mbwc.h>
#include <qse/cmn/path.h>
#include <qse/cmn/dir.h>
#include "mem.h"
#if defined(_WIN32)
@ -44,17 +45,7 @@
# define IS_ESC(c) ((c) == QSE_T('\\'))
#endif
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
# define SEPC QSE_T('\\')
#else
# define SEPC QSE_T('/')
#endif
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
# define IS_SEP(c) ((c) == QSE_T('/') || (c) == QSE_T('\\'))
#else
# define IS_SEP(c) ((c) == QSE_T('/'))
#endif
#define IS_SEP(c) QSE_ISPATHSEP(c)
#define IS_NIL(c) ((c) == QSE_T('\0'))
#define IS_SEP_OR_NIL(c) (IS_SEP(c) || IS_NIL(c))
@ -83,7 +74,6 @@ struct glob_t
void* cbctx;
qse_mmgr_t* mmgr;
qse_cmgr_t* cmgr;
qse_str_t path;
qse_str_t tbuf; /* temporary buffer */
@ -108,10 +98,10 @@ static qse_mchar_t* wcs_to_mbuf (glob_t* g, const qse_wchar_t* wcs, qse_mbs_t* m
{
qse_size_t ml, wl;
if (qse_wcstombswithcmgr (wcs, &wl, QSE_NULL, &ml, g->cmgr) <= -1 ||
if (qse_wcstombs (wcs, &wl, QSE_NULL, &ml) <= -1 ||
qse_mbs_setlen (mbs, ml) == (qse_size_t)-1) return QSE_NULL;
qse_wcstombswithcmgr (wcs, &wl, QSE_MBS_PTR(mbs), &ml, g->cmgr);
qse_wcstombs (wcs, &wl, QSE_MBS_PTR(mbs), &ml);
return QSE_MBS_PTR(mbs);
}
@ -322,338 +312,6 @@ static int get_next_segment (glob_t* g, segment_t* seg)
return seg->type;
}
#if defined(_WIN32)
struct qse_dir_t
{
HANDLE h;
WIN32_FIND_DATA wfd;
int done;
};
typedef struct qse_dir_t qse_dir_t;
#elif defined(__OS2__)
struct qse_dir_t
{
HDIR h;
FILEFINDBUF3L ffb;
ULONG count;
};
typedef struct qse_dir_t qse_dir_t;
#elif defined(__DOS__)
struct qse_dir_t
{
struct find_t f;
int done;
};
typedef struct qse_dir_t qse_dir_t;
#endif
static qse_dir_t* xopendir (glob_t* g, const qse_cstr_t* path)
{
#if defined(_WIN32)
/* ------------------------------------------------------------------- */
qse_dir_t* dp;
dp = QSE_MMGR_ALLOC (g->mmgr, QSE_SIZEOF(*dp));
if (dp == QSE_NULL) return QSE_NULL;
dp->done = 0;
if (path->len <= 0)
{
if (qse_str_cpy (&g->tbuf, QSE_T("*")) == (qse_size_t)-1)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
}
else
{
if (qse_str_cpy (&g->tbuf, path->ptr) == (qse_size_t)-1 ||
(!IS_SEP(path->ptr[path->len-1]) &&
!qse_isdrivecurpath(path->ptr) &&
qse_str_ccat (&g->tbuf, QSE_T('\\')) == (qse_size_t)-1) ||
qse_str_ccat (&g->tbuf, QSE_T('*')) == (qse_size_t)-1)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
}
dp->h = FindFirstFile (QSE_STR_PTR(&g->tbuf), &dp->wfd);
if (dp->h == INVALID_HANDLE_VALUE)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
return dp;
/* ------------------------------------------------------------------- */
#elif defined(__OS2__)
/* ------------------------------------------------------------------- */
qse_dir_t* dp;
APIRET rc;
qse_mchar_t* mptr;
dp = QSE_MMGR_ALLOC (g->mmgr, QSE_SIZEOF(*dp));
if (dp == QSE_NULL) return QSE_NULL;
if (path->len <= 0)
{
if (qse_str_cpy (&g->tbuf, QSE_T("*.*")) == (qse_size_t)-1)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
}
else
{
if (qse_str_cpy (&g->tbuf, path->ptr) == (qse_size_t)-1 ||
(!IS_SEP(path->ptr[path->len-1]) &&
!qse_isdrivecurpath(path->ptr) &&
qse_str_ccat (&g->tbuf, QSE_T('\\')) == (qse_size_t)-1) ||
qse_str_cat (&g->tbuf, QSE_T("*.*")) == (qse_size_t)-1)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
}
dp->h = HDIR_CREATE;
dp->count = 1;
#if defined(QSE_CHAR_IS_MCHAR)
mptr = QSE_STR_PTR(&g->tbuf);
#else
mptr = wcs_to_mbuf (g, QSE_STR_PTR(&g->tbuf), &g->mbuf);
if (mptr == QSE_NULL)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
#endif
rc = DosFindFirst (
mptr,
&dp->h,
FILE_DIRECTORY | FILE_READONLY,
&dp->ffb,
QSE_SIZEOF(dp->ffb),
&dp->count,
FIL_STANDARDL);
if (rc != NO_ERROR)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
return dp;
/* ------------------------------------------------------------------- */
#elif defined(__DOS__)
/* ------------------------------------------------------------------- */
qse_dir_t* dp;
unsigned int rc;
qse_mchar_t* mptr;
qse_size_t wl, ml;
dp = QSE_MMGR_ALLOC (g->mmgr, QSE_SIZEOF(*dp));
if (dp == QSE_NULL) return QSE_NULL;
dp->done = 0;
if (path->len <= 0)
{
if (qse_str_cpy (&g->tbuf, QSE_T("*.*")) == (qse_size_t)-1)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
}
else
{
if (qse_str_cpy (&g->tbuf, path->ptr) == (qse_size_t)-1 ||
(!IS_SEP(path->ptr[path->len-1]) &&
!qse_isdrivecurpath(path->ptr) &&
qse_str_ccat (&g->tbuf, QSE_T('\\')) == (qse_size_t)-1) ||
qse_str_cat (&g->tbuf, QSE_T("*.*")) == (qse_size_t)-1)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
}
#if defined(QSE_CHAR_IS_MCHAR)
mptr = QSE_STR_PTR(&g->tbuf);
#else
mptr = wcs_to_mbuf (g, QSE_STR_PTR(&g->tbuf), &g->mbuf);
if (mptr == QSE_NULL)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
#endif
rc = _dos_findfirst (mptr, _A_NORMAL | _A_SUBDIR, &dp->f);
if (rc != 0)
{
QSE_MMGR_FREE (g->mmgr, dp);
return QSE_NULL;
}
return dp;
/* ------------------------------------------------------------------- */
#else
/* ------------------------------------------------------------------- */
#if defined(QSE_CHAR_IS_MCHAR)
return QSE_OPENDIR ((path->len <= 0)? QSE_T("."): path->ptr);
#else
if (path->len <= 0)
{
return QSE_OPENDIR (QSE_MT("."));
}
else
{
qse_mchar_t* mptr;
mptr = wcs_to_mbuf (g, path->ptr, &g->mbuf);
if (mptr == QSE_NULL) return QSE_NULL;
return QSE_OPENDIR (mptr);
}
#endif
/* ------------------------------------------------------------------- */
#endif
}
static int xreaddir (glob_t* g, qse_dir_t* dp, qse_str_t* path)
{
#if defined(_WIN32)
/* ------------------------------------------------------------------- */
if (dp->done) return (dp->done > 0)? 0: -1;
if (qse_str_cat (path, dp->wfd.cFileName) == (qse_size_t)-1) return -1;
if (FindNextFile (dp->h, &dp->wfd) == FALSE)
dp->done = (GetLastError() == ERROR_NO_MORE_FILES)? 1: -1;
return 1;
/* ------------------------------------------------------------------- */
#elif defined(__OS2__)
/* ------------------------------------------------------------------- */
APIRET rc;
#if defined(QSE_CHAR_IS_MCHAR)
/* nothing */
#else
qse_size_t ml, wl, tmp;
#endif
if (dp->count <= 0) return 0;
#if defined(QSE_CHAR_IS_MCHAR)
if (qse_str_cat (path, dp->ffb.achName) == (qse_size_t)-1) return -1;
#else
tmp = QSE_STR_LEN(path);
if (qse_mbstowcswithcmgr (dp->ffb.achName, &ml, QSE_NULL, &wl, g->cmgr) <= -1 ||
qse_str_setlen (path, tmp + wl) == (qse_size_t)-1) return -1;
qse_mbstowcswithcmgr (dp->ffb.achName, &ml, QSE_STR_CPTR(&g->path,tmp), &wl, g->cmgr);
#endif
rc = DosFindNext (dp->h, &dp->ffb, QSE_SIZEOF(dp->ffb), &dp->count);
if (rc == ERROR_NO_MORE_FILES) dp->count = 0;
else if (rc != NO_ERROR) return -1;
return 1;
/* ------------------------------------------------------------------- */
#elif defined(__DOS__)
/* ------------------------------------------------------------------- */
unsigned int rc;
#if defined(QSE_CHAR_IS_MCHAR)
/* nothing */
#else
qse_size_t ml, wl, tmp;
#endif
if (dp->done) return (dp->done > 0)? 0: -1;
#if defined(QSE_CHAR_IS_MCHAR)
if (qse_str_cat (path, dp->f.name) == (qse_size_t)-1) return -1;
#else
tmp = QSE_STR_LEN(path);
if (qse_mbstowcswithcmgr (dp->f.name, &ml, QSE_NULL, &wl, g->cmgr) <= -1 ||
qse_str_setlen (path, tmp + wl) == (qse_size_t)-1) return -1;
qse_mbstowcswithcmgr (dp->f.name, &ml, QSE_STR_CPTR(&g->path,tmp), &wl, g->cmgr);
#endif
rc = _dos_findnext (&dp->f);
if (rc != 0) dp->done = (errno == ENOENT)? 1: -1;
return 1;
/* ------------------------------------------------------------------- */
#else
/* ------------------------------------------------------------------- */
qse_dirent_t* de;
#if defined(QSE_CHAR_IS_MCHAR)
/* nothing */
#else
qse_size_t ml, wl, tmp;
#endif
de = QSE_READDIR (dp);
if (de == NULL) return 0;
#if defined(QSE_CHAR_IS_MCHAR)
if (qse_str_cat (path, de->d_name) == (qse_size_t)-1) return -1;
#else
tmp = QSE_STR_LEN(path);
if (qse_mbstowcswithcmgr (de->d_name, &ml, QSE_NULL, &wl, g->cmgr) <= -1 ||
qse_str_setlen (path, tmp + wl) == (qse_size_t)-1) return -1;
qse_mbstowcswithcmgr (de->d_name, &ml, QSE_STR_CPTR(&g->path,tmp), &wl, g->cmgr);
#endif
return 1;
/* ------------------------------------------------------------------- */
#endif
}
static void xclosedir (glob_t* g, qse_dir_t* dp)
{
#if defined(_WIN32)
FindClose (dp->h);
QSE_MMGR_FREE (g->mmgr, dp);
#elif defined(__OS2__)
DosFindClose (dp->h);
QSE_MMGR_FREE (g->mmgr, dp);
#elif defined(__DOS__)
_dos_findclose (&dp->f);
QSE_MMGR_FREE (g->mmgr, dp);
#else
QSE_CLOSEDIR (dp);
#endif
}
static int handle_non_wild_segments (glob_t* g, segment_t* seg)
{
while (get_next_segment(g, seg) != NONE && !seg->wild)
@ -731,6 +389,8 @@ static int search (glob_t* g, segment_t* seg)
{
qse_dir_t* dp;
qse_size_t tmp, tmp2;
qse_dir_ent_t ent;
int x;
#if defined(NO_RECURSION)
stack_node_t* r;
@ -744,7 +404,7 @@ entry:
if (seg->wild)
{
dp = xopendir (g, QSE_STR_CSTR(&g->path));
dp = qse_dir_open (g->mmgr, 0, QSE_STR_PTR(&g->path), 0);
if (dp)
{
tmp = QSE_STR_LEN(&g->path);
@ -756,7 +416,11 @@ entry:
{
qse_str_setlen (&g->path, tmp2);
if (xreaddir (g, dp, &g->path) <= 0) break;
x = qse_dir_read (dp, &ent);
if (x <= -1) goto oops;
if (x == 0) break;
if (qse_str_cat (&g->path, ent.name) == (qse_size_t)-1) goto oops;
if (qse_strnfnmat (QSE_STR_CPTR(&g->path,tmp2), seg->ptr, seg->len, g->fnmat_flags) > 0)
{
@ -810,7 +474,7 @@ entry:
}
qse_str_setlen (&g->path, tmp);
xclosedir (g, dp); dp = QSE_NULL;
qse_dir_close (dp); dp = QSE_NULL;
}
}
@ -850,14 +514,14 @@ entry:
return 0;
oops:
if (dp) xclosedir (g, dp);
if (dp) qse_dir_close (dp);
#if defined(NO_RECURSION)
while (g->stack)
{
r = g->stack;
g->stack = r->next;
xclosedir (g, r->dp);
qse_dir_close (r->dp);
QSE_MMGR_FREE (g->mmgr, r);
}
@ -871,7 +535,7 @@ oops:
return -1;
}
int qse_globwithcmgr (const qse_char_t* pattern, qse_glob_cbimpl_t cbimpl, void* cbctx, int flags, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr)
int qse_glob (const qse_char_t* pattern, qse_glob_cbimpl_t cbimpl, void* cbctx, int flags, qse_mmgr_t* mmgr)
{
segment_t seg;
glob_t g;
@ -881,7 +545,6 @@ int qse_globwithcmgr (const qse_char_t* pattern, qse_glob_cbimpl_t cbimpl, void*
g.cbimpl = cbimpl;
g.cbctx = cbctx;
g.mmgr = mmgr;
g.cmgr = cmgr;
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
g.fnmat_flags |= QSE_STRFNMAT_IGNORECASE;
@ -928,8 +591,3 @@ int qse_globwithcmgr (const qse_char_t* pattern, qse_glob_cbimpl_t cbimpl, void*
return g.expanded;
}
int qse_glob (const qse_char_t* pattern, qse_glob_cbimpl_t cbimpl, void* cbctx, int flags, qse_mmgr_t* mmgr)
{
return qse_globwithcmgr (pattern, cbimpl, cbctx, flags, mmgr, qse_getdflcmgr());
}

621
qse/lib/cmn/mux.c Normal file
View File

@ -0,0 +1,621 @@
/*
* $Id$
*
Copyright 2006-2012 Chung, Hyung-Hwan.
This file is part of QSE.
QSE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
QSE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/
#include <qse/cmn/mux.h>
#include "mem.h"
#if defined(_WIN32)
# define FD_SETSIZE 4096 /* what is the best value??? */
# include <winsock2.h>
# include <windows.h>
# define USE_SELECT
#elif defined(__OS2__)
# include <types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <tcpustd.h>
# include <sys/ioctl.h>
# include <nerrno.h>
# define INCL_DOSERRORS
# include <os2.h>
# pragma library("tcpip32.lib")
#elif defined(__DOS__)
# include <errno.h>
#else
# include <unistd.h>
# include <fcntl.h>
# include <errno.h>
# if defined(HAVE_SYS_EPOLL_H)
# include <sys/epoll.h>
# if defined(HAVE_EPOLL_CREATE)
# define USE_EPOLL
# endif
# elif defined(HAVE_POLL_H)
# define USE_POLL
# else
# define USE_SELECT
# endif
#endif
struct qse_mux_t
{
qse_mmgr_t* mmgr;
qse_mux_errnum_t errnum;
qse_mux_evtfun_t evtfun;
#if defined(USE_SELECT)
fd_set rset;
fd_set wset;
fd_set tmprset;
fd_set tmpwset;
int size;
int maxhnd;
struct
{
qse_mux_evt_t** ptr;
int ubound;
} me;
#elif defined(USE_EPOLL)
int fd;
struct
{
struct epoll_event* ptr;
qse_size_t len;
qse_size_t capa;
} ee;
struct
{
qse_mux_evt_t** ptr;
int ubound;
} me;
#endif
};
int qse_mux_init (qse_mux_t* mux, qse_mmgr_t* mmgr, qse_mux_evtfun_t evtfun, qse_size_t capahint);
void qse_mux_fini (qse_mux_t* mux);
#if defined(_WIN32)
static qse_mux_errnum_t syserr_to_errnum (DWORD e)
{
switch (e)
{
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OUTOFMEMORY:
return QSE_MUX_ENOMEM;
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_NAME:
return QSE_MUX_EINVAL;
case ERROR_ACCESS_DENIED:
return QSE_MUX_EACCES;
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
return QSE_MUX_ENOENT;
case ERROR_ALREADY_EXISTS:
case ERROR_FILE_EXISTS:
return QSE_MUX_EEXIST;
default:
return QSE_MUX_ESYSERR;
}
}
#elif defined(__OS2__)
static qse_mux_errnum_t syserr_to_errnum (APIRET e)
{
switch (e)
{
case ERROR_NOT_ENOUGH_MEMORY:
return QSE_MUX_ENOMEM;
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_NAME:
return QSE_MUX_EINVAL;
case ERROR_ACCESS_DENIED:
return QSE_MUX_EACCES;
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
return QSE_MUX_ENOENT;
case ERROR_ALREADY_EXISTS:
return QSE_MUX_EEXIST;
default:
return QSE_MUX_ESYSERR;
}
}
#elif defined(__DOS__)
static qse_mux_errnum_t syserr_to_errnum (int e)
{
switch (e)
{
case ENOMEM:
return QSE_MUX_ENOMEM;
case EINVAL:
return QSE_MUX_EINVAL;
case EACCES:
return QSE_MUX_EACCES;
case ENOENT:
return QSE_MUX_ENOENT;
case EEXIST:
return QSE_MUX_EEXIST;
default:
return QSE_MUX_ESYSERR;
}
}
#else
static qse_mux_errnum_t syserr_to_errnum (int e)
{
switch (e)
{
case ENOMEM:
return QSE_MUX_ENOMEM;
case EINVAL:
return QSE_MUX_EINVAL;
case ENOENT:
return QSE_MUX_ENOENT;
case EACCES:
return QSE_MUX_EACCES;
case EEXIST:
return QSE_MUX_EEXIST;
case EINTR:
return QSE_MUX_EINTR;
default:
return QSE_MUX_ESYSERR;
}
}
#endif
qse_mux_t* qse_mux_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, qse_mux_evtfun_t evtfun, qse_size_t capahint)
{
qse_mux_t* mux;
mux = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(*mux) + xtnsize);
if (mux)
{
if (qse_mux_init (mux, mmgr, evtfun, capahint) <= -1)
{
QSE_MMGR_FREE (mmgr, mux);
mux = QSE_NULL;
}
else QSE_MEMSET (mux + 1, 0, xtnsize);
}
return mux;
}
void qse_mux_close (qse_mux_t* mux)
{
qse_mux_fini (mux);
QSE_MMGR_FREE (mux->mmgr, mux);
}
int qse_mux_init (qse_mux_t* mux, qse_mmgr_t* mmgr, qse_mux_evtfun_t evtfun, qse_size_t capahint)
{
QSE_MEMSET (mux, 0, QSE_SIZEOF(*mux));
mux->mmgr = mmgr;
mux->evtfun = evtfun;
/* epoll_create returns an error and set errno to EINVAL
* if size is 0. Having a positive size greater than 0
* also makes easier other parts like maintaining internal
* event buffers */
if (capahint <= 0) capahint = 1;
#if defined(USE_SELECT)
FD_ZERO (&mux->rset);
FD_ZERO (&mux->wset);
mux->maxhnd = -1;
#elif defined(USE_EPOLL)
#if defined(HAVE_EPOLL_CREATE1) && defined(O_CLOEXEC)
mux->fd = epoll_create1 (O_CLOEXEC);
#else
mux->fd = epoll_create (capahint);
#endif
if (mux->fd <= -1)
{
mux->errnum = syserr_to_errnum (errno);
return -1;
}
#if defined(HAVE_EPOLL_CREATE1) && defined(O_CLOEXEC)
/* nothing to do */
#elif defined(FD_CLOEXEC)
{
int flag = fcntl (mux->fd, F_GETFD);
if (flag >= 0) fcntl (mux->fd, F_SETFD, flag | FD_CLOEXEC);
}
#endif
#else
/* TODO: */
mux->errnum = QSE_MUX_ENOIMPL;
return -1;
#endif
return 0;
}
void qse_mux_fini (qse_mux_t* mux)
{
#if defined(USE_SELECT)
FD_ZERO (&mux->rset);
FD_ZERO (&mux->wset);
if (mux->me.ptr)
{
int i;
for (i = 0; i < mux->me.ubound; i++)
{
if (mux->me.ptr[i])
QSE_MMGR_FREE (mux->mmgr, mux->me.ptr[i]);
}
QSE_MMGR_FREE (mux->mmgr, mux->me.ptr);
mux->me.ubound = 0;
mux->maxhnd = -1;
}
#elif defined(USE_EPOLL)
close (mux->fd);
if (mux->ee.ptr)
{
QSE_MMGR_FREE (mux->mmgr, mux->ee.ptr);
mux->ee.len = 0;
mux->ee.capa = 0;
}
if (mux->me.ptr)
{
int i;
for (i = 0; i < mux->me.ubound; i++)
{
if (mux->me.ptr[i])
QSE_MMGR_FREE (mux->mmgr, mux->me.ptr[i]);
}
QSE_MMGR_FREE (mux->mmgr, mux->me.ptr);
mux->me.ubound = 0;
}
#endif
}
qse_mmgr_t* qse_mux_getmmgr (qse_mux_t* mux)
{
return mux->mmgr;
}
void* qse_mux_getxtn (qse_mux_t* mux)
{
return QSE_XTN (mux);
}
#define ALIGN_TO(num,align) ((((num) + (align) - 1) / (align)) * (align))
int qse_mux_insert (qse_mux_t* mux, const qse_mux_evt_t* evt)
{
#if defined(USE_SELECT)
if (evt->hnd >= mux->me.ubound)
{
qse_mux_evt_t** tmp;
int ubound;
ubound = evt->hnd + 1;
ubound = ALIGN_TO (ubound, 128);
tmp = QSE_MMGR_REALLOC (mux->mmgr, mux->me.ptr, QSE_SIZEOF(*mux->me.ptr) * ubound);
if (tmp == QSE_NULL)
{
mux->errnum = QSE_MUX_ENOMEM;
return -1;
}
QSE_MEMSET (&tmp[mux->me.ubound], 0, QSE_SIZEOF(*mux->me.ptr) * (ubound - mux->me.ubound));
mux->me.ptr = tmp;
mux->me.ubound = ubound;
}
if (!mux->me.ptr[evt->hnd])
{
mux->me.ptr[evt->hnd] = QSE_MMGR_ALLOC (mux->mmgr, QSE_SIZEOF(*evt));
if (!mux->me.ptr[evt->hnd])
{
mux->errnum = QSE_MUX_ENOMEM;
return -1;
}
}
if (evt->mask & QSE_MUX_IN) FD_SET (evt->hnd, &mux->rset);
if (evt->mask & QSE_MUX_OUT) FD_SET (evt->hnd, &mux->wset);
*mux->me.ptr[evt->hnd] = *evt;
if (evt->hnd > mux->maxhnd) mux->maxhnd = evt->hnd;
mux->size++;
return 0;
#elif defined(USE_EPOLL)
struct epoll_event ev;
QSE_MEMSET (&ev, 0, QSE_SIZEOF(ev));
if (evt->mask & QSE_MUX_IN) ev.events |= EPOLLIN;
if (evt->mask & QSE_MUX_OUT) ev.events |= EPOLLOUT;
ev.data.fd = evt->hnd;
if (ev.events == 0 || evt->hnd < 0)
{
mux->errnum = QSE_MUX_EINVAL;
return -1;
}
if (evt->hnd >= mux->me.ubound)
{
qse_mux_evt_t** tmp;
int ubound;
ubound = evt->hnd + 1;
ubound = ALIGN_TO (ubound, 128);
tmp = QSE_MMGR_REALLOC (mux->mmgr, mux->me.ptr, QSE_SIZEOF(*mux->me.ptr) * ubound);
if (tmp == QSE_NULL)
{
mux->errnum = QSE_MUX_ENOMEM;
return -1;
}
QSE_MEMSET (&tmp[mux->me.ubound], 0, QSE_SIZEOF(*mux->me.ptr) * (ubound - mux->me.ubound));
mux->me.ptr = tmp;
mux->me.ubound = ubound;
}
if (!mux->me.ptr[evt->hnd])
{
mux->me.ptr[evt->hnd] = QSE_MMGR_ALLOC (mux->mmgr, QSE_SIZEOF(*evt));
if (!mux->me.ptr[evt->hnd])
{
mux->errnum = QSE_MUX_ENOMEM;
return -1;
}
}
if (mux->ee.len >= mux->ee.capa)
{
struct epoll_event* tmp;
qse_size_t newcapa;
newcapa = (mux->ee.capa + 1) * 2;
newcapa = ALIGN_TO (newcapa, 256);
tmp = QSE_MMGR_REALLOC (
mux->mmgr, mux->ee.ptr,
QSE_SIZEOF(*mux->ee.ptr) * newcapa);
if (tmp == QSE_NULL)
{
mux->errnum = QSE_MUX_ENOMEM;
return -1;
}
mux->ee.ptr = tmp;
mux->ee.capa = newcapa;
}
if (epoll_ctl (mux->fd, EPOLL_CTL_ADD, evt->hnd, &ev) == -1)
{
mux->errnum = syserr_to_errnum (errno);
return -1;
}
*mux->me.ptr[evt->hnd] = *evt;
mux->ee.len++;
return 0;
#else
/* TODO: */
mux->errnum = QSE_MUX_ENOIMPL;
return -1;
#endif
}
int qse_mux_delete (qse_mux_t* mux, const qse_mux_evt_t* evt)
{
#if defined(USE_SELECT)
qse_mux_evt_t* mevt;
if (mux->size <= 0 || evt->hnd < 0 || evt->hnd >= mux->me.ubound)
{
mux->errnum = QSE_MUX_EINVAL;
return -1;
}
mevt = mux->me.ptr[evt->hnd];
if (mevt->hnd != evt->hnd)
{
/* already deleted??? */
mux->errnum = QSE_MUX_EINVAL;
return -1;
}
if (mevt->mask & QSE_MUX_IN) FD_CLR (evt->hnd, &mux->rset);
if (mevt->mask & QSE_MUX_OUT) FD_CLR (evt->hnd, &mux->wset);
if (mevt->hnd == mux->maxhnd)
{
qse_mux_hnd_t i;
for (i = mevt->hnd; i > 0; )
{
i--;
if (mux->me.ptr[i] && mux->me.ptr[i]->hnd >= 0)
{
QSE_ASSERT (i == mux->me.ptr[i]->hnd);
mux->maxhnd = mux->me.ptr[i]->hnd;
goto done;
}
}
mux->maxhnd = -1;
QSE_ASSERT (mux->size == 1);
}
done:
mevt->hnd = -1;
mux->size--;
return 0;
#elif defined(USE_EPOLL)
if (mux->ee.len <= 0)
{
mux->errnum = QSE_MUX_EINVAL;
return -1;
}
if (epoll_ctl (mux->fd, EPOLL_CTL_DEL, evt->hnd, QSE_NULL) <= -1)
{
mux->errnum = syserr_to_errnum(errno);
return -1;
}
mux->ee.len--;
return 0;
#else
/* TODO */
mux->errnum = QSE_MUX_ENOIMPL;
return -1;
#endif
}
int qse_mux_poll (qse_mux_t* mux, qse_ntime_t timeout)
{
#if defined(USE_SELECT)
struct timeval tv;
int n;
tv.tv_sec = timeout / QSE_MSECS_PER_SEC;
tv.tv_usec = (timeout % QSE_MSECS_PER_SEC) * QSE_USECS_PER_MSEC;
mux->tmprset = mux->rset;
mux->tmpwset = mux->wset;
n = select (mux->maxhnd + 1, &mux->tmprset, &mux->tmpwset, QSE_NULL, &tv);
if (n <= -1)
{
#if defined(_WIN32)
mux->errnum = syserr_to_errnum(WSAGetLastError());
#else
mux->errnum = syserr_to_errnum(errno);
#endif
return -1;
}
if (n > 0)
{
qse_mux_hnd_t i;
qse_mux_evt_t* evt, xevt;
for (i = 0 ; i < mux->maxhnd; i++)
{
evt = mux->me.ptr[i];
if (!evt || evt->hnd != i) continue;
QSE_MEMCPY (&xevt, evt, QSE_SIZEOF(xevt));
xevt.mask = 0;
if ((evt->mask & QSE_MUX_IN) && FD_ISSET(evt->hnd, &mux->tmprset)) xevt.mask |= QSE_MUX_IN;
if ((evt->mask & QSE_MUX_OUT) && FD_ISSET(evt->hnd, &mux->tmpwset)) xevt.mask |= QSE_MUX_OUT;
if (xevt.mask > 0) mux->evtfun (mux, &xevt);
}
}
return n;
#elif defined(USE_EPOLL)
int nfds, hnd, i, mask;
qse_mux_evt_t* evt, xevt;
nfds = epoll_wait (mux->fd, mux->ee.ptr, mux->ee.len, timeout);
if (nfds <= -1)
{
mux->errnum = syserr_to_errnum(errno);
return -1;
}
for (i = 0; i < nfds; i++)
{
hnd = mux->ee.ptr[i].data.fd;
evt = mux->me.ptr[hnd];
QSE_ASSERT (evt->hnd == hnd);
QSE_MEMCPY (&xevt, evt, QSE_SIZEOF(xevt));
xevt.mask = 0;
if (mux->ee.ptr[i].events & EPOLLIN) xevt.mask |= QSE_MUX_IN;
if (mux->ee.ptr[i].events & EPOLLOUT) xevt.mask |= QSE_MUX_OUT;
if (mux->ee.ptr[i].events & EPOLLHUP)
{
if (evt->mask & QSE_MUX_IN)
xevt.mask |= QSE_MUX_IN;
if (evt->mask & QSE_MUX_OUT)
xevt.mask |= QSE_MUX_OUT;
}
mux->evtfun (mux, &xevt);
}
return nfds;
#else
/* TODO */
mux->errnum = QSE_MUX_ENOIMPL;
return -1;
#endif
}

View File

@ -20,13 +20,8 @@
#include <qse/cmn/path.h>
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
# define IS_MSEP(c) ((c) == QSE_MT('/') || (c) == QSE_MT('\\'))
# define IS_WSEP(c) ((c) == QSE_WT('/') || (c) == QSE_WT('\\'))
#else
# define IS_MSEP(c) ((c) == QSE_MT('/'))
# define IS_WSEP(c) ((c) == QSE_WT('/'))
#endif
#define IS_MSEP(c) QSE_ISPATHMBSEP(c)
#define IS_WSEP(c) QSE_ISPATHWCSEP(c)
const qse_mchar_t* qse_mbsbasename (const qse_mchar_t* path)
{

View File

@ -24,12 +24,7 @@
/* MBS IMPLEMENTATION */
/* ------------------------------------------------------------------ */
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
# define IS_MSEP(c) ((c) == QSE_MT('/') || (c) == QSE_MT('\\'))
#else
# define IS_MSEP(c) ((c) == QSE_MT('/'))
#endif
#define IS_MSEP(c) QSE_ISPATHMBSEP(c)
#define IS_MNIL(c) ((c) == QSE_MT('\0'))
#define IS_MSEP_OR_MNIL(c) (IS_MSEP(c) || IS_MNIL(c))

View File

@ -363,7 +363,6 @@
#endif
/* ===== DIRECTORY - not really system calls ===== */
typedef DIR qse_dir_t;
#define QSE_OPENDIR(name) opendir(name)
#define QSE_CLOSEDIR(name) closedir(name)

View File

@ -448,11 +448,6 @@ void qse_htrd_clear (qse_htrd_t* htrd)
clear_feed (htrd);
}
void qse_htrd_setmmgr (qse_htrd_t* htrd, qse_mmgr_t* mmgr)
{
htrd->mmgr = mmgr;
}
qse_mmgr_t* qse_htrd_getmmgr (qse_htrd_t* htrd)
{
return htrd->mmgr;

View File

@ -28,6 +28,8 @@
#include <qse/cmn/alg.h>
#include <qse/cmn/fmt.h>
#include <qse/cmn/path.h>
#include <qse/cmn/mux.h>
#include <qse/cmn/dir.h>
#if defined(_WIN32)
# include <winsock2.h>
@ -47,7 +49,7 @@
# if defined(HAVE_SYS_SENDFILE_H)
# include <sys/sendfile.h>
# endif
# if defined(HAVE_EPOLL) && defined(HAVE_SYS_EPOLL_H)
# if defined(HAVE_SYS_EPOLL_H)
# include <sys/epoll.h>
# endif
# if defined(__linux__)
@ -544,11 +546,15 @@ static int server_open (qse_httpd_t* httpd, qse_httpd_server_t* server)
fd = socket (SOCKADDR_FAMILY(&addr), SOCK_STREAM, IPPROTO_TCP);
if (fd <= -1) goto oops;
#if defined(FD_CLOEXEC)
flag = fcntl (fd, F_GETFD);
if (flag >= 0) fcntl (fd, F_SETFD, flag | FD_CLOEXEC);
#endif
#if defined(SO_REUSEADDR)
flag = 1;
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &flag, QSE_SIZEOF(flag));
#endif
/* TODO: linux. use capset() to set required capabilities just in case */
#if defined(IP_TRANSPARENT)
@ -621,21 +627,41 @@ IP_TRANSPRENT is needed for:
if (listen (fd, 10) <= -1) goto oops;
#if defined(O_NONBLOCK)
flag = fcntl (fd, F_GETFL);
if (flag >= 0) fcntl (fd, F_SETFL, flag | O_NONBLOCK);
#endif
server->handle.i = fd;
return 0;
oops:
#if defined(_WIN32)
qse_httpd_seterrnum (httpd, syserr_to_errnum(WSAGetLastError()));
if (fd != INVALID_SOCKET) closesocket (fd);
#elif defined(__OS2__)
qse_httpd_seterrnum (httpd, syserr_to_errnum(sock_errno()));
if (fd >= 0) soclose (fd);
#elif defined(__DOS__)
/* TODO: */
#else
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
if (fd >= 0) QSE_CLOSE (fd);
#endif
return -1;
}
static void server_close (qse_httpd_t* httpd, qse_httpd_server_t* server)
{
#if defined(_WIN32)
closesocket (server->handle.i);
#elif defined(__OS2__)
soclose (server->handle.i);
#elif defined(__DOS__)
/* TODO: */
#else
QSE_CLOSE (server->handle.i);
#endif
}
static int server_accept (
@ -643,7 +669,7 @@ static int server_accept (
{
sockaddr_t addr;
#ifdef HAVE_SOCKLEN_T
#if defined(HAVE_SOCKLEN_T)
socklen_t addrlen;
#else
int addrlen;
@ -667,12 +693,16 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
return -1;
}
#endif
#if defined(FD_CLOEXEC)
flag = fcntl (fd, F_GETFD);
if (flag >= 0) fcntl (fd, F_SETFD, flag | FD_CLOEXEC);
#endif
#if defined(O_NONBLOCK)
flag = fcntl (fd, F_GETFL);
if (flag >= 0) fcntl (fd, F_SETFL, flag | O_NONBLOCK);
#endif
if (sockaddr_to_nwad (&addr, &client->remote_addr) <= -1)
{
@ -721,10 +751,22 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
{
int fd = -1, flag;
sockaddr_t connaddr, bindaddr;
int connaddrsize, bindaddrsize;
int connected = 1;
#if defined(_WIN32)
SOCKET fd = -1;
unsigned long cmd;
#elif defined(__OS2__)
int fd = -1;
int flag;
#elif defined(__DOS__)
int fd = -1;
int flag;
#else
int fd = -1;
int flag;
#endif
connaddrsize = nwad_to_sockaddr (&peer->nwad, &connaddr);
bindaddrsize = nwad_to_sockaddr (&peer->local, &bindaddr);
@ -741,14 +783,37 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
flag = 1;
setsockopt (fd, SOL_IP, IP_TRANSPARENT, &flag, QSE_SIZEOF(flag));
#endif
if (bind (fd, (struct sockaddr*)&bindaddr, bindaddrsize) <= -1)
{
/* i won't care about binding faiulre */
/* TODO: some logging for this failure though */
}
#if defined(_WIN32)
cmd = 1;
if (ioctlsocket(fd, FIONBIO, &cmd) == SOCKET_ERROR) goto oops;
if (connect (fd, (struct sockaddr*)&connaddr, connaddrsize) <= -1)
{
if (WSAGetLastError() != WSAEWOULDBLOCK) goto oops;
connected = 0;
}
cmd = 0;
if (ioctlsocket(fd, FIONBIO, &cmd) == SOCKET_ERROR) goto oops;
#elif defined(__OS2__)
/* TODO: */
#elif defined(__DOS__)
/* TODO: */
#else
#if defined(FD_CLOEXEC)
flag = fcntl (fd, F_GETFD);
if (flag >= 0) fcntl (fd, F_SETFD, flag | FD_CLOEXEC);
#endif
flag = fcntl (fd, F_GETFL);
if (flag >= 0) fcntl (fd, F_SETFL, flag | O_NONBLOCK);
@ -761,32 +826,85 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
/* restore flags */
if (fcntl (fd, F_SETFL, flag) <= -1) goto oops;
#endif
peer->handle.i = fd;
return connected;
oops:
#if defined(_WIN32)
qse_httpd_seterrnum (httpd, syserr_to_errnum(WSAGetLastError()));
if (fd != INVALID_SOCKET) closesocket (fd);
#elif defined(__OS2__)
qse_httpd_seterrnum (httpd, syserr_to_errnum(sock_errno()));
if (fd >= 0) soclose (fd);
#elif defined(__DOS__)
/* TODO: */
#else
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
if (fd >= 0) QSE_CLOSE (fd);
#endif
return -1;
}
static void peer_close (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
{
#if defined(_WIN32)
closesocket (peer->handle.i);
#elif defined(__OS2__)
soclose (peer->handle.i);
#elif defined(__DOS__)
/* TODO: */
#else
QSE_CLOSE (peer->handle.i);
#endif
}
static int peer_connected (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
{
#ifdef HAVE_SOCKLEN_T
socklen_t len;
#else
#if defined(_WIN32)
int len;
#endif
DWORD ret;
len = QSE_SIZEOF(ret);
if (getsockopt (peer->handle.i, SOL_SOCKET, SO_ERROR, (char*)&ret, &len) == SOCKET_ERROR)
{
qse_httpd_seterrnum (httpd, syserr_to_errnum (ret));
return -1;
}
if (ret == WSAEWOULDBLOCK) return 0;
if (ret != 0)
{
qse_httpd_seterrnum (httpd, syserr_to_errnum (ret));
return -1;
}
return 1; /* connection completed */
#elif defined(__OS2__)
/* TODO */
httpd->errnum = QSE_HTTPD_ENOIMPL;
return -1;
#elif defined(__DOS__)
/* TODO */
httpd->errnum = QSE_HTTPD_ENOIMPL;
return -1;
#else
#if defined(HAVE_SOCKLEN_T)
socklen_t len;
#else
int len;
#endif
int ret;
len = QSE_SIZEOF(ret);
if (getsockopt (peer->handle.i, SOL_SOCKET, SO_ERROR, &ret, &len) <= -1) return -1;
if (getsockopt (peer->handle.i, SOL_SOCKET, SO_ERROR, &ret, &len) <= -1)
{
qse_httpd_seterrnum (httpd, syserr_to_errnum (ret));
return -1;
}
if (ret == EINPROGRESS) return 0;
if (ret != 0)
@ -796,13 +914,14 @@ static int peer_connected (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
}
return 1; /* connection completed */
#endif
}
static qse_ssize_t peer_recv (
qse_httpd_t* httpd, qse_httpd_peer_t* peer,
qse_mchar_t* buf, qse_size_t bufsize)
{
ssize_t ret = read (peer->handle.i, buf, bufsize);
ssize_t ret = recv (peer->handle.i, buf, bufsize, 0);
if (ret <= -1) qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
return ret;
}
@ -811,216 +930,101 @@ static qse_ssize_t peer_send (
qse_httpd_t* httpd, qse_httpd_peer_t* peer,
const qse_mchar_t* buf, qse_size_t bufsize)
{
ssize_t ret = write (peer->handle.i, buf, bufsize);
ssize_t ret = send (peer->handle.i, buf, bufsize, 0);
if (ret <= -1) qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
return ret;
}
/* ------------------------------------------------------------------- */
struct mux_ev_t
typedef struct mux_xtn_t mux_xtn_t;
struct mux_xtn_t
{
qse_ubi_t handle;
int reqmask;
qse_httpd_t* httpd;
qse_httpd_muxcb_t cbfun;
void* cbarg;
};
struct mux_t
static void dispatch_muxcb (qse_mux_t* mux, const qse_mux_evt_t* evt)
{
int fd;
mux_xtn_t* xtn;
qse_ubi_t ubi;
struct
{
struct epoll_event* ptr;
qse_size_t len;
qse_size_t capa;
} ee;
xtn = qse_mux_getxtn (mux);
ubi.i = evt->hnd;
xtn->cbfun (xtn->httpd, mux, ubi, evt->mask, evt->data);
}
struct
{
struct mux_ev_t** ptr;
qse_size_t capa;
} mev;
};
#define MUX_EV_ALIGN 64
static void* mux_open (qse_httpd_t* httpd)
static void* mux_open (qse_httpd_t* httpd, qse_httpd_muxcb_t cbfun)
{
struct mux_t* mux;
qse_mux_t* mux;
mux_xtn_t* xtn;
mux = qse_httpd_allocmem (httpd, QSE_SIZEOF(*mux));
if (mux == QSE_NULL) return QSE_NULL;
QSE_MEMSET (mux, 0, QSE_SIZEOF(*mux));
#if defined(HAVE_EPOLL_CREATE1) && defined(O_CLOEXEC)
mux->fd = epoll_create1 (O_CLOEXEC);
#else
mux->fd = epoll_create (100);
#endif
if (mux->fd <= -1)
mux = qse_mux_open (httpd->mmgr, QSE_SIZEOF(*xtn), dispatch_muxcb, 256);
if (!mux)
{
qse_httpd_freemem (httpd, mux);
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
/* TODO
qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux));
*/
return QSE_NULL;
}
#if defined(HAVE_EPOLL_CREATE1) && defined(O_CLOEXEC)
/* nothing else to do */
#else
{
int flag = fcntl (mux->fd, F_GETFD);
if (flag >= 0) fcntl (mux->fd, F_SETFD, flag | FD_CLOEXEC);
}
#endif
xtn = qse_mux_getxtn (mux);
xtn->httpd = httpd;
xtn->cbfun = cbfun;
return mux;
}
static void mux_close (qse_httpd_t* httpd, void* vmux)
{
struct mux_t* mux = (struct mux_t*)vmux;
if (mux->ee.ptr) qse_httpd_freemem (httpd, mux->ee.ptr);
if (mux->mev.ptr)
{
qse_size_t i;
for (i = 0; i < mux->mev.capa; i++)
if (mux->mev.ptr[i]) qse_httpd_freemem (httpd, mux->mev.ptr[i]);
qse_httpd_freemem (httpd, mux->mev.ptr);
}
QSE_CLOSE (mux->fd);
qse_httpd_freemem (httpd, mux);
qse_mux_close ((qse_mux_t*)vmux);
}
static int mux_addhnd (
qse_httpd_t* httpd, void* vmux, qse_ubi_t handle,
int mask, qse_httpd_muxcb_t cbfun, void* cbarg)
qse_httpd_t* httpd, void* vmux, qse_ubi_t handle, int mask, void* data)
{
struct mux_t* mux = (struct mux_t*)vmux;
struct epoll_event ev;
struct mux_ev_t* mev;
qse_mux_evt_t evt;
ev.events = 0;
if (mask & QSE_HTTPD_MUX_READ) ev.events |= EPOLLIN;
if (mask & QSE_HTTPD_MUX_WRITE) ev.events |= EPOLLOUT;
evt.hnd = handle.i;
evt.mask = 0;
if (mask & QSE_HTTPD_MUX_READ) evt.mask |= QSE_MUX_IN;
if (mask & QSE_HTTPD_MUX_WRITE) evt.mask |= QSE_MUX_OUT;
evt.data = data;
if (ev.events == 0 || handle.i <= -1)
if (qse_mux_insert ((qse_mux_t*)vmux, &evt) <= -1)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
/* TODO
qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux));
*/
return -1;
}
if (handle.i >= mux->mev.capa)
{
struct mux_ev_t** tmp;
qse_size_t tmpcapa, i;
tmpcapa = (((handle.i + MUX_EV_ALIGN) / MUX_EV_ALIGN) * MUX_EV_ALIGN);
tmp = (struct mux_ev_t**) qse_httpd_reallocmem (
httpd, mux->mev.ptr,
QSE_SIZEOF(*mux->mev.ptr) * tmpcapa);
if (tmp == QSE_NULL) return -1;
for (i = mux->mev.capa; i < tmpcapa; i++) tmp[i] = QSE_NULL;
mux->mev.ptr = tmp;
mux->mev.capa = tmpcapa;
}
if (mux->mev.ptr[handle.i] == QSE_NULL)
{
/* the location of the data passed to epoll_ctl()
* must not change unless i update the info with epoll()
* whenever there is reallocation. so i simply
* make mux-mev.ptr reallocatable but auctual
* data fixed once allocated. */
mux->mev.ptr[handle.i] = qse_httpd_allocmem (
httpd, QSE_SIZEOF(*mux->mev.ptr[handle.i]));
if (mux->mev.ptr[handle.i] == QSE_NULL) return -1;
}
if (mux->ee.len >= mux->ee.capa)
{
struct epoll_event* tmp;
tmp = qse_httpd_reallocmem (
httpd, mux->ee.ptr,
QSE_SIZEOF(*mux->ee.ptr) * (mux->ee.capa + 1) * 2);
if (tmp == QSE_NULL) return -1;
mux->ee.ptr = tmp;
mux->ee.capa = (mux->ee.capa + 1) * 2;
}
mev = mux->mev.ptr[handle.i];
mev->handle = handle;
mev->reqmask = mask;
mev->cbfun = cbfun;
mev->cbarg = cbarg;
ev.data.ptr = mev;
if (epoll_ctl (mux->fd, EPOLL_CTL_ADD, handle.i, &ev) <= -1)
{
/* don't rollback ee.ptr */
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
return -1;
}
mux->ee.len++;
return 0;
}
static int mux_delhnd (qse_httpd_t* httpd, void* vmux, qse_ubi_t handle)
{
struct mux_t* mux = (struct mux_t*)vmux;
if (epoll_ctl (mux->fd, EPOLL_CTL_DEL, handle.i, QSE_NULL) <= -1)
qse_mux_evt_t evt;
evt.hnd = handle.i;
if (qse_mux_delete ((qse_mux_t*)vmux, &evt) <= -1)
{
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
/* TODO
qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux));
*/
return -1;
}
mux->ee.len--;
return 0;
}
static int mux_poll (qse_httpd_t* httpd, void* vmux, qse_ntime_t timeout)
{
struct mux_t* mux = (struct mux_t*)vmux;
struct mux_ev_t* mev;
int mask, nfds, i;
nfds = epoll_wait (mux->fd, mux->ee.ptr, mux->ee.len, timeout);
if (nfds <= -1)
if (qse_mux_poll ((qse_mux_t*)vmux, timeout) <= -1)
{
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
/* TODO
qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux));
*/
return -1;
}
for (i = 0; i < nfds; i++)
{
mev = mux->ee.ptr[i].data.ptr;
mask = 0;
if (mux->ee.ptr[i].events & EPOLLIN)
mask |= QSE_HTTPD_MUX_READ;
if (mux->ee.ptr[i].events & EPOLLOUT)
mask |= QSE_HTTPD_MUX_WRITE;
if (mux->ee.ptr[i].events & EPOLLHUP)
{
if (mev->reqmask & QSE_HTTPD_MUX_READ)
mask |= QSE_HTTPD_MUX_READ;
if (mev->reqmask & QSE_HTTPD_MUX_WRITE)
mask |= QSE_HTTPD_MUX_WRITE;
}
mev->cbfun (httpd, mux, mev->handle, mask, mev->cbarg);
}
return 0;
}
@ -1064,11 +1068,24 @@ static int mux_writable (qse_httpd_t* httpd, qse_ubi_t handle, qse_ntoff_t msec)
/* ------------------------------------------------------------------- */
static int stat_file (
qse_httpd_t* httpd, const qse_mchar_t* path,
qse_httpd_stat_t* hst, int regonly)
{
#if defined(_WIN32)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__OS2__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__DOS__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
qse_stat_t st;
/* TODO: lstat? or stat? */
@ -1092,24 +1109,39 @@ static int stat_file (
hst->dev = st.st_dev;
hst->ino = st.st_ino;
hst->size = st.st_size;
#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
hst->mtime = QSE_SECNSEC_TO_MSEC(st.st_mtim.tv_sec,st.st_mtim.tv_nsec);
#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
hst->mtime = QSE_SECNSEC_TO_MSEC(st.st_mtimespec.tv_sec,st.st_mtimespec.tv_nsec);
#else
#else
hst->mtime = QSE_SEC_TO_MSEC(st.st_mtime);
#endif
#endif
return 0;
#endif
}
/* ------------------------------------------------------------------- */
static int file_executable (qse_httpd_t* httpd, const qse_mchar_t* path)
{
#if defined(_WIN32)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__OS2__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__DOS__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
if (access (path, X_OK) == -1)
return (errno == EACCES)? 0 /*no*/: -1 /*error*/;
return 1; /* yes */
#endif
}
static int file_stat (
@ -1121,13 +1153,27 @@ static int file_stat (
static int file_ropen (
qse_httpd_t* httpd, const qse_mchar_t* path, qse_ubi_t* handle)
{
#if defined(_WIN32)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__OS2__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__DOS__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
int fd;
int flags;
flags = O_RDONLY;
#if defined(O_LARGEFILE)
#if defined(O_LARGEFILE)
flags |= O_LARGEFILE;
#endif
#endif
qse_printf (QSE_T("opening file [%hs] for reading\n"), path);
fd = QSE_OPEN (path, flags, 0);
@ -1143,19 +1189,34 @@ qse_printf (QSE_T("opening file [%hs] for reading\n"), path);
handle->i = fd;
qse_printf (QSE_T("opened file %hs\n"), path);
return 0;
#endif
}
static int file_wopen (
qse_httpd_t* httpd, const qse_mchar_t* path,
qse_ubi_t* handle)
{
#if defined(_WIN32)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__OS2__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__DOS__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
int fd;
int flags;
flags = O_WRONLY | O_CREAT | O_TRUNC;
#if defined(O_LARGEFILE)
#if defined(O_LARGEFILE)
flags |= O_LARGEFILE;
#endif
#endif
qse_printf (QSE_T("opening file [%hs] for writing\n"), path);
fd = QSE_OPEN (path, flags, 0644);
@ -1167,26 +1228,69 @@ qse_printf (QSE_T("opening file [%hs] for writing\n"), path);
handle->i = fd;
return 0;
#endif
}
static void file_close (qse_httpd_t* httpd, qse_ubi_t handle)
{
#if defined(_WIN32)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__OS2__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__DOS__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
qse_printf (QSE_T("closing file %d\n"), handle.i);
QSE_CLOSE (handle.i);
#endif
}
static qse_ssize_t file_read (
qse_httpd_t* httpd, qse_ubi_t handle,
qse_mchar_t* buf, qse_size_t len)
{
#if defined(_WIN32)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__OS2__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__DOS__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
return QSE_READ (handle.i, buf, len);
#endif
}
static qse_ssize_t file_write (
qse_httpd_t* httpd, qse_ubi_t handle,
const qse_mchar_t* buf, qse_size_t len)
{
#if defined(_WIN32)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__OS2__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#elif defined(__DOS__)
/* TODO: */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
return QSE_WRITE (handle.i, buf, len);
#endif
}
/* ------------------------------------------------------------------- */
@ -1217,7 +1321,7 @@ static int dir_open (qse_httpd_t* httpd, const qse_mchar_t* path, qse_ubi_t* han
return -1;
}
d->dp = QSE_OPENDIR (path);
d->dp = qse_dir_open (httpd->mmgr, 0, (const qse_char_t*)path, QSE_DIR_MBSPATH | QSE_DIR_SORT);
if (d->dp == QSE_NULL)
{
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
@ -1236,7 +1340,7 @@ static void dir_close (qse_httpd_t* httpd, qse_ubi_t handle)
d = (dir_t*)handle.ptr;
QSE_CLOSEDIR (d->dp);
qse_dir_close (d->dp);
QSE_MMGR_FREE (httpd->mmgr, d->path);
QSE_MMGR_FREE (httpd->mmgr, d);
@ -1245,23 +1349,22 @@ static void dir_close (qse_httpd_t* httpd, qse_ubi_t handle)
static int dir_read (qse_httpd_t* httpd, qse_ubi_t handle, qse_httpd_dirent_t* dirent)
{
dir_t* d;
qse_dirent_t* de;
qse_dir_ent_t de;
qse_mchar_t* fpath;
int n;
d = (dir_t*)handle.ptr;
errno = 0;
de = QSE_READDIR (d->dp);
if (de == QSE_NULL)
n = qse_dir_read (d->dp, &de);
if (n <= -1)
{
if (errno == 0) return 0;
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR);
return -1;
}
else if (n == 0) return 0;
/* i assume that d->path ends with a slash */
fpath = qse_mbsdup2 (d->path, de->d_name, httpd->mmgr);
fpath = qse_mbsdup2 (d->path, (const qse_mchar_t*)de.name, httpd->mmgr);
if (fpath == QSE_NULL)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
@ -1272,7 +1375,7 @@ static int dir_read (qse_httpd_t* httpd, qse_ubi_t handle, qse_httpd_dirent_t* d
QSE_MMGR_FREE (httpd->mmgr, fpath);
if (n <= -1) QSE_MEMSET (dirent, 0, QSE_SIZEOF(*dirent));
dirent->name = de->d_name;
dirent->name = (const qse_mchar_t*)de.name;
return 1;
}
@ -1966,7 +2069,17 @@ auth_ok:
xpath = merge_paths (httpd, server_xtn->cfg[SERVER_XTN_CFG_DOCROOT], qpath);
if (xpath == QSE_NULL) return -1;
#if defined(_WIN32)
/* TODO */
#elif defined(__OS2__)
/* TODO */
#elif defined(__DOS__)
/* TODO */
#else
if (QSE_STAT (xpath, &st) == 0 && S_ISDIR(st.st_mode))
#endif
{
/* it is a directory */
if (server_xtn->cfg2.s.idxstd)

View File

@ -99,11 +99,6 @@ void qse_httpd_seterrnum (qse_httpd_t* httpd, qse_httpd_errnum_t errnum)
httpd->errnum = errnum;
}
void qse_httpd_setmmgr (qse_httpd_t* httpd, qse_mmgr_t* mmgr)
{
httpd->mmgr = mmgr;
}
qse_mmgr_t* qse_httpd_getmmgr (qse_httpd_t* httpd)
{
return httpd->mmgr;
@ -300,6 +295,7 @@ static qse_httpd_client_t* new_client (
QSE_MEMSET (client, 0, QSE_SIZEOF(*client));
client->type = QSE_HTTPD_CLIENT;
client->htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(*xtn));
if (client->htrd == QSE_NULL)
{
@ -442,8 +438,7 @@ qse_printf (QSE_T("failed to accept from server %s\n"), tmp);
qse_printf (QSE_T("MUX ADDHND CLIENT READ %d\n"), client->handle.i);
if (httpd->scb->mux.addhnd (
httpd, mux, client->handle, QSE_HTTPD_MUX_READ,
perform_client_task, client) <= -1)
httpd, mux, client->handle, QSE_HTTPD_MUX_READ, client) <= -1)
{
free_client (httpd, client);
return -1;
@ -511,8 +506,7 @@ qse_printf (QSE_T("FAILED TO ACTIVATE SERVER....[%s]\n"), buf);
qse_printf (QSE_T("MUX ADDHND SERVER %d\n"), server->handle.i);
if (httpd->scb->mux.addhnd (
httpd, httpd->mux, server->handle, QSE_HTTPD_MUX_READ,
accept_client, server) <= -1)
httpd, httpd->mux, server->handle, QSE_HTTPD_MUX_READ, server) <= -1)
{
qse_printf (QSE_T("FAILED TO ADD SERVER HANDLE TO MUX....\n"));
httpd->scb->server.close (httpd, server);
@ -556,6 +550,7 @@ qse_httpd_server_t* qse_httpd_attachserver (
QSE_MEMCPY (server, tmpl, QSE_SIZEOF(*server));
QSE_MEMSET (server + 1, 0, xtnsize);
server->type = QSE_HTTPD_SERVER;
server->flags &= ~QSE_HTTPD_SERVER_ACTIVE;
server->predetach = predetach;
@ -827,8 +822,7 @@ qse_printf (QSE_T("REMOVING XXXXX FROM READING NO MORE TASK....\n"));
if (mux_status)
{
if (httpd->scb->mux.addhnd (
httpd, httpd->mux, client->handle,
mux_mask, perform_client_task, client) <= -1)
httpd, httpd->mux, client->handle, mux_mask, client) <= -1)
{
return -1;
}
@ -915,7 +909,7 @@ qse_printf (QSE_T("REMOVING XXXXX FROM READING NO MORE TASK....\n"));
{
if (httpd->scb->mux.addhnd (
httpd, httpd->mux, task->trigger[i].handle,
trigger_mux_mask, perform_client_task, client) <= -1)
trigger_mux_mask, client) <= -1)
{
return -1;
}
@ -949,7 +943,7 @@ qse_printf (QSE_T("REMOVING XXXXX FROM READING NO MORE TASK....\n"));
{
if (httpd->scb->mux.addhnd (
httpd, httpd->mux, client->handle,
client_handle_mux_mask, perform_client_task, client) <= -1)
client_handle_mux_mask, client) <= -1)
{
return -1;
}
@ -1073,7 +1067,7 @@ qse_printf (QSE_T("MUX ADDHND CLIENT RW(ENTASK) %d\n"), client->handle.i);
if (httpd->scb->mux.addhnd (
httpd, httpd->mux, client->handle,
QSE_HTTPD_MUX_READ | QSE_HTTPD_MUX_WRITE,
perform_client_task, client) <= -1)
client) <= -1)
{
/*purge_client (httpd, client);*/
client->status |= CLIENT_BAD;
@ -1085,6 +1079,14 @@ qse_printf (QSE_T("MUX ADDHND CLIENT RW(ENTASK) %d\n"), client->handle.i);
return new_task;
}
static int dispatch_mux (
qse_httpd_t* httpd, void* mux, qse_ubi_t handle, int mask, void* cbarg)
{
return ((qse_httpd_server_t*)cbarg)->type == QSE_HTTPD_SERVER?
accept_client (httpd, mux, handle, mask, cbarg):
perform_client_task (httpd, mux, handle, mask, cbarg);
}
int qse_httpd_loop (qse_httpd_t* httpd, qse_httpd_scb_t* scb, qse_httpd_rcb_t* rcb, qse_ntime_t timeout)
{
QSE_ASSERTX (httpd->server.list.head != QSE_NULL,
@ -1106,7 +1108,7 @@ int qse_httpd_loop (qse_httpd_t* httpd, qse_httpd_scb_t* scb, qse_httpd_rcb_t* r
QSE_ASSERT (httpd->server.navail > 0);
httpd->mux = httpd->scb->mux.open (httpd);
httpd->mux = httpd->scb->mux.open (httpd, dispatch_mux);
if (httpd->mux == QSE_NULL)
{
qse_printf (QSE_T("can't open mux....\n"));

View File

@ -73,12 +73,6 @@ void qse_upxd_fini (qse_upxd_t* upxd)
free_all_servers (upxd);
}
void qse_upxd_setmmgr (qse_upxd_t* upxd, qse_mmgr_t* mmgr)
{
upxd->mmgr = mmgr;
}
qse_mmgr_t* qse_upxd_getmmgr (qse_upxd_t* upxd)
{
return upxd->mmgr;

View File

@ -143,11 +143,6 @@ void qse_sed_fini (qse_sed_t* sed)
qse_str_fini (&sed->tmp.rex);
}
void qse_sed_setmmgr (qse_sed_t* sed, qse_mmgr_t* mmgr)
{
sed->mmgr = mmgr;
}
qse_mmgr_t* qse_sed_getmmgr (qse_sed_t* sed)
{
return sed->mmgr;