added hton,ntoh

renamed qse_getcmgrbyname() to qse_findcmgr()
added qse_setcmgrfinder()/qse_getcmgrfinder()
started adding ipad,nwad
This commit is contained in:
hyung-hwan 2012-02-13 14:43:50 +00:00
parent 35ac9924ac
commit b330d2c350
19 changed files with 1309 additions and 431 deletions

View File

@ -651,7 +651,7 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
if (qse_strcmp(opt.lngopt, QSE_T("script-encoding")) == 0)
{
arg->script_cmgr = qse_getcmgrbyname (opt.arg);
arg->script_cmgr = qse_findcmgr (opt.arg);
if (arg->script_cmgr == QSE_NULL)
{
print_err (QSE_T("unknown script encoding - %s\n"), opt.arg);
@ -660,7 +660,7 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
}
else if (qse_strcmp(opt.lngopt, QSE_T("console-encoding")) == 0)
{
arg->console_cmgr = qse_getcmgrbyname (opt.arg);
arg->console_cmgr = qse_findcmgr (opt.arg);
if (arg->console_cmgr == QSE_NULL)
{
print_err (QSE_T("unknown console encoding - %s\n"), opt.arg);

View File

@ -11,11 +11,14 @@ pkginclude_HEADERS = \
fs.h \
gdl.h \
htb.h \
hton.h \
ipad.h \
lda.h \
main.h \
map.h \
mbwc.h \
mem.h \
nwad.h \
oht.h \
opt.h \
path.h \

View File

@ -52,10 +52,10 @@ CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
am__pkginclude_HEADERS_DIST = alg.h chr.h dll.h env.h fio.h fma.h \
fmt.h fs.h gdl.h htb.h lda.h main.h map.h mbwc.h mem.h oht.h \
opt.h path.h pio.h pma.h rbt.h rex.h sio.h sll.h slmb.h \
stdio.h str.h time.h tio.h tre.h utf8.h xma.h Mmgr.hpp \
StdMmgr.hpp Mmged.hpp
fmt.h fs.h gdl.h htb.h hton.h ipad.h lda.h main.h map.h mbwc.h \
mem.h nwad.h oht.h opt.h path.h pio.h pma.h rbt.h rex.h sio.h \
sll.h slmb.h stdio.h str.h time.h tio.h tre.h utf8.h xma.h \
Mmgr.hpp StdMmgr.hpp Mmged.hpp
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@ -229,9 +229,10 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
pkginclude_HEADERS = alg.h chr.h dll.h env.h fio.h fma.h fmt.h fs.h \
gdl.h htb.h lda.h main.h map.h mbwc.h mem.h oht.h opt.h path.h \
pio.h pma.h rbt.h rex.h sio.h sll.h slmb.h stdio.h str.h \
time.h tio.h tre.h utf8.h xma.h $(am__append_1)
gdl.h htb.h hton.h ipad.h lda.h main.h map.h mbwc.h mem.h \
nwad.h oht.h opt.h path.h pio.h pma.h rbt.h rex.h sio.h sll.h \
slmb.h stdio.h str.h time.h tio.h tre.h utf8.h xma.h \
$(am__append_1)
all: all-am
.SUFFIXES:

View File

@ -0,0 +1,75 @@
/*
* $Id$
*
Copyright 2006-2011 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/>.
*/
#ifndef _QSE_CMN_HTON_H_
#define _QSE_CMN_HTON_H_
#include <qse/types.h>
#include <qse/macros.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(QSE_HAVE_UINT16_T)
qse_uint16_t qse_ntoh16 (
qse_uint16_t x
);
qse_uint16_t qse_hton16 (
qse_uint16_t x
);
#endif
#if defined(QSE_HAVE_UINT32_T)
qse_uint32_t qse_ntoh32 (
qse_uint32_t x
);
qse_uint32_t qse_hton32 (
qse_uint32_t x
);
#endif
#if defined(QSE_HAVE_UINT64_T)
qse_uint64_t qse_ntoh64 (
qse_uint64_t x
);
qse_uint64_t qse_hton64 (
qse_uint64_t x
);
#endif
#if defined(QSE_HAVE_UINT128_T)
qse_uint128_t qse_ntoh128 (
qse_uint128_t x
);
qse_uint128_t qse_hton128 (
qse_uint128_t x
);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,66 @@
/*
* $Id$
*
Copyright 2006-2011 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/>.
*/
#ifndef _QSE_CMN_IPAD_H_
#define _QSE_CMN_IPAD_H_
#include <qse/types.h>
#include <qse/macros.h>
typedef struct qse_ipad_t qse_ipad_t;
typedef struct qse_ipad4_t qse_ipad4_t;
typedef struct qse_ipad6_t qse_ipad6_t;
#include <qse/pack1.h>
struct qse_ipad4_t
{
qse_uint32_t value;
};
struct qse_ipad6_t
{
qse_uint8_t value[16];
};
#include <qse/unpack.h>
struct qse_ipad_t
{
enum
{
QSE_IPAD_IP4,
QSE_IPAD_IP6
} type;
union
{
qse_ipad4_t ip4;
qse_ipad4_t ip6;
} u;
};
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -28,6 +28,8 @@
#include <qse/types.h>
#include <qse/macros.h>
typedef qse_cmgr_t* (*qse_cmgr_finder_t) (const qse_char_t* name);
#ifdef __cplusplus
extern "C" {
#endif
@ -39,15 +41,23 @@ extern qse_cmgr_t* qse_utf8cmgr;
extern qse_cmgr_t* qse_slmbcmgr;
/**
* The qse_getcmgrbyname() function find a builtin cmgr matching a given
* The qse_getfindcmgr() function find a builtin cmgr matching a given
* @a name and returns it. It returns #QSE_NULL if no match is found.
* The @a name can be one of "utf8", "slmb", and an empty string. Calling this
* function with an empty string is the same as calling qse_getdflcmgr().
*/
qse_cmgr_t* qse_getcmgrbyname (
qse_cmgr_t* qse_findcmgr (
const qse_char_t* name
);
void qse_setcmgrfinder (
qse_cmgr_finder_t finder
);
qse_cmgr_finder_t qse_getcmgrfinder (
void
);
/* --------------------------------------------------- */
/* DEFAULT GLOBAL CMGR */
/* --------------------------------------------------- */

View File

@ -0,0 +1,52 @@
/*
* $Id$
*
Copyright 2006-2011 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/>.
*/
#ifndef _QSE_CMN_NWAD_H_
#define _QSE_CMN_NWAD_H_
#include <qse/types.h>
#include <qse/macros.h>
#include <qse/cmn/ipad.h>
struct qse_nwad_t
{
enum
{
QSE_NWAD_IP4,
QSE_NWAD_IP6
} type;
union
{
struct
{
qse_ipad4_t addr;
qse_uint16_t port;
} ip4;
struct
{
qse_ipad6_t addr;
qse_uint16_t port;
} ip6;
} u;
};
#endif

View File

@ -52,6 +52,14 @@ enum qse_httpd_option_t
QSE_HTTPD_CGINOCLOEXEC = (1 << 1)
};
typedef struct qse_httpd_stat_t qse_httpd_stat_t;
struct qse_httpd_stat_t
{
qse_foff_t size;
qse_ntime_t mtime;
const qse_mchar_t* mime;
};
typedef struct qse_httpd_cbs_t qse_httpd_cbs_t;
struct qse_httpd_cbs_t
{
@ -65,14 +73,16 @@ struct qse_httpd_cbs_t
struct
{
int (*executable) (qse_httpd_t* httpd, const qse_mchar_t* path);
} path;
int (*executable) (
qse_httpd_t* httpd, const qse_mchar_t* path);
struct
{
int (*stat) (
qse_httpd_t* httpd, const qse_mchar_t* path,
qse_httpd_stat_t* stat);
int (*ropen) (
qse_httpd_t* httpd, const qse_mchar_t* path,
qse_ubi_t* handle, qse_foff_t* size);
qse_ubi_t* handle);
int (*wopen) (
qse_httpd_t* httpd, const qse_mchar_t* path,
qse_ubi_t* handle);
@ -115,7 +125,6 @@ struct qse_httpd_cbs_t
int (*handle_request) (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req);
const qse_mchar_t* (*getmimetype) (qse_httpd_t* httpd, const qse_mchar_t* path);
int (*listdir) (qse_httpd_t* httpd, const qse_mchar_t* path);
};
@ -313,6 +322,14 @@ qse_httpd_task_t* qse_httpd_entaskcontinue (
qse_htre_t* req
);
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
);
qse_httpd_task_t* qse_httpd_entaskdir (
qse_httpd_t* httpd,
qse_httpd_client_t* client,

View File

@ -238,7 +238,7 @@ int StdAwk::setenc (Run& run, Value& ret, const Value* args, size_t nargs,
return ret.setInt ((long_t)-1);
}
qse_cmgr_t* cmgr = qse_getcmgrbyname (ptr[1]);
qse_cmgr_t* cmgr = qse_findcmgr (ptr[1]);
if (cmgr == QSE_NULL)
{
return ret.setInt ((long_t)-1);

View File

@ -124,7 +124,8 @@ typedef struct rxtn_t
} rxtn_t;
#if defined(QSE_CHAR_IS_WCHAR)
static qse_cmgr_t* getcmgr_from_cmgrtab (qse_awk_rtx_t* rtx, const qse_char_t* ioname);
static qse_cmgr_t* getcmgr_from_cmgrtab (
qse_awk_rtx_t* rtx, const qse_char_t* ioname);
#endif
static qse_flt_t custom_awk_pow (qse_awk_t* awk, qse_flt_t x, qse_flt_t y)
@ -1562,7 +1563,8 @@ skip_system:
}
#if defined(QSE_CHAR_IS_WCHAR)
static qse_cmgr_t* getcmgr_from_cmgrtab (qse_awk_rtx_t* rtx, const qse_char_t* ioname)
static qse_cmgr_t* getcmgr_from_cmgrtab (
qse_awk_rtx_t* rtx, const qse_char_t* ioname)
{
rxtn_t* rxtn;
qse_htb_pair_t* pair;
@ -1617,7 +1619,7 @@ static int fnc_setenc (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm)
}
}
cmgr = qse_getcmgrbyname (ptr[1]);
cmgr = qse_findcmgr (ptr[1]);
if (cmgr == QSE_NULL) fret = -1;
else
{

View File

@ -36,10 +36,13 @@ libqsecmn_la_SOURCES = \
fs.c \
fs-err.c \
fs-move.c \
hton.c \
ipad.c \
main.c \
mbwc.c \
mbwc-str.c \
mem.c \
nwad.c \
oht.c \
opt.c \
path-basename.c \

View File

@ -77,18 +77,18 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libqsecmn_la_DEPENDENCIES =
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 main.lo mbwc.lo \
mbwc-str.lo mem.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 \
str-dynw.lo str-end.lo str-excl.lo str-fcpy.lo str-fnmat.lo \
str-incl.lo str-len.lo str-pac.lo str-pbrk.lo str-put.lo \
str-rev.lo str-rot.lo str-set.lo str-spl.lo str-spn.lo \
str-str.lo str-subst.lo str-tok.lo str-trm.lo str-word.lo \
time.lo tio.lo tio-get.lo tio-put.lo tre.lo tre-ast.lo \
tre-compile.lo tre-match-backtrack.lo tre-match-parallel.lo \
tre-parse.lo tre-stack.lo utf8.lo xma.lo
fma.lo fmt.lo fs.lo fs-err.lo fs-move.lo hton.lo ipad.lo \
main.lo mbwc.lo mbwc-str.lo mem.lo nwad.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 str-dynw.lo str-end.lo str-excl.lo \
str-fcpy.lo str-fnmat.lo str-incl.lo str-len.lo str-pac.lo \
str-pbrk.lo str-put.lo str-rev.lo str-rot.lo str-set.lo \
str-spl.lo str-spn.lo str-str.lo str-subst.lo str-tok.lo \
str-trm.lo str-word.lo time.lo tio.lo tio-get.lo tio-put.lo \
tre.lo tre-ast.lo tre-compile.lo tre-match-backtrack.lo \
tre-match-parallel.lo tre-parse.lo tre-stack.lo utf8.lo xma.lo
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
libqsecmn_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@ -310,10 +310,13 @@ libqsecmn_la_SOURCES = \
fs.c \
fs-err.c \
fs-move.c \
hton.c \
ipad.c \
main.c \
mbwc.c \
mbwc-str.c \
mem.c \
nwad.c \
oht.c \
opt.c \
path-basename.c \
@ -468,11 +471,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hton.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipad.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Plo@am__quote@
@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)/nwad.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oht.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/path-basename.Plo@am__quote@

203
qse/lib/cmn/hton.c Normal file
View File

@ -0,0 +1,203 @@
/*
* $Id$
*
Copyright 2006-2011 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/hton.h>
/* --------------------------------------------------------------- */
#if defined(QSE_HAVE_UINT16_T)
qse_uint16_t qse_ntoh16 (qse_uint16_t x)
{
#if defined(QSE_ENDIAN_BIG)
return x;
#elif defined(QSE_ENDIAN_LITTLE)
qse_uint8_t* c = (qse_uint8_t*)&x;
return (qse_uint16_t)(
((qse_uint16_t)c[0] << 8) |
((qse_uint16_t)c[1] << 0));
#else
# error Unknown endian
#endif
}
qse_uint16_t qse_hton16 (qse_uint16_t x)
{
#if defined(QSE_ENDIAN_BIG)
return x;
#elif defined(QSE_ENDIAN_LITTLE)
qse_uint8_t* c = (qse_uint8_t*)&x;
return (qse_uint16_t)(
((qse_uint16_t)c[0] << 8) |
((qse_uint16_t)c[1] << 0));
#else
# error Unknown endian
#endif
}
#endif
/* --------------------------------------------------------------- */
#if defined(QSE_HAVE_UINT32_T)
qse_uint32_t qse_ntoh32 (qse_uint32_t x)
{
#if defined(QSE_ENDIAN_BIG)
return x;
#elif defined(QSE_ENDIAN_LITTLE)
qse_uint8_t* c = (qse_uint8_t*)&x;
return (qse_uint32_t)(
((qse_uint32_t)c[0] << 24) |
((qse_uint32_t)c[1] << 16) |
((qse_uint32_t)c[2] << 8) |
((qse_uint32_t)c[3] << 0));
#else
# error Unknown endian
#endif
}
qse_uint32_t qse_hton32 (qse_uint32_t x)
{
#if defined(QSE_ENDIAN_BIG)
return x;
#elif defined(QSE_ENDIAN_LITTLE)
qse_uint8_t* c = (qse_uint8_t*)&x;
return (qse_uint32_t)(
((qse_uint32_t)c[0] << 24) |
((qse_uint32_t)c[1] << 16) |
((qse_uint32_t)c[2] << 8) |
((qse_uint32_t)c[3] << 0));
#else
# error Unknown endian
#endif
}
#endif
/* --------------------------------------------------------------- */
#if defined(QSE_HAVE_UINT64_T)
qse_uint64_t qse_ntoh64 (qse_uint64_t x)
{
#if defined(QSE_ENDIAN_BIG)
return x;
#elif defined(QSE_ENDIAN_LITTLE)
qse_uint8_t* c = (qse_uint8_t*)&x;
return (qse_uint64_t)(
((qse_uint64_t)c[0] << 56) |
((qse_uint64_t)c[1] << 48) |
((qse_uint64_t)c[2] << 40) |
((qse_uint64_t)c[3] << 32) |
((qse_uint64_t)c[4] << 24) |
((qse_uint64_t)c[5] << 16) |
((qse_uint64_t)c[6] << 8) |
((qse_uint64_t)c[7] << 0));
#else
# error Unknown endian
#endif
}
qse_uint64_t qse_hton64 (qse_uint64_t x)
{
#if defined(QSE_ENDIAN_BIG)
return x;
#elif defined(QSE_ENDIAN_LITTLE)
qse_uint8_t* c = (qse_uint8_t*)&x;
return (qse_uint64_t)(
((qse_uint64_t)c[0] << 56) |
((qse_uint64_t)c[1] << 48) |
((qse_uint64_t)c[2] << 40) |
((qse_uint64_t)c[3] << 32) |
((qse_uint64_t)c[4] << 24) |
((qse_uint64_t)c[5] << 16) |
((qse_uint64_t)c[6] << 8) |
((qse_uint64_t)c[7] << 0));
#else
# error Unknown endian
#endif
}
#endif
/* --------------------------------------------------------------- */
#if defined(QSE_HAVE_UINT128_T)
qse_uint128_t qse_ntoh128 (qse_uint128_t x)
{
#if defined(QSE_ENDIAN_BIG)
return x;
#elif defined(QSE_ENDIAN_LITTLE)
qse_uint8_t* c = (qse_uint8_t*)&x;
return (qse_uint128_t)(
((qse_uint128_t)c[0] << 120) |
((qse_uint128_t)c[1] << 112) |
((qse_uint128_t)c[2] << 104) |
((qse_uint128_t)c[3] << 96) |
((qse_uint128_t)c[4] << 88) |
((qse_uint128_t)c[5] << 80) |
((qse_uint128_t)c[6] << 72) |
((qse_uint128_t)c[7] << 64) |
((qse_uint128_t)c[8] << 56) |
((qse_uint128_t)c[9] << 48) |
((qse_uint128_t)c[10] << 40) |
((qse_uint128_t)c[11] << 32) |
((qse_uint128_t)c[12] << 24) |
((qse_uint128_t)c[13] << 16) |
((qse_uint128_t)c[14] << 8) |
((qse_uint128_t)c[15] << 0));
#else
# error Unknown endian
#endif
}
qse_uint128_t qse_hton128 (qse_uint128_t x)
{
#if defined(QSE_ENDIAN_BIG)
return x;
#elif defined(QSE_ENDIAN_LITTLE)
qse_uint8_t* c = (qse_uint8_t*)&x;
return (qse_uint128_t)(
((qse_uint128_t)c[0] << 120) |
((qse_uint128_t)c[1] << 112) |
((qse_uint128_t)c[2] << 104) |
((qse_uint128_t)c[3] << 96) |
((qse_uint128_t)c[4] << 88) |
((qse_uint128_t)c[5] << 80) |
((qse_uint128_t)c[6] << 72) |
((qse_uint128_t)c[7] << 64) |
((qse_uint128_t)c[8] << 56) |
((qse_uint128_t)c[9] << 48) |
((qse_uint128_t)c[10] << 40) |
((qse_uint128_t)c[11] << 32) |
((qse_uint128_t)c[12] << 24) |
((qse_uint128_t)c[13] << 16) |
((qse_uint128_t)c[14] << 8) |
((qse_uint128_t)c[15] << 0));
#else
# error Unknown endian
#endif
}
#endif
/* --------------------------------------------------------------- */

573
qse/lib/cmn/ipad.c Normal file
View File

@ -0,0 +1,573 @@
/*
* $Id$
*
Copyright 2006-2011 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/>.
*/
/* Copyright (c) 1996-1999 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <qse/cmn/ipad.h>
#if 0
const qse_ipad4_t qse_ipad4_any =
{
0 /* 0.0.0.0 */
};
const qse_ipad4_t qse_ipad4_loopback =
{
#if defined(QSE_ENDIAN_BIG)
0x7F000001u /* 127.0.0.1 */
#elif defined(QSE_ENDIAN_LITTLE)
0x0100007Fu
#else
# error Unknown endian
#endif
};
const qse_ipad6_t qse_ipad6_any =
{
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* :: */
};
const qse_ipad6_t qse_ipad6_loopback =
{
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } /* ::1 */
};
#endif
#if 0
int qse_strtoipad4 (const qse_char_t* str, qse_ipad4_t* ipad)
{
qse_char_t c;
int dots = 0, digits = 0;
qse_uint32_t acc = 0, addr = 0;
do
{
c = *str;
if (c == QSE_T('\0'))
{
if (dots < 3 || digits == 0) return -1;
addr = (addr << 8) | acc;
break;
}
else if (c >= QSE_T('0') && c <= QSE_T('9'))
{
if (digits > 0 && acc == 0) return -1;
acc = acc * 10 + (c - QSE_T('0'));
if (acc > 255) return -1;
digits++;
}
else if (c == QSE_T('.'))
{
if (dots >= 3 || digits == 0) return -1;
addr = (addr << 8) | acc;
dots++; acc = 0; digits = 0;
}
else return -1;
str++;
}
while (1);
if (ipad != QSE_NULL) ipad->value = qse_hton32(addr);
return 0;
}
int qse_strxtoipad4 (
const qse_char_t* str, qse_size_t len, qse_ipad4_t* ipad)
{
qse_char_t c;
int dots = 0, digits = 0;
qse_uint32_t acc = 0, addr = 0;
const qse_char_t* end = str + len;
do
{
if (str >= end)
{
if (dots < 3 || digits == 0) return -1;
addr = (addr << 8) | acc;
break;
}
c = *str;
if (c >= QSE_T('0') && c <= QSE_T('9'))
{
if (digits > 0 && acc == 0) return -1;
acc = acc * 10 + (c - QSE_T('0'));
if (acc > 255) return -1;
digits++;
}
else if (c == QSE_T('.'))
{
if (dots >= 3 || digits == 0) return -1;
addr = (addr << 8) | acc;
dots++; acc = 0; digits = 0;
}
else return -1;
str++;
}
while (1);
if (ipad != QSE_NULL) ipad->value = qse_hton32(addr);
return 0;
}
#define __BTOA(b,p,end) \
do { \
qse_char_t* sp = p; \
do { \
if (p >= end) { \
if (p == sp) break; \
if (p - sp > 1) p[-2] = p[-1]; \
p[-1] = (b % 10) + QSE_T('0'); \
} \
else *p++ = (b % 10) + QSE_T('0'); \
b /= 10; \
} while (b > 0); \
if (p - sp > 1) { \
qse_char_t t = sp[0]; \
sp[0] = p[-1]; \
p[-1] = t; \
} \
} while (0);
#define __ADDDOT(p, end) \
do { \
if (p >= end) break; \
*p++ = QSE_T('.'); \
} while (0)
qse_size_t qse_ipad4tostrx (
const qse_ipad4_t* ipad, qse_char_t* buf, qse_size_t size)
{
qse_byte_t b;
qse_char_t* p, * end;
qse_uint32_t ip;
if (size <= 0) return 0;
ip = ipad->value;
p = buf;
end = buf + size - 1;
#if defined(QSE_ENDIAN_BIG)
b = (ip >> 24) & 0xFF; __BTOA (b, p, end); __ADDDOT (p, end);
b = (ip >> 16) & 0xFF; __BTOA (b, p, end); __ADDDOT (p, end);
b = (ip >> 8) & 0xFF; __BTOA (b, p, end); __ADDDOT (p, end);
b = (ip >> 0) & 0xFF; __BTOA (b, p, end);
#elif defined(QSE_ENDIAN_LITTLE)
b = (ip >> 0) & 0xFF; __BTOA (b, p, end); __ADDDOT (p, end);
b = (ip >> 8) & 0xFF; __BTOA (b, p, end); __ADDDOT (p, end);
b = (ip >> 16) & 0xFF; __BTOA (b, p, end); __ADDDOT (p, end);
b = (ip >> 24) & 0xFF; __BTOA (b, p, end);
#else
# error Unknown Endian
#endif
*p = QSE_T('\0');
return p - buf;
}
int qse_strtoipad6 (const qse_char_t* src, qse_ipad6_t* ipad)
{
#if 0
static const qse_char_t xdigits_l[] = QSE_T("0123456789abcdef"),
xdigits_u[] = QSE_T("0123456789ABCDEF");
const qse_char_t* xdigits;
#endif
qse_ipad6_t tmp;
qse_byte_t* tp, * endp, * colonp;
const qse_char_t* curtok;
qse_char_t ch;
int saw_xdigit;
unsigned int val;
qse_memset (&tmp, 0, QSE_SIZEOF(tmp));
tp = &tmp.value[0];
endp = &tmp.value[QSE_COUNTOF(tmp.value)];
colonp = QSE_NULL;
/* Leading :: requires some special handling. */
if (*src == QSE_T(':'))
{
if (*++src != QSE_T(':')) return -1;
}
curtok = src;
saw_xdigit = 0;
val = 0;
while ((ch = *src++) != QSE_T('\0'))
{
#if 0
const char *pch;
if ((pch = qse_strchr((xdigits = xdigits_l), ch)) == QSE_NULL)
pch = qse_strchr((xdigits = xdigits_u), ch);
if (pch != QSE_NULL)
{
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff) return -1;
saw_xdigit = 1;
continue;
}
#endif
int v1;
if (ch >= QSE_T('0') && ch <= QSE_T('9'))
v1 = ch - QSE_T('0');
else if (ch >= QSE_T('A') && ch <= QSE_T('F'))
v1 = ch - QSE_T('A') + 10;
else if (ch >= QSE_T('a') && ch <= QSE_T('f'))
v1 = ch - QSE_T('a') + 10;
else v1 = -1;
if (v1 >= 0)
{
val <<= 4;
val |= v1;
if (val > 0xffff) return -1;
saw_xdigit = 1;
continue;
}
if (ch == QSE_T(':'))
{
curtok = src;
if (!saw_xdigit)
{
if (colonp) return -1;
colonp = tp;
continue;
}
else if (*src == QSE_T('\0'))
{
/* a colon can't be the last character */
return -1;
}
if (tp + QSE_SIZEOF(qse_uint16_t) > endp) return -1;
*tp++ = (qse_byte_t) (val >> 8) & 0xff;
*tp++ = (qse_byte_t) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
#if 0
if (ch == QSE_T('.') && ((tp + NS_INADDRSZ) <= endp) &&
inet_pton4(curtok, tp) > 0)
{
tp += NS_INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
#endif
if (ch == QSE_T('.') && ((tp + QSE_SIZEOF(qse_ipad4_t)) <= endp) &&
qse_strtoipad4(curtok, (qse_ipad4_t*)tp) == 0)
{
tp += QSE_SIZEOF(qse_ipad4_t);
saw_xdigit = 0;
break;
}
return -1;
}
if (saw_xdigit)
{
if (tp + QSE_SIZEOF(qse_uint16_t) > endp) return -1;
*tp++ = (qse_byte_t) (val >> 8) & 0xff;
*tp++ = (qse_byte_t) val & 0xff;
}
if (colonp != QSE_NULL)
{
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
qse_size_t n = tp - colonp;
qse_size_t i;
for (i = 1; i <= n; i++)
{
endp[-i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp) return -1;
*ipad = tmp;
return 0;
}
int qse_strxtoipad6 (const qse_char_t* src, qse_size_t len, qse_ipad6_t* ipad)
{
qse_ipad6_t tmp;
qse_byte_t* tp, * endp, * colonp;
const qse_char_t* curtok;
qse_char_t ch;
int saw_xdigit;
unsigned int val;
const qse_char_t* src_end;
src_end = src + len;
qse_memset (&tmp, 0, QSE_SIZEOF(tmp));
tp = &tmp.value[0];
endp = &tmp.value[QSE_COUNTOF(tmp.value)];
colonp = QSE_NULL;
/* Leading :: requires some special handling. */
if (src < src_end && *src == QSE_T(':'))
{
src++;
if (src >= src_end || *src != QSE_T(':')) return -1;
}
curtok = src;
saw_xdigit = 0;
val = 0;
while (src < src_end)
{
int v1;
ch = *src++;
if (ch >= QSE_T('0') && ch <= QSE_T('9'))
v1 = ch - QSE_T('0');
else if (ch >= QSE_T('A') && ch <= QSE_T('F'))
v1 = ch - QSE_T('A') + 10;
else if (ch >= QSE_T('a') && ch <= QSE_T('f'))
v1 = ch - QSE_T('a') + 10;
else v1 = -1;
if (v1 >= 0)
{
val <<= 4;
val |= v1;
if (val > 0xffff) return -1;
saw_xdigit = 1;
continue;
}
if (ch == QSE_T(':'))
{
curtok = src;
if (!saw_xdigit)
{
if (colonp) return -1;
colonp = tp;
continue;
}
else if (src >= src_end)
{
/* a colon can't be the last character */
return -1;
}
*tp++ = (qse_byte_t) (val >> 8) & 0xff;
*tp++ = (qse_byte_t) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == QSE_T('.') && ((tp + QSE_SIZEOF(qse_ipad4_t)) <= endp) &&
qse_strxtoipad4(curtok, src_end - curtok, (qse_ipad4_t*)tp) == 0)
{
tp += QSE_SIZEOF(qse_ipad4_t);
saw_xdigit = 0;
break;
}
return -1;
}
if (saw_xdigit)
{
if (tp + QSE_SIZEOF(qse_uint16_t) > endp) return -1;
*tp++ = (qse_byte_t) (val >> 8) & 0xff;
*tp++ = (qse_byte_t) val & 0xff;
}
if (colonp != QSE_NULL)
{
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
qse_size_t n = tp - colonp;
qse_size_t i;
for (i = 1; i <= n; i++)
{
endp[-i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp) return -1;
*ipad = tmp;
return 0;
}
qse_size_t qse_ipad6tostrx (
const qse_ipad6_t* ipad, qse_char_t* buf, qse_size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
#define IP6ADDR_NWORDS (QSE_SIZEOF(ipad->value) / QSE_SIZEOF(qse_uint16_t))
qse_char_t tmp[QSE_COUNTOF(QSE_T("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"))], *tp;
struct { int base, len; } best, cur;
qse_uint16_t words[IP6ADDR_NWORDS];
int i;
if (size <= 0) return 0;
/*
* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
qse_memset (words, 0, QSE_SIZEOF(words));
for (i = 0; i < QSE_SIZEOF(ipad->value); i++)
words[i / 2] |= (ipad->value[i] << ((1 - (i % 2)) << 3));
best.base = -1;
cur.base = -1;
for (i = 0; i < IP6ADDR_NWORDS; i++)
{
if (words[i] == 0)
{
if (cur.base == -1)
{
cur.base = i;
cur.len = 1;
}
else
{
cur.len++;
}
}
else
{
if (cur.base != -1)
{
if (best.base == -1 || cur.len > best.len) best = cur;
cur.base = -1;
}
}
}
if (cur.base != -1)
{
if (best.base == -1 || cur.len > best.len) best = cur;
}
if (best.base != -1 && best.len < 2) best.base = -1;
/*
* Format the result.
*/
tp = tmp;
for (i = 0; i < IP6ADDR_NWORDS; i++)
{
/* Are we inside the best run of 0x00's? */
if (best.base != -1 && i >= best.base &&
i < (best.base + best.len))
{
if (i == best.base) *tp++ = QSE_T(':');
continue;
}
/* Are we following an initial run of 0x00s or any real hex? */
if (i != 0) *tp++ = QSE_T(':');
/* Is this address an encapsulated IPv4? ipv4-compatible or ipv4-mapped */
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
{
qse_ipad4_t ipad4;
qse_memcpy (&ipad4.value, ipad->value+12, QSE_SIZEOF(ipad4.value));
tp += qse_ipad4tostrx (&ipad4, tp, QSE_SIZEOF(tmp) - (tp - tmp));
break;
}
tp += qse_uint16tostr_lower (words[i], tp, QSE_SIZEOF(tmp) - (tp - tmp), 16, QSE_T('\0'));
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 &&
(best.base + best.len) == IP6ADDR_NWORDS) *tp++ = QSE_T(':');
*tp++ = QSE_T('\0');
return qse_strxcpy (buf, size, tmp);
#undef IP6ADDR_NWORDS
}
int qse_strtoipad (const qse_char_t* str, qse_ipad_t* ipad)
{
if (qse_strtoipad4 (str, &ipad->u.ip4) <= -1)
{
if (qse_strtoipad6 (str, &ipad->u.ip6) <= -1) return -1;
ipad->type = QSE_IPAD_IP6;
}
else ipad->type = QSE_IPAD_IP4;
return 0;
}
int qse_strxtoipad (const qse_char_t* str, qse_size_t len, qse_ipad_t* ipad)
{
if (qse_strxtoipad4 (str, len, &ipad->u.ip4) <= -1)
{
if (qse_strxtoipad6 (str, len, &ipad->u.ip6) <= -1) return -1;
ipad->type = QSE_IPAD_IP6;
}
else ipad->type = QSE_IPAD_IP4;
return 0;
}
#endif

View File

@ -47,6 +47,7 @@ qse_cmgr_t* qse_slmbcmgr = &builtin_cmgr[0];
qse_cmgr_t* qse_utf8cmgr = &builtin_cmgr[1];
static qse_cmgr_t* dfl_cmgr = &builtin_cmgr[0];
static qse_cmgr_finder_t cmgr_finder = QSE_NULL;
qse_cmgr_t* qse_getdflcmgr (void)
{
@ -58,24 +59,34 @@ void qse_setdflcmgr (qse_cmgr_t* cmgr)
dfl_cmgr = (cmgr? cmgr: &builtin_cmgr[0]);
}
/* TODO:
qse_addcmgr (const qse_char_t* name, qse_cmgr_t* cmgr);
qse_delcmgr (const qse_char_t* name);
*/
qse_cmgr_t* qse_getcmgrbyname (const qse_char_t* name)
qse_cmgr_t* qse_findcmgr (const qse_char_t* name)
{
if (name)
{
/* TODO: binary search */
if (cmgr_finder)
{
qse_cmgr_t* cmgr;
cmgr = cmgr_finder (name);
if (cmgr) return cmgr;
}
if (qse_strcmp(name, QSE_T("")) == 0) return dfl_cmgr;
if (qse_strcmp(name, QSE_T("utf8")) == 0) return qse_utf8cmgr;
if (qse_strcmp(name, QSE_T("slmb")) == 0) return qse_slmbcmgr;
/* TODO: add more - handle those added with qse_addcmgr() */
}
return QSE_NULL;
}
void qse_setcmgrfinder (qse_cmgr_finder_t finder)
{
cmgr_finder = finder;
}
qse_cmgr_finder_t qse_getcmgrfinder (void)
{
return cmgr_finder;
}
/* string conversion function using default character conversion manager */
int qse_mbstowcs (

37
qse/lib/cmn/nwad.c Normal file
View File

@ -0,0 +1,37 @@
/*
* $Id$
*
Copyright 2006-2011 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/>.
*/
/* Copyright (c) 1996-1999 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <qse/cmn/nwad.h>

View File

@ -49,7 +49,6 @@ static qse_ssize_t pio_output (
#if defined(_WIN32)
static qse_pio_errnum_t syserr_to_errnum (DWORD e)
{
switch (e)
{
case ERROR_INVALID_PARAMETER:
@ -573,13 +572,18 @@ int qse_pio_init (
if (flags & QSE_PIO_WRITEIN)
{
/* child reads, parent writes */
if (CreatePipe (
&handle[0], &handle[1],
&secattr, 0) == FALSE) goto oops;
if (CreatePipe (&handle[0], &handle[1], &secattr, 0) == FALSE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
}
/* don't inherit write handle */
if (SetHandleInformation (
handle[1], HANDLE_FLAG_INHERIT, 0) == FALSE) goto oops;
if (SetHandleInformation (handle[1], HANDLE_FLAG_INHERIT, 0) == FALSE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
}
minidx = 0; maxidx = 1;
}
@ -587,13 +591,18 @@ int qse_pio_init (
if (flags & QSE_PIO_READOUT)
{
/* child writes, parent reads */
if (CreatePipe (
&handle[2], &handle[3],
&secattr, 0) == FALSE) goto oops;
if (CreatePipe (&handle[2], &handle[3], &secattr, 0) == FALSE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
}
/* don't inherit read handle */
if (SetHandleInformation (
handle[2], HANDLE_FLAG_INHERIT, 0) == FALSE) goto oops;
if (SetHandleInformation (handle[2], HANDLE_FLAG_INHERIT, 0) == FALSE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
}
if (minidx == -1) minidx = 2;
maxidx = 3;
@ -602,13 +611,18 @@ int qse_pio_init (
if (flags & QSE_PIO_READERR)
{
/* child writes, parent reads */
if (CreatePipe (
&handle[4], &handle[5],
&secattr, 0) == FALSE) goto oops;
if (CreatePipe (&handle[4], &handle[5], &secattr, 0) == FALSE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
}
/* don't inherit read handle */
if (SetHandleInformation (
handle[4], HANDLE_FLAG_INHERIT, 0) == FALSE) goto oops;
if (SetHandleInformation (handle[4], HANDLE_FLAG_INHERIT, 0) == FALSE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
}
if (minidx == -1) minidx = 4;
maxidx = 5;
@ -629,7 +643,11 @@ int qse_pio_init (
FILE_SHARE_READ | FILE_SHARE_WRITE,
&secattr, OPEN_EXISTING, 0, NULL
);
if (windevnul == INVALID_HANDLE_VALUE) goto oops;
if (windevnul == INVALID_HANDLE_VALUE)
{
pio->errnum = syserr_to_errnum (GetLastError());
goto oops;
}
}
QSE_MEMSET (&procinfo, 0, QSE_SIZEOF(procinfo));
@ -743,25 +761,7 @@ int qse_pio_init (
QSE_MMGR_FREE (mmgr, dupcmd);
if (x == FALSE)
{
DWORD e = GetLastError ();
switch (e)
{
case ERROR_ACCESS_DENIED:
pio->errnum = QSE_PIO_EACCES;
break;
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
pio->errnum = QSE_PIO_ENOENT;
break;
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OUTOFMEMORY:
pio->errnum = QSE_PIO_ENOMEM;
break;
}
}
pio->errnum = syserr_to_errnum (GetLastError());
}
if (windevnul != INVALID_HANDLE_VALUE)
@ -792,18 +792,32 @@ int qse_pio_init (
#elif defined(__OS2__)
#define DOS_DUP_HANDLE(x,y) QSE_BLOCK ( \
if (DosDupHandle(x,y) != NO_ERROR) goto oops; \
rc = DosDupHandle(x,y); \
if (rc != NO_ERROR) \
{ \
pio->errnum = syserr_to_errnum (rc); \
goto oops; \
} \
)
if (flags & QSE_PIO_WRITEIN)
{
/* child reads, parent writes */
if (DosCreatePipe (
&handle[0], &handle[1], pipe_size) != NO_ERROR) goto oops;
rc = DosCreatePipe (&handle[0], &handle[1], pipe_size);
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
goto oops;
}
/* the parent writes to handle[1] and the child reads from
* handle[0] inherited. set the flag not to inherit handle[1]. */
if (DosSetFHState (handle[1], OPEN_FLAGS_NOINHERIT) != NO_ERROR) goto oops;
rc = DosSetFHState (handle[1], OPEN_FLAGS_NOINHERIT);
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
goto oops;
}
/* Need to do somthing like this to set the flag instead?
ULONG state;
@ -816,12 +830,21 @@ int qse_pio_init (
if (flags & QSE_PIO_READOUT)
{
/* child writes, parent reads */
if (DosCreatePipe (
&handle[2], &handle[3], pipe_size) != NO_ERROR) goto oops;
rc = DosCreatePipe (&handle[2], &handle[3], pipe_size);
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
goto oops;
}
/* the parent reads from handle[2] and the child writes to
* handle[3] inherited. set the flag not to inherit handle[2] */
if (DosSetFHState (handle[2], OPEN_FLAGS_NOINHERIT) != NO_ERROR) goto oops;
rc = DosSetFHState (handle[2], OPEN_FLAGS_NOINHERIT);
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
goto oops;
}
if (minidx == -1) minidx = 2;
maxidx = 3;
@ -830,12 +853,21 @@ int qse_pio_init (
if (flags & QSE_PIO_READERR)
{
/* child writes, parent reads */
if (DosCreatePipe (
&handle[4], &handle[5], pipe_size) != NO_ERROR) goto oops;
rc = DosCreatePipe (&handle[4], &handle[5], pipe_size);
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
goto oops;
}
/* the parent reads from handle[4] and the child writes to
* handle[5] inherited. set the flag not to inherit handle[4] */
if (DosSetFHState (handle[4], OPEN_FLAGS_NOINHERIT) != NO_ERROR) goto oops;
rc = DosSetFHState (handle[4], OPEN_FLAGS_NOINHERIT);
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
goto oops;
}
if (minidx == -1) minidx = 4;
maxidx = 5;
@ -867,22 +899,32 @@ int qse_pio_init (
OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE,
0L
);
if (rc != NO_ERROR) goto oops;
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
goto oops;
}
}
/* duplicate the current stdin/out/err to old_in/out/err as a new handle */
if (DosDupHandle (std_in, &old_in) != NO_ERROR)
rc = DosDupHandle (std_in, &old_in);
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
goto oops;
}
if (DosDupHandle (std_out, &old_out) != NO_ERROR)
rc = DosDupHandle (std_out, &old_out);
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
DosClose (old_in); old_in = QSE_PIO_HND_NIL;
goto oops;
}
if (DosDupHandle (std_err, &old_err) != NO_ERROR)
rc = DosDupHandle (std_err, &old_err);
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
DosClose (old_out); old_out = QSE_PIO_HND_NIL;
DosClose (old_in); old_in = QSE_PIO_HND_NIL;
goto oops;
@ -1060,8 +1102,6 @@ int qse_pio_init (
cmd_file
);
/* TODO: translate error code ... */
QSE_MMGR_FREE (mmgr, cmd_line);
cmd_line = QSE_NULL;
@ -1074,7 +1114,11 @@ int qse_pio_init (
DosDupHandle (old_err, &std_err);
DosClose (old_err); old_err = QSE_PIO_HND_NIL;
if (rc != NO_ERROR) goto oops;
if (rc != NO_ERROR)
{
pio->errnum = syserr_to_errnum (rc);
goto oops;
}
pio->child = child_rc.codeTerminate;
#elif defined(__DOS__)
@ -1085,20 +1129,32 @@ int qse_pio_init (
#elif defined(HAVE_POSIX_SPAWN)
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;
}

View File

@ -411,94 +411,21 @@ qse_httpd_task_t* qse_httpd_entaskcontinue (
/*------------------------------------------------------------------------*/
#if 0
typedef struct task_file_t task_file_t;
struct task_file_t
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)
{
qse_ubi_t handle;
qse_foff_t left;
qse_foff_t offset;
};
static int task_init_file (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{
task_file_t* xtn = qse_httpd_gettaskxtn (httpd, task);
QSE_MEMCPY (xtn, task->ctx, QSE_SIZEOF(*xtn));
task->ctx = xtn;
return 0;
}
static void task_fini_file (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{
task_file_t* ctx = (task_file_t*)task->ctx;
qse_printf (QSE_T("closing file %d\n"), ctx->handle.i);
QSE_CLOSE (ctx->handle.i);
}
static int task_main_file (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{
qse_ssize_t n;
qse_size_t count;
task_file_t* ctx = (task_file_t*)task->ctx;
count = MAX_SEND_SIZE;
if (count >= ctx->left) count = ctx->left;
/* TODO: more adjustment needed for OS with different sendfile semantics... */
n = httpd->cbs->client.sendfile (
httpd, client, ctx->handle, &ctx->offset, count);
if (n <= -1)
{
// HANDLE EGAIN specially???
return -1; /* TODO: any logging */
}
if (n == 0 && count > 0)
{
/* The file could be truncated when this condition is set.
* The content-length sent in the header can't be fulfilled.
* So let's return an error here so that the main loop abort
* the connection. */
/* TODO: any logging....??? */
return -1;
}
ctx->left -= n;
if (ctx->left <= 0) return 0;
return 1; /* more work to do */
}
qse_httpd_task_t* qse_httpd_entaskfile (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
const qse_httpd_task_t* pred,
qse_ubi_t handle,
qse_foff_t offset,
qse_foff_t size)
{
qse_httpd_task_t task;
task_file_t data;
QSE_MEMSET (&data, 0, QSE_SIZEOF(data));
data.handle = handle;
data.offset = offset;
data.left = size;
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
task.init = task_init_file;
task.main = task_main_file;
task.fini = task_fini_file;
task.ctx = &data;
qse_printf (QSE_T("Debug: entasking file (%d)\n"), client->handle.i);
return qse_httpd_entask (httpd, client, pred, &task, QSE_SIZEOF(data));
const qse_http_version_t* version = qse_htre_getversion(req);
/* TODO: */
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);
}
/*------------------------------------------------------------------------*/
#if 0
typedef struct task_dir_t task_dir_t;
struct task_dir_t
{
@ -867,161 +794,6 @@ static int task_init_path (
return 0;
}
static QSE_INLINE int task_main_path_file (
qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* task, qse_foff_t filesize)
{
task_path_t* data = (task_path_t*)task->ctx;
qse_httpd_task_t* x = task;
qse_ubi_t handle;
int oflags;
/* TODO: if you should deal with files on a network-mounted drive,
setting a trigger or non-blocking I/O are needed. */
/* when it comes to the file size, using fstat after opening
* can be more accurate. but this function uses information
* set into the task context before the call to this function */
qse_printf (QSE_T("opening file %hs\n"), data->name);
oflags = O_RDONLY;
#if defined(O_LARGEFILE)
oflags |= O_LARGEFILE;
#endif
handle.i = QSE_OPEN (data->name, oflags, 0);
if (handle.i <= -1)
{
x = entask_error (
httpd, client, x, 404, &data->version, data->keepalive);
goto no_file_send;
}
oflags = QSE_FCNTL (handle.i, F_GETFD, 0);
if (oflags >= 0)
QSE_FCNTL (handle.i, F_SETFD, oflags | FD_CLOEXEC);
if (data->range.type != QSE_HTTP_RANGE_NONE)
{
const qse_mchar_t* mime_type = QSE_NULL;
if (data->range.type == QSE_HTTP_RANGE_SUFFIX)
{
if (data->range.to > filesize) data->range.to = filesize;
data->range.from = filesize - data->range.to;
data->range.to = data->range.to + data->range.from;
if (filesize > 0) data->range.to--;
}
if (data->range.from >= filesize)
{
x = entask_error (
httpd, client, x, 416, &data->version, data->keepalive);
goto no_file_send;
}
if (data->range.to >= filesize) data->range.to = filesize - 1;
if (httpd->cbs->getmimetype)
{
httpd->errnum = QSE_HTTPD_ENOERR;
mime_type = httpd->cbs->getmimetype (httpd, data->name);
/*TODO: how to handle an error... */
}
#if (QSE_SIZEOF_LONG_LONG > 0)
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 206 Partial Content\r\nConnection: %s\r\n%s%s%sContent-Length: %llu\r\nContent-Range: bytes %llu-%llu/%llu\r\n\r\n"),
data->version.major,
data->version.minor,
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
(mime_type? mime_type: QSE_MT("")),
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long long)(data->range.to - data->range.from + 1),
(unsigned long long)data->range.from,
(unsigned long long)data->range.to,
(unsigned long long)filesize
);
#else
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 206 Partial Content\r\nConnection: %s\r\n%s%s%sContent-Length: %lu\r\nContent-Range: bytes %lu-%lu/%lu\r\n\r\n"),
data->version.major,
data->version.minor,
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
(mime_type? mime_type: QSE_MT("")),
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long)(data->range.to - data->range.from + 1),
(unsigned long)data->range.from,
(unsigned long)data->range.to,
(unsigned long)filesize
);
#endif
if (x)
{
x = qse_httpd_entaskfile (
httpd, client, x,
handle,
data->range.from,
(data->range.to - data->range.from + 1)
);
}
}
else
{
/* TODO: int64 format.... don't hard code it llu */
const qse_mchar_t* mime_type = QSE_NULL;
if (httpd->cbs->getmimetype)
{
httpd->errnum = QSE_HTTPD_ENOERR;
mime_type = httpd->cbs->getmimetype (httpd, data->name);
/*TODO: how to handle an error... */
}
/* wget 1.8.2 set 'Connection: keep-alive' in the http 1.0 header.
* if the reply doesn't contain 'Connection: keep-alive', it didn't
* close connection.*/
#if (QSE_SIZEOF_LONG_LONG > 0)
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\n%s%s%sContent-Length: %llu\r\n\r\n"),
data->version.major, data->version.minor,
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
(mime_type? mime_type: QSE_MT("")),
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long long)filesize
);
#else
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\n%s%s%sContent-Length: %lu\r\n\r\n"),
data->version.major,
data->version.minor,
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
(mime_type? mime_type: QSE_MT("")),
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long)filesize
);
#endif
if (x)
{
x = qse_httpd_entaskfile (
httpd, client, x, handle, 0, filesize);
}
}
return (x == QSE_NULL)? -1: 0;
no_file_send:
if (handle.i >= 0) close (handle.i);
return (x == QSE_NULL)? -1: 0;
}
static QSE_INLINE int task_main_path_dir (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{
@ -1259,8 +1031,8 @@ static QSE_INLINE int task_main_file (
task_file_t* file;
qse_httpd_task_t* x;
qse_ubi_t handle;
qse_foff_t filesize;
int fileopen = 0;
qse_httpd_stat_t st;
file = (task_file_t*)task->ctx;
x = task;
@ -1269,9 +1041,21 @@ static QSE_INLINE int task_main_file (
setting a trigger or non-blocking I/O are needed. */
qse_printf (QSE_T("opening file %hs\n"), file->path);
httpd->errnum = QSE_HTTPD_ENOERR;
if (httpd->cbs->file.stat (httpd, file->path, &st) <= -1)
{
int http_errnum;
http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404:
(httpd->errnum == QSE_HTTPD_EACCES)? 403: 500;
x = entask_error (
httpd, client, x, http_errnum,
&file->version, file->keepalive);
goto no_file_send;
}
httpd->errnum = QSE_HTTPD_ENOERR;
if (httpd->cbs->file.ropen (httpd, file->path, &handle, &filesize) <= -1)
if (httpd->cbs->file.ropen (httpd, file->path, &handle) <= -1)
{
int http_errnum;
http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404:
@ -1285,31 +1069,22 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
if (file->range.type != QSE_HTTP_RANGE_NONE)
{
const qse_mchar_t* mime_type = QSE_NULL;
if (file->range.type == QSE_HTTP_RANGE_SUFFIX)
{
if (file->range.to > filesize) file->range.to = filesize;
file->range.from = filesize - file->range.to;
if (file->range.to > st.size) file->range.to = st.size;
file->range.from = st.size - file->range.to;
file->range.to = file->range.to + file->range.from;
if (filesize > 0) file->range.to--;
if (st.size > 0) file->range.to--;
}
if (file->range.from >= filesize)
if (file->range.from >= st.size)
{
x = entask_error (
httpd, client, x, 416, &file->version, file->keepalive);
goto no_file_send;
}
if (file->range.to >= filesize) file->range.to = filesize - 1;
if (httpd->cbs->getmimetype)
{
httpd->errnum = QSE_HTTPD_ENOERR;
mime_type = httpd->cbs->getmimetype (httpd, file->path);
/*TODO: how to handle an error... */
}
if (file->range.to >= st.size) file->range.to = st.size - 1;
#if (QSE_SIZEOF_LONG_LONG > 0)
x = qse_httpd_entaskformat (
@ -1318,13 +1093,13 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
file->version.major,
file->version.minor,
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
(mime_type? mime_type: QSE_MT("")),
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
(st.mime? QSE_MT("Content-Type: "): QSE_MT("")),
(st.mime? st.mime: QSE_MT("")),
(st.mime? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long long)(file->range.to - file->range.from + 1),
(unsigned long long)file->range.from,
(unsigned long long)file->range.to,
(unsigned long long)filesize
(unsigned long long)st.size
);
#else
x = qse_httpd_entaskformat (
@ -1333,13 +1108,13 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
file->version.major,
file->version.minor,
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
(mime_type? mime_type: QSE_MT("")),
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
(st.mime? QSE_MT("Content-Type: "): QSE_MT("")),
(st.mime? st.mime: QSE_MT("")),
(st.mime? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long)(file->range.to - file->range.from + 1),
(unsigned long)file->range.from,
(unsigned long)file->range.to,
(unsigned long)filesize
(unsigned long)st.size
);
#endif
if (x)
@ -1355,15 +1130,6 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
else
{
/* TODO: int64 format.... don't hard code it llu */
const qse_mchar_t* mime_type = QSE_NULL;
if (httpd->cbs->getmimetype)
{
httpd->errnum = QSE_HTTPD_ENOERR;
mime_type = httpd->cbs->getmimetype (httpd, file->path);
/*TODO: how to handle an error... */
}
/* wget 1.8.2 set 'Connection: keep-alive' in the http 1.0 header.
* if the reply doesn't contain 'Connection: keep-alive', it didn't
* close connection.*/
@ -1373,10 +1139,10 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\n%s%s%sContent-Length: %llu\r\n\r\n"),
file->version.major, file->version.minor,
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
(mime_type? mime_type: QSE_MT("")),
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long long)filesize
(st.mime? QSE_MT("Content-Type: "): QSE_MT("")),
(st.mime? st.mime: QSE_MT("")),
(st.mime? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long long)st.size
);
#else
x = qse_httpd_entaskformat (
@ -1385,16 +1151,15 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
file->version.major,
file->version.minor,
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
(mime_type? mime_type: QSE_MT("")),
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long)filesize
(st.mime? QSE_MT("Content-Type: "): QSE_MT("")),
(st.mime? st.mime: QSE_MT("")),
(st.mime? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long)st.size
);
#endif
if (x)
{
x = entask_file_segment (
httpd, client, x, handle, 0, filesize);
x = entask_file_segment (httpd, client, x, handle, 0, st.size);
}
}
@ -1772,6 +1537,7 @@ qse_mbsxncpy (tmp, QSE_COUNTOF(tmp), qse_htre_getqpathptr(req), qse_htre_getqpat
qse_env_insertmbs (env, QSE_MT("SERVER_PROTOCOL"), proto);
}
// TODO: HTTP_ headers.
// TODO: REMOTE_USER ...
#if 0
qse_env_insertmbs (env, "SERVER_NAME",
@ -2573,19 +2339,6 @@ static QSE_INLINE qse_httpd_task_t* entask_cgi (
qse_httpd_task_t task;
task_cgi_arg_t arg;
#if 0
int x;
/* TODO: NEED TO CHECK IF it's a regular file and executable??
directory may be treated as executable???
*/
x = httpd->cbs->path.executable (httpd, path);
if (x == 0)
return qse_httpd_entaskerror (httpd, client, pred, 403, req);
else if (x <= -1)
return qse_httpd_entaskerror (httpd, client, pred, 404, req);
#endif
arg.path = path;
arg.req = req;
arg.nph = nph;

View File

@ -5,9 +5,11 @@
#include <qse/cmn/str.h>
#include <qse/cmn/mem.h>
#include <qse/cmn/mbwc.h>
#include <qse/cmn/time.h>
#include <signal.h>
#include <locale.h>
#include <string.h>
#if defined(_WIN32)
# include <windows.h>
#else
@ -18,6 +20,8 @@
#endif
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/engine.h>
// TODO: remove this and export structured needed like qse_httpd_client_t
@ -226,22 +230,59 @@ static int mux_writable (qse_httpd_t* httpd, qse_ubi_t handle, qse_ntoff_t msec)
/* ------------------------------------------------------------------- */
static int path_executable (qse_httpd_t* httpd, const qse_mchar_t* path)
static int file_executable (qse_httpd_t* httpd, const qse_mchar_t* path)
{
if (access (path, X_OK) == -1)
return (errno == EACCES)? 0 /*no*/: -1 /*error*/;
return 1; /* yes */
}
/* ------------------------------------------------------------------- */
static int file_stat (
qse_httpd_t* httpd, const qse_mchar_t* path, qse_httpd_stat_t* hst)
{
struct stat st;
/* TODO: lstat? or stat? */
if (stat (path, &st) <= -1)
{
qse_httpd_seterrnum (httpd,
(errno == ENOENT? QSE_HTTPD_ENOENT:
errno == EACCES? QSE_HTTPD_EACCES: QSE_HTTPD_ESUBSYS));
return -1;
}
/* stating for a file. it should be a regular file.
* i don't allow other file types. */
if (!S_ISREG(st.st_mode))
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_EACCES);
return -1;
}
memset (hst, 0, QSE_SIZEOF(*hst));
hst->size = st.st_size;
#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)
hst->mtime = QSE_SECNSEC_TO_MSEC(st.st_mtimespec.tv_sec,st.st_mtimespec.tv_nsec);
#else
hst->mtime = st.st_mtime * QSE_MSECS_PER_SEC;
#endif
hst->mime = qse_mbsend (path, QSE_MT(".html"))? QSE_MT("text/html"):
qse_mbsend (path, QSE_MT(".txt"))? QSE_MT("text/plain"):
qse_mbsend (path, QSE_MT(".jpg"))? QSE_MT("image/jpeg"):
qse_mbsend (path, QSE_MT(".mp4"))? QSE_MT("video/mp4"):
qse_mbsend (path, QSE_MT(".mp3"))? QSE_MT("audio/mpeg"): QSE_NULL;
return 0;
}
static int file_ropen (
qse_httpd_t* httpd, const qse_mchar_t* path,
qse_ubi_t* handle, qse_foff_t* size)
qse_httpd_t* httpd, const qse_mchar_t* path, qse_ubi_t* handle)
{
int fd;
int flags;
struct stat st;
flags = O_RDONLY;
#if defined(O_LARGEFILE)
@ -261,25 +302,6 @@ qse_printf (QSE_T("opening file [%hs] for reading\n"), path);
flags = fcntl (fd, F_GETFD);
if (flags >= 0) fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
/* TODO: fstat64??? */
if (fstat (fd, &st) <= -1)
{
qse_httpd_seterrnum (httpd,
(errno == ENOENT? QSE_HTTPD_ENOENT:
errno == EACCES? QSE_HTTPD_EACCES: QSE_HTTPD_ESUBSYS));
close (fd);
return -1;
}
/* check if it is a link. symbolic link??? */
if (!S_ISREG(st.st_mode))
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_EACCES);
close (fd);
return -1;
}
*size = (st.st_size <= 0)? 0: st.st_size;
handle->i = fd;
qse_printf (QSE_T("opened file %hs\n"), path);
return 0;
@ -617,16 +639,6 @@ static int handle_request (
return process_request (httpd, client, req, 0);
}
const qse_mchar_t* get_mime_type (qse_httpd_t* httpd, const qse_mchar_t* path)
{
if (qse_mbsend (path, QSE_MT(".html"))) return QSE_MT("text/html");
if (qse_mbsend (path, QSE_MT(".txt"))) return QSE_MT("text/plain");
if (qse_mbsend (path, QSE_MT(".jpg"))) return QSE_MT("image/jpeg");
if (qse_mbsend (path, QSE_MT(".mp4"))) return QSE_MT("video/mp4");
if (qse_mbsend (path, QSE_MT(".mp3"))) return QSE_MT("audio/mpeg");
return QSE_NULL;
}
int list_directory (qse_httpd_t* httpd, const qse_mchar_t* path)
{
return 404;
@ -637,11 +649,10 @@ static qse_httpd_cbs_t httpd_cbs =
/* multiplexer */
{ mux_readable, mux_writable },
/* path operation */
{ path_executable },
/* file operation */
{ file_ropen,
{ file_executable,
file_stat,
file_ropen,
file_wopen,
file_close,
file_read,
@ -659,7 +670,6 @@ static qse_httpd_cbs_t httpd_cbs =
peek_request,
handle_request,
get_mime_type,
list_directory
};