1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-07-05 23:01:12 +03:00

python: Support Python 3 on Windows

Copy updated implementation of PyFileGET from libxml2.
This commit is contained in:
Nick Wellnhofer
2022-09-06 13:36:42 +02:00
parent 5d8d8dd892
commit 5443ca169c

View File

@ -25,42 +25,182 @@ xmlParserInputPtr xmlNoNetExternalEntityLoader(const char *URL,
#if PY_MAJOR_VERSION >= 3
#include <stdio.h>
#include <stdint.h>
#ifdef _WIN32
#include <windows.h>
#include <crtdbg.h>
/* Taken from info on MSDN site, as we may not have the Windows WDK/DDK headers */
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} DUMMYUNIONNAME;
ULONG_PTR Information;
} IO_STATUS_BLOCK;
typedef struct _FILE_ACCESS_INFORMATION {
ACCESS_MASK AccessFlags;
} FILE_ACCESS_INFORMATION;
typedef NTSTATUS (*t_NtQueryInformationFile) (HANDLE FileHandle,
IO_STATUS_BLOCK *IoStatusBlock,
PVOID FileInformation,
ULONG Length,
int FileInformationClass); /* this is an Enum */
#if (defined (_MSC_VER) && _MSC_VER >= 1400)
/*
* This is the (empty) invalid parameter handler
* that is used for Visual C++ 2005 (and later) builds
* so that we can use this instead of the system automatically
* aborting the process.
*
* This is necessary as we use _get_oshandle() to check the validity
* of the file descriptors as we close them, so when an invalid file
* descriptor is passed into that function as we check on it, we get
* -1 as the result, instead of the gspawn helper program aborting.
*
* Please see http://msdn.microsoft.com/zh-tw/library/ks2530z6%28v=vs.80%29.aspx
* for an explanation on this.
*/
void
myInvalidParameterHandler(const wchar_t *expression,
const wchar_t *function,
const wchar_t *file,
unsigned int line,
uintptr_t pReserved)
{
}
#endif
#else
#include <unistd.h>
#include <fcntl.h>
#endif
FILE *
libxml_PyFileGet(PyObject *f) {
int fd, flags;
FILE *res;
const char *mode;
int fd = PyObject_AsFileDescriptor(f);
#ifdef _WIN32
intptr_t w_fh = -1;
HMODULE hntdll = NULL;
IO_STATUS_BLOCK status_block;
FILE_ACCESS_INFORMATION ai;
t_NtQueryInformationFile NtQueryInformationFile;
BOOL is_read = FALSE;
BOOL is_write = FALSE;
BOOL is_append = FALSE;
#if (defined (_MSC_VER) && _MSC_VER >= 1400)
/* set up our empty invalid parameter handler */
_invalid_parameter_handler oldHandler, newHandler;
newHandler = myInvalidParameterHandler;
oldHandler = _set_invalid_parameter_handler(newHandler);
/* Disable the message box for assertions. */
_CrtSetReportMode(_CRT_ASSERT, 0);
#endif
w_fh = _get_osfhandle(fd);
if (w_fh == -1)
return(NULL);
hntdll = GetModuleHandleW(L"ntdll.dll");
if (hntdll == NULL)
return(NULL);
XML_IGNORE_FPTR_CAST_WARNINGS
NtQueryInformationFile = (t_NtQueryInformationFile)GetProcAddress(hntdll, "NtQueryInformationFile");
XML_POP_WARNINGS
if (NtQueryInformationFile != NULL &&
(NtQueryInformationFile((HANDLE)w_fh,
&status_block,
&ai,
sizeof(FILE_ACCESS_INFORMATION),
8) == 0)) /* 8 means "FileAccessInformation" */
{
if (ai.AccessFlags & FILE_READ_DATA)
is_read = TRUE;
if (ai.AccessFlags & FILE_WRITE_DATA)
is_write = TRUE;
if (ai.AccessFlags & FILE_APPEND_DATA)
is_append = TRUE;
if (is_write) {
if (is_read) {
if (is_append)
mode = "a+";
else
mode = "rw";
} else {
if (is_append)
mode = "a";
else
mode = "w";
}
} else {
if (is_append)
mode = "r+";
else
mode = "r";
}
}
FreeLibrary(hntdll);
if (!is_write && !is_read) /* also happens if we did not load or run NtQueryInformationFile() successfully */
return(NULL);
#else
int flags;
fd = PyObject_AsFileDescriptor(f);
/*
* Get the flags on the fd to understand how it was opened
* macOS returns O_RDWR for standard streams, but fails to write to
* stdout or stderr when opened with fdopen(dup_fd, "rw").
*/
flags = fcntl(fd, F_GETFL, 0);
switch (flags & O_ACCMODE) {
case O_RDWR:
if (flags & O_APPEND)
mode = "a+";
else
mode = "rw";
break;
case O_RDONLY:
if (flags & O_APPEND)
mode = "r+";
else
mode = "r";
break;
case O_WRONLY:
if (flags & O_APPEND)
mode = "a";
else
mode = "w";
break;
default:
return(NULL);
switch (fd) {
case STDIN_FILENO:
mode = "r";
break;
case STDOUT_FILENO:
case STDERR_FILENO:
mode = "w";
break;
default:
/*
* Get the flags on the fd to understand how it was opened
*/
flags = fcntl(fd, F_GETFL, 0);
switch (flags & O_ACCMODE) {
case O_RDWR:
if (flags & O_APPEND)
mode = "a+";
else
mode = "rw";
break;
case O_RDONLY:
if (flags & O_APPEND)
mode = "r+";
else
mode = "r";
break;
case O_WRONLY:
if (flags & O_APPEND)
mode = "a";
else
mode = "w";
break;
default:
return(NULL);
}
}
#endif
/*
* the FILE struct gets a new fd, so that it can be closed