mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	closes bpo-27805: Ignore ESPIPE in initializing seek of append-mode files. (GH-17112)
This change, which follows the behavior of C stdio's fdopen and Python 2's file object, allows pipes to be opened in append mode.
This commit is contained in:
		
							parent
							
								
									d593881505
								
							
						
					
					
						commit
						74fa9f723f
					
				
					 4 changed files with 33 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
#include "Python.h"
 | 
			
		||||
#include "pycore_object.h"
 | 
			
		||||
#include "structmember.h"
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#ifdef HAVE_SYS_TYPES_H
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +76,7 @@ _Py_IDENTIFIER(name);
 | 
			
		|||
#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
 | 
			
		||||
 | 
			
		||||
/* Forward declarations */
 | 
			
		||||
static PyObject* portable_lseek(fileio *self, PyObject *posobj, int whence);
 | 
			
		||||
static PyObject* portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_error);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
_PyFileIO_closed(PyObject *self)
 | 
			
		||||
| 
						 | 
				
			
			@ -480,7 +481,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
 | 
			
		|||
        /* For consistent behaviour, we explicitly seek to the
 | 
			
		||||
           end of file (otherwise, it might be done only on the
 | 
			
		||||
           first write()). */
 | 
			
		||||
        PyObject *pos = portable_lseek(self, NULL, 2);
 | 
			
		||||
        PyObject *pos = portable_lseek(self, NULL, 2, true);
 | 
			
		||||
        if (pos == NULL)
 | 
			
		||||
            goto error;
 | 
			
		||||
        Py_DECREF(pos);
 | 
			
		||||
| 
						 | 
				
			
			@ -603,7 +604,7 @@ _io_FileIO_seekable_impl(fileio *self)
 | 
			
		|||
        return err_closed();
 | 
			
		||||
    if (self->seekable < 0) {
 | 
			
		||||
        /* portable_lseek() sets the seekable attribute */
 | 
			
		||||
        PyObject *pos = portable_lseek(self, NULL, SEEK_CUR);
 | 
			
		||||
        PyObject *pos = portable_lseek(self, NULL, SEEK_CUR, false);
 | 
			
		||||
        assert(self->seekable >= 0);
 | 
			
		||||
        if (pos == NULL) {
 | 
			
		||||
            PyErr_Clear();
 | 
			
		||||
| 
						 | 
				
			
			@ -870,7 +871,7 @@ _io_FileIO_write_impl(fileio *self, Py_buffer *b)
 | 
			
		|||
 | 
			
		||||
/* Cribbed from posix_lseek() */
 | 
			
		||||
static PyObject *
 | 
			
		||||
portable_lseek(fileio *self, PyObject *posobj, int whence)
 | 
			
		||||
portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_error)
 | 
			
		||||
{
 | 
			
		||||
    Py_off_t pos, res;
 | 
			
		||||
    int fd = self->fd;
 | 
			
		||||
| 
						 | 
				
			
			@ -921,8 +922,13 @@ portable_lseek(fileio *self, PyObject *posobj, int whence)
 | 
			
		|||
        self->seekable = (res >= 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (res < 0)
 | 
			
		||||
        return PyErr_SetFromErrno(PyExc_OSError);
 | 
			
		||||
    if (res < 0) {
 | 
			
		||||
        if (suppress_pipe_error && errno == ESPIPE) {
 | 
			
		||||
            res = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            return PyErr_SetFromErrno(PyExc_OSError);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_LARGEFILE_SUPPORT)
 | 
			
		||||
    return PyLong_FromLongLong(res);
 | 
			
		||||
| 
						 | 
				
			
			@ -955,7 +961,7 @@ _io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence)
 | 
			
		|||
    if (self->fd < 0)
 | 
			
		||||
        return err_closed();
 | 
			
		||||
 | 
			
		||||
    return portable_lseek(self, pos, whence);
 | 
			
		||||
    return portable_lseek(self, pos, whence, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*[clinic input]
 | 
			
		||||
| 
						 | 
				
			
			@ -973,7 +979,7 @@ _io_FileIO_tell_impl(fileio *self)
 | 
			
		|||
    if (self->fd < 0)
 | 
			
		||||
        return err_closed();
 | 
			
		||||
 | 
			
		||||
    return portable_lseek(self, NULL, 1);
 | 
			
		||||
    return portable_lseek(self, NULL, 1, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_FTRUNCATE
 | 
			
		||||
| 
						 | 
				
			
			@ -1004,7 +1010,7 @@ _io_FileIO_truncate_impl(fileio *self, PyObject *posobj)
 | 
			
		|||
 | 
			
		||||
    if (posobj == Py_None) {
 | 
			
		||||
        /* Get the current position. */
 | 
			
		||||
        posobj = portable_lseek(self, NULL, 1);
 | 
			
		||||
        posobj = portable_lseek(self, NULL, 1, false);
 | 
			
		||||
        if (posobj == NULL)
 | 
			
		||||
            return NULL;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue