added hton,ntoh
renamed qse_getcmgrbyname() to qse_findcmgr() added qse_setcmgrfinder()/qse_getcmgrfinder() started adding ipad,nwad
This commit is contained in:
parent
35ac9924ac
commit
b330d2c350
@ -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);
|
||||
|
@ -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 \
|
||||
|
@ -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:
|
||||
|
75
qse/include/qse/cmn/hton.h
Normal file
75
qse/include/qse/cmn/hton.h
Normal 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
|
66
qse/include/qse/cmn/ipad.h
Normal file
66
qse/include/qse/cmn/ipad.h
Normal 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
|
@ -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 */
|
||||
/* --------------------------------------------------- */
|
||||
|
52
qse/include/qse/cmn/nwad.h
Normal file
52
qse/include/qse/cmn/nwad.h
Normal 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
|
@ -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);
|
||||
|
||||
int (*stat) (
|
||||
qse_httpd_t* httpd, const qse_mchar_t* path,
|
||||
qse_httpd_stat_t* stat);
|
||||
|
||||
struct
|
||||
{
|
||||
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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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 \
|
||||
|
@ -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
203
qse/lib/cmn/hton.c
Normal 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
573
qse/lib/cmn/ipad.c
Normal 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
|
@ -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
37
qse/lib/cmn/nwad.c
Normal 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>
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -1271,7 +1043,19 @@ static QSE_INLINE int task_main_file (
|
||||
qse_printf (QSE_T("opening file %hs\n"), file->path);
|
||||
|
||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||
if (httpd->cbs->file.ropen (httpd, file->path, &handle, &filesize) <= -1)
|
||||
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) <= -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;
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user