blob: 82a34c0c72f64508838294aab482072b7558e46c [file] [log] [blame]
/* Emulation of PyFile_Check() and PyFile_AsFile() for Python 3. */
static PyObject *PyIOBase_TypeObj;
static int init_file_emulator(void)
{
if (PyIOBase_TypeObj == NULL) {
PyObject *io = PyImport_ImportModule("_io");
if (io == NULL)
return -1;
PyIOBase_TypeObj = PyObject_GetAttrString(io, "_IOBase");
if (PyIOBase_TypeObj == NULL)
return -1;
}
return 0;
}
#define PyFile_Check(p) PyObject_IsInstance(p, PyIOBase_TypeObj)
static void _close_file_capsule(PyObject *ob_capsule)
{
FILE *f = (FILE *)PyCapsule_GetPointer(ob_capsule, "FILE");
if (f != NULL)
fclose(f);
}
static FILE *PyFile_AsFile(PyObject *ob_file)
{
PyObject *ob, *ob_capsule = NULL, *ob_mode = NULL;
FILE *f;
int fd;
const char *mode;
ob = PyObject_CallMethod(ob_file, "flush", NULL);
if (ob == NULL)
goto fail;
Py_DECREF(ob);
ob_capsule = PyObject_GetAttrString(ob_file, "__cffi_FILE");
if (ob_capsule == NULL) {
PyErr_Clear();
fd = PyObject_AsFileDescriptor(ob_file);
if (fd < 0)
goto fail;
ob_mode = PyObject_GetAttrString(ob_file, "mode");
if (ob_mode == NULL)
goto fail;
mode = PyText_AsUTF8(ob_mode);
if (mode == NULL)
goto fail;
fd = dup(fd);
if (fd < 0) {
PyErr_SetFromErrno(PyExc_OSError);
goto fail;
}
f = fdopen(fd, mode);
if (f == NULL) {
close(fd);
PyErr_SetFromErrno(PyExc_OSError);
goto fail;
}
setbuf(f, NULL); /* non-buffered */
Py_DECREF(ob_mode);
ob_mode = NULL;
ob_capsule = PyCapsule_New(f, "FILE", _close_file_capsule);
if (ob_capsule == NULL) {
fclose(f);
goto fail;
}
if (PyObject_SetAttrString(ob_file, "__cffi_FILE", ob_capsule) < 0)
goto fail;
}
else {
f = PyCapsule_GetPointer(ob_capsule, "FILE");
}
Py_DECREF(ob_capsule); /* assumes still at least one reference */
return f;
fail:
Py_XDECREF(ob_mode);
Py_XDECREF(ob_capsule);
return NULL;
}