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:
190
python/types.c
190
python/types.c
@ -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
|
||||
|
Reference in New Issue
Block a user