1
2 /* Emulation of PyFile_Check() and PyFile_AsFile() for Python 3. */
3
4 static PyObject *PyIOBase_TypeObj;
5
init_file_emulator(void)6 static int init_file_emulator(void)
7 {
8 if (PyIOBase_TypeObj == NULL) {
9 PyObject *io = PyImport_ImportModule("_io");
10 if (io == NULL)
11 return -1;
12 PyIOBase_TypeObj = PyObject_GetAttrString(io, "_IOBase");
13 if (PyIOBase_TypeObj == NULL)
14 return -1;
15 }
16 return 0;
17 }
18
19
20 #define PyFile_Check(p) PyObject_IsInstance(p, PyIOBase_TypeObj)
21
22
_close_file_capsule(PyObject * ob_capsule)23 static void _close_file_capsule(PyObject *ob_capsule)
24 {
25 FILE *f = (FILE *)PyCapsule_GetPointer(ob_capsule, "FILE");
26 if (f != NULL)
27 fclose(f);
28 }
29
30
PyFile_AsFile(PyObject * ob_file)31 static FILE *PyFile_AsFile(PyObject *ob_file)
32 {
33 PyObject *ob, *ob_capsule = NULL, *ob_mode = NULL;
34 FILE *f;
35 int fd;
36 const char *mode;
37
38 ob = PyObject_CallMethod(ob_file, "flush", NULL);
39 if (ob == NULL)
40 goto fail;
41 Py_DECREF(ob);
42
43 ob_capsule = PyObject_GetAttrString(ob_file, "__cffi_FILE");
44 if (ob_capsule == NULL) {
45 PyErr_Clear();
46
47 fd = PyObject_AsFileDescriptor(ob_file);
48 if (fd < 0)
49 goto fail;
50
51 ob_mode = PyObject_GetAttrString(ob_file, "mode");
52 if (ob_mode == NULL)
53 goto fail;
54 mode = PyText_AsUTF8(ob_mode);
55 if (mode == NULL)
56 goto fail;
57
58 fd = dup(fd);
59 if (fd < 0) {
60 PyErr_SetFromErrno(PyExc_OSError);
61 goto fail;
62 }
63
64 f = fdopen(fd, mode);
65 if (f == NULL) {
66 close(fd);
67 PyErr_SetFromErrno(PyExc_OSError);
68 goto fail;
69 }
70 setbuf(f, NULL); /* non-buffered */
71 Py_DECREF(ob_mode);
72 ob_mode = NULL;
73
74 ob_capsule = PyCapsule_New(f, "FILE", _close_file_capsule);
75 if (ob_capsule == NULL) {
76 fclose(f);
77 goto fail;
78 }
79
80 if (PyObject_SetAttrString(ob_file, "__cffi_FILE", ob_capsule) < 0)
81 goto fail;
82 }
83 else {
84 f = PyCapsule_GetPointer(ob_capsule, "FILE");
85 }
86 Py_DECREF(ob_capsule); /* assumes still at least one reference */
87 return f;
88
89 fail:
90 Py_XDECREF(ob_mode);
91 Py_XDECREF(ob_capsule);
92 return NULL;
93 }
94