| |
| /* 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; |
| } |