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