ยปCore Development>Code coverage>Modules/_io/fileio.c

Python code coverage for Modules/_io/fileio.c

#countcontent
1n/a/* Author: Daniel Stutzbach */
2n/a
3n/a#define PY_SSIZE_T_CLEAN
4n/a#include "Python.h"
5n/a#include "structmember.h"
6n/a#ifdef HAVE_SYS_TYPES_H
7n/a#include <sys/types.h>
8n/a#endif
9n/a#ifdef HAVE_SYS_STAT_H
10n/a#include <sys/stat.h>
11n/a#endif
12n/a#ifdef HAVE_IO_H
13n/a#include <io.h>
14n/a#endif
15n/a#ifdef HAVE_FCNTL_H
16n/a#include <fcntl.h>
17n/a#endif
18n/a#include <stddef.h> /* For offsetof */
19n/a#include "_iomodule.h"
20n/a
21n/a/*
22n/a * Known likely problems:
23n/a *
24n/a * - Files larger then 2**32-1
25n/a * - Files with unicode filenames
26n/a * - Passing numbers greater than 2**32-1 when an integer is expected
27n/a * - Making it work on Windows and other oddball platforms
28n/a *
29n/a * To Do:
30n/a *
31n/a * - autoconfify header file inclusion
32n/a */
33n/a
34n/a#ifdef MS_WINDOWS
35n/a/* can simulate truncate with Win32 API functions; see file_truncate */
36n/a#define HAVE_FTRUNCATE
37n/a#define WIN32_LEAN_AND_MEAN
38n/a#include <windows.h>
39n/a#endif
40n/a
41n/a#if BUFSIZ < (8*1024)
42n/a#define SMALLCHUNK (8*1024)
43n/a#elif (BUFSIZ >= (2 << 25))
44n/a#error "unreasonable BUFSIZ > 64MB defined"
45n/a#else
46n/a#define SMALLCHUNK BUFSIZ
47n/a#endif
48n/a
49n/a/*[clinic input]
50n/amodule _io
51n/aclass _io.FileIO "fileio *" "&PyFileIO_Type"
52n/a[clinic start generated code]*/
53n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1c77708b41fda70c]*/
54n/a
55n/a/*[python input]
56n/aclass io_ssize_t_converter(CConverter):
57n/a type = 'Py_ssize_t'
58n/a converter = '_PyIO_ConvertSsize_t'
59n/a[python start generated code]*/
60n/a/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/
61n/a
62n/atypedef struct {
63n/a PyObject_HEAD
64n/a int fd;
65n/a unsigned int created : 1;
66n/a unsigned int readable : 1;
67n/a unsigned int writable : 1;
68n/a unsigned int appending : 1;
69n/a signed int seekable : 2; /* -1 means unknown */
70n/a unsigned int closefd : 1;
71n/a char finalizing;
72n/a unsigned int blksize;
73n/a PyObject *weakreflist;
74n/a PyObject *dict;
75n/a} fileio;
76n/a
77n/aPyTypeObject PyFileIO_Type;
78n/a
79n/a_Py_IDENTIFIER(name);
80n/a
81n/a#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
82n/a
83n/aint
84n/a_PyFileIO_closed(PyObject *self)
85n/a{
86n/a return ((fileio *)self)->fd < 0;
87n/a}
88n/a
89n/a/* Because this can call arbitrary code, it shouldn't be called when
90n/a the refcount is 0 (that is, not directly from tp_dealloc unless
91n/a the refcount has been temporarily re-incremented). */
92n/astatic PyObject *
93n/afileio_dealloc_warn(fileio *self, PyObject *source)
94n/a{
95n/a if (self->fd >= 0 && self->closefd) {
96n/a PyObject *exc, *val, *tb;
97n/a PyErr_Fetch(&exc, &val, &tb);
98n/a if (PyErr_ResourceWarning(source, 1, "unclosed file %R", source)) {
99n/a /* Spurious errors can appear at shutdown */
100n/a if (PyErr_ExceptionMatches(PyExc_Warning))
101n/a PyErr_WriteUnraisable((PyObject *) self);
102n/a }
103n/a PyErr_Restore(exc, val, tb);
104n/a }
105n/a Py_RETURN_NONE;
106n/a}
107n/a
108n/astatic PyObject *
109n/aportable_lseek(int fd, PyObject *posobj, int whence);
110n/a
111n/astatic PyObject *portable_lseek(int fd, PyObject *posobj, int whence);
112n/a
113n/a/* Returns 0 on success, -1 with exception set on failure. */
114n/astatic int
115n/ainternal_close(fileio *self)
116n/a{
117n/a int err = 0;
118n/a int save_errno = 0;
119n/a if (self->fd >= 0) {
120n/a int fd = self->fd;
121n/a self->fd = -1;
122n/a /* fd is accessible and someone else may have closed it */
123n/a Py_BEGIN_ALLOW_THREADS
124n/a _Py_BEGIN_SUPPRESS_IPH
125n/a err = close(fd);
126n/a if (err < 0)
127n/a save_errno = errno;
128n/a _Py_END_SUPPRESS_IPH
129n/a Py_END_ALLOW_THREADS
130n/a }
131n/a if (err < 0) {
132n/a errno = save_errno;
133n/a PyErr_SetFromErrno(PyExc_IOError);
134n/a return -1;
135n/a }
136n/a return 0;
137n/a}
138n/a
139n/a/*[clinic input]
140n/a_io.FileIO.close
141n/a
142n/aClose the file.
143n/a
144n/aA closed file cannot be used for further I/O operations. close() may be
145n/acalled more than once without error.
146n/a[clinic start generated code]*/
147n/a
148n/astatic PyObject *
149n/a_io_FileIO_close_impl(fileio *self)
150n/a/*[clinic end generated code: output=7737a319ef3bad0b input=f35231760d54a522]*/
151n/a{
152n/a PyObject *res;
153n/a PyObject *exc, *val, *tb;
154n/a int rc;
155n/a _Py_IDENTIFIER(close);
156n/a res = _PyObject_CallMethodIdObjArgs((PyObject*)&PyRawIOBase_Type,
157n/a &PyId_close, self, NULL);
158n/a if (!self->closefd) {
159n/a self->fd = -1;
160n/a return res;
161n/a }
162n/a if (res == NULL)
163n/a PyErr_Fetch(&exc, &val, &tb);
164n/a if (self->finalizing) {
165n/a PyObject *r = fileio_dealloc_warn(self, (PyObject *) self);
166n/a if (r)
167n/a Py_DECREF(r);
168n/a else
169n/a PyErr_Clear();
170n/a }
171n/a rc = internal_close(self);
172n/a if (res == NULL)
173n/a _PyErr_ChainExceptions(exc, val, tb);
174n/a if (rc < 0)
175n/a Py_CLEAR(res);
176n/a return res;
177n/a}
178n/a
179n/astatic PyObject *
180n/afileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
181n/a{
182n/a fileio *self;
183n/a
184n/a assert(type != NULL && type->tp_alloc != NULL);
185n/a
186n/a self = (fileio *) type->tp_alloc(type, 0);
187n/a if (self != NULL) {
188n/a self->fd = -1;
189n/a self->created = 0;
190n/a self->readable = 0;
191n/a self->writable = 0;
192n/a self->appending = 0;
193n/a self->seekable = -1;
194n/a self->blksize = 0;
195n/a self->closefd = 1;
196n/a self->weakreflist = NULL;
197n/a }
198n/a
199n/a return (PyObject *) self;
200n/a}
201n/a
202n/a#ifdef O_CLOEXEC
203n/aextern int _Py_open_cloexec_works;
204n/a#endif
205n/a
206n/a/*[clinic input]
207n/a_io.FileIO.__init__
208n/a file as nameobj: object
209n/a mode: str = "r"
210n/a closefd: int(c_default="1") = True
211n/a opener: object = None
212n/a
213n/aOpen a file.
214n/a
215n/aThe mode can be 'r' (default), 'w', 'x' or 'a' for reading,
216n/awriting, exclusive creation or appending. The file will be created if it
217n/adoesn't exist when opened for writing or appending; it will be truncated
218n/awhen opened for writing. A FileExistsError will be raised if it already
219n/aexists when opened for creating. Opening a file for creating implies
220n/awriting so this mode behaves in a similar way to 'w'.Add a '+' to the mode
221n/ato allow simultaneous reading and writing. A custom opener can be used by
222n/apassing a callable as *opener*. The underlying file descriptor for the file
223n/aobject is then obtained by calling opener with (*name*, *flags*).
224n/a*opener* must return an open file descriptor (passing os.open as *opener*
225n/aresults in functionality similar to passing None).
226n/a[clinic start generated code]*/
227n/a
228n/astatic int
229n/a_io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
230n/a int closefd, PyObject *opener)
231n/a/*[clinic end generated code: output=23413f68e6484bbd input=193164e293d6c097]*/
232n/a{
233n/a#ifdef MS_WINDOWS
234n/a Py_UNICODE *widename = NULL;
235n/a#else
236n/a const char *name = NULL;
237n/a#endif
238n/a PyObject *stringobj = NULL;
239n/a const char *s;
240n/a int ret = 0;
241n/a int rwa = 0, plus = 0;
242n/a int flags = 0;
243n/a int fd = -1;
244n/a int fd_is_own = 0;
245n/a#ifdef O_CLOEXEC
246n/a int *atomic_flag_works = &_Py_open_cloexec_works;
247n/a#elif !defined(MS_WINDOWS)
248n/a int *atomic_flag_works = NULL;
249n/a#endif
250n/a struct _Py_stat_struct fdfstat;
251n/a int fstat_result;
252n/a int async_err = 0;
253n/a
254n/a assert(PyFileIO_Check(self));
255n/a if (self->fd >= 0) {
256n/a if (self->closefd) {
257n/a /* Have to close the existing file first. */
258n/a if (internal_close(self) < 0)
259n/a return -1;
260n/a }
261n/a else
262n/a self->fd = -1;
263n/a }
264n/a
265n/a if (PyFloat_Check(nameobj)) {
266n/a PyErr_SetString(PyExc_TypeError,
267n/a "integer argument expected, got float");
268n/a return -1;
269n/a }
270n/a
271n/a fd = _PyLong_AsInt(nameobj);
272n/a if (fd < 0) {
273n/a if (!PyErr_Occurred()) {
274n/a PyErr_SetString(PyExc_ValueError,
275n/a "negative file descriptor");
276n/a return -1;
277n/a }
278n/a PyErr_Clear();
279n/a }
280n/a
281n/a if (fd < 0) {
282n/a#ifdef MS_WINDOWS
283n/a Py_ssize_t length;
284n/a if (!PyUnicode_FSDecoder(nameobj, &stringobj)) {
285n/a return -1;
286n/a }
287n/a widename = PyUnicode_AsUnicodeAndSize(stringobj, &length);
288n/a if (widename == NULL)
289n/a return -1;
290n/a#else
291n/a if (!PyUnicode_FSConverter(nameobj, &stringobj)) {
292n/a return -1;
293n/a }
294n/a name = PyBytes_AS_STRING(stringobj);
295n/a#endif
296n/a }
297n/a
298n/a s = mode;
299n/a while (*s) {
300n/a switch (*s++) {
301n/a case 'x':
302n/a if (rwa) {
303n/a bad_mode:
304n/a PyErr_SetString(PyExc_ValueError,
305n/a "Must have exactly one of create/read/write/append "
306n/a "mode and at most one plus");
307n/a goto error;
308n/a }
309n/a rwa = 1;
310n/a self->created = 1;
311n/a self->writable = 1;
312n/a flags |= O_EXCL | O_CREAT;
313n/a break;
314n/a case 'r':
315n/a if (rwa)
316n/a goto bad_mode;
317n/a rwa = 1;
318n/a self->readable = 1;
319n/a break;
320n/a case 'w':
321n/a if (rwa)
322n/a goto bad_mode;
323n/a rwa = 1;
324n/a self->writable = 1;
325n/a flags |= O_CREAT | O_TRUNC;
326n/a break;
327n/a case 'a':
328n/a if (rwa)
329n/a goto bad_mode;
330n/a rwa = 1;
331n/a self->writable = 1;
332n/a self->appending = 1;
333n/a flags |= O_APPEND | O_CREAT;
334n/a break;
335n/a case 'b':
336n/a break;
337n/a case '+':
338n/a if (plus)
339n/a goto bad_mode;
340n/a self->readable = self->writable = 1;
341n/a plus = 1;
342n/a break;
343n/a default:
344n/a PyErr_Format(PyExc_ValueError,
345n/a "invalid mode: %.200s", mode);
346n/a goto error;
347n/a }
348n/a }
349n/a
350n/a if (!rwa)
351n/a goto bad_mode;
352n/a
353n/a if (self->readable && self->writable)
354n/a flags |= O_RDWR;
355n/a else if (self->readable)
356n/a flags |= O_RDONLY;
357n/a else
358n/a flags |= O_WRONLY;
359n/a
360n/a#ifdef O_BINARY
361n/a flags |= O_BINARY;
362n/a#endif
363n/a
364n/a#ifdef MS_WINDOWS
365n/a flags |= O_NOINHERIT;
366n/a#elif defined(O_CLOEXEC)
367n/a flags |= O_CLOEXEC;
368n/a#endif
369n/a
370n/a if (fd >= 0) {
371n/a self->fd = fd;
372n/a self->closefd = closefd;
373n/a }
374n/a else {
375n/a self->closefd = 1;
376n/a if (!closefd) {
377n/a PyErr_SetString(PyExc_ValueError,
378n/a "Cannot use closefd=False with file name");
379n/a goto error;
380n/a }
381n/a
382n/a errno = 0;
383n/a if (opener == Py_None) {
384n/a do {
385n/a Py_BEGIN_ALLOW_THREADS
386n/a#ifdef MS_WINDOWS
387n/a self->fd = _wopen(widename, flags, 0666);
388n/a#else
389n/a self->fd = open(name, flags, 0666);
390n/a#endif
391n/a Py_END_ALLOW_THREADS
392n/a } while (self->fd < 0 && errno == EINTR &&
393n/a !(async_err = PyErr_CheckSignals()));
394n/a
395n/a if (async_err)
396n/a goto error;
397n/a }
398n/a else {
399n/a PyObject *fdobj;
400n/a
401n/a#ifndef MS_WINDOWS
402n/a /* the opener may clear the atomic flag */
403n/a atomic_flag_works = NULL;
404n/a#endif
405n/a
406n/a fdobj = PyObject_CallFunction(opener, "Oi", nameobj, flags);
407n/a if (fdobj == NULL)
408n/a goto error;
409n/a if (!PyLong_Check(fdobj)) {
410n/a Py_DECREF(fdobj);
411n/a PyErr_SetString(PyExc_TypeError,
412n/a "expected integer from opener");
413n/a goto error;
414n/a }
415n/a
416n/a self->fd = _PyLong_AsInt(fdobj);
417n/a Py_DECREF(fdobj);
418n/a if (self->fd < 0) {
419n/a if (!PyErr_Occurred()) {
420n/a /* The opener returned a negative but didn't set an
421n/a exception. See issue #27066 */
422n/a PyErr_Format(PyExc_ValueError,
423n/a "opener returned %d", self->fd);
424n/a }
425n/a goto error;
426n/a }
427n/a }
428n/a
429n/a fd_is_own = 1;
430n/a if (self->fd < 0) {
431n/a PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj);
432n/a goto error;
433n/a }
434n/a
435n/a#ifndef MS_WINDOWS
436n/a if (_Py_set_inheritable(self->fd, 0, atomic_flag_works) < 0)
437n/a goto error;
438n/a#endif
439n/a }
440n/a
441n/a self->blksize = DEFAULT_BUFFER_SIZE;
442n/a Py_BEGIN_ALLOW_THREADS
443n/a fstat_result = _Py_fstat_noraise(self->fd, &fdfstat);
444n/a Py_END_ALLOW_THREADS
445n/a if (fstat_result < 0) {
446n/a /* Tolerate fstat() errors other than EBADF. See Issue #25717, where
447n/a an anonymous file on a Virtual Box shared folder filesystem would
448n/a raise ENOENT. */
449n/a#ifdef MS_WINDOWS
450n/a if (GetLastError() == ERROR_INVALID_HANDLE) {
451n/a PyErr_SetFromWindowsErr(0);
452n/a#else
453n/a if (errno == EBADF) {
454n/a PyErr_SetFromErrno(PyExc_OSError);
455n/a#endif
456n/a goto error;
457n/a }
458n/a }
459n/a else {
460n/a#if defined(S_ISDIR) && defined(EISDIR)
461n/a /* On Unix, open will succeed for directories.
462n/a In Python, there should be no file objects referring to
463n/a directories, so we need a check. */
464n/a if (S_ISDIR(fdfstat.st_mode)) {
465n/a errno = EISDIR;
466n/a PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
467n/a goto error;
468n/a }
469n/a#endif /* defined(S_ISDIR) */
470n/a#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
471n/a if (fdfstat.st_blksize > 1)
472n/a self->blksize = fdfstat.st_blksize;
473n/a#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
474n/a }
475n/a
476n/a#if defined(MS_WINDOWS) || defined(__CYGWIN__)
477n/a /* don't translate newlines (\r\n <=> \n) */
478n/a _setmode(self->fd, O_BINARY);
479n/a#endif
480n/a
481n/a if (_PyObject_SetAttrId((PyObject *)self, &PyId_name, nameobj) < 0)
482n/a goto error;
483n/a
484n/a if (self->appending) {
485n/a /* For consistent behaviour, we explicitly seek to the
486n/a end of file (otherwise, it might be done only on the
487n/a first write()). */
488n/a PyObject *pos = portable_lseek(self->fd, NULL, 2);
489n/a if (pos == NULL)
490n/a goto error;
491n/a Py_DECREF(pos);
492n/a }
493n/a
494n/a goto done;
495n/a
496n/a error:
497n/a ret = -1;
498n/a if (!fd_is_own)
499n/a self->fd = -1;
500n/a if (self->fd >= 0)
501n/a internal_close(self);
502n/a
503n/a done:
504n/a Py_CLEAR(stringobj);
505n/a return ret;
506n/a}
507n/a
508n/astatic int
509n/afileio_traverse(fileio *self, visitproc visit, void *arg)
510n/a{
511n/a Py_VISIT(self->dict);
512n/a return 0;
513n/a}
514n/a
515n/astatic int
516n/afileio_clear(fileio *self)
517n/a{
518n/a Py_CLEAR(self->dict);
519n/a return 0;
520n/a}
521n/a
522n/astatic void
523n/afileio_dealloc(fileio *self)
524n/a{
525n/a self->finalizing = 1;
526n/a if (_PyIOBase_finalize((PyObject *) self) < 0)
527n/a return;
528n/a _PyObject_GC_UNTRACK(self);
529n/a if (self->weakreflist != NULL)
530n/a PyObject_ClearWeakRefs((PyObject *) self);
531n/a Py_CLEAR(self->dict);
532n/a Py_TYPE(self)->tp_free((PyObject *)self);
533n/a}
534n/a
535n/astatic PyObject *
536n/aerr_closed(void)
537n/a{
538n/a PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
539n/a return NULL;
540n/a}
541n/a
542n/astatic PyObject *
543n/aerr_mode(const char *action)
544n/a{
545n/a _PyIO_State *state = IO_STATE();
546n/a if (state != NULL)
547n/a PyErr_Format(state->unsupported_operation,
548n/a "File not open for %s", action);
549n/a return NULL;
550n/a}
551n/a
552n/a/*[clinic input]
553n/a_io.FileIO.fileno
554n/a
555n/aReturn the underlying file descriptor (an integer).
556n/a[clinic start generated code]*/
557n/a
558n/astatic PyObject *
559n/a_io_FileIO_fileno_impl(fileio *self)
560n/a/*[clinic end generated code: output=a9626ce5398ece90 input=0b9b2de67335ada3]*/
561n/a{
562n/a if (self->fd < 0)
563n/a return err_closed();
564n/a return PyLong_FromLong((long) self->fd);
565n/a}
566n/a
567n/a/*[clinic input]
568n/a_io.FileIO.readable
569n/a
570n/aTrue if file was opened in a read mode.
571n/a[clinic start generated code]*/
572n/a
573n/astatic PyObject *
574n/a_io_FileIO_readable_impl(fileio *self)
575n/a/*[clinic end generated code: output=640744a6150fe9ba input=a3fdfed6eea721c5]*/
576n/a{
577n/a if (self->fd < 0)
578n/a return err_closed();
579n/a return PyBool_FromLong((long) self->readable);
580n/a}
581n/a
582n/a/*[clinic input]
583n/a_io.FileIO.writable
584n/a
585n/aTrue if file was opened in a write mode.
586n/a[clinic start generated code]*/
587n/a
588n/astatic PyObject *
589n/a_io_FileIO_writable_impl(fileio *self)
590n/a/*[clinic end generated code: output=96cefc5446e89977 input=c204a808ca2e1748]*/
591n/a{
592n/a if (self->fd < 0)
593n/a return err_closed();
594n/a return PyBool_FromLong((long) self->writable);
595n/a}
596n/a
597n/a/*[clinic input]
598n/a_io.FileIO.seekable
599n/a
600n/aTrue if file supports random-access.
601n/a[clinic start generated code]*/
602n/a
603n/astatic PyObject *
604n/a_io_FileIO_seekable_impl(fileio *self)
605n/a/*[clinic end generated code: output=47909ca0a42e9287 input=c8e5554d2fd63c7f]*/
606n/a{
607n/a if (self->fd < 0)
608n/a return err_closed();
609n/a if (self->seekable < 0) {
610n/a PyObject *pos = portable_lseek(self->fd, NULL, SEEK_CUR);
611n/a if (pos == NULL) {
612n/a PyErr_Clear();
613n/a self->seekable = 0;
614n/a } else {
615n/a Py_DECREF(pos);
616n/a self->seekable = 1;
617n/a }
618n/a }
619n/a return PyBool_FromLong((long) self->seekable);
620n/a}
621n/a
622n/a/*[clinic input]
623n/a_io.FileIO.readinto
624n/a buffer: Py_buffer(accept={rwbuffer})
625n/a /
626n/a
627n/aSame as RawIOBase.readinto().
628n/a[clinic start generated code]*/
629n/a
630n/astatic PyObject *
631n/a_io_FileIO_readinto_impl(fileio *self, Py_buffer *buffer)
632n/a/*[clinic end generated code: output=b01a5a22c8415cb4 input=4721d7b68b154eaf]*/
633n/a{
634n/a Py_ssize_t n;
635n/a int err;
636n/a
637n/a if (self->fd < 0)
638n/a return err_closed();
639n/a if (!self->readable)
640n/a return err_mode("reading");
641n/a
642n/a n = _Py_read(self->fd, buffer->buf, buffer->len);
643n/a /* copy errno because PyBuffer_Release() can indirectly modify it */
644n/a err = errno;
645n/a
646n/a if (n == -1) {
647n/a if (err == EAGAIN) {
648n/a PyErr_Clear();
649n/a Py_RETURN_NONE;
650n/a }
651n/a return NULL;
652n/a }
653n/a
654n/a return PyLong_FromSsize_t(n);
655n/a}
656n/a
657n/astatic size_t
658n/anew_buffersize(fileio *self, size_t currentsize)
659n/a{
660n/a size_t addend;
661n/a
662n/a /* Expand the buffer by an amount proportional to the current size,
663n/a giving us amortized linear-time behavior. For bigger sizes, use a
664n/a less-than-double growth factor to avoid excessive allocation. */
665n/a assert(currentsize <= PY_SSIZE_T_MAX);
666n/a if (currentsize > 65536)
667n/a addend = currentsize >> 3;
668n/a else
669n/a addend = 256 + currentsize;
670n/a if (addend < SMALLCHUNK)
671n/a /* Avoid tiny read() calls. */
672n/a addend = SMALLCHUNK;
673n/a return addend + currentsize;
674n/a}
675n/a
676n/a/*[clinic input]
677n/a_io.FileIO.readall
678n/a
679n/aRead all data from the file, returned as bytes.
680n/a
681n/aIn non-blocking mode, returns as much as is immediately available,
682n/aor None if no data is available. Return an empty bytes object at EOF.
683n/a[clinic start generated code]*/
684n/a
685n/astatic PyObject *
686n/a_io_FileIO_readall_impl(fileio *self)
687n/a/*[clinic end generated code: output=faa0292b213b4022 input=dbdc137f55602834]*/
688n/a{
689n/a struct _Py_stat_struct status;
690n/a Py_off_t pos, end;
691n/a PyObject *result;
692n/a Py_ssize_t bytes_read = 0;
693n/a Py_ssize_t n;
694n/a size_t bufsize;
695n/a
696n/a if (self->fd < 0)
697n/a return err_closed();
698n/a
699n/a _Py_BEGIN_SUPPRESS_IPH
700n/a#ifdef MS_WINDOWS
701n/a pos = _lseeki64(self->fd, 0L, SEEK_CUR);
702n/a#else
703n/a pos = lseek(self->fd, 0L, SEEK_CUR);
704n/a#endif
705n/a _Py_END_SUPPRESS_IPH
706n/a
707n/a if (_Py_fstat_noraise(self->fd, &status) == 0)
708n/a end = status.st_size;
709n/a else
710n/a end = (Py_off_t)-1;
711n/a
712n/a if (end > 0 && end >= pos && pos >= 0 && end - pos < PY_SSIZE_T_MAX) {
713n/a /* This is probably a real file, so we try to allocate a
714n/a buffer one byte larger than the rest of the file. If the
715n/a calculation is right then we should get EOF without having
716n/a to enlarge the buffer. */
717n/a bufsize = (size_t)(end - pos + 1);
718n/a } else {
719n/a bufsize = SMALLCHUNK;
720n/a }
721n/a
722n/a result = PyBytes_FromStringAndSize(NULL, bufsize);
723n/a if (result == NULL)
724n/a return NULL;
725n/a
726n/a while (1) {
727n/a if (bytes_read >= (Py_ssize_t)bufsize) {
728n/a bufsize = new_buffersize(self, bytes_read);
729n/a if (bufsize > PY_SSIZE_T_MAX || bufsize <= 0) {
730n/a PyErr_SetString(PyExc_OverflowError,
731n/a "unbounded read returned more bytes "
732n/a "than a Python bytes object can hold");
733n/a Py_DECREF(result);
734n/a return NULL;
735n/a }
736n/a
737n/a if (PyBytes_GET_SIZE(result) < (Py_ssize_t)bufsize) {
738n/a if (_PyBytes_Resize(&result, bufsize) < 0)
739n/a return NULL;
740n/a }
741n/a }
742n/a
743n/a n = _Py_read(self->fd,
744n/a PyBytes_AS_STRING(result) + bytes_read,
745n/a bufsize - bytes_read);
746n/a
747n/a if (n == 0)
748n/a break;
749n/a if (n == -1) {
750n/a if (errno == EAGAIN) {
751n/a PyErr_Clear();
752n/a if (bytes_read > 0)
753n/a break;
754n/a Py_DECREF(result);
755n/a Py_RETURN_NONE;
756n/a }
757n/a Py_DECREF(result);
758n/a return NULL;
759n/a }
760n/a bytes_read += n;
761n/a pos += n;
762n/a }
763n/a
764n/a if (PyBytes_GET_SIZE(result) > bytes_read) {
765n/a if (_PyBytes_Resize(&result, bytes_read) < 0)
766n/a return NULL;
767n/a }
768n/a return result;
769n/a}
770n/a
771n/a/*[clinic input]
772n/a_io.FileIO.read
773n/a size: io_ssize_t = -1
774n/a /
775n/a
776n/aRead at most size bytes, returned as bytes.
777n/a
778n/aOnly makes one system call, so less data may be returned than requested.
779n/aIn non-blocking mode, returns None if no data is available.
780n/aReturn an empty bytes object at EOF.
781n/a[clinic start generated code]*/
782n/a
783n/astatic PyObject *
784n/a_io_FileIO_read_impl(fileio *self, Py_ssize_t size)
785n/a/*[clinic end generated code: output=42528d39dd0ca641 input=5c6caa5490c13a9b]*/
786n/a{
787n/a char *ptr;
788n/a Py_ssize_t n;
789n/a PyObject *bytes;
790n/a
791n/a if (self->fd < 0)
792n/a return err_closed();
793n/a if (!self->readable)
794n/a return err_mode("reading");
795n/a
796n/a if (size < 0)
797n/a return _io_FileIO_readall_impl(self);
798n/a
799n/a#ifdef MS_WINDOWS
800n/a /* On Windows, the count parameter of read() is an int */
801n/a if (size > INT_MAX)
802n/a size = INT_MAX;
803n/a#endif
804n/a
805n/a bytes = PyBytes_FromStringAndSize(NULL, size);
806n/a if (bytes == NULL)
807n/a return NULL;
808n/a ptr = PyBytes_AS_STRING(bytes);
809n/a
810n/a n = _Py_read(self->fd, ptr, size);
811n/a if (n == -1) {
812n/a /* copy errno because Py_DECREF() can indirectly modify it */
813n/a int err = errno;
814n/a Py_DECREF(bytes);
815n/a if (err == EAGAIN) {
816n/a PyErr_Clear();
817n/a Py_RETURN_NONE;
818n/a }
819n/a return NULL;
820n/a }
821n/a
822n/a if (n != size) {
823n/a if (_PyBytes_Resize(&bytes, n) < 0) {
824n/a Py_CLEAR(bytes);
825n/a return NULL;
826n/a }
827n/a }
828n/a
829n/a return (PyObject *) bytes;
830n/a}
831n/a
832n/a/*[clinic input]
833n/a_io.FileIO.write
834n/a b: Py_buffer
835n/a /
836n/a
837n/aWrite buffer b to file, return number of bytes written.
838n/a
839n/aOnly makes one system call, so not all of the data may be written.
840n/aThe number of bytes actually written is returned. In non-blocking mode,
841n/areturns None if the write would block.
842n/a[clinic start generated code]*/
843n/a
844n/astatic PyObject *
845n/a_io_FileIO_write_impl(fileio *self, Py_buffer *b)
846n/a/*[clinic end generated code: output=b4059db3d363a2f7 input=6e7908b36f0ce74f]*/
847n/a{
848n/a Py_ssize_t n;
849n/a int err;
850n/a
851n/a if (self->fd < 0)
852n/a return err_closed();
853n/a if (!self->writable)
854n/a return err_mode("writing");
855n/a
856n/a n = _Py_write(self->fd, b->buf, b->len);
857n/a /* copy errno because PyBuffer_Release() can indirectly modify it */
858n/a err = errno;
859n/a
860n/a if (n < 0) {
861n/a if (err == EAGAIN) {
862n/a PyErr_Clear();
863n/a Py_RETURN_NONE;
864n/a }
865n/a return NULL;
866n/a }
867n/a
868n/a return PyLong_FromSsize_t(n);
869n/a}
870n/a
871n/a/* XXX Windows support below is likely incomplete */
872n/a
873n/a/* Cribbed from posix_lseek() */
874n/astatic PyObject *
875n/aportable_lseek(int fd, PyObject *posobj, int whence)
876n/a{
877n/a Py_off_t pos, res;
878n/a
879n/a#ifdef SEEK_SET
880n/a /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
881n/a switch (whence) {
882n/a#if SEEK_SET != 0
883n/a case 0: whence = SEEK_SET; break;
884n/a#endif
885n/a#if SEEK_CUR != 1
886n/a case 1: whence = SEEK_CUR; break;
887n/a#endif
888n/a#if SEEK_END != 2
889n/a case 2: whence = SEEK_END; break;
890n/a#endif
891n/a }
892n/a#endif /* SEEK_SET */
893n/a
894n/a if (posobj == NULL)
895n/a pos = 0;
896n/a else {
897n/a if(PyFloat_Check(posobj)) {
898n/a PyErr_SetString(PyExc_TypeError, "an integer is required");
899n/a return NULL;
900n/a }
901n/a#if defined(HAVE_LARGEFILE_SUPPORT)
902n/a pos = PyLong_AsLongLong(posobj);
903n/a#else
904n/a pos = PyLong_AsLong(posobj);
905n/a#endif
906n/a if (PyErr_Occurred())
907n/a return NULL;
908n/a }
909n/a
910n/a Py_BEGIN_ALLOW_THREADS
911n/a _Py_BEGIN_SUPPRESS_IPH
912n/a#ifdef MS_WINDOWS
913n/a res = _lseeki64(fd, pos, whence);
914n/a#else
915n/a res = lseek(fd, pos, whence);
916n/a#endif
917n/a _Py_END_SUPPRESS_IPH
918n/a Py_END_ALLOW_THREADS
919n/a if (res < 0)
920n/a return PyErr_SetFromErrno(PyExc_IOError);
921n/a
922n/a#if defined(HAVE_LARGEFILE_SUPPORT)
923n/a return PyLong_FromLongLong(res);
924n/a#else
925n/a return PyLong_FromLong(res);
926n/a#endif
927n/a}
928n/a
929n/a/*[clinic input]
930n/a_io.FileIO.seek
931n/a pos: object
932n/a whence: int = 0
933n/a /
934n/a
935n/aMove to new file position and return the file position.
936n/a
937n/aArgument offset is a byte count. Optional argument whence defaults to
938n/aSEEK_SET or 0 (offset from start of file, offset should be >= 0); other values
939n/aare SEEK_CUR or 1 (move relative to current position, positive or negative),
940n/aand SEEK_END or 2 (move relative to end of file, usually negative, although
941n/amany platforms allow seeking beyond the end of a file).
942n/a
943n/aNote that not all file objects are seekable.
944n/a[clinic start generated code]*/
945n/a
946n/astatic PyObject *
947n/a_io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence)
948n/a/*[clinic end generated code: output=c976acdf054e6655 input=0439194b0774d454]*/
949n/a{
950n/a if (self->fd < 0)
951n/a return err_closed();
952n/a
953n/a return portable_lseek(self->fd, pos, whence);
954n/a}
955n/a
956n/a/*[clinic input]
957n/a_io.FileIO.tell
958n/a
959n/aCurrent file position.
960n/a
961n/aCan raise OSError for non seekable files.
962n/a[clinic start generated code]*/
963n/a
964n/astatic PyObject *
965n/a_io_FileIO_tell_impl(fileio *self)
966n/a/*[clinic end generated code: output=ffe2147058809d0b input=807e24ead4cec2f9]*/
967n/a{
968n/a if (self->fd < 0)
969n/a return err_closed();
970n/a
971n/a return portable_lseek(self->fd, NULL, 1);
972n/a}
973n/a
974n/a#ifdef HAVE_FTRUNCATE
975n/a/*[clinic input]
976n/a_io.FileIO.truncate
977n/a size as posobj: object = NULL
978n/a /
979n/a
980n/aTruncate the file to at most size bytes and return the truncated size.
981n/a
982n/aSize defaults to the current file position, as returned by tell().
983n/aThe current file position is changed to the value of size.
984n/a[clinic start generated code]*/
985n/a
986n/astatic PyObject *
987n/a_io_FileIO_truncate_impl(fileio *self, PyObject *posobj)
988n/a/*[clinic end generated code: output=e49ca7a916c176fa input=9026af44686b7318]*/
989n/a{
990n/a Py_off_t pos;
991n/a int ret;
992n/a int fd;
993n/a
994n/a fd = self->fd;
995n/a if (fd < 0)
996n/a return err_closed();
997n/a if (!self->writable)
998n/a return err_mode("writing");
999n/a
1000n/a if (posobj == Py_None || posobj == NULL) {
1001n/a /* Get the current position. */
1002n/a posobj = portable_lseek(fd, NULL, 1);
1003n/a if (posobj == NULL)
1004n/a return NULL;
1005n/a }
1006n/a else {
1007n/a Py_INCREF(posobj);
1008n/a }
1009n/a
1010n/a#if defined(HAVE_LARGEFILE_SUPPORT)
1011n/a pos = PyLong_AsLongLong(posobj);
1012n/a#else
1013n/a pos = PyLong_AsLong(posobj);
1014n/a#endif
1015n/a if (PyErr_Occurred()){
1016n/a Py_DECREF(posobj);
1017n/a return NULL;
1018n/a }
1019n/a
1020n/a Py_BEGIN_ALLOW_THREADS
1021n/a _Py_BEGIN_SUPPRESS_IPH
1022n/a errno = 0;
1023n/a#ifdef MS_WINDOWS
1024n/a ret = _chsize_s(fd, pos);
1025n/a#else
1026n/a ret = ftruncate(fd, pos);
1027n/a#endif
1028n/a _Py_END_SUPPRESS_IPH
1029n/a Py_END_ALLOW_THREADS
1030n/a
1031n/a if (ret != 0) {
1032n/a Py_DECREF(posobj);
1033n/a PyErr_SetFromErrno(PyExc_IOError);
1034n/a return NULL;
1035n/a }
1036n/a
1037n/a return posobj;
1038n/a}
1039n/a#endif /* HAVE_FTRUNCATE */
1040n/a
1041n/astatic const char *
1042n/amode_string(fileio *self)
1043n/a{
1044n/a if (self->created) {
1045n/a if (self->readable)
1046n/a return "xb+";
1047n/a else
1048n/a return "xb";
1049n/a }
1050n/a if (self->appending) {
1051n/a if (self->readable)
1052n/a return "ab+";
1053n/a else
1054n/a return "ab";
1055n/a }
1056n/a else if (self->readable) {
1057n/a if (self->writable)
1058n/a return "rb+";
1059n/a else
1060n/a return "rb";
1061n/a }
1062n/a else
1063n/a return "wb";
1064n/a}
1065n/a
1066n/astatic PyObject *
1067n/afileio_repr(fileio *self)
1068n/a{
1069n/a PyObject *nameobj, *res;
1070n/a
1071n/a if (self->fd < 0)
1072n/a return PyUnicode_FromFormat("<_io.FileIO [closed]>");
1073n/a
1074n/a nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
1075n/a if (nameobj == NULL) {
1076n/a if (PyErr_ExceptionMatches(PyExc_AttributeError))
1077n/a PyErr_Clear();
1078n/a else
1079n/a return NULL;
1080n/a res = PyUnicode_FromFormat(
1081n/a "<_io.FileIO fd=%d mode='%s' closefd=%s>",
1082n/a self->fd, mode_string(self), self->closefd ? "True" : "False");
1083n/a }
1084n/a else {
1085n/a res = PyUnicode_FromFormat(
1086n/a "<_io.FileIO name=%R mode='%s' closefd=%s>",
1087n/a nameobj, mode_string(self), self->closefd ? "True" : "False");
1088n/a Py_DECREF(nameobj);
1089n/a }
1090n/a return res;
1091n/a}
1092n/a
1093n/a/*[clinic input]
1094n/a_io.FileIO.isatty
1095n/a
1096n/aTrue if the file is connected to a TTY device.
1097n/a[clinic start generated code]*/
1098n/a
1099n/astatic PyObject *
1100n/a_io_FileIO_isatty_impl(fileio *self)
1101n/a/*[clinic end generated code: output=932c39924e9a8070 input=cd94ca1f5e95e843]*/
1102n/a{
1103n/a long res;
1104n/a
1105n/a if (self->fd < 0)
1106n/a return err_closed();
1107n/a Py_BEGIN_ALLOW_THREADS
1108n/a _Py_BEGIN_SUPPRESS_IPH
1109n/a res = isatty(self->fd);
1110n/a _Py_END_SUPPRESS_IPH
1111n/a Py_END_ALLOW_THREADS
1112n/a return PyBool_FromLong(res);
1113n/a}
1114n/a
1115n/astatic PyObject *
1116n/afileio_getstate(fileio *self)
1117n/a{
1118n/a PyErr_Format(PyExc_TypeError,
1119n/a "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
1120n/a return NULL;
1121n/a}
1122n/a
1123n/a#include "clinic/fileio.c.h"
1124n/a
1125n/astatic PyMethodDef fileio_methods[] = {
1126n/a _IO_FILEIO_READ_METHODDEF
1127n/a _IO_FILEIO_READALL_METHODDEF
1128n/a _IO_FILEIO_READINTO_METHODDEF
1129n/a _IO_FILEIO_WRITE_METHODDEF
1130n/a _IO_FILEIO_SEEK_METHODDEF
1131n/a _IO_FILEIO_TELL_METHODDEF
1132n/a _IO_FILEIO_TRUNCATE_METHODDEF
1133n/a _IO_FILEIO_CLOSE_METHODDEF
1134n/a _IO_FILEIO_SEEKABLE_METHODDEF
1135n/a _IO_FILEIO_READABLE_METHODDEF
1136n/a _IO_FILEIO_WRITABLE_METHODDEF
1137n/a _IO_FILEIO_FILENO_METHODDEF
1138n/a _IO_FILEIO_ISATTY_METHODDEF
1139n/a {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL},
1140n/a {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL},
1141n/a {NULL, NULL} /* sentinel */
1142n/a};
1143n/a
1144n/a/* 'closed' and 'mode' are attributes for backwards compatibility reasons. */
1145n/a
1146n/astatic PyObject *
1147n/aget_closed(fileio *self, void *closure)
1148n/a{
1149n/a return PyBool_FromLong((long)(self->fd < 0));
1150n/a}
1151n/a
1152n/astatic PyObject *
1153n/aget_closefd(fileio *self, void *closure)
1154n/a{
1155n/a return PyBool_FromLong((long)(self->closefd));
1156n/a}
1157n/a
1158n/astatic PyObject *
1159n/aget_mode(fileio *self, void *closure)
1160n/a{
1161n/a return PyUnicode_FromString(mode_string(self));
1162n/a}
1163n/a
1164n/astatic PyGetSetDef fileio_getsetlist[] = {
1165n/a {"closed", (getter)get_closed, NULL, "True if the file is closed"},
1166n/a {"closefd", (getter)get_closefd, NULL,
1167n/a "True if the file descriptor will be closed by close()."},
1168n/a {"mode", (getter)get_mode, NULL, "String giving the file mode"},
1169n/a {NULL},
1170n/a};
1171n/a
1172n/astatic PyMemberDef fileio_members[] = {
1173n/a {"_blksize", T_UINT, offsetof(fileio, blksize), 0},
1174n/a {"_finalizing", T_BOOL, offsetof(fileio, finalizing), 0},
1175n/a {NULL}
1176n/a};
1177n/a
1178n/aPyTypeObject PyFileIO_Type = {
1179n/a PyVarObject_HEAD_INIT(NULL, 0)
1180n/a "_io.FileIO",
1181n/a sizeof(fileio),
1182n/a 0,
1183n/a (destructor)fileio_dealloc, /* tp_dealloc */
1184n/a 0, /* tp_print */
1185n/a 0, /* tp_getattr */
1186n/a 0, /* tp_setattr */
1187n/a 0, /* tp_reserved */
1188n/a (reprfunc)fileio_repr, /* tp_repr */
1189n/a 0, /* tp_as_number */
1190n/a 0, /* tp_as_sequence */
1191n/a 0, /* tp_as_mapping */
1192n/a 0, /* tp_hash */
1193n/a 0, /* tp_call */
1194n/a 0, /* tp_str */
1195n/a PyObject_GenericGetAttr, /* tp_getattro */
1196n/a 0, /* tp_setattro */
1197n/a 0, /* tp_as_buffer */
1198n/a Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1199n/a | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
1200n/a _io_FileIO___init____doc__, /* tp_doc */
1201n/a (traverseproc)fileio_traverse, /* tp_traverse */
1202n/a (inquiry)fileio_clear, /* tp_clear */
1203n/a 0, /* tp_richcompare */
1204n/a offsetof(fileio, weakreflist), /* tp_weaklistoffset */
1205n/a 0, /* tp_iter */
1206n/a 0, /* tp_iternext */
1207n/a fileio_methods, /* tp_methods */
1208n/a fileio_members, /* tp_members */
1209n/a fileio_getsetlist, /* tp_getset */
1210n/a 0, /* tp_base */
1211n/a 0, /* tp_dict */
1212n/a 0, /* tp_descr_get */
1213n/a 0, /* tp_descr_set */
1214n/a offsetof(fileio, dict), /* tp_dictoffset */
1215n/a _io_FileIO___init__, /* tp_init */
1216n/a PyType_GenericAlloc, /* tp_alloc */
1217n/a fileio_new, /* tp_new */
1218n/a PyObject_GC_Del, /* tp_free */
1219n/a 0, /* tp_is_gc */
1220n/a 0, /* tp_bases */
1221n/a 0, /* tp_mro */
1222n/a 0, /* tp_cache */
1223n/a 0, /* tp_subclasses */
1224n/a 0, /* tp_weaklist */
1225n/a 0, /* tp_del */
1226n/a 0, /* tp_version_tag */
1227n/a 0, /* tp_finalize */
1228n/a};