Kaydet (Commit) 657e5ac1 authored tarafından Antoine Pitrou's avatar Antoine Pitrou

Merged revisions 80796 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r80796 | antoine.pitrou | 2010-05-05 18:27:30 +0200 (mer., 05 mai 2010) | 3 lines

  Untabify Modules/_io/fileio.c
........
üst 7fd622af
...@@ -28,13 +28,13 @@ ...@@ -28,13 +28,13 @@
#endif #endif
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
int fd; int fd;
unsigned int readable : 1; unsigned int readable : 1;
unsigned int writable : 1; unsigned int writable : 1;
signed int seekable : 2; /* -1 means unknown */ signed int seekable : 2; /* -1 means unknown */
signed int closefd : 1; signed int closefd : 1;
PyObject *weakreflist; PyObject *weakreflist;
} PyFileIOObject; } PyFileIOObject;
PyTypeObject PyFileIO_Type; PyTypeObject PyFileIO_Type;
...@@ -48,52 +48,52 @@ portable_lseek(int fd, PyObject *posobj, int whence); ...@@ -48,52 +48,52 @@ portable_lseek(int fd, PyObject *posobj, int whence);
static int static int
internal_close(PyFileIOObject *self) internal_close(PyFileIOObject *self)
{ {
int save_errno = 0; int save_errno = 0;
if (self->fd >= 0) { if (self->fd >= 0) {
int fd = self->fd; int fd = self->fd;
self->fd = -1; self->fd = -1;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
if (close(fd) < 0) if (close(fd) < 0)
save_errno = errno; save_errno = errno;
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} }
return save_errno; return save_errno;
} }
static PyObject * static PyObject *
fileio_close(PyFileIOObject *self) fileio_close(PyFileIOObject *self)
{ {
if (!self->closefd) { if (!self->closefd) {
self->fd = -1; self->fd = -1;
Py_RETURN_NONE; Py_RETURN_NONE;
} }
errno = internal_close(self); errno = internal_close(self);
if (errno < 0) { if (errno < 0) {
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject * static PyObject *
fileio_new(PyTypeObject *type, PyObject *args, PyObject *kews) fileio_new(PyTypeObject *type, PyObject *args, PyObject *kews)
{ {
PyFileIOObject *self; PyFileIOObject *self;
assert(type != NULL && type->tp_alloc != NULL); assert(type != NULL && type->tp_alloc != NULL);
self = (PyFileIOObject *) type->tp_alloc(type, 0); self = (PyFileIOObject *) type->tp_alloc(type, 0);
if (self != NULL) { if (self != NULL) {
self->fd = -1; self->fd = -1;
self->readable = 0; self->readable = 0;
self->writable = 0; self->writable = 0;
self->seekable = -1; self->seekable = -1;
self->closefd = 1; self->closefd = 1;
self->weakreflist = NULL; self->weakreflist = NULL;
} }
return (PyObject *) self; return (PyObject *) self;
} }
/* On Unix, open will succeed for directories. /* On Unix, open will succeed for directories.
...@@ -104,321 +104,321 @@ static int ...@@ -104,321 +104,321 @@ static int
dircheck(PyFileIOObject* self, char *name) dircheck(PyFileIOObject* self, char *name)
{ {
#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
struct stat buf; struct stat buf;
if (self->fd < 0) if (self->fd < 0)
return 0; return 0;
if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) { if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
char *msg = strerror(EISDIR); char *msg = strerror(EISDIR);
PyObject *exc; PyObject *exc;
internal_close(self); internal_close(self);
exc = PyObject_CallFunction(PyExc_IOError, "(iss)", exc = PyObject_CallFunction(PyExc_IOError, "(iss)",
EISDIR, msg, name); EISDIR, msg, name);
PyErr_SetObject(PyExc_IOError, exc); PyErr_SetObject(PyExc_IOError, exc);
Py_XDECREF(exc); Py_XDECREF(exc);
return -1; return -1;
} }
#endif #endif
return 0; return 0;
} }
static int static int
check_fd(int fd) check_fd(int fd)
{ {
#if defined(HAVE_FSTAT) #if defined(HAVE_FSTAT)
struct stat buf; struct stat buf;
if (fstat(fd, &buf) < 0 && errno == EBADF) { if (fstat(fd, &buf) < 0 && errno == EBADF) {
PyObject *exc; PyObject *exc;
char *msg = strerror(EBADF); char *msg = strerror(EBADF);
exc = PyObject_CallFunction(PyExc_OSError, "(is)", exc = PyObject_CallFunction(PyExc_OSError, "(is)",
EBADF, msg); EBADF, msg);
PyErr_SetObject(PyExc_OSError, exc); PyErr_SetObject(PyExc_OSError, exc);
Py_XDECREF(exc); Py_XDECREF(exc);
return -1; return -1;
} }
#endif #endif
return 0; return 0;
} }
static int static int
fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
{ {
PyFileIOObject *self = (PyFileIOObject *) oself; PyFileIOObject *self = (PyFileIOObject *) oself;
static char *kwlist[] = {"file", "mode", "closefd", NULL}; static char *kwlist[] = {"file", "mode", "closefd", NULL};
char *name = NULL; char *name = NULL;
char *mode = "r"; char *mode = "r";
char *s; char *s;
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
Py_UNICODE *widename = NULL; Py_UNICODE *widename = NULL;
#endif #endif
int ret = 0; int ret = 0;
int rwa = 0, plus = 0, append = 0; int rwa = 0, plus = 0, append = 0;
int flags = 0; int flags = 0;
int fd = -1; int fd = -1;
int closefd = 1; int closefd = 1;
assert(PyFileIO_Check(oself)); assert(PyFileIO_Check(oself));
if (self->fd >= 0) { if (self->fd >= 0) {
/* Have to close the existing file first. */ /* Have to close the existing file first. */
if (internal_close(self) < 0) if (internal_close(self) < 0)
return -1; return -1;
} }
if (PyArg_ParseTupleAndKeywords(args, kwds, "i|si:fileio", if (PyArg_ParseTupleAndKeywords(args, kwds, "i|si:fileio",
kwlist, &fd, &mode, &closefd)) { kwlist, &fd, &mode, &closefd)) {
if (fd < 0) { if (fd < 0) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"Negative filedescriptor"); "Negative filedescriptor");
return -1; return -1;
} }
if (check_fd(fd)) if (check_fd(fd))
return -1; return -1;
} }
else { else {
PyErr_Clear(); PyErr_Clear();
#ifdef Py_WIN_WIDE_FILENAMES #ifdef Py_WIN_WIDE_FILENAMES
if (GetVersion() < 0x80000000) { if (GetVersion() < 0x80000000) {
/* On NT, so wide API available */ /* On NT, so wide API available */
PyObject *po; PyObject *po;
if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:fileio", if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:fileio",
kwlist, &po, &mode, &closefd) kwlist, &po, &mode, &closefd)
) { ) {
widename = PyUnicode_AS_UNICODE(po); widename = PyUnicode_AS_UNICODE(po);
} else { } else {
/* Drop the argument parsing error as narrow /* Drop the argument parsing error as narrow
strings are also valid. */ strings are also valid. */
PyErr_Clear(); PyErr_Clear();
} }
} }
if (widename == NULL) if (widename == NULL)
#endif #endif
{ {
if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:fileio", if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:fileio",
kwlist, kwlist,
Py_FileSystemDefaultEncoding, Py_FileSystemDefaultEncoding,
&name, &mode, &closefd)) &name, &mode, &closefd))
return -1; return -1;
} }
} }
s = mode; s = mode;
while (*s) { while (*s) {
switch (*s++) { switch (*s++) {
case 'r': case 'r':
if (rwa) { if (rwa) {
bad_mode: bad_mode:
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"Must have exactly one of read/write/append mode"); "Must have exactly one of read/write/append mode");
goto error; goto error;
} }
rwa = 1; rwa = 1;
self->readable = 1; self->readable = 1;
break; break;
case 'w': case 'w':
if (rwa) if (rwa)
goto bad_mode; goto bad_mode;
rwa = 1; rwa = 1;
self->writable = 1; self->writable = 1;
flags |= O_CREAT | O_TRUNC; flags |= O_CREAT | O_TRUNC;
break; break;
case 'a': case 'a':
if (rwa) if (rwa)
goto bad_mode; goto bad_mode;
rwa = 1; rwa = 1;
self->writable = 1; self->writable = 1;
flags |= O_CREAT; flags |= O_CREAT;
append = 1; append = 1;
break; break;
case 'b': case 'b':
break; break;
case '+': case '+':
if (plus) if (plus)
goto bad_mode; goto bad_mode;
self->readable = self->writable = 1; self->readable = self->writable = 1;
plus = 1; plus = 1;
break; break;
default: default:
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
"invalid mode: %.200s", mode); "invalid mode: %.200s", mode);
goto error; goto error;
} }
} }
if (!rwa) if (!rwa)
goto bad_mode; goto bad_mode;
if (self->readable && self->writable) if (self->readable && self->writable)
flags |= O_RDWR; flags |= O_RDWR;
else if (self->readable) else if (self->readable)
flags |= O_RDONLY; flags |= O_RDONLY;
else else
flags |= O_WRONLY; flags |= O_WRONLY;
#ifdef O_BINARY #ifdef O_BINARY
flags |= O_BINARY; flags |= O_BINARY;
#endif #endif
#ifdef O_APPEND #ifdef O_APPEND
if (append) if (append)
flags |= O_APPEND; flags |= O_APPEND;
#endif #endif
if (fd >= 0) { if (fd >= 0) {
self->fd = fd; self->fd = fd;
self->closefd = closefd; self->closefd = closefd;
} }
else { else {
self->closefd = 1; self->closefd = 1;
if (!closefd) { if (!closefd) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"Cannot use closefd=False with file name"); "Cannot use closefd=False with file name");
goto error; goto error;
} }
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
errno = 0; errno = 0;
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
if (widename != NULL) if (widename != NULL)
self->fd = _wopen(widename, flags, 0666); self->fd = _wopen(widename, flags, 0666);
else else
#endif #endif
self->fd = open(name, flags, 0666); self->fd = open(name, flags, 0666);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (self->fd < 0) { if (self->fd < 0) {
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
if (widename != NULL) if (widename != NULL)
PyErr_SetFromErrnoWithUnicodeFilename(PyExc_IOError, widename); PyErr_SetFromErrnoWithUnicodeFilename(PyExc_IOError, widename);
else else
#endif #endif
PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
goto error; goto error;
} }
if(dircheck(self, name) < 0) if(dircheck(self, name) < 0)
goto error; goto error;
} }
if (append) { if (append) {
/* For consistent behaviour, we explicitly seek to the /* For consistent behaviour, we explicitly seek to the
end of file (otherwise, it might be done only on the end of file (otherwise, it might be done only on the
first write()). */ first write()). */
PyObject *pos = portable_lseek(self->fd, NULL, 2); PyObject *pos = portable_lseek(self->fd, NULL, 2);
if (pos == NULL) if (pos == NULL)
goto error; goto error;
Py_DECREF(pos); Py_DECREF(pos);
} }
goto done; goto done;
error: error:
ret = -1; ret = -1;
done: done:
PyMem_Free(name); PyMem_Free(name);
return ret; return ret;
} }
static void static void
fileio_dealloc(PyFileIOObject *self) fileio_dealloc(PyFileIOObject *self)
{ {
if (self->weakreflist != NULL) if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self); PyObject_ClearWeakRefs((PyObject *) self);
if (self->fd >= 0 && self->closefd) { if (self->fd >= 0 && self->closefd) {
errno = internal_close(self); errno = internal_close(self);
if (errno < 0) { if (errno < 0) {
PySys_WriteStderr("close failed: [Errno %d] %s\n", PySys_WriteStderr("close failed: [Errno %d] %s\n",
errno, strerror(errno)); errno, strerror(errno));
} }
} }
Py_TYPE(self)->tp_free((PyObject *)self); Py_TYPE(self)->tp_free((PyObject *)self);
} }
static PyObject * static PyObject *
err_closed(void) err_closed(void)
{ {
PyErr_SetString(PyExc_ValueError, "I/O operation on closed file"); PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
return NULL; return NULL;
} }
static PyObject * static PyObject *
err_mode(char *action) err_mode(char *action)
{ {
PyErr_Format(PyExc_ValueError, "File not open for %s", action); PyErr_Format(PyExc_ValueError, "File not open for %s", action);
return NULL; return NULL;
} }
static PyObject * static PyObject *
fileio_fileno(PyFileIOObject *self) fileio_fileno(PyFileIOObject *self)
{ {
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
return PyInt_FromLong((long) self->fd); return PyInt_FromLong((long) self->fd);
} }
static PyObject * static PyObject *
fileio_readable(PyFileIOObject *self) fileio_readable(PyFileIOObject *self)
{ {
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
return PyBool_FromLong((long) self->readable); return PyBool_FromLong((long) self->readable);
} }
static PyObject * static PyObject *
fileio_writable(PyFileIOObject *self) fileio_writable(PyFileIOObject *self)
{ {
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
return PyBool_FromLong((long) self->writable); return PyBool_FromLong((long) self->writable);
} }
static PyObject * static PyObject *
fileio_seekable(PyFileIOObject *self) fileio_seekable(PyFileIOObject *self)
{ {
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
if (self->seekable < 0) { if (self->seekable < 0) {
int ret; int ret;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
ret = lseek(self->fd, 0, SEEK_CUR); ret = lseek(self->fd, 0, SEEK_CUR);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (ret < 0) if (ret < 0)
self->seekable = 0; self->seekable = 0;
else else
self->seekable = 1; self->seekable = 1;
} }
return PyBool_FromLong((long) self->seekable); return PyBool_FromLong((long) self->seekable);
} }
static PyObject * static PyObject *
fileio_readinto(PyFileIOObject *self, PyObject *args) fileio_readinto(PyFileIOObject *self, PyObject *args)
{ {
Py_buffer pbuf; Py_buffer pbuf;
Py_ssize_t n; Py_ssize_t n;
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
if (!self->readable) if (!self->readable)
return err_mode("reading"); return err_mode("reading");
if (!PyArg_ParseTuple(args, "w*", &pbuf)) if (!PyArg_ParseTuple(args, "w*", &pbuf))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
errno = 0; errno = 0;
n = read(self->fd, pbuf.buf, pbuf.len); n = read(self->fd, pbuf.buf, pbuf.len);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyBuffer_Release(&pbuf); PyBuffer_Release(&pbuf);
if (n < 0) { if (n < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
Py_RETURN_NONE; Py_RETURN_NONE;
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
return PyLong_FromSsize_t(n); return PyLong_FromSsize_t(n);
} }
#define DEFAULT_BUFFER_SIZE (8*1024) #define DEFAULT_BUFFER_SIZE (8*1024)
...@@ -426,134 +426,134 @@ fileio_readinto(PyFileIOObject *self, PyObject *args) ...@@ -426,134 +426,134 @@ fileio_readinto(PyFileIOObject *self, PyObject *args)
static PyObject * static PyObject *
fileio_readall(PyFileIOObject *self) fileio_readall(PyFileIOObject *self)
{ {
PyObject *result; PyObject *result;
Py_ssize_t total = 0; Py_ssize_t total = 0;
int n; int n;
result = PyString_FromStringAndSize(NULL, DEFAULT_BUFFER_SIZE); result = PyString_FromStringAndSize(NULL, DEFAULT_BUFFER_SIZE);
if (result == NULL) if (result == NULL)
return NULL; return NULL;
while (1) { while (1) {
Py_ssize_t newsize = total + DEFAULT_BUFFER_SIZE; Py_ssize_t newsize = total + DEFAULT_BUFFER_SIZE;
if (PyString_GET_SIZE(result) < newsize) { if (PyString_GET_SIZE(result) < newsize) {
if (_PyString_Resize(&result, newsize) < 0) { if (_PyString_Resize(&result, newsize) < 0) {
if (total == 0) { if (total == 0) {
Py_DECREF(result); Py_DECREF(result);
return NULL; return NULL;
} }
PyErr_Clear(); PyErr_Clear();
break; break;
} }
} }
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
errno = 0; errno = 0;
n = read(self->fd, n = read(self->fd,
PyString_AS_STRING(result) + total, PyString_AS_STRING(result) + total,
newsize - total); newsize - total);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (n == 0) if (n == 0)
break; break;
if (n < 0) { if (n < 0) {
if (total > 0) if (total > 0)
break; break;
if (errno == EAGAIN) { if (errno == EAGAIN) {
Py_DECREF(result); Py_DECREF(result);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
Py_DECREF(result); Py_DECREF(result);
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
total += n; total += n;
} }
if (PyString_GET_SIZE(result) > total) { if (PyString_GET_SIZE(result) > total) {
if (_PyString_Resize(&result, total) < 0) { if (_PyString_Resize(&result, total) < 0) {
/* This should never happen, but just in case */ /* This should never happen, but just in case */
Py_DECREF(result); Py_DECREF(result);
return NULL; return NULL;
} }
} }
return result; return result;
} }
static PyObject * static PyObject *
fileio_read(PyFileIOObject *self, PyObject *args) fileio_read(PyFileIOObject *self, PyObject *args)
{ {
char *ptr; char *ptr;
Py_ssize_t n; Py_ssize_t n;
Py_ssize_t size = -1; Py_ssize_t size = -1;
PyObject *bytes; PyObject *bytes;
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
if (!self->readable) if (!self->readable)
return err_mode("reading"); return err_mode("reading");
if (!PyArg_ParseTuple(args, "|n", &size)) if (!PyArg_ParseTuple(args, "|n", &size))
return NULL; return NULL;
if (size < 0) { if (size < 0) {
return fileio_readall(self); return fileio_readall(self);
} }
bytes = PyString_FromStringAndSize(NULL, size); bytes = PyString_FromStringAndSize(NULL, size);
if (bytes == NULL) if (bytes == NULL)
return NULL; return NULL;
ptr = PyString_AS_STRING(bytes); ptr = PyString_AS_STRING(bytes);
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
errno = 0; errno = 0;
n = read(self->fd, ptr, size); n = read(self->fd, ptr, size);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (n < 0) { if (n < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
Py_RETURN_NONE; Py_RETURN_NONE;
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
if (n != size) { if (n != size) {
if (_PyString_Resize(&bytes, n) < 0) { if (_PyString_Resize(&bytes, n) < 0) {
Py_DECREF(bytes); Py_DECREF(bytes);
return NULL; return NULL;
} }
} }
return (PyObject *) bytes; return (PyObject *) bytes;
} }
static PyObject * static PyObject *
fileio_write(PyFileIOObject *self, PyObject *args) fileio_write(PyFileIOObject *self, PyObject *args)
{ {
Py_buffer pbuf; Py_buffer pbuf;
Py_ssize_t n; Py_ssize_t n;
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
if (!self->writable) if (!self->writable)
return err_mode("writing"); return err_mode("writing");
if (!PyArg_ParseTuple(args, "s*", &pbuf)) if (!PyArg_ParseTuple(args, "s*", &pbuf))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
errno = 0; errno = 0;
n = write(self->fd, pbuf.buf, pbuf.len); n = write(self->fd, pbuf.buf, pbuf.len);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyBuffer_Release(&pbuf); PyBuffer_Release(&pbuf);
if (n < 0) { if (n < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
Py_RETURN_NONE; Py_RETURN_NONE;
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
return PyLong_FromSsize_t(n); return PyLong_FromSsize_t(n);
} }
/* XXX Windows support below is likely incomplete */ /* XXX Windows support below is likely incomplete */
...@@ -568,217 +568,217 @@ typedef off_t Py_off_t; ...@@ -568,217 +568,217 @@ typedef off_t Py_off_t;
static PyObject * static PyObject *
portable_lseek(int fd, PyObject *posobj, int whence) portable_lseek(int fd, PyObject *posobj, int whence)
{ {
Py_off_t pos, res; Py_off_t pos, res;
#ifdef SEEK_SET #ifdef SEEK_SET
/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
switch (whence) { switch (whence) {
#if SEEK_SET != 0 #if SEEK_SET != 0
case 0: whence = SEEK_SET; break; case 0: whence = SEEK_SET; break;
#endif #endif
#if SEEK_CUR != 1 #if SEEK_CUR != 1
case 1: whence = SEEK_CUR; break; case 1: whence = SEEK_CUR; break;
#endif #endif
#if SEEL_END != 2 #if SEEL_END != 2
case 2: whence = SEEK_END; break; case 2: whence = SEEK_END; break;
#endif #endif
} }
#endif /* SEEK_SET */ #endif /* SEEK_SET */
if (posobj == NULL) if (posobj == NULL)
pos = 0; pos = 0;
else { else {
if(PyFloat_Check(posobj)) { if(PyFloat_Check(posobj)) {
PyErr_SetString(PyExc_TypeError, "an integer is required"); PyErr_SetString(PyExc_TypeError, "an integer is required");
return NULL; return NULL;
} }
#if defined(HAVE_LARGEFILE_SUPPORT) #if defined(HAVE_LARGEFILE_SUPPORT)
pos = PyLong_AsLongLong(posobj); pos = PyLong_AsLongLong(posobj);
#else #else
pos = PyLong_AsLong(posobj); pos = PyLong_AsLong(posobj);
#endif #endif
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; return NULL;
} }
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
#if defined(MS_WIN64) || defined(MS_WINDOWS) #if defined(MS_WIN64) || defined(MS_WINDOWS)
res = _lseeki64(fd, pos, whence); res = _lseeki64(fd, pos, whence);
#else #else
res = lseek(fd, pos, whence); res = lseek(fd, pos, whence);
#endif #endif
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (res < 0) if (res < 0)
return PyErr_SetFromErrno(PyExc_IOError); return PyErr_SetFromErrno(PyExc_IOError);
#if defined(HAVE_LARGEFILE_SUPPORT) #if defined(HAVE_LARGEFILE_SUPPORT)
return PyLong_FromLongLong(res); return PyLong_FromLongLong(res);
#else #else
return PyLong_FromLong(res); return PyLong_FromLong(res);
#endif #endif
} }
static PyObject * static PyObject *
fileio_seek(PyFileIOObject *self, PyObject *args) fileio_seek(PyFileIOObject *self, PyObject *args)
{ {
PyObject *posobj; PyObject *posobj;
int whence = 0; int whence = 0;
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence)) if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence))
return NULL; return NULL;
return portable_lseek(self->fd, posobj, whence); return portable_lseek(self->fd, posobj, whence);
} }
static PyObject * static PyObject *
fileio_tell(PyFileIOObject *self, PyObject *args) fileio_tell(PyFileIOObject *self, PyObject *args)
{ {
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
return portable_lseek(self->fd, NULL, 1); return portable_lseek(self->fd, NULL, 1);
} }
#ifdef HAVE_FTRUNCATE #ifdef HAVE_FTRUNCATE
static PyObject * static PyObject *
fileio_truncate(PyFileIOObject *self, PyObject *args) fileio_truncate(PyFileIOObject *self, PyObject *args)
{ {
PyObject *posobj = NULL; /* the new size wanted by the user */ PyObject *posobj = NULL; /* the new size wanted by the user */
#ifndef MS_WINDOWS #ifndef MS_WINDOWS
Py_off_t pos; Py_off_t pos;
#endif #endif
int ret; int ret;
int fd; int fd;
fd = self->fd; fd = self->fd;
if (fd < 0) if (fd < 0)
return err_closed(); return err_closed();
if (!self->writable) if (!self->writable)
return err_mode("writing"); return err_mode("writing");
if (!PyArg_ParseTuple(args, "|O", &posobj)) if (!PyArg_ParseTuple(args, "|O", &posobj))
return NULL; return NULL;
if (posobj == Py_None || posobj == NULL) { if (posobj == Py_None || posobj == NULL) {
/* Get the current position. */ /* Get the current position. */
posobj = portable_lseek(fd, NULL, 1); posobj = portable_lseek(fd, NULL, 1);
if (posobj == NULL) if (posobj == NULL)
return NULL; return NULL;
} }
else { else {
Py_INCREF(posobj); Py_INCREF(posobj);
} }
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
/* MS _chsize doesn't work if newsize doesn't fit in 32 bits, /* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
so don't even try using it. */ so don't even try using it. */
{ {
PyObject *oldposobj, *tempposobj; PyObject *oldposobj, *tempposobj;
HANDLE hFile; HANDLE hFile;
/* we save the file pointer position */ /* we save the file pointer position */
oldposobj = portable_lseek(fd, NULL, 1); oldposobj = portable_lseek(fd, NULL, 1);
if (oldposobj == NULL) { if (oldposobj == NULL) {
Py_DECREF(posobj); Py_DECREF(posobj);
return NULL; return NULL;
} }
/* we then move to the truncation position */ /* we then move to the truncation position */
tempposobj = portable_lseek(fd, posobj, 0); tempposobj = portable_lseek(fd, posobj, 0);
if (tempposobj == NULL) { if (tempposobj == NULL) {
Py_DECREF(oldposobj); Py_DECREF(oldposobj);
Py_DECREF(posobj); Py_DECREF(posobj);
return NULL; return NULL;
} }
Py_DECREF(tempposobj); Py_DECREF(tempposobj);
/* Truncate. Note that this may grow the file! */ /* Truncate. Note that this may grow the file! */
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
errno = 0; errno = 0;
hFile = (HANDLE)_get_osfhandle(fd); hFile = (HANDLE)_get_osfhandle(fd);
ret = hFile == (HANDLE)-1; /* testing for INVALID_HANDLE value */ ret = hFile == (HANDLE)-1; /* testing for INVALID_HANDLE value */
if (ret == 0) { if (ret == 0) {
ret = SetEndOfFile(hFile) == 0; ret = SetEndOfFile(hFile) == 0;
if (ret) if (ret)
errno = EACCES; errno = EACCES;
} }
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
/* we restore the file pointer position in any case */ /* we restore the file pointer position in any case */
tempposobj = portable_lseek(fd, oldposobj, 0); tempposobj = portable_lseek(fd, oldposobj, 0);
Py_DECREF(oldposobj); Py_DECREF(oldposobj);
if (tempposobj == NULL) { if (tempposobj == NULL) {
Py_DECREF(posobj); Py_DECREF(posobj);
return NULL; return NULL;
} }
Py_DECREF(tempposobj); Py_DECREF(tempposobj);
} }
#else #else
#if defined(HAVE_LARGEFILE_SUPPORT) #if defined(HAVE_LARGEFILE_SUPPORT)
pos = PyLong_AsLongLong(posobj); pos = PyLong_AsLongLong(posobj);
#else #else
pos = PyLong_AsLong(posobj); pos = PyLong_AsLong(posobj);
#endif #endif
if (PyErr_Occurred()){ if (PyErr_Occurred()){
Py_DECREF(posobj); Py_DECREF(posobj);
return NULL; return NULL;
} }
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
errno = 0; errno = 0;
ret = ftruncate(fd, pos); ret = ftruncate(fd, pos);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
#endif /* !MS_WINDOWS */ #endif /* !MS_WINDOWS */
if (ret != 0) { if (ret != 0) {
Py_DECREF(posobj); Py_DECREF(posobj);
PyErr_SetFromErrno(PyExc_IOError); PyErr_SetFromErrno(PyExc_IOError);
return NULL; return NULL;
} }
return posobj; return posobj;
} }
#endif /* HAVE_FTRUNCATE */ #endif /* HAVE_FTRUNCATE */
static char * static char *
mode_string(PyFileIOObject *self) mode_string(PyFileIOObject *self)
{ {
if (self->readable) { if (self->readable) {
if (self->writable) if (self->writable)
return "rb+"; return "rb+";
else else
return "rb"; return "rb";
} }
else else
return "wb"; return "wb";
} }
static PyObject * static PyObject *
fileio_repr(PyFileIOObject *self) fileio_repr(PyFileIOObject *self)
{ {
if (self->fd < 0) if (self->fd < 0)
return PyString_FromFormat("_fileio._FileIO(-1)"); return PyString_FromFormat("_fileio._FileIO(-1)");
return PyString_FromFormat("_fileio._FileIO(%d, '%s')", return PyString_FromFormat("_fileio._FileIO(%d, '%s')",
self->fd, mode_string(self)); self->fd, mode_string(self));
} }
static PyObject * static PyObject *
fileio_isatty(PyFileIOObject *self) fileio_isatty(PyFileIOObject *self)
{ {
long res; long res;
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
res = isatty(self->fd); res = isatty(self->fd);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
return PyBool_FromLong(res); return PyBool_FromLong(res);
} }
...@@ -786,7 +786,7 @@ PyDoc_STRVAR(fileio_doc, ...@@ -786,7 +786,7 @@ PyDoc_STRVAR(fileio_doc,
"file(name: str[, mode: str]) -> file IO object\n" "file(name: str[, mode: str]) -> file IO object\n"
"\n" "\n"
"Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n" "Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n"
"writing or appending. The file will be created if it doesn't exist\n" "writing or appending. The file will be created if it doesn't exist\n"
"when opened for writing or appending; it will be truncated when\n" "when opened for writing or appending; it will be truncated when\n"
"opened for writing. Add a '+' to the mode to allow simultaneous\n" "opened for writing. Add a '+' to the mode to allow simultaneous\n"
"reading and writing."); "reading and writing.");
...@@ -828,14 +828,14 @@ PyDoc_STRVAR(seek_doc, ...@@ -828,14 +828,14 @@ PyDoc_STRVAR(seek_doc,
#ifdef HAVE_FTRUNCATE #ifdef HAVE_FTRUNCATE
PyDoc_STRVAR(truncate_doc, PyDoc_STRVAR(truncate_doc,
"truncate([size: int]) -> None. Truncate the file to at most size bytes.\n" "truncate([size: int]) -> None. Truncate the file to at most size bytes.\n"
"\n" "\n"
"Size defaults to the current file position, as returned by tell()." "Size defaults to the current file position, as returned by tell()."
"The current file position is changed to the value of size."); "The current file position is changed to the value of size.");
#endif #endif
PyDoc_STRVAR(tell_doc, PyDoc_STRVAR(tell_doc,
"tell() -> int. Current file position"); "tell() -> int. Current file position");
PyDoc_STRVAR(readinto_doc, PyDoc_STRVAR(readinto_doc,
"readinto() -> Undocumented. Don't use this; it may go away."); "readinto() -> Undocumented. Don't use this; it may go away.");
...@@ -859,22 +859,22 @@ PyDoc_STRVAR(writable_doc, ...@@ -859,22 +859,22 @@ PyDoc_STRVAR(writable_doc,
"writable() -> bool. True if file was opened in a write mode."); "writable() -> bool. True if file was opened in a write mode.");
static PyMethodDef fileio_methods[] = { static PyMethodDef fileio_methods[] = {
{"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc}, {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc},
{"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc}, {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc},
{"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc}, {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc},
{"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc}, {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc},
{"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc}, {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc},
{"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc}, {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc},
#ifdef HAVE_FTRUNCATE #ifdef HAVE_FTRUNCATE
{"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc}, {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc},
#endif #endif
{"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc}, {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc},
{"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc}, {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc},
{"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc}, {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc},
{"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc}, {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc},
{"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc}, {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc},
{"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc}, {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
/* 'closed' and 'mode' are attributes for backwards compatibility reasons. */ /* 'closed' and 'mode' are attributes for backwards compatibility reasons. */
...@@ -882,86 +882,86 @@ static PyMethodDef fileio_methods[] = { ...@@ -882,86 +882,86 @@ static PyMethodDef fileio_methods[] = {
static PyObject * static PyObject *
get_closed(PyFileIOObject *self, void *closure) get_closed(PyFileIOObject *self, void *closure)
{ {
return PyBool_FromLong((long)(self->fd < 0)); return PyBool_FromLong((long)(self->fd < 0));
} }
static PyObject * static PyObject *
get_closefd(PyFileIOObject *self, void *closure) get_closefd(PyFileIOObject *self, void *closure)
{ {
return PyBool_FromLong((long)(self->closefd)); return PyBool_FromLong((long)(self->closefd));
} }
static PyObject * static PyObject *
get_mode(PyFileIOObject *self, void *closure) get_mode(PyFileIOObject *self, void *closure)
{ {
return PyString_FromString(mode_string(self)); return PyString_FromString(mode_string(self));
} }
static PyGetSetDef fileio_getsetlist[] = { static PyGetSetDef fileio_getsetlist[] = {
{"closed", (getter)get_closed, NULL, "True if the file is closed"}, {"closed", (getter)get_closed, NULL, "True if the file is closed"},
{"closefd", (getter)get_closefd, NULL, {"closefd", (getter)get_closefd, NULL,
"True if the file descriptor will be closed"}, "True if the file descriptor will be closed"},
{"mode", (getter)get_mode, NULL, "String giving the file mode"}, {"mode", (getter)get_mode, NULL, "String giving the file mode"},
{0}, {0},
}; };
PyTypeObject PyFileIO_Type = { PyTypeObject PyFileIO_Type = {
PyVarObject_HEAD_INIT(NULL, 0) PyVarObject_HEAD_INIT(NULL, 0)
"_FileIO", "_FileIO",
sizeof(PyFileIOObject), sizeof(PyFileIOObject),
0, 0,
(destructor)fileio_dealloc, /* tp_dealloc */ (destructor)fileio_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
0, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
(reprfunc)fileio_repr, /* tp_repr */ (reprfunc)fileio_repr, /* tp_repr */
0, /* tp_as_number */ 0, /* tp_as_number */
0, /* tp_as_sequence */ 0, /* tp_as_sequence */
0, /* tp_as_mapping */ 0, /* tp_as_mapping */
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
fileio_doc, /* tp_doc */ fileio_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */
offsetof(PyFileIOObject, weakreflist), /* tp_weaklistoffset */ offsetof(PyFileIOObject, weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */ 0, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
fileio_methods, /* tp_methods */ fileio_methods, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
fileio_getsetlist, /* tp_getset */ fileio_getsetlist, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
0, /* tp_dict */ 0, /* tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
0, /* tp_dictoffset */ 0, /* tp_dictoffset */
fileio_init, /* tp_init */ fileio_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */ PyType_GenericAlloc, /* tp_alloc */
fileio_new, /* tp_new */ fileio_new, /* tp_new */
PyObject_Del, /* tp_free */ PyObject_Del, /* tp_free */
}; };
static PyMethodDef module_methods[] = { static PyMethodDef module_methods[] = {
{NULL, NULL} {NULL, NULL}
}; };
PyMODINIT_FUNC PyMODINIT_FUNC
init_fileio(void) init_fileio(void)
{ {
PyObject *m; /* a module object */ PyObject *m; /* a module object */
m = Py_InitModule3("_fileio", module_methods, m = Py_InitModule3("_fileio", module_methods,
"Fast implementation of io.FileIO."); "Fast implementation of io.FileIO.");
if (m == NULL) if (m == NULL)
return; return;
if (PyType_Ready(&PyFileIO_Type) < 0) if (PyType_Ready(&PyFileIO_Type) < 0)
return; return;
Py_INCREF(&PyFileIO_Type); Py_INCREF(&PyFileIO_Type);
PyModule_AddObject(m, "_FileIO", (PyObject *) &PyFileIO_Type); PyModule_AddObject(m, "_FileIO", (PyObject *) &PyFileIO_Type);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment