added qse_isdriveabspath().

enhanced httpd to accept drive path as a doc root for win/os2
This commit is contained in:
hyung-hwan 2012-12-10 03:10:44 +00:00
parent 5936aea85f
commit a523f1443b
7 changed files with 124 additions and 68 deletions

View File

@ -102,6 +102,10 @@ QSE_EXPORT void* qse_mux_getxtn (
qse_mux_t* mux qse_mux_t* mux
); );
QSE_EXPORT qse_mux_errnum_t qse_mux_geterrnum (
qse_mux_t* mux
);
QSE_EXPORT int qse_mux_insert ( QSE_EXPORT int qse_mux_insert (
qse_mux_t* mux, qse_mux_t* mux,
const qse_mux_evt_t* evt const qse_mux_evt_t* evt

View File

@ -99,6 +99,14 @@ QSE_EXPORT int qse_ismbsdrivepath (
const qse_mchar_t* path const qse_mchar_t* path
); );
/**
* The qse_ismbsdriveabspath() function determines if a path name is in the form
* of a drive letter followed by a colon like A: and a path separator.
*/
QSE_EXPORT int qse_ismbsdriveabspath (
const qse_mchar_t* path
);
/** /**
* The qse_ismbsdrivecurpath() function determines if a path name is in the form * The qse_ismbsdrivecurpath() function determines if a path name is in the form
* of a drive letter followed by a colon like A:, without any trailing path. * of a drive letter followed by a colon like A:, without any trailing path.
@ -165,6 +173,14 @@ QSE_EXPORT int qse_iswcsdrivepath (
const qse_wchar_t* path const qse_wchar_t* path
); );
/**
* The qse_iswcsdriveabspath() function determines if a path name is in the form
* of a drive letter followed by a colon like A: and a path separtor.
*/
QSE_EXPORT int qse_iswcsdriveabspath (
const qse_wchar_t* path
);
/** /**
* The qse_iswcsdrivecurpath() function determines if a path name is in the form * The qse_iswcsdrivecurpath() function determines if a path name is in the form
* of a drive letter followed by a colon like A:, without any trailing path. * of a drive letter followed by a colon like A:, without any trailing path.
@ -215,11 +231,13 @@ QSE_EXPORT qse_size_t qse_canonwcspath (
#if defined(QSE_CHAR_IS_MCHAR) #if defined(QSE_CHAR_IS_MCHAR)
# define qse_isabspath(p) qse_ismbsabspath(p) # define qse_isabspath(p) qse_ismbsabspath(p)
# define qse_isdrivepath(p) qse_ismbsdrivepath(p) # define qse_isdrivepath(p) qse_ismbsdrivepath(p)
# define qse_isdriveabspath(p) qse_ismbsdriveabspath(p)
# define qse_isdrivecurpath(p) qse_ismbsdrivecurpath(p) # define qse_isdrivecurpath(p) qse_ismbsdrivecurpath(p)
# define qse_canonpath(p,c,f) qse_canonmbspath(p,c,f) # define qse_canonpath(p,c,f) qse_canonmbspath(p,c,f)
#else #else
# define qse_isabspath(p) qse_iswcsabspath(p) # define qse_isabspath(p) qse_iswcsabspath(p)
# define qse_isdrivepath(p) qse_iswcsdrivepath(p) # define qse_isdrivepath(p) qse_iswcsdrivepath(p)
# define qse_isdriveabspath(p) qse_iswcsdriveabspath(p)
# define qse_isdrivecurpath(p) qse_iswcsdrivecurpath(p) # define qse_isdrivecurpath(p) qse_iswcsdrivecurpath(p)
# define qse_canonpath(p,c,f) qse_canonwcspath(p,c,f) # define qse_canonpath(p,c,f) qse_canonwcspath(p,c,f)
#endif #endif

View File

@ -49,7 +49,6 @@ enum qse_httpd_errnum_t
QSE_HTTPD_EAGAIN, QSE_HTTPD_EAGAIN,
QSE_HTTPD_ENOBUF, QSE_HTTPD_ENOBUF,
QSE_HTTPD_EIOMUX,
QSE_HTTPD_EDISCON, /* client disconnnected */ QSE_HTTPD_EDISCON, /* client disconnnected */
QSE_HTTPD_EBADREQ, /* bad request */ QSE_HTTPD_EBADREQ, /* bad request */
QSE_HTTPD_ETASK QSE_HTTPD_ETASK

View File

@ -363,14 +363,17 @@ void* qse_mux_getxtn (qse_mux_t* mux)
return QSE_XTN (mux); return QSE_XTN (mux);
} }
qse_mux_errnum_t qse_mux_geterrnum (qse_mux_t* mux)
{
return mux->errnum;
}
#define ALIGN_TO(num,align) ((((num) + (align) - 1) / (align)) * (align)) #define ALIGN_TO(num,align) ((((num) + (align) - 1) / (align)) * (align))
int qse_mux_insert (qse_mux_t* mux, const qse_mux_evt_t* evt) int qse_mux_insert (qse_mux_t* mux, const qse_mux_evt_t* evt)
{ {
#if defined(__OS2__) #if defined(__OS2__)
if (evt) qse_printf (QSE_T("INSERTING HANDLE %d\n"), (int)evt->hnd);
else qse_printf (QSE_T("WHAT..... NULL\n"));
if (evt->hnd >= mux->me.ubound) if (evt->hnd >= mux->me.ubound)
{ {
qse_mux_evt_t** tmp; qse_mux_evt_t** tmp;
@ -564,6 +567,7 @@ int qse_mux_delete (qse_mux_t* mux, const qse_mux_evt_t* evt)
} }
mevt->hnd = -1; mevt->hnd = -1;
mevt->mask = 0;
mux->size--; mux->size--;
return 0; return 0;
@ -608,6 +612,7 @@ int qse_mux_delete (qse_mux_t* mux, const qse_mux_evt_t* evt)
done: done:
mevt->hnd = -1; mevt->hnd = -1;
mevt->mask = 0;
mux->size--; mux->size--;
return 0; return 0;
@ -652,15 +657,13 @@ int qse_mux_poll (qse_mux_t* mux, const qse_ntime_t* tmout)
for (i = 0; i < mux->me.ubound; i++) for (i = 0; i < mux->me.ubound; i++)
{ {
evt = mux->me.ptr[i]; evt = mux->me.ptr[i];
if (evt && (evt->mask & QSE_MUX_IN)) if (evt && (evt->mask & QSE_MUX_IN)) mux->fdarr[count++] = evt->hnd;
mux->fdarr[count++] = evt->hnd;
} }
rcount = count; rcount = count;
for (i = 0; i < mux->me.ubound; i++) for (i = 0; i < mux->me.ubound; i++)
{ {
evt = mux->me.ptr[i]; evt = mux->me.ptr[i];
if (evt && (evt->mask & QSE_MUX_OUT)) if (evt && (evt->mask & QSE_MUX_OUT)) mux->fdarr[count++] = evt->hnd;
mux->fdarr[count++] = evt->hnd;
} }
wcount = count - rcount; wcount = count - rcount;
@ -677,22 +680,21 @@ int qse_mux_poll (qse_mux_t* mux, const qse_ntime_t* tmout)
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
evt = mux->me.ptr[i]; if (mux->fdarr[i] == -1) continue;
if (!evt || evt->hnd != i || mux->fdarr[i] == -1) continue;
QSE_MEMCPY (&xevt, evt, QSE_SIZEOF(xevt)); evt = mux->me.ptr[mux->fdarr[i]];
if (!evt || evt->hnd != mux->fdarr[i]) continue;
xevt.mask = 0; xevt = *evt;
if ((evt->mask & QSE_MUX_IN) && i < rcount)
xevt.mask |= QSE_MUX_IN;
if ((evt->mask & QSE_MUX_OUT) && i >= rcount)
xevt.mask |= QSE_MUX_OUT;
if (xevt.mask > 0) mux->evtfun (mux, &xevt); /* due to the way i check 'fdarr' , it can't have
* both IN and OUT at the same time. they are
* triggered separately */
xevt.mask = (i < rcount)? QSE_MUX_IN: QSE_MUX_OUT;
mux->evtfun (mux, &xevt);
} }
} }
return n; return n;
#elif defined(USE_SELECT) #elif defined(USE_SELECT)
@ -728,8 +730,7 @@ int qse_mux_poll (qse_mux_t* mux, const qse_ntime_t* tmout)
evt = mux->me.ptr[i]; evt = mux->me.ptr[i];
if (!evt || evt->hnd != i) continue; if (!evt || evt->hnd != i) continue;
QSE_MEMCPY (&xevt, evt, QSE_SIZEOF(xevt)); xevt = *evt;
xevt.mask = 0; xevt.mask = 0;
if ((evt->mask & QSE_MUX_IN) && if ((evt->mask & QSE_MUX_IN) &&
FD_ISSET(evt->hnd, &mux->tmprset)) xevt.mask |= QSE_MUX_IN; FD_ISSET(evt->hnd, &mux->tmprset)) xevt.mask |= QSE_MUX_IN;
@ -764,8 +765,7 @@ int qse_mux_poll (qse_mux_t* mux, const qse_ntime_t* tmout)
evt = mux->ee.ptr[i].data.ptr; evt = mux->ee.ptr[i].data.ptr;
QSE_MEMCPY (&xevt, evt, QSE_SIZEOF(xevt)); xevt = *evt;
xevt.mask = 0; xevt.mask = 0;
if (mux->ee.ptr[i].events & EPOLLIN) xevt.mask |= QSE_MUX_IN; if (mux->ee.ptr[i].events & EPOLLIN) xevt.mask |= QSE_MUX_IN;
if (mux->ee.ptr[i].events & EPOLLOUT) xevt.mask |= QSE_MUX_OUT; if (mux->ee.ptr[i].events & EPOLLOUT) xevt.mask |= QSE_MUX_OUT;

