[Python-checkins] CVS: python/dist/src/Objects fileobject.c,2.125,2.126
Tim Peters
tim_one@users.sourceforge.net
Thu, 13 Sep 2001 20:26:10 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv9095/python/Objects
Modified Files:
fileobject.c
Log Message:
The end of [#460467] file objects should be subclassable.
A surprising number of changes to split tp_new into tp_new and tp_init.
Turned out the older PyFile_FromFile() didn't initialize the memory it
allocated in all (error) cases, which caused new sanity asserts
elsewhere to fail left & right (and could have, e.g., caused file_dealloc
to try decrefing random addresses).
Index: fileobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v
retrieving revision 2.125
retrieving revision 2.126
diff -C2 -d -r2.125 -r2.126
*** fileobject.c 2001/09/13 21:49:44 2.125
--- fileobject.c 2001/09/14 03:26:08 2.126
***************
*** 73,82 ****
assert(f != NULL);
assert(PyFile_Check(f));
! f->f_fp = NULL;
f->f_name = PyString_FromString(name);
f->f_mode = PyString_FromString(mode);
f->f_close = close;
f->f_softspace = 0;
f->f_binary = strchr(mode,'b') != NULL;
if (f->f_name == NULL || f->f_mode == NULL)
return NULL;
--- 73,87 ----
assert(f != NULL);
assert(PyFile_Check(f));
! assert(f->f_fp == NULL);
!
! Py_DECREF(f->f_name);
! Py_DECREF(f->f_mode);
f->f_name = PyString_FromString(name);
f->f_mode = PyString_FromString(mode);
+
f->f_close = close;
f->f_softspace = 0;
f->f_binary = strchr(mode,'b') != NULL;
+
if (f->f_name == NULL || f->f_mode == NULL)
return NULL;
***************
*** 92,95 ****
--- 97,101 ----
assert(name != NULL);
assert(mode != NULL);
+ assert(f->f_fp == NULL);
/* rexec.py can't stop a user from getting the file() constructor --
***************
*** 131,135 ****
PyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *))
{
! PyFileObject *f = PyObject_NEW(PyFileObject, &PyFile_Type);
if (f != NULL) {
if (fill_file_fields(f, fp, name, mode, close) == NULL) {
--- 137,142 ----
PyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *))
{
! PyFileObject *f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type,
! NULL, NULL);
if (f != NULL) {
if (fill_file_fields(f, fp, name, mode, close) == NULL) {
***************
*** 199,209 ****
(*f->f_close)(f->f_fp);
Py_END_ALLOW_THREADS
- }
- if (f->f_name != NULL) {
- Py_DECREF(f->f_name);
- }
- if (f->f_mode != NULL) {
- Py_DECREF(f->f_mode);
}
PyObject_DEL(f);
}
--- 206,212 ----
(*f->f_close)(f->f_fp);
Py_END_ALLOW_THREADS
}
+ Py_XDECREF(f->f_name);
+ Py_XDECREF(f->f_mode);
PyObject_DEL(f);
}
***************
*** 1329,1361 ****
file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
! /* XXX As for all XXX_new functions, file_new is called
! with kwds=NULL by type_call(), so the kwlist is impotent. */
static char *kwlist[] = {"name", "mode", "buffering", 0};
char *name = NULL;
char *mode = "r";
int bufsize = -1;
- PyObject *f;
- extern int fclose(FILE *);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,
Py_FileSystemDefaultEncoding, &name,
&mode, &bufsize))
! return NULL;
! f = PyType_GenericAlloc(type, 0);
! if (f != NULL) {
! PyFileObject *g = (PyFileObject *)f;
! if (fill_file_fields(g, NULL, name, mode, fclose) == NULL) {
! Py_DECREF(f);
! f = NULL;
! }
! if (f != NULL && open_the_file(g, name, mode) == NULL) {
! Py_DECREF(f);
! f = NULL;
! }
! if (f != NULL)
! PyFile_SetBufSize(f, bufsize);
! }
PyMem_Free(name); /* free the encoded string */
! return f;
}
--- 1332,1394 ----
file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
! PyObject *self;
! static PyObject *not_yet_string;
!
! assert(type != NULL && type->tp_alloc != NULL);
!
! if (not_yet_string == NULL) {
! not_yet_string = PyString_FromString("<uninitialized file>");
! if (not_yet_string == NULL)
! return NULL;
! }
!
! self = type->tp_alloc(type, 0);
! if (self != NULL) {
! /* Always fill in the name and mode, so that nobody else
! needs to special-case NULLs there. */
! Py_INCREF(not_yet_string);
! ((PyFileObject *)self)->f_name = not_yet_string;
! Py_INCREF(not_yet_string);
! ((PyFileObject *)self)->f_mode = not_yet_string;
! }
! return self;
! }
!
! static int
! file_init(PyObject *self, PyObject *args, PyObject *kwds)
! {
! PyFileObject *foself = (PyFileObject *)self;
! int ret = 0;
static char *kwlist[] = {"name", "mode", "buffering", 0};
char *name = NULL;
char *mode = "r";
int bufsize = -1;
+ assert(PyFile_Check(self));
+ if (foself->f_fp != NULL) {
+ /* Have to close the existing file first. */
+ PyObject *closeresult = file_close(foself);
+ if (closeresult == NULL)
+ return -1;
+ Py_DECREF(closeresult);
+ }
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,
Py_FileSystemDefaultEncoding, &name,
&mode, &bufsize))
! return -1;
! if (fill_file_fields(foself, NULL, name, mode, fclose) == NULL)
! goto Error;
! if (open_the_file(foself, name, mode) == NULL)
! goto Error;
! PyFile_SetBufSize(self, bufsize);
! goto Done;
!
! Error:
! ret = -1;
! /* fall through */
! Done:
PyMem_Free(name); /* free the encoded string */
! return ret;
}
***************
*** 1410,1415 ****
0, /* tp_descr_set */
0, /* tp_dictoffset */
! 0, /* tp_init */
! 0, /* tp_alloc */
file_new, /* tp_new */
};
--- 1443,1448 ----
0, /* tp_descr_set */
0, /* tp_dictoffset */
! (initproc)file_init, /* tp_init */
! PyType_GenericAlloc, /* tp_alloc */
file_new, /* tp_new */
};