Branch data Line data Source code
1 : : /* File object implementation (what's left of it -- see io.py) */
2 : :
3 : : #define PY_SSIZE_T_CLEAN
4 : : #include "Python.h"
5 : : #include "pycore_call.h" // _PyObject_CallNoArgs()
6 : : #include "pycore_runtime.h" // _PyRuntime
7 : :
8 : : #if defined(HAVE_GETC_UNLOCKED) && !defined(_Py_MEMORY_SANITIZER)
9 : : /* clang MemorySanitizer doesn't yet understand getc_unlocked. */
10 : : #define GETC(f) getc_unlocked(f)
11 : : #define FLOCKFILE(f) flockfile(f)
12 : : #define FUNLOCKFILE(f) funlockfile(f)
13 : : #else
14 : : #define GETC(f) getc(f)
15 : : #define FLOCKFILE(f)
16 : : #define FUNLOCKFILE(f)
17 : : #endif
18 : :
19 : : /* Newline flags */
20 : : #define NEWLINE_UNKNOWN 0 /* No newline seen, yet */
21 : : #define NEWLINE_CR 1 /* \r newline seen */
22 : : #define NEWLINE_LF 2 /* \n newline seen */
23 : : #define NEWLINE_CRLF 4 /* \r\n newline seen */
24 : :
25 : : #ifdef __cplusplus
26 : : extern "C" {
27 : : #endif
28 : :
29 : : /* External C interface */
30 : :
31 : : PyObject *
32 : 0 : PyFile_FromFd(int fd, const char *name, const char *mode, int buffering, const char *encoding,
33 : : const char *errors, const char *newline, int closefd)
34 : : {
35 : : PyObject *open, *stream;
36 : :
37 : : /* import _io in case we are being used to open io.py */
38 : 0 : open = _PyImport_GetModuleAttrString("_io", "open");
39 [ # # ]: 0 : if (open == NULL)
40 : 0 : return NULL;
41 [ # # ]: 0 : stream = PyObject_CallFunction(open, "isisssO", fd, mode,
42 : : buffering, encoding, errors,
43 : : newline, closefd ? Py_True : Py_False);
44 : 0 : Py_DECREF(open);
45 [ # # ]: 0 : if (stream == NULL)
46 : 0 : return NULL;
47 : : /* ignore name attribute because the name attribute of _BufferedIOMixin
48 : : and TextIOWrapper is read only */
49 : 0 : return stream;
50 : : }
51 : :
52 : : PyObject *
53 : 465174 : PyFile_GetLine(PyObject *f, int n)
54 : : {
55 : : PyObject *result;
56 : :
57 [ - + ]: 465174 : if (f == NULL) {
58 : 0 : PyErr_BadInternalCall();
59 : 0 : return NULL;
60 : : }
61 : :
62 [ + - ]: 465174 : if (n <= 0) {
63 : 465174 : result = PyObject_CallMethodNoArgs(f, &_Py_ID(readline));
64 : : }
65 : : else {
66 : 0 : result = _PyObject_CallMethod(f, &_Py_ID(readline), "i", n);
67 : : }
68 [ + + + - : 930347 : if (result != NULL && !PyBytes_Check(result) &&
- + ]
69 : 465173 : !PyUnicode_Check(result)) {
70 : 0 : Py_DECREF(result);
71 : 0 : result = NULL;
72 : 0 : PyErr_SetString(PyExc_TypeError,
73 : : "object.readline() returned non-string");
74 : : }
75 : :
76 [ + - + + : 465174 : if (n < 0 && result != NULL && PyBytes_Check(result)) {
- + ]
77 : 0 : const char *s = PyBytes_AS_STRING(result);
78 : 0 : Py_ssize_t len = PyBytes_GET_SIZE(result);
79 [ # # ]: 0 : if (len == 0) {
80 : 0 : Py_DECREF(result);
81 : 0 : result = NULL;
82 : 0 : PyErr_SetString(PyExc_EOFError,
83 : : "EOF when reading a line");
84 : : }
85 [ # # ]: 0 : else if (s[len-1] == '\n') {
86 [ # # ]: 0 : if (Py_REFCNT(result) == 1)
87 : 0 : _PyBytes_Resize(&result, len-1);
88 : : else {
89 : : PyObject *v;
90 : 0 : v = PyBytes_FromStringAndSize(s, len-1);
91 : 0 : Py_DECREF(result);
92 : 0 : result = v;
93 : : }
94 : : }
95 : : }
96 [ + - + + : 465174 : if (n < 0 && result != NULL && PyUnicode_Check(result)) {
+ - ]
97 : 465173 : Py_ssize_t len = PyUnicode_GET_LENGTH(result);
98 [ + + ]: 465173 : if (len == 0) {
99 : 6 : Py_DECREF(result);
100 : 6 : result = NULL;
101 : 6 : PyErr_SetString(PyExc_EOFError,
102 : : "EOF when reading a line");
103 : : }
104 [ + + ]: 465167 : else if (PyUnicode_READ_CHAR(result, len-1) == '\n') {
105 : : PyObject *v;
106 : 465149 : v = PyUnicode_Substring(result, 0, len-1);
107 : 465149 : Py_DECREF(result);
108 : 465149 : result = v;
109 : : }
110 : : }
111 : 465174 : return result;
112 : : }
113 : :
114 : : /* Interfaces to write objects/strings to file-like objects */
115 : :
116 : : int
117 : 202548 : PyFile_WriteObject(PyObject *v, PyObject *f, int flags)
118 : : {
119 : : PyObject *writer, *value, *result;
120 : :
121 [ - + ]: 202548 : if (f == NULL) {
122 : 0 : PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");
123 : 0 : return -1;
124 : : }
125 : 202548 : writer = PyObject_GetAttr(f, &_Py_ID(write));
126 [ + + ]: 202548 : if (writer == NULL)
127 : 35 : return -1;
128 [ + + ]: 202513 : if (flags & Py_PRINT_RAW) {
129 : 200850 : value = PyObject_Str(v);
130 : : }
131 : : else
132 : 1663 : value = PyObject_Repr(v);
133 [ + + ]: 202513 : if (value == NULL) {
134 : 1 : Py_DECREF(writer);
135 : 1 : return -1;
136 : : }
137 : 202512 : result = PyObject_CallOneArg(writer, value);
138 : 202512 : Py_DECREF(value);
139 : 202512 : Py_DECREF(writer);
140 [ + + ]: 202512 : if (result == NULL)
141 : 11 : return -1;
142 : 202501 : Py_DECREF(result);
143 : 202501 : return 0;
144 : : }
145 : :
146 : : int
147 : 84087 : PyFile_WriteString(const char *s, PyObject *f)
148 : : {
149 [ - + ]: 84087 : if (f == NULL) {
150 : : /* Should be caused by a pre-existing error */
151 [ # # ]: 0 : if (!PyErr_Occurred())
152 : 0 : PyErr_SetString(PyExc_SystemError,
153 : : "null file for PyFile_WriteString");
154 : 0 : return -1;
155 : : }
156 [ + - ]: 84087 : else if (!PyErr_Occurred()) {
157 : 84087 : PyObject *v = PyUnicode_FromString(s);
158 : : int err;
159 [ + + ]: 84087 : if (v == NULL)
160 : 52 : return -1;
161 : 84035 : err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
162 : 84035 : Py_DECREF(v);
163 : 84035 : return err;
164 : : }
165 : : else
166 : 0 : return -1;
167 : : }
168 : :
169 : : /* Try to get a file-descriptor from a Python object. If the object
170 : : is an integer, its value is returned. If not, the
171 : : object's fileno() method is called if it exists; the method must return
172 : : an integer, which is returned as the file descriptor value.
173 : : -1 is returned on failure.
174 : : */
175 : :
176 : : int
177 : 241476 : PyObject_AsFileDescriptor(PyObject *o)
178 : : {
179 : : int fd;
180 : : PyObject *meth;
181 : :
182 [ + + ]: 241476 : if (PyLong_Check(o)) {
183 : 240623 : fd = _PyLong_AsInt(o);
184 : : }
185 [ - + ]: 853 : else if (_PyObject_LookupAttr(o, &_Py_ID(fileno), &meth) < 0) {
186 : 0 : return -1;
187 : : }
188 [ + + ]: 853 : else if (meth != NULL) {
189 : 845 : PyObject *fno = _PyObject_CallNoArgs(meth);
190 : 845 : Py_DECREF(meth);
191 [ - + ]: 845 : if (fno == NULL)
192 : 0 : return -1;
193 : :
194 [ + + ]: 845 : if (PyLong_Check(fno)) {
195 : 842 : fd = _PyLong_AsInt(fno);
196 : 842 : Py_DECREF(fno);
197 : : }
198 : : else {
199 : 3 : PyErr_SetString(PyExc_TypeError,
200 : : "fileno() returned a non-integer");
201 : 3 : Py_DECREF(fno);
202 : 3 : return -1;
203 : : }
204 : : }
205 : : else {
206 : 8 : PyErr_SetString(PyExc_TypeError,
207 : : "argument must be an int, or have a fileno() method.");
208 : 8 : return -1;
209 : : }
210 : :
211 [ + + + + ]: 241465 : if (fd == -1 && PyErr_Occurred())
212 : 5 : return -1;
213 [ + + ]: 241460 : if (fd < 0) {
214 : 5 : PyErr_Format(PyExc_ValueError,
215 : : "file descriptor cannot be a negative integer (%i)",
216 : : fd);
217 : 5 : return -1;
218 : : }
219 : 241455 : return fd;
220 : : }
221 : :
222 : : int
223 : 188342 : _PyLong_FileDescriptor_Converter(PyObject *o, void *ptr)
224 : : {
225 : 188342 : int fd = PyObject_AsFileDescriptor(o);
226 [ + + ]: 188342 : if (fd == -1) {
227 : 19 : return 0;
228 : : }
229 : 188323 : *(int *)ptr = fd;
230 : 188323 : return 1;
231 : : }
232 : :
233 : : /*
234 : : ** Py_UniversalNewlineFgets is an fgets variation that understands
235 : : ** all of \r, \n and \r\n conventions.
236 : : ** The stream should be opened in binary mode.
237 : : ** The fobj parameter exists solely for legacy reasons and must be NULL.
238 : : ** Note that we need no error handling: fgets() treats error and eof
239 : : ** identically.
240 : : */
241 : : char *
242 : 56509 : Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
243 : : {
244 : 56509 : char *p = buf;
245 : : int c;
246 : :
247 [ - + ]: 56509 : if (fobj) {
248 : 0 : errno = ENXIO; /* What can you do... */
249 : 0 : return NULL;
250 : : }
251 : 56509 : FLOCKFILE(stream);
252 [ + - + + ]: 1916288 : while (--n > 0 && (c = GETC(stream)) != EOF ) {
253 [ + + ]: 1915902 : if (c == '\r') {
254 : : // A \r is translated into a \n, and we skip an adjacent \n, if any.
255 : 7 : c = GETC(stream);
256 [ + + ]: 7 : if (c != '\n') {
257 : 3 : ungetc(c, stream);
258 : 3 : c = '\n';
259 : : }
260 : : }
261 : 1915902 : *p++ = c;
262 [ + + ]: 1915902 : if (c == '\n') {
263 : 56123 : break;
264 : : }
265 : : }
266 : 56509 : FUNLOCKFILE(stream);
267 : 56509 : *p = '\0';
268 [ + + ]: 56509 : if (p == buf)
269 : 326 : return NULL;
270 : 56183 : return buf;
271 : : }
272 : :
273 : : /* **************************** std printer ****************************
274 : : * The stdprinter is used during the boot strapping phase as a preliminary
275 : : * file like object for sys.stderr.
276 : : */
277 : :
278 : : typedef struct {
279 : : PyObject_HEAD
280 : : int fd;
281 : : } PyStdPrinter_Object;
282 : :
283 : : PyObject *
284 : 3141 : PyFile_NewStdPrinter(int fd)
285 : : {
286 : : PyStdPrinter_Object *self;
287 : :
288 [ + + - + ]: 3141 : if (fd != fileno(stdout) && fd != fileno(stderr)) {
289 : : /* not enough infrastructure for PyErr_BadInternalCall() */
290 : 0 : return NULL;
291 : : }
292 : :
293 : 3141 : self = PyObject_New(PyStdPrinter_Object,
294 : : &PyStdPrinter_Type);
295 [ + - ]: 3141 : if (self != NULL) {
296 : 3141 : self->fd = fd;
297 : : }
298 : 3141 : return (PyObject*)self;
299 : : }
300 : :
301 : : static PyObject *
302 : 693 : stdprinter_write(PyStdPrinter_Object *self, PyObject *args)
303 : : {
304 : : PyObject *unicode;
305 : 693 : PyObject *bytes = NULL;
306 : : const char *str;
307 : : Py_ssize_t n;
308 : : int err;
309 : :
310 : : /* The function can clear the current exception */
311 : : assert(!PyErr_Occurred());
312 : :
313 [ - + ]: 693 : if (self->fd < 0) {
314 : : /* fd might be invalid on Windows
315 : : * I can't raise an exception here. It may lead to an
316 : : * unlimited recursion in the case stderr is invalid.
317 : : */
318 : 0 : Py_RETURN_NONE;
319 : : }
320 : :
321 [ - + ]: 693 : if (!PyArg_ParseTuple(args, "U", &unicode)) {
322 : 0 : return NULL;
323 : : }
324 : :
325 : : /* Encode Unicode to UTF-8/backslashreplace */
326 : 693 : str = PyUnicode_AsUTF8AndSize(unicode, &n);
327 [ + + ]: 693 : if (str == NULL) {
328 : 1 : PyErr_Clear();
329 : 1 : bytes = _PyUnicode_AsUTF8String(unicode, "backslashreplace");
330 [ - + ]: 1 : if (bytes == NULL)
331 : 0 : return NULL;
332 : 1 : str = PyBytes_AS_STRING(bytes);
333 : 1 : n = PyBytes_GET_SIZE(bytes);
334 : : }
335 : :
336 : 693 : n = _Py_write(self->fd, str, n);
337 : : /* save errno, it can be modified indirectly by Py_XDECREF() */
338 : 693 : err = errno;
339 : :
340 : 693 : Py_XDECREF(bytes);
341 : :
342 [ - + ]: 693 : if (n == -1) {
343 [ # # ]: 0 : if (err == EAGAIN) {
344 : 0 : PyErr_Clear();
345 : 0 : Py_RETURN_NONE;
346 : : }
347 : 0 : return NULL;
348 : : }
349 : :
350 : 693 : return PyLong_FromSsize_t(n);
351 : : }
352 : :
353 : : static PyObject *
354 : 1095 : stdprinter_fileno(PyStdPrinter_Object *self, PyObject *Py_UNUSED(ignored))
355 : : {
356 : 1095 : return PyLong_FromLong((long) self->fd);
357 : : }
358 : :
359 : : static PyObject *
360 : 0 : stdprinter_repr(PyStdPrinter_Object *self)
361 : : {
362 : 0 : return PyUnicode_FromFormat("<stdprinter(fd=%d) object at %p>",
363 : : self->fd, self);
364 : : }
365 : :
366 : : static PyObject *
367 : 1105 : stdprinter_noop(PyStdPrinter_Object *self, PyObject *Py_UNUSED(ignored))
368 : : {
369 : 1105 : Py_RETURN_NONE;
370 : : }
371 : :
372 : : static PyObject *
373 : 1 : stdprinter_isatty(PyStdPrinter_Object *self, PyObject *Py_UNUSED(ignored))
374 : : {
375 : : long res;
376 [ - + ]: 1 : if (self->fd < 0) {
377 : 0 : Py_RETURN_FALSE;
378 : : }
379 : :
380 : 1 : Py_BEGIN_ALLOW_THREADS
381 : 1 : res = isatty(self->fd);
382 : 1 : Py_END_ALLOW_THREADS
383 : :
384 : 1 : return PyBool_FromLong(res);
385 : : }
386 : :
387 : : static PyMethodDef stdprinter_methods[] = {
388 : : {"close", (PyCFunction)stdprinter_noop, METH_NOARGS, ""},
389 : : {"flush", (PyCFunction)stdprinter_noop, METH_NOARGS, ""},
390 : : {"fileno", (PyCFunction)stdprinter_fileno, METH_NOARGS, ""},
391 : : {"isatty", (PyCFunction)stdprinter_isatty, METH_NOARGS, ""},
392 : : {"write", (PyCFunction)stdprinter_write, METH_VARARGS, ""},
393 : : {NULL, NULL} /*sentinel */
394 : : };
395 : :
396 : : static PyObject *
397 : 3 : get_closed(PyStdPrinter_Object *self, void *closure)
398 : : {
399 : 3 : Py_RETURN_FALSE;
400 : : }
401 : :
402 : : static PyObject *
403 : 0 : get_mode(PyStdPrinter_Object *self, void *closure)
404 : : {
405 : 0 : return PyUnicode_FromString("w");
406 : : }
407 : :
408 : : static PyObject *
409 : 0 : get_encoding(PyStdPrinter_Object *self, void *closure)
410 : : {
411 : 0 : Py_RETURN_NONE;
412 : : }
413 : :
414 : : static PyGetSetDef stdprinter_getsetlist[] = {
415 : : {"closed", (getter)get_closed, NULL, "True if the file is closed"},
416 : : {"encoding", (getter)get_encoding, NULL, "Encoding of the file"},
417 : : {"mode", (getter)get_mode, NULL, "String giving the file mode"},
418 : : {0},
419 : : };
420 : :
421 : : PyTypeObject PyStdPrinter_Type = {
422 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
423 : : "stderrprinter", /* tp_name */
424 : : sizeof(PyStdPrinter_Object), /* tp_basicsize */
425 : : 0, /* tp_itemsize */
426 : : /* methods */
427 : : 0, /* tp_dealloc */
428 : : 0, /* tp_vectorcall_offset */
429 : : 0, /* tp_getattr */
430 : : 0, /* tp_setattr */
431 : : 0, /* tp_as_async */
432 : : (reprfunc)stdprinter_repr, /* tp_repr */
433 : : 0, /* tp_as_number */
434 : : 0, /* tp_as_sequence */
435 : : 0, /* tp_as_mapping */
436 : : 0, /* tp_hash */
437 : : 0, /* tp_call */
438 : : 0, /* tp_str */
439 : : PyObject_GenericGetAttr, /* tp_getattro */
440 : : 0, /* tp_setattro */
441 : : 0, /* tp_as_buffer */
442 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, /* tp_flags */
443 : : 0, /* tp_doc */
444 : : 0, /* tp_traverse */
445 : : 0, /* tp_clear */
446 : : 0, /* tp_richcompare */
447 : : 0, /* tp_weaklistoffset */
448 : : 0, /* tp_iter */
449 : : 0, /* tp_iternext */
450 : : stdprinter_methods, /* tp_methods */
451 : : 0, /* tp_members */
452 : : stdprinter_getsetlist, /* tp_getset */
453 : : 0, /* tp_base */
454 : : 0, /* tp_dict */
455 : : 0, /* tp_descr_get */
456 : : 0, /* tp_descr_set */
457 : : 0, /* tp_dictoffset */
458 : : 0, /* tp_init */
459 : : PyType_GenericAlloc, /* tp_alloc */
460 : : 0, /* tp_new */
461 : : PyObject_Del, /* tp_free */
462 : : };
463 : :
464 : :
465 : : /* ************************** open_code hook ***************************
466 : : * The open_code hook allows embedders to override the method used to
467 : : * open files that are going to be used by the runtime to execute code
468 : : */
469 : :
470 : : int
471 : 2 : PyFile_SetOpenCodeHook(Py_OpenCodeHookFunction hook, void *userData) {
472 [ - + - - ]: 2 : if (Py_IsInitialized() &&
473 : 0 : PySys_Audit("setopencodehook", NULL) < 0) {
474 : 0 : return -1;
475 : : }
476 : :
477 [ + + ]: 2 : if (_PyRuntime.open_code_hook) {
478 [ - + ]: 1 : if (Py_IsInitialized()) {
479 : 0 : PyErr_SetString(PyExc_SystemError,
480 : : "failed to change existing open_code hook");
481 : : }
482 : 1 : return -1;
483 : : }
484 : :
485 : 1 : _PyRuntime.open_code_hook = hook;
486 : 1 : _PyRuntime.open_code_userdata = userData;
487 : 1 : return 0;
488 : : }
489 : :
490 : : PyObject *
491 : 178738 : PyFile_OpenCodeObject(PyObject *path)
492 : : {
493 : 178738 : PyObject *f = NULL;
494 : :
495 [ - + ]: 178738 : if (!PyUnicode_Check(path)) {
496 : 0 : PyErr_Format(PyExc_TypeError, "'path' must be 'str', not '%.200s'",
497 : 0 : Py_TYPE(path)->tp_name);
498 : 0 : return NULL;
499 : : }
500 : :
501 : 178738 : Py_OpenCodeHookFunction hook = _PyRuntime.open_code_hook;
502 [ + + ]: 178738 : if (hook) {
503 : 5 : f = hook(path, _PyRuntime.open_code_userdata);
504 : : } else {
505 : 178733 : PyObject *open = _PyImport_GetModuleAttrString("_io", "open");
506 [ + - ]: 178733 : if (open) {
507 : 178733 : f = PyObject_CallFunction(open, "Os", path, "rb");
508 : 178733 : Py_DECREF(open);
509 : : }
510 : : }
511 : :
512 : 178738 : return f;
513 : : }
514 : :
515 : : PyObject *
516 : 1 : PyFile_OpenCode(const char *utf8path)
517 : : {
518 : 1 : PyObject *pathobj = PyUnicode_FromString(utf8path);
519 : : PyObject *f;
520 [ - + ]: 1 : if (!pathobj) {
521 : 0 : return NULL;
522 : : }
523 : 1 : f = PyFile_OpenCodeObject(pathobj);
524 : 1 : Py_DECREF(pathobj);
525 : 1 : return f;
526 : : }
527 : :
528 : :
529 : : #ifdef __cplusplus
530 : : }
531 : : #endif
|