View File

@ -53,6 +53,14 @@ int qse_ismbsdrivepath (const qse_mchar_t* path)
return 0; return 0;
} }
int qse_ismbsdriveabspath (const qse_mchar_t* path)
{
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
if (IS_MDRIVE(path) && IS_MSEP(path[2])) return 1;
#endif
return 0;
}
int qse_ismbsdrivecurpath (const qse_mchar_t* path) int qse_ismbsdrivecurpath (const qse_mchar_t* path)
{ {
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) #if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
@ -360,6 +368,14 @@ int qse_iswcsdrivepath (const qse_wchar_t* path)
return 0; return 0;
} }
int qse_iswcsdriveabspath (const qse_wchar_t* path)
{
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
if (IS_WDRIVE(path) && IS_WSEP(path[2])) return 1;
#endif
return 0;
}
int qse_iswcsdrivecurpath (const qse_wchar_t* path) int qse_iswcsdrivecurpath (const qse_wchar_t* path)
{ {
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) #if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)

View File

@ -241,6 +241,35 @@ static qse_httpd_errnum_t syserr_to_errnum (int e)
} }
#endif #endif
static qse_httpd_errnum_t muxerr_to_errnum (qse_mux_errnum_t e)
{
switch (e)
{
case QSE_MUX_ENOMEM:
return QSE_HTTPD_ENOMEM;
case QSE_MUX_EINVAL:
return QSE_HTTPD_EINVAL;
case QSE_MUX_EACCES:
return QSE_HTTPD_EACCES;
case QSE_MUX_ENOENT:
return QSE_HTTPD_ENOENT;
case QSE_MUX_EEXIST:
return QSE_HTTPD_EEXIST;
case QSE_MUX_EINTR:
return QSE_HTTPD_EINTR;
default:
return QSE_HTTPD_ESYSERR;
}
}
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
#define MAX_SEND_SIZE 4096 #define MAX_SEND_SIZE 4096
@ -891,9 +920,7 @@ static void* mux_open (qse_httpd_t* httpd, qse_httpd_muxcb_t cbfun)
mux = qse_mux_open (httpd->mmgr, QSE_SIZEOF(*xtn), dispatch_muxcb, 256); mux = qse_mux_open (httpd->mmgr, QSE_SIZEOF(*xtn), dispatch_muxcb, 256);
if (!mux) if (!mux)
{ {
/* TODO qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR);
qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux));
*/
return QSE_NULL; return QSE_NULL;
} }
@ -921,9 +948,7 @@ static int mux_addhnd (
if (qse_mux_insert ((qse_mux_t*)vmux, &evt) <= -1) if (qse_mux_insert ((qse_mux_t*)vmux, &evt) <= -1)
{ {
/* TODO qse_httpd_seterrnum (httpd, muxerr_to_errnum(qse_mux_geterrnum((qse_mux_t*)vmux)));
qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux));
*/
return -1; return -1;
} }
@ -936,9 +961,7 @@ static int mux_delhnd (qse_httpd_t* httpd, void* vmux, qse_ubi_t handle)
evt.hnd = handle.i; evt.hnd = handle.i;
if (qse_mux_delete ((qse_mux_t*)vmux, &evt) <= -1) if (qse_mux_delete ((qse_mux_t*)vmux, &evt) <= -1)
{ {
/* TODO qse_httpd_seterrnum (httpd, muxerr_to_errnum(qse_mux_geterrnum((qse_mux_t*)vmux)));
qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux));
*/
return -1; return -1;
} }
return 0; return 0;
@ -948,9 +971,7 @@ static int mux_poll (qse_httpd_t* httpd, void* vmux, const qse_ntime_t* tmout)
{ {
if (qse_mux_poll ((qse_mux_t*)vmux, tmout) <= -1) if (qse_mux_poll ((qse_mux_t*)vmux, tmout) <= -1)
{ {
/* TODO qse_httpd_seterrnum (httpd, muxerr_to_errnum(qse_mux_geterrnum((qse_mux_t*)vmux)));
qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux));
*/
return -1; return -1;
} }
@ -1021,9 +1042,6 @@ static int stat_file (
WIN32_FIND_DATAA fdata; WIN32_FIND_DATAA fdata;
ULARGE_INTEGER li; ULARGE_INTEGER li;
/* fail if the path name contains a wilecard letter */
if (qse_mbspbrk (path, QSE_MT("?*")) != QSE_NULL) return -1;
if (path[0] == QSE_MT('/') && path[1] == QSE_MT('\0')) if (path[0] == QSE_MT('/') && path[1] == QSE_MT('\0'))
{ {
/* the root directory won't work well with FindFirstFile().*/ /* the root directory won't work well with FindFirstFile().*/
@ -1035,6 +1053,9 @@ static int stat_file (
{ {
/* TODO: hst->dev can be set to the drive letter's index. */ /* TODO: hst->dev can be set to the drive letter's index. */
/* fail if the path name contains a wilecard letter */
if (qse_mbspbrk (path, QSE_MT("?*")) != QSE_NULL) return -1;
fh = FindFirstFileA (path, &fdata); fh = FindFirstFileA (path, &fdata);
if (fh == INVALID_HANDLE_VALUE) return -1; if (fh == INVALID_HANDLE_VALUE) return -1;
@ -1056,29 +1077,10 @@ static int stat_file (
#elif defined(__OS2__) #elif defined(__OS2__)
APIRET rc; APIRET rc;
FILEFINDBUF3L ffb;
qse_btime_t bt; qse_btime_t bt;
qse_ntime_t nt; qse_ntime_t nt;
#if 0 FILESTATUS3L ffb;
HDIR h;
ULONG count;
/* fail if the path name contains a wilecard letter */
if (qse_mbspbrk (path, QSE_MT("?*")) != QSE_NULL) return -1;
rc = DosFindFirst (
path,
&h,
FILE_DIRECTORY | FILE_READONLY,
&ffb,
QSE_SIZEOF(ffb),
&count,
FIL_STANDARDL);
if (rc != NO_ERROR) return -1;
DosFindClose (h);
#endif
rc = DosQueryPathInfo (path, FIL_STANDARDL, &ffb, QSE_SIZEOF(ffb)); rc = DosQueryPathInfo (path, FIL_STANDARDL, &ffb, QSE_SIZEOF(ffb));
if (rc != NO_ERROR) return -1; if (rc != NO_ERROR) return -1;
@ -1987,7 +1989,7 @@ static int make_resource (
qse_mchar_t* xpath; qse_mchar_t* xpath;
qse_httpd_stat_t st; qse_httpd_stat_t st;
qse_size_t i; qse_size_t i;
int n; int n, stx;
qpath = qse_htre_getqpath(req); qpath = qse_htre_getqpath(req);
@ -2022,10 +2024,23 @@ auth_ok:
xpath = merge_paths (httpd, server_xtn->cfg[SERVER_XTN_CFG_DOCROOT], qpath); xpath = merge_paths (httpd, server_xtn->cfg[SERVER_XTN_CFG_DOCROOT], qpath);
if (xpath == QSE_NULL) return -1; if (xpath == QSE_NULL) return -1;
qse_printf (QSE_T(">>> check if [%hs] is a directory\n"), xpath); stx = stat_file (httpd, xpath, &st, 0);
if (stat_file (httpd, xpath, &st, 0) >= 0 && st.isdir) #if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
if (stx <= -1)
{
/* these OS may fail if the path contains the trailing separator.
* i work around it here */
qse_size_t pl = qse_mbslen(xpath);
if (pl > 1 && xpath[pl - 1] == QSE_MT('/'))
{
xpath[pl-1] = QSE_MT('\0');
stx = stat_file (httpd, xpath, &st, 0);
xpath[pl-1] = QSE_MT('/');
}
}
#endif
if (stx >= 0 && st.isdir)
{ {
qse_printf (QSE_T(">>> [%hs] is a directory\n"), xpath);
/* it is a directory */ /* it is a directory */
if (server_xtn->cfg2.s.idxstd) if (server_xtn->cfg2.s.idxstd)
{ {
@ -2056,11 +2071,9 @@ qse_printf (QSE_T(">>> [%hs] is a directory\n"), xpath);
target->type = QSE_HTTPD_RSRC_DIR; target->type = QSE_HTTPD_RSRC_DIR;
target->u.dir.path = xpath; target->u.dir.path = xpath;
qse_printf (QSE_T(">>> MADE DIREcTORY RESOURCE [%hs]\n"), xpath);
} }
else else
{ {
qse_printf (QSE_T(">>> [%hs] is a file\n"), xpath);
attempt_file: attempt_file:
if (server_xtn->cfg2.s.cgistd) if (server_xtn->cfg2.s.cgistd)
{ {
@ -2216,6 +2229,7 @@ qse_httpd_server_t* qse_httpd_attachserverstd (
if (!xuri.path.ptr) if (!xuri.path.ptr)
{ {
/* the path part is not specified */
#if defined(QSE_CHAR_IS_MCHAR) #if defined(QSE_CHAR_IS_MCHAR)
xuri.path.ptr = QSE_MT("/"); xuri.path.ptr = QSE_MT("/");
#else #else
@ -2236,12 +2250,18 @@ qse_httpd_server_t* qse_httpd_attachserverstd (
} }
#if defined(QSE_CHAR_IS_MCHAR) #if defined(QSE_CHAR_IS_MCHAR)
server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_mbsxdup (xuri.path.ptr, xuri.path.len, httpd->mmgr); if (qse_ismbsdriveabspath((const qse_mchar_t*)xuri.path.ptr + 1))
server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_mbsxdup ((const qse_mchar_t*)xuri.path.ptr + 1, xuri.path.len - 1, httpd->mmgr);
else
server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_mbsxdup (xuri.path.ptr, xuri.path.len, httpd->mmgr);
if (xuri.frag.ptr) server_xtn->cfg[SERVER_XTN_CFG_REALM] = qse_mbsxdup (xuri.frag.ptr, xuri.frag.len, httpd->mmgr); if (xuri.frag.ptr) server_xtn->cfg[SERVER_XTN_CFG_REALM] = qse_mbsxdup (xuri.frag.ptr, xuri.frag.len, httpd->mmgr);
ba.ptr = qse_mcstradup (tmp, &ba.len, httpd->mmgr); ba.ptr = qse_mcstradup (tmp, &ba.len, httpd->mmgr);
#else #else
server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_wcsntombsdup (xuri.path.ptr, xuri.path.len, QSE_NULL, httpd->mmgr); if (qse_iswcsdriveabspath((const qse_wchar_t*)xuri.path.ptr + 1))
server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_wcsntombsdup ((const qse_wchar_t*)xuri.path.ptr + 1, xuri.path.len - 1, QSE_NULL, httpd->mmgr);
else
server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_wcsntombsdup (xuri.path.ptr, xuri.path.len, QSE_NULL, httpd->mmgr);
if (xuri.frag.ptr) server_xtn->cfg[SERVER_XTN_CFG_REALM] = qse_wcsntombsdup (xuri.frag.ptr, xuri.frag.len, QSE_NULL, httpd->mmgr); if (xuri.frag.ptr) server_xtn->cfg[SERVER_XTN_CFG_REALM] = qse_wcsntombsdup (xuri.frag.ptr, xuri.frag.len, QSE_NULL, httpd->mmgr);
ba.ptr = qse_wcsnatombsdup (tmp, &ba.len, httpd->mmgr); ba.ptr = qse_wcsnatombsdup (tmp, &ba.len, httpd->mmgr);
#endif #endif

View File

@ -647,10 +647,12 @@ qse_printf (QSE_T(">>>>> Returning failure for client %d\n"), client->handle.i);
} }
qse_printf (QSE_T("!!!!!FEEDING %d from %d ["), (int)m, (int)client->handle.i); qse_printf (QSE_T("!!!!!FEEDING %d from %d ["), (int)m, (int)client->handle.i);
#if !defined(__OS2__)
{ {
int i; int i;
for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]); for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]);
} }
#endif
qse_printf (QSE_T("]\n")); qse_printf (QSE_T("]\n"));
/* qse_htrd_feed() may call the request callback /* qse_htrd_feed() may call the request callback
@ -1134,15 +1136,12 @@ qse_printf (QSE_T("no servers are active....\n"));
{ {
int count; int count;
qse_printf (QSE_T("POLLING %d tmout ..\n"), tmout->sec);
count = httpd->scb->mux.poll (httpd, httpd->mux, tmout); count = httpd->scb->mux.poll (httpd, httpd->mux, tmout);
qse_printf (QSE_T("POLLING %d return ..\n"), count);
if (count <= -1) if (count <= -1)
{ {
httpd->errnum = QSE_HTTPD_EIOMUX;
/* TODO: call user callback for this multiplexer error */ /* TODO: call user callback for this multiplexer error */
/*if (errno == EINTR) continue;*/ /*if (errno == EINTR) continue;*/
qse_fprintf (QSE_STDERR, QSE_T("Error: mux returned failure\n")); qse_fprintf (QSE_STDERR, QSE_T("Error: mux returned failure %d\n"), (int)httpd->errnum);
/* break; */ /* break; */
} }