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