You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

589 lines
17 KiB

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