Skip to content

Instantly share code, notes, and snippets.

@novocaine
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save novocaine/09d5c00e67fd0aa13cfc to your computer and use it in GitHub Desktop.
Save novocaine/09d5c00e67fd0aa13cfc to your computer and use it in GitHub Desktop.
fix libxml2 2.9.2 python 3 on windows
diff -ur libxml2-2.9.2.old/python/setup.py libxml2-2.9.2/python/setup.py
--- libxml2-2.9.2.old/python/setup.py 2014-10-16 09:35:22.000000000 +0100
+++ libxml2-2.9.2/python/setup.py 2015-01-22 12:23:18.804795900 +0000
@@ -123,7 +123,7 @@
with_xslt=0
if missing("libxslt-py.c") or missing("libxslt.py"):
- if missing("xsltgenerator.py") or missing("libxslt-api.xml"):
+ if missing("xsltgenerator.py") or missing("libxslt-python-api.xml"):
print("libxslt stub generator not found, libxslt not built")
else:
try:
@@ -192,7 +192,6 @@
includes.append(xslt_includes)
modules.append('libxslt')
-
extens=[Extension('libxml2mod', c_files, include_dirs=includes,
library_dirs=libdirs,
libraries=libs, define_macros=macros)]
diff -ur libxml2-2.9.2.old/python/setup.py.in libxml2-2.9.2/python/setup.py.in
--- libxml2-2.9.2.old/python/setup.py.in 2014-10-16 05:46:36.000000000 +0100
+++ libxml2-2.9.2/python/setup.py.in 2015-01-22 12:24:13.423100400 +0000
@@ -123,7 +123,7 @@
with_xslt=0
if missing("libxslt-py.c") or missing("libxslt.py"):
- if missing("xsltgenerator.py") or missing("libxslt-api.xml"):
+ if missing("xsltgenerator.py") or missing("libxslt-python-api.xml"):
print("libxslt stub generator not found, libxslt not built")
else:
try:
diff -ur libxml2-2.9.2.old/python/types.c libxml2-2.9.2/python/types.c
--- libxml2-2.9.2.old/python/types.c 2014-10-03 11:00:54.000000000 +0100
+++ libxml2-2.9.2/python/types.c 2015-01-22 12:04:53.157630900 +0000
@@ -21,18 +21,115 @@
#if PY_MAJOR_VERSION >= 3
#include <stdio.h>
+
+#ifndef _WIN32
#include <unistd.h>
#include <fcntl.h>
+#else
+#include <io.h>
+#endif
+
+/* On unix, _PyVerify_fd is a no-op macro; on windows it is
+ * defined in .c and not exported, so we replicate it here
+ * (from (python 3 source)/Modules/posixmodule.c)
+ *
+ * Performing this check is vital to prevent run-time
+ * assertions due to invalid fds. */
+
+#if defined _WIN32 && _MSC_VER && _MSC_VER >= 1400
+#include <malloc.h>
+/* Microsoft CRT in VS2005 and higher will verify that a filehandle is
+ * valid and raise an assertion if it isn't.
+ * Normally, an invalid fd is likely to be a C program error and therefore
+ * an assertion can be useful, but it does contradict the POSIX standard
+ * which for write(2) states:
+ * "Otherwise, -1 shall be returned and errno set to indicate the error."
+ * "[EBADF] The fildes argument is not a valid file descriptor open for
+ * writing."
+ * Furthermore, python allows the user to enter any old integer
+ * as a fd and should merely raise a python exception on error.
+ * The Microsoft CRT doesn't provide an official way to check for the
+ * validity of a file descriptor, but we can emulate its internal behaviour
+ * by using the exported __pinfo data member and knowledge of the
+ * internal structures involved.
+ * The structures below must be updated for each version of visual studio
+ * according to the file internal.h in the CRT source, until MS comes
+ * up with a less hacky way to do this.
+ * (all of this is to avoid globally modifying the CRT behaviour using
+ * _set_invalid_parameter_handler() and _CrtSetReportMode())
+ */
+/* The actual size of the structure is determined at runtime.
+ * Only the first items must be present.
+ */
+typedef struct {
+ intptr_t osfhnd;
+ char osfile;
+} my_ioinfo;
+
+extern __declspec(dllimport) char * __pioinfo[];
+#define IOINFO_L2E 5
+#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
+#define IOINFO_ARRAYS 64
+#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
+#define FOPEN 0x01
+#define _NO_CONSOLE_FILENO (intptr_t)-2
+
+/* This function emulates what the windows CRT does to validate file handles */
+int
+_PyVerify_fd(int fd)
+{
+ const int i1 = fd >> IOINFO_L2E;
+ const int i2 = fd & ((1 << IOINFO_L2E) - 1);
+
+ static size_t sizeof_ioinfo = 0;
+
+ /* Determine the actual size of the ioinfo structure,
+ * as used by the CRT loaded in memory
+ */
+ if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
+ sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
+ }
+ if (sizeof_ioinfo == 0) {
+ /* This should not happen... */
+ goto fail;
+ }
+
+ /* See that it isn't a special CLEAR fileno */
+ if (fd != _NO_CONSOLE_FILENO) {
+ /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that. Instead
+ * we check pointer validity and other info
+ */
+ if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
+ /* finally, check that the file is open */
+ my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
+ if (info->osfile & FOPEN) {
+ return 1;
+ }
+ }
+ }
+ fail:
+ errno = EBADF;
+ return 0;
+}
+
+#endif
FILE *
libxml_PyFileGet(PyObject *f) {
- int fd, flags;
+ int fd;
FILE *res;
const char *mode;
+#ifdef _WIN32
+ PyObject *modeObj, *modeBytes;
+#else
+ int flags;
+#endif
fd = PyObject_AsFileDescriptor(f);
if (!_PyVerify_fd(fd))
return(NULL);
+
+#ifndef _WIN32
/*
* Get the flags on the fd to understand how it was opened
*/
@@ -78,6 +175,67 @@
return(NULL);
}
return(res);
+#else
+ /*
+ * The mode sniffing above isn't possible on windows -
+ * the CRT simply doesn't expose an interface for
+ * retreiving the mode of the fd (even though it supports
+ * the same POSIX set at creation).
+ *
+ * So instead, we look for a .mode attribute on f.
+ *
+ * Python 3's open() always sets a .mode attribute
+ * before returning a value (even when a custom opener
+ * is provided), so this covers the majority of cases.
+ *
+ * This won't work for callers passing other file-like
+ * objects that don't implement .mode; they will just
+ * have to implement it somehow (hopefully they are
+ * just wrapping something that does know the mode).
+ */
+
+ modeObj = PyObject_GetAttrString(f, "mode");
+ if (!modeObj) {
+ return(NULL);
+ }
+
+ if (PyUnicode_Check(modeObj)) {
+ modeBytes = PyObject_CallMethod(
+ modeObj, "encode", "s", "ascii");
+ if (!modeBytes) {
+ Py_DECREF(modeObj);
+ return(NULL);
+ }
+ mode = PyBytes_AsString(modeBytes);
+ if (!mode) {
+ Py_DECREF(modeObj);
+ return(NULL);
+ }
+ Py_DECREF(modeBytes);
+ } else if (PyBytes_Check(modeObj)) {
+ mode = PyBytes_AsString(modeObj);
+ if (!mode) {
+ Py_DECREF(modeObj);
+ return(NULL);
+ }
+ } else {
+ Py_DECREF(modeObj);
+ return(NULL);
+ }
+
+ Py_DECREF(modeObj);
+
+ fd = _dup(fd);
+ if (fd == -1) {
+ return(NULL);
+ }
+ res = _fdopen(fd, mode);
+ if (res == NULL) {
+ _close(fd);
+ return(NULL);
+ }
+ return(res);
+#endif
}
void libxml_PyFileRelease(FILE *f) {
Only in libxml2-2.9.2/win32: config.msvc
diff -ur libxml2-2.9.2.old/win32/configure.js libxml2-2.9.2/win32/configure.js
--- libxml2-2.9.2.old/win32/configure.js 2014-10-03 11:00:56.000000000 +0100
+++ libxml2-2.9.2/win32/configure.js 2015-01-21 12:32:09.664068100 +0000
@@ -14,7 +14,7 @@
var baseName = "libxml2";
/* Configure file which contains the version and the output file where
we can store our build configuration. */
-var configFile = srcDirXml + "\\configure.in";
+var configFile = srcDirXml + "\\configure.ac";
var versionFile = ".\\config.msvc";
/* Input and output files regarding the libxml features. */
var optsFileIn = srcDirXml + "\\include\\libxml\\xmlversion.h.in";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment