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