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