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 :
6 : #ifdef HAVE_GETC_UNLOCKED
7 : #define GETC(f) getc_unlocked(f)
8 : #define FLOCKFILE(f) flockfile(f)
9 : #define FUNLOCKFILE(f) funlockfile(f)
10 : #else
11 : #define GETC(f) getc(f)
12 : #define FLOCKFILE(f)
13 : #define FUNLOCKFILE(f)
14 : #endif
15 :
16 : /* Newline flags */
17 : #define NEWLINE_UNKNOWN 0 /* No newline seen, yet */
18 : #define NEWLINE_CR 1 /* \r newline seen */
19 : #define NEWLINE_LF 2 /* \n newline seen */
20 : #define NEWLINE_CRLF 4 /* \r\n newline seen */
21 :
22 : #ifdef __cplusplus
23 : extern "C" {
24 : #endif
25 :
26 : /* External C interface */
27 :
28 : PyObject *
29 0 : PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding,
30 : char *errors, char *newline, int closefd)
31 : {
32 : PyObject *io, *stream;
33 : _Py_IDENTIFIER(open);
34 :
35 0 : io = PyImport_ImportModule("io");
36 0 : if (io == NULL)
37 0 : return NULL;
38 0 : stream = _PyObject_CallMethodId(io, &PyId_open, "isisssi", fd, mode,
39 : buffering, encoding, errors,
40 : newline, closefd);
41 0 : Py_DECREF(io);
42 0 : if (stream == NULL)
43 0 : return NULL;
44 : /* ignore name attribute because the name attribute of _BufferedIOMixin
45 : and TextIOWrapper is read only */
46 0 : return stream;
47 : }
48 :
49 : PyObject *
50 0 : PyFile_GetLine(PyObject *f, int n)
51 : {
52 : PyObject *result;
53 :
54 0 : if (f == NULL) {
55 0 : PyErr_BadInternalCall();
56 0 : return NULL;
57 : }
58 :
59 : {
60 : PyObject *reader;
61 : PyObject *args;
62 : _Py_IDENTIFIER(readline);
63 :
64 0 : reader = _PyObject_GetAttrId(f, &PyId_readline);
65 0 : if (reader == NULL)
66 0 : return NULL;
67 0 : if (n <= 0)
68 0 : args = PyTuple_New(0);
69 : else
70 0 : args = Py_BuildValue("(i)", n);
71 0 : if (args == NULL) {
72 0 : Py_DECREF(reader);
73 0 : return NULL;
74 : }
75 0 : result = PyEval_CallObject(reader, args);
76 0 : Py_DECREF(reader);
77 0 : Py_DECREF(args);
78 0 : if (result != NULL && !PyBytes_Check(result) &&
79 0 : !PyUnicode_Check(result)) {
80 0 : Py_DECREF(result);
81 0 : result = NULL;
82 0 : PyErr_SetString(PyExc_TypeError,
83 : "object.readline() returned non-string");
84 : }
85 : }
86 :
87 0 : if (n < 0 && result != NULL && PyBytes_Check(result)) {
88 0 : char *s = PyBytes_AS_STRING(result);
89 0 : Py_ssize_t len = PyBytes_GET_SIZE(result);
90 0 : if (len == 0) {
91 0 : Py_DECREF(result);
92 0 : result = NULL;
93 0 : PyErr_SetString(PyExc_EOFError,
94 : "EOF when reading a line");
95 : }
96 0 : else if (s[len-1] == '\n') {
97 0 : if (result->ob_refcnt == 1)
98 0 : _PyBytes_Resize(&result, len-1);
99 : else {
100 : PyObject *v;
101 0 : v = PyBytes_FromStringAndSize(s, len-1);
102 0 : Py_DECREF(result);
103 0 : result = v;
104 : }
105 : }
106 : }
107 0 : if (n < 0 && result != NULL && PyUnicode_Check(result)) {
108 0 : Py_ssize_t len = PyUnicode_GET_LENGTH(result);
109 0 : if (len == 0) {
110 0 : Py_DECREF(result);
111 0 : result = NULL;
112 0 : PyErr_SetString(PyExc_EOFError,
113 : "EOF when reading a line");
114 : }
115 0 : else if (PyUnicode_READ_CHAR(result, len-1) == '\n') {
116 : PyObject *v;
117 0 : v = PyUnicode_Substring(result, 0, len-1);
118 0 : Py_DECREF(result);
119 0 : result = v;
120 : }
121 : }
122 0 : return result;
123 : }
124 :
125 : /* Interfaces to write objects/strings to file-like objects */
126 :
127 : int
128 0 : PyFile_WriteObject(PyObject *v, PyObject *f, int flags)
129 : {
130 : PyObject *writer, *value, *args, *result;
131 : _Py_IDENTIFIER(write);
132 :
133 0 : if (f == NULL) {
134 0 : PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");
135 0 : return -1;
136 : }
137 0 : writer = _PyObject_GetAttrId(f, &PyId_write);
138 0 : if (writer == NULL)
139 0 : return -1;
140 0 : if (flags & Py_PRINT_RAW) {
141 0 : value = PyObject_Str(v);
142 : }
143 : else
144 0 : value = PyObject_Repr(v);
145 0 : if (value == NULL) {
146 0 : Py_DECREF(writer);
147 0 : return -1;
148 : }
149 0 : args = PyTuple_Pack(1, value);
150 0 : if (args == NULL) {
151 0 : Py_DECREF(value);
152 0 : Py_DECREF(writer);
153 0 : return -1;
154 : }
155 0 : result = PyEval_CallObject(writer, args);
156 0 : Py_DECREF(args);
157 0 : Py_DECREF(value);
158 0 : Py_DECREF(writer);
159 0 : if (result == NULL)
160 0 : return -1;
161 0 : Py_DECREF(result);
162 0 : return 0;
163 : }
164 :
165 : int
166 0 : PyFile_WriteString(const char *s, PyObject *f)
167 : {
168 0 : if (f == NULL) {
169 : /* Should be caused by a pre-existing error */
170 0 : if (!PyErr_Occurred())
171 0 : PyErr_SetString(PyExc_SystemError,
172 : "null file for PyFile_WriteString");
173 0 : return -1;
174 : }
175 0 : else if (!PyErr_Occurred()) {
176 0 : PyObject *v = PyUnicode_FromString(s);
177 : int err;
178 0 : if (v == NULL)
179 0 : return -1;
180 0 : err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
181 0 : Py_DECREF(v);
182 0 : return err;
183 : }
184 : else
185 0 : return -1;
186 : }
187 :
188 : /* Try to get a file-descriptor from a Python object. If the object
189 : is an integer or long integer, its value is returned. If not, the
190 : object's fileno() method is called if it exists; the method must return
191 : an integer or long integer, which is returned as the file descriptor value.
192 : -1 is returned on failure.
193 : */
194 :
195 : int
196 0 : PyObject_AsFileDescriptor(PyObject *o)
197 : {
198 : int fd;
199 : PyObject *meth;
200 : _Py_IDENTIFIER(fileno);
201 :
202 0 : if (PyLong_Check(o)) {
203 0 : fd = PyLong_AsLong(o);
204 : }
205 0 : else if ((meth = _PyObject_GetAttrId(o, &PyId_fileno)) != NULL)
206 : {
207 0 : PyObject *fno = PyEval_CallObject(meth, NULL);
208 0 : Py_DECREF(meth);
209 0 : if (fno == NULL)
210 0 : return -1;
211 :
212 0 : if (PyLong_Check(fno)) {
213 0 : fd = PyLong_AsLong(fno);
214 0 : Py_DECREF(fno);
215 : }
216 : else {
217 0 : PyErr_SetString(PyExc_TypeError,
218 : "fileno() returned a non-integer");
219 0 : Py_DECREF(fno);
220 0 : return -1;
221 : }
222 : }
223 : else {
224 0 : PyErr_SetString(PyExc_TypeError,
225 : "argument must be an int, or have a fileno() method.");
226 0 : return -1;
227 : }
228 :
229 0 : if (fd == -1 && PyErr_Occurred())
230 0 : return -1;
231 0 : if (fd < 0) {
232 0 : PyErr_Format(PyExc_ValueError,
233 : "file descriptor cannot be a negative integer (%i)",
234 : fd);
235 0 : return -1;
236 : }
237 0 : return fd;
238 : }
239 :
240 : /*
241 : ** Py_UniversalNewlineFgets is an fgets variation that understands
242 : ** all of \r, \n and \r\n conventions.
243 : ** The stream should be opened in binary mode.
244 : ** If fobj is NULL the routine always does newline conversion, and
245 : ** it may peek one char ahead to gobble the second char in \r\n.
246 : ** If fobj is non-NULL it must be a PyFileObject. In this case there
247 : ** is no readahead but in stead a flag is used to skip a following
248 : ** \n on the next read. Also, if the file is open in binary mode
249 : ** the whole conversion is skipped. Finally, the routine keeps track of
250 : ** the different types of newlines seen.
251 : ** Note that we need no error handling: fgets() treats error and eof
252 : ** identically.
253 : */
254 : char *
255 0 : Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
256 : {
257 0 : char *p = buf;
258 : int c;
259 0 : int newlinetypes = 0;
260 0 : int skipnextlf = 0;
261 :
262 0 : if (fobj) {
263 0 : errno = ENXIO; /* What can you do... */
264 0 : return NULL;
265 : }
266 0 : FLOCKFILE(stream);
267 0 : c = 'x'; /* Shut up gcc warning */
268 0 : while (--n > 0 && (c = GETC(stream)) != EOF ) {
269 0 : if (skipnextlf ) {
270 0 : skipnextlf = 0;
271 0 : if (c == '\n') {
272 : /* Seeing a \n here with skipnextlf true
273 : ** means we saw a \r before.
274 : */
275 0 : newlinetypes |= NEWLINE_CRLF;
276 0 : c = GETC(stream);
277 0 : if (c == EOF) break;
278 : } else {
279 : /*
280 : ** Note that c == EOF also brings us here,
281 : ** so we're okay if the last char in the file
282 : ** is a CR.
283 : */
284 0 : newlinetypes |= NEWLINE_CR;
285 : }
286 : }
287 0 : if (c == '\r') {
288 : /* A \r is translated into a \n, and we skip
289 : ** an adjacent \n, if any. We don't set the
290 : ** newlinetypes flag until we've seen the next char.
291 : */
292 0 : skipnextlf = 1;
293 0 : c = '\n';
294 0 : } else if ( c == '\n') {
295 0 : newlinetypes |= NEWLINE_LF;
296 : }
297 0 : *p++ = c;
298 0 : if (c == '\n') break;
299 : }
300 : /* if ( c == EOF && skipnextlf )
301 : newlinetypes |= NEWLINE_CR; */
302 0 : FUNLOCKFILE(stream);
303 0 : *p = '\0';
304 0 : if ( skipnextlf ) {
305 : /* If we have no file object we cannot save the
306 : ** skipnextlf flag. We have to readahead, which
307 : ** will cause a pause if we're reading from an
308 : ** interactive stream, but that is very unlikely
309 : ** unless we're doing something silly like
310 : ** exec(open("/dev/tty").read()).
311 : */
312 0 : c = GETC(stream);
313 0 : if ( c != '\n' )
314 0 : ungetc(c, stream);
315 : }
316 0 : if (p == buf)
317 0 : return NULL;
318 0 : return buf;
319 : }
320 :
321 : /* **************************** std printer ****************************
322 : * The stdprinter is used during the boot strapping phase as a preliminary
323 : * file like object for sys.stderr.
324 : */
325 :
326 : typedef struct {
327 : PyObject_HEAD
328 : int fd;
329 : } PyStdPrinter_Object;
330 :
331 : static PyObject *
332 0 : stdprinter_new(PyTypeObject *type, PyObject *args, PyObject *kews)
333 : {
334 : PyStdPrinter_Object *self;
335 :
336 : assert(type != NULL && type->tp_alloc != NULL);
337 :
338 0 : self = (PyStdPrinter_Object *) type->tp_alloc(type, 0);
339 0 : if (self != NULL) {
340 0 : self->fd = -1;
341 : }
342 :
343 0 : return (PyObject *) self;
344 : }
345 :
346 : static int
347 0 : stdprinter_init(PyObject *self, PyObject *args, PyObject *kwds)
348 : {
349 0 : PyErr_SetString(PyExc_TypeError,
350 : "cannot create 'stderrprinter' instances");
351 0 : return -1;
352 : }
353 :
354 : PyObject *
355 1 : PyFile_NewStdPrinter(int fd)
356 : {
357 : PyStdPrinter_Object *self;
358 :
359 1 : if (fd != fileno(stdout) && fd != fileno(stderr)) {
360 : /* not enough infrastructure for PyErr_BadInternalCall() */
361 0 : return NULL;
362 : }
363 :
364 1 : self = PyObject_New(PyStdPrinter_Object,
365 : &PyStdPrinter_Type);
366 1 : if (self != NULL) {
367 1 : self->fd = fd;
368 : }
369 1 : return (PyObject*)self;
370 : }
371 :
372 : static PyObject *
373 0 : stdprinter_write(PyStdPrinter_Object *self, PyObject *args)
374 : {
375 : char *c;
376 : Py_ssize_t n;
377 :
378 0 : if (self->fd < 0) {
379 : /* fd might be invalid on Windows
380 : * I can't raise an exception here. It may lead to an
381 : * unlimited recursion in the case stderr is invalid.
382 : */
383 0 : Py_RETURN_NONE;
384 : }
385 :
386 0 : if (!PyArg_ParseTuple(args, "s", &c)) {
387 0 : return NULL;
388 : }
389 0 : n = strlen(c);
390 :
391 0 : Py_BEGIN_ALLOW_THREADS
392 0 : errno = 0;
393 : #if defined(MS_WIN64) || defined(MS_WINDOWS)
394 : if (n > INT_MAX)
395 : n = INT_MAX;
396 : n = write(self->fd, c, (int)n);
397 : #else
398 0 : n = write(self->fd, c, n);
399 : #endif
400 0 : Py_END_ALLOW_THREADS
401 :
402 0 : if (n < 0) {
403 0 : if (errno == EAGAIN)
404 0 : Py_RETURN_NONE;
405 0 : PyErr_SetFromErrno(PyExc_IOError);
406 0 : return NULL;
407 : }
408 :
409 0 : return PyLong_FromSsize_t(n);
410 : }
411 :
412 : static PyObject *
413 0 : stdprinter_fileno(PyStdPrinter_Object *self)
414 : {
415 0 : return PyLong_FromLong((long) self->fd);
416 : }
417 :
418 : static PyObject *
419 0 : stdprinter_repr(PyStdPrinter_Object *self)
420 : {
421 0 : return PyUnicode_FromFormat("<stdprinter(fd=%d) object at 0x%x>",
422 : self->fd, self);
423 : }
424 :
425 : static PyObject *
426 0 : stdprinter_noop(PyStdPrinter_Object *self)
427 : {
428 0 : Py_RETURN_NONE;
429 : }
430 :
431 : static PyObject *
432 0 : stdprinter_isatty(PyStdPrinter_Object *self)
433 : {
434 : long res;
435 0 : if (self->fd < 0) {
436 0 : Py_RETURN_FALSE;
437 : }
438 :
439 0 : Py_BEGIN_ALLOW_THREADS
440 0 : res = isatty(self->fd);
441 0 : Py_END_ALLOW_THREADS
442 :
443 0 : return PyBool_FromLong(res);
444 : }
445 :
446 : static PyMethodDef stdprinter_methods[] = {
447 : {"close", (PyCFunction)stdprinter_noop, METH_NOARGS, ""},
448 : {"flush", (PyCFunction)stdprinter_noop, METH_NOARGS, ""},
449 : {"fileno", (PyCFunction)stdprinter_fileno, METH_NOARGS, ""},
450 : {"isatty", (PyCFunction)stdprinter_isatty, METH_NOARGS, ""},
451 : {"write", (PyCFunction)stdprinter_write, METH_VARARGS, ""},
452 : {NULL, NULL} /*sentinel */
453 : };
454 :
455 : static PyObject *
456 0 : get_closed(PyStdPrinter_Object *self, void *closure)
457 : {
458 0 : Py_INCREF(Py_False);
459 0 : return Py_False;
460 : }
461 :
462 : static PyObject *
463 0 : get_mode(PyStdPrinter_Object *self, void *closure)
464 : {
465 0 : return PyUnicode_FromString("w");
466 : }
467 :
468 : static PyObject *
469 0 : get_encoding(PyStdPrinter_Object *self, void *closure)
470 : {
471 0 : Py_RETURN_NONE;
472 : }
473 :
474 : static PyGetSetDef stdprinter_getsetlist[] = {
475 : {"closed", (getter)get_closed, NULL, "True if the file is closed"},
476 : {"encoding", (getter)get_encoding, NULL, "Encoding of the file"},
477 : {"mode", (getter)get_mode, NULL, "String giving the file mode"},
478 : {0},
479 : };
480 :
481 : PyTypeObject PyStdPrinter_Type = {
482 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
483 : "stderrprinter", /* tp_name */
484 : sizeof(PyStdPrinter_Object), /* tp_basicsize */
485 : 0, /* tp_itemsize */
486 : /* methods */
487 : 0, /* tp_dealloc */
488 : 0, /* tp_print */
489 : 0, /* tp_getattr */
490 : 0, /* tp_setattr */
491 : 0, /* tp_reserved */
492 : (reprfunc)stdprinter_repr, /* tp_repr */
493 : 0, /* tp_as_number */
494 : 0, /* tp_as_sequence */
495 : 0, /* tp_as_mapping */
496 : 0, /* tp_hash */
497 : 0, /* tp_call */
498 : 0, /* tp_str */
499 : PyObject_GenericGetAttr, /* tp_getattro */
500 : 0, /* tp_setattro */
501 : 0, /* tp_as_buffer */
502 : Py_TPFLAGS_DEFAULT, /* tp_flags */
503 : 0, /* tp_doc */
504 : 0, /* tp_traverse */
505 : 0, /* tp_clear */
506 : 0, /* tp_richcompare */
507 : 0, /* tp_weaklistoffset */
508 : 0, /* tp_iter */
509 : 0, /* tp_iternext */
510 : stdprinter_methods, /* tp_methods */
511 : 0, /* tp_members */
512 : stdprinter_getsetlist, /* tp_getset */
513 : 0, /* tp_base */
514 : 0, /* tp_dict */
515 : 0, /* tp_descr_get */
516 : 0, /* tp_descr_set */
517 : 0, /* tp_dictoffset */
518 : stdprinter_init, /* tp_init */
519 : PyType_GenericAlloc, /* tp_alloc */
520 : stdprinter_new, /* tp_new */
521 : PyObject_Del, /* tp_free */
522 : };
523 :
524 :
525 : #ifdef __cplusplus
526 : }
527 : #endif
|