mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 06:37:08 +00:00
#664: Fix issue with Python 3 mapping of FILE* using file_py3.i from ldns.
git-svn-id: file:///svn/unbound/trunk@3403 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
da612901d7
commit
863b12ffd4
@ -25,6 +25,7 @@ DNSTAP_SRC=@DNSTAP_SRC@
|
||||
DNSTAP_OBJ=@DNSTAP_OBJ@
|
||||
WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
|
||||
WITH_PYUNBOUND=@WITH_PYUNBOUND@
|
||||
PY_MAJOR_VERSION=@PY_MAJOR_VERSION@
|
||||
PYTHON_SITE_PKG=@PYTHON_SITE_PKG@
|
||||
PYTHONMOD_INSTALL=@PYTHONMOD_INSTALL@
|
||||
PYTHONMOD_UNINSTALL=@PYTHONMOD_UNINSTALL@
|
||||
@ -393,7 +394,7 @@ libunbound_wrap.lo libunbound_wrap.o: libunbound/python/libunbound_wrap.c \
|
||||
unbound.h
|
||||
libunbound/python/libunbound_wrap.c: $(srcdir)/libunbound/python/libunbound.i unbound.h
|
||||
@-if test ! -d libunbound/python; then $(INSTALL) -d libunbound/python; fi
|
||||
$(SWIG) -python -o $@ $(CPPFLAGS) $(srcdir)/libunbound/python/libunbound.i
|
||||
$(SWIG) -python -o $@ $(CPPFLAGS) -DPY_MAJOR_VERSION=$(PY_MAJOR_VERSION) $(srcdir)/libunbound/python/libunbound.i
|
||||
|
||||
# Pyunbound python unbound wrapper
|
||||
_unbound.la: libunbound_wrap.lo libunbound.la
|
||||
|
@ -475,6 +475,8 @@ if test x_$ub_test_python != x_no; then
|
||||
AC_ERROR([Python version >= 2.4.0 is required])
|
||||
fi
|
||||
|
||||
PY_MAJOR_VERSION="`$PYTHON -c "import sys; print(sys.version_info.major)"`"
|
||||
AC_SUBST(PY_MAJOR_VERSION)
|
||||
# Have Python
|
||||
AC_DEFINE(HAVE_PYTHON,1,[Define if you have Python libraries and header files.])
|
||||
LIBS="$PYTHON_LDFLAGS $LIBS"
|
||||
|
@ -7,6 +7,7 @@
|
||||
Use print_function also for Python2.
|
||||
libunbound examples: produce sorted output.
|
||||
libunbound-Python: libldns is not used anymore.
|
||||
Fix issue with Python 3 mapping of FILE* using file_py3.i from ldns.
|
||||
|
||||
10 April 2015: Wouter
|
||||
- unbound-control ratelimit_list lists high rate domains.
|
||||
|
155
libunbound/python/file_py3.i
Normal file
155
libunbound/python/file_py3.i
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* file_py3.i: Typemaps for FILE* for Python 3
|
||||
*
|
||||
* Copyright (c) 2011, Karel Slany (karel.slany AT nic.cz)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the organization nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
%{
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
%}
|
||||
|
||||
%types(FILE *);
|
||||
|
||||
//#define SWIG_FILE3_DEBUG
|
||||
|
||||
/* converts basic file descriptor flags onto a string */
|
||||
%fragment("fdfl_to_str", "header") {
|
||||
const char *
|
||||
fdfl_to_str(int fdfl) {
|
||||
|
||||
static const char * const file_mode[] = {"w+", "w", "r"};
|
||||
|
||||
if (fdfl & O_RDWR) {
|
||||
return file_mode[0];
|
||||
} else if (fdfl & O_WRONLY) {
|
||||
return file_mode[1];
|
||||
} else {
|
||||
return file_mode[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%fragment("is_obj_file", "header") {
|
||||
int
|
||||
is_obj_file(PyObject *obj) {
|
||||
int fd, fdfl;
|
||||
if (!PyLong_Check(obj) && /* is not an integer */
|
||||
PyObject_HasAttrString(obj, "fileno") && /* has fileno method */
|
||||
(PyObject_CallMethod(obj, "flush", NULL) != NULL) && /* flush() succeeded */
|
||||
((fd = PyObject_AsFileDescriptor(obj)) != -1) && /* got file descriptor */
|
||||
((fdfl = fcntl(fd, F_GETFL)) != -1) /* got descriptor flags */
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%fragment("obj_to_file","header", fragment="fdfl_to_str,is_obj_file") {
|
||||
FILE *
|
||||
obj_to_file(PyObject *obj) {
|
||||
int fd, fdfl;
|
||||
FILE *fp;
|
||||
if (is_obj_file(obj)) {
|
||||
fd = PyObject_AsFileDescriptor(obj);
|
||||
fdfl = fcntl(fd, F_GETFL);
|
||||
fp = fdopen(dup(fd), fdfl_to_str(fdfl)); /* the FILE* must be flushed
|
||||
and closed after being used */
|
||||
#ifdef SWIG_FILE3_DEBUG
|
||||
fprintf(stderr, "opening fd %d (fl %d \"%s\") as FILE %p\n",
|
||||
fd, fdfl, fdfl_to_str(fdfl), (void *)fp);
|
||||
#endif
|
||||
return fp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* returns -1 if error occurred */
|
||||
/* caused magic SWIG Syntax errors when was commented out */
|
||||
#if 0
|
||||
%fragment("dispose_file", "header") {
|
||||
int
|
||||
dispose_file(FILE **fp) {
|
||||
#ifdef SWIG_FILE3_DEBUG
|
||||
fprintf(stderr, "flushing FILE %p\n", (void *)fp);
|
||||
#endif
|
||||
if (*fp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if ((fflush(*fp) == 0) && /* flush file */
|
||||
(fclose(*fp) == 0)) { /* close file */
|
||||
*fp = NULL;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
%typemap(arginit, noblock = 1) FILE* {
|
||||
$1 = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* added due to ub_ctx_debugout since since it is overloaded:
|
||||
* takes void* and FILE*. In reality only FILE* but the wrapper
|
||||
* and the function is declared in such way.
|
||||
*/
|
||||
%typemap(typecheck, noblock = 1, fragment = "is_obj_file", precedence = SWIG_TYPECHECK_POINTER) FILE* {
|
||||
$1 = is_obj_file($input);
|
||||
}
|
||||
|
||||
%typemap(check, noblock = 1) FILE* {
|
||||
if ($1 == NULL) {
|
||||
/* The generated wrapper function raises TypeError on mismatching types. */
|
||||
SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument "
|
||||
"$argnum"" of type '" "$type""'");
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(in, noblock = 1, fragment = "obj_to_file") FILE* {
|
||||
$1 = obj_to_file($input);
|
||||
}
|
||||
|
||||
/*
|
||||
* Commented out due the way how ub_ctx_debugout() uses the parameter.
|
||||
* This typemap would cause the FILE* to be closed after return from
|
||||
* the function. This caused Python interpreter to crash, since the
|
||||
* function just stores the FILE* internally in ctx and use it for
|
||||
* logging. So we'll leave the closing of the file on the OS.
|
||||
*/
|
||||
/*%typemap(freearg, noblock = 1, fragment = "dispose_file") FILE* {
|
||||
if (dispose_file(&$1) == -1) {
|
||||
SWIG_exception_fail(SWIG_IOError, "closing file in method '" "$symname" "', argument "
|
||||
"$argnum"" of type '" "$type""'");
|
||||
}
|
||||
}*/
|
@ -60,7 +60,11 @@
|
||||
%}
|
||||
|
||||
//%include "doc.i"
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
%include "file_py3.i" // python 3 FILE *
|
||||
#else
|
||||
%include "file.i"
|
||||
#endif
|
||||
|
||||
%feature("docstring") strerror "Convert error value to a human readable string."
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
%include "stdint.i" // uint_16_t can be known type now
|
||||
|
||||
%inline %{
|
||||
//converts [len][data][len][data][0] string to a List of labels (PyStrings)
|
||||
//converts [len][data][len][data][0] string to a List of labels (PyBytes)
|
||||
PyObject* GetNameAsLabelList(const char* name, int len) {
|
||||
PyObject* list;
|
||||
int cnt=0, i;
|
||||
@ -79,8 +79,8 @@ struct query_info {
|
||||
%inline %{
|
||||
enum enum_rr_class {
|
||||
RR_CLASS_IN = 1,
|
||||
RR_CLASS_CH = 3,
|
||||
RR_CLASS_HS = 4,
|
||||
RR_CLASS_CH = 3,
|
||||
RR_CLASS_HS = 4,
|
||||
RR_CLASS_NONE = 254,
|
||||
RR_CLASS_ANY = 255,
|
||||
};
|
||||
@ -164,7 +164,7 @@ struct query_info {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
buf[0] = '\0';
|
||||
dname_str((uint8_t*)dname, buf);
|
||||
return PyString_FromString(buf);
|
||||
return PyBytes_FromString(buf);
|
||||
}
|
||||
%}
|
||||
|
||||
@ -440,7 +440,7 @@ struct comm_reply {
|
||||
reply_addr2str(reply, dest, 64);
|
||||
if (dest[0] == 0)
|
||||
return Py_None;
|
||||
return PyString_FromString(dest);
|
||||
return PyBytes_FromString(dest);
|
||||
}
|
||||
|
||||
PyObject* _comm_reply_family_get(struct comm_reply* reply) {
|
||||
@ -448,9 +448,9 @@ struct comm_reply {
|
||||
int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
|
||||
|
||||
switch(af) {
|
||||
case AF_INET: return PyString_FromString("ip4");
|
||||
case AF_INET6: return PyString_FromString("ip6");
|
||||
case AF_UNIX: return PyString_FromString("unix");
|
||||
case AF_INET: return PyBytes_FromString("ip4");
|
||||
case AF_INET6: return PyBytes_FromString("ip6");
|
||||
case AF_UNIX: return PyBytes_FromString("unix");
|
||||
}
|
||||
|
||||
return Py_None;
|
||||
@ -711,13 +711,13 @@ struct delegpt {
|
||||
|
||||
%inline %{
|
||||
PyObject* _get_dp_dname(struct delegpt* dp) {
|
||||
return PyString_FromStringAndSize((char*)dp->name, dp->namelen);
|
||||
return PyBytes_FromStringAndSize((char*)dp->name, dp->namelen);
|
||||
}
|
||||
PyObject* _get_dp_dname_components(struct delegpt* dp) {
|
||||
return GetNameAsLabelList((char*)dp->name, dp->namelen);
|
||||
}
|
||||
PyObject* _get_dpns_dname(struct delegpt_ns* dpns) {
|
||||
return PyString_FromStringAndSize((char*)dpns->name, dpns->namelen);
|
||||
return PyBytes_FromStringAndSize((char*)dpns->name, dpns->namelen);
|
||||
}
|
||||
PyObject* _get_dpns_dname_components(struct delegpt_ns* dpns) {
|
||||
return GetNameAsLabelList((char*)dpns->name, dpns->namelen);
|
||||
@ -728,7 +728,7 @@ struct delegpt {
|
||||
delegpt_addr_addr2str(target, dest, 64);
|
||||
if (dest[0] == 0)
|
||||
return Py_None;
|
||||
return PyString_FromString(dest);
|
||||
return PyBytes_FromString(dest);
|
||||
}
|
||||
|
||||
%}
|
||||
@ -842,7 +842,7 @@ int checkList(PyObject *l)
|
||||
for (i=0; i < PyList_Size(l); i++)
|
||||
{
|
||||
item = PyList_GetItem(l, i);
|
||||
if (!PyString_Check(item))
|
||||
if (!PyBytes_Check(item))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -864,12 +864,12 @@ int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec,
|
||||
|
||||
len = sldns_buffer_remaining(qb);
|
||||
if(qsec) {
|
||||
if(sldns_str2wire_rr_question_buf(PyString_AsString(item),
|
||||
if(sldns_str2wire_rr_question_buf(PyBytes_AsString(item),
|
||||
sldns_buffer_current(qb), &len, NULL, NULL, 0, NULL, 0)
|
||||
!= 0)
|
||||
return 0;
|
||||
} else {
|
||||
if(sldns_str2wire_rr_buf(PyString_AsString(item),
|
||||
if(sldns_str2wire_rr_buf(PyBytes_AsString(item),
|
||||
sldns_buffer_current(qb), &len, NULL, default_ttl,
|
||||
NULL, 0, NULL, 0) != 0)
|
||||
return 0;
|
||||
|
@ -133,7 +133,13 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
/* Initialize Python libraries */
|
||||
if (!Py_IsInitialized())
|
||||
{
|
||||
Py_SetProgramName("unbound");
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
wchar_t progname[8];
|
||||
mbstowcs(progname, "unbound", 8);
|
||||
#else
|
||||
char *progname = "unbound";
|
||||
#endif
|
||||
Py_SetProgramName(progname);
|
||||
Py_NoSiteFlag = 1;
|
||||
Py_Initialize();
|
||||
PyEval_InitThreads();
|
||||
|
Loading…
Reference in New Issue
Block a user