⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileobject.c

📁 python s60 1.4.5版本的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Portions Copyright (c) 2005 Nokia Corporation */

/* File object implementation */

#include "Python.h"
#include "structmember.h"

#ifndef DONT_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* DONT_HAVE_SYS_TYPES_H */

#ifdef MS_WIN32
#define fileno _fileno
/* can (almost fully) duplicate with _chsize, see file_truncate */
#define HAVE_FTRUNCATE
#endif

#ifdef macintosh
#ifdef USE_GUSI
#define HAVE_FTRUNCATE
#endif
#endif

#ifdef __MWERKS__
/* Mwerks fopen() doesn't always set errno */
#define NO_FOPEN_ERRNO
#endif

#define BUF(v) PyString_AS_STRING((PyStringObject *)v)

#ifndef DONT_HAVE_ERRNO_H
#include <errno.h>
#endif


typedef struct {
	PyObject_HEAD
	FILE *f_fp;
	PyObject *f_name;
	PyObject *f_mode;
	int (*f_close)(FILE *);
	int f_softspace; /* Flag used by 'print' command */
	int f_binary; /* Flag which indicates whether the file is open
			 open in binary (1) or test (0) mode */
} PyFileObject;

DL_EXPORT(FILE *)
PyFile_AsFile(PyObject *f)
{
	if (f == NULL || !PyFile_Check(f))
		return NULL;
	else
		return ((PyFileObject *)f)->f_fp;
}

DL_EXPORT(PyObject *)
PyFile_Name(PyObject *f)
{
	if (f == NULL || !PyFile_Check(f))
		return NULL;
	else
		return ((PyFileObject *)f)->f_name;
}


static PyObject *
fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode,
		 int (*close)(FILE *))
{
	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;
	f->f_fp = fp;
	return (PyObject *) f;
}

static PyObject *
open_the_file(PyFileObject *f, char *name, char *mode)
{
	assert(f != NULL);
	assert(PyFile_Check(f));
	assert(name != NULL);
	assert(mode != NULL);
	assert(f->f_fp == NULL);

	/* rexec.py can't stop a user from getting the file() constructor --
	   all they have to do is get *any* file object f, and then do
	   type(f).  Here we prevent them from doing damage with it. */
	if (PyEval_GetRestricted()) {
		PyErr_SetString(PyExc_IOError,
			"file() constructor not accessible in restricted mode");
		return NULL;
	}
	errno = 0;
#ifdef HAVE_FOPENRF
	if (*mode == '*') {
		FILE *fopenRF();
		f->f_fp = fopenRF(name, mode+1);
	}
	else
#endif
	{
#ifdef SYMBIAN
		/* Remove the eventual 'b' from mode to compensate for a bug
		   in Symbian OS STDLIB implementation. */
		char tmp_mode[8];
		char* t = tmp_mode;
		char* p = mode;
		while (*p && (t < (tmp_mode+7))) {
			if (*p != 'b') *t++ = *p;
			p++;
		}
		*t = '\0';
#endif
		Py_BEGIN_ALLOW_THREADS
#ifdef SYMBIAN
		f->f_fp = fopen(name, tmp_mode);
#else
		f->f_fp = fopen(name, mode);
#endif
		Py_END_ALLOW_THREADS
	}
	if (f->f_fp == NULL) {
#ifdef NO_FOPEN_ERRNO
		/* Metroworks only, wich does not always sets errno */
		if (errno == 0) {
			PyObject *v;
			v = Py_BuildValue("(is)", 0, "Cannot open file");
			if (v != NULL) {
				PyErr_SetObject(PyExc_IOError, v);
				Py_DECREF(v);
			}
			return NULL;
		}
#endif
#ifdef _MSC_VER
		/* MSVC 6 (Microsoft) leaves errno at 0 for bad mode strings,
		 * across all Windows flavors.  When it sets EINVAL varies
		 * across Windows flavors, the exact conditions aren't
		 * documented, and the answer lies in the OS's implementation
		 * of Win32's CreateFile function (whose source is secret).
		 * Seems the best we can do is map EINVAL to ENOENT.
		 */
		if (errno == 0)	/* bad mode string */
			errno = EINVAL;
		else if (errno == EINVAL) /* unknown, but not a mode string */
			errno = ENOENT;
#endif
		if (errno == EINVAL)
			PyErr_Format(PyExc_IOError, "invalid mode: %s",
				     mode);
		else
			PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
		f = NULL;
	}
	return (PyObject *)f;
}

DL_EXPORT(PyObject *)
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) {
			Py_DECREF(f);
			f = NULL;
		}
	}
	return (PyObject *) f;
}

DL_EXPORT(PyObject *)
PyFile_FromString(char *name, char *mode)
{
	extern int fclose(FILE *);
	PyFileObject *f;

	f = (PyFileObject *)PyFile_FromFile((FILE *)NULL, name, mode, fclose);
	if (f != NULL) {
		if (open_the_file(f, name, mode) == NULL) {
			Py_DECREF(f);
			f = NULL;
		}
	}
	return (PyObject *)f;
}

DL_EXPORT(void)
PyFile_SetBufSize(PyObject *f, int bufsize)
{
	if (bufsize >= 0) {
#ifdef HAVE_SETVBUF
		int type;
		switch (bufsize) {
		case 0:
			type = _IONBF;
			break;
		case 1:
			type = _IOLBF;
			bufsize = BUFSIZ;
			break;
		default:
			type = _IOFBF;
		}
		setvbuf(((PyFileObject *)f)->f_fp, (char *)NULL,
			type, bufsize);
#else /* !HAVE_SETVBUF */
		if (bufsize <= 1)
			setbuf(((PyFileObject *)f)->f_fp, (char *)NULL);
#endif /* !HAVE_SETVBUF */
	}
}

static PyObject *
err_closed(void)
{
	PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
	return NULL;
}

/* Methods */

static void
file_dealloc(PyFileObject *f)
{
	if (f->f_fp != NULL && f->f_close != NULL) {
		Py_BEGIN_ALLOW_THREADS
		(*f->f_close)(f->f_fp);
		Py_END_ALLOW_THREADS
	}
	Py_XDECREF(f->f_name);
	Py_XDECREF(f->f_mode);
	f->ob_type->tp_free((PyObject *)f);
}

static PyObject *
file_repr(PyFileObject *f)
{
	return PyString_FromFormat("<%s file '%s', mode '%s' at %p>",
				   f->f_fp == NULL ? "closed" : "open",
				   PyString_AsString(f->f_name),
				   PyString_AsString(f->f_mode),
				   f);
}

static PyObject *
file_close(PyFileObject *f)
{
	int sts = 0;
	if (f->f_fp != NULL) {
		if (f->f_close != NULL) {
			Py_BEGIN_ALLOW_THREADS
			errno = 0;
			sts = (*f->f_close)(f->f_fp);
			Py_END_ALLOW_THREADS
		}
		f->f_fp = NULL;
	}
	if (sts == EOF)
		return PyErr_SetFromErrno(PyExc_IOError);
	if (sts != 0)
		return PyInt_FromLong((long)sts);
	Py_INCREF(Py_None);
	return Py_None;
}


/* Our very own off_t-like type, 64-bit if possible */
#if !defined(HAVE_LARGEFILE_SUPPORT)
typedef off_t Py_off_t;
#elif SIZEOF_OFF_T >= 8
typedef off_t Py_off_t;
#elif SIZEOF_FPOS_T >= 8
typedef fpos_t Py_off_t;
#else
#error "Large file support, but neither off_t nor fpos_t is large enough."
#endif


/* a portable fseek() function
   return 0 on success, non-zero on failure (with errno set) */
static int
_portable_fseek(FILE *fp, Py_off_t offset, int whence)
{
#if !defined(HAVE_LARGEFILE_SUPPORT)
	return fseek(fp, offset, whence);
#elif defined(HAVE_FSEEKO) && SIZEOF_OFF_T >= 8
	return fseeko(fp, offset, whence);
#elif defined(HAVE_FSEEK64)
	return fseek64(fp, offset, whence);
#elif defined(__BEOS__)
	return _fseek(fp, offset, whence);
#elif SIZEOF_FPOS_T >= 8
	/* lacking a 64-bit capable fseek(), use a 64-bit capable fsetpos()
	   and fgetpos() to implement fseek()*/
	fpos_t pos;
	switch (whence) {
	case SEEK_END:
#ifdef MS_WINDOWS
		fflush(fp);
		if (_lseeki64(fileno(fp), 0, 2) == -1)
			return -1;
#else
		if (fseek(fp, 0, SEEK_END) != 0)
			return -1;
#endif
		/* fall through */
	case SEEK_CUR:
		if (fgetpos(fp, &pos) != 0)
			return -1;
		offset += pos;
		break;
	/* case SEEK_SET: break; */
	}
	return fsetpos(fp, &offset);
#else
#error "Large file support, but no way to fseek."
#endif
}


/* a portable ftell() function
   Return -1 on failure with errno set appropriately, current file
   position on success */
static Py_off_t
_portable_ftell(FILE* fp)
{
#if !defined(HAVE_LARGEFILE_SUPPORT)
	return ftell(fp);
#elif defined(HAVE_FTELLO) && SIZEOF_OFF_T >= 8
	return ftello(fp);
#elif defined(HAVE_FTELL64)
	return ftell64(fp);
#elif SIZEOF_FPOS_T >= 8
	fpos_t pos;
	if (fgetpos(fp, &pos) != 0)
		return -1;
	return pos;
#else
#error "Large file support, but no way to ftell."
#endif
}


static PyObject *
file_seek(PyFileObject *f, PyObject *args)
{
	int whence;
	int ret;
	Py_off_t offset;
	PyObject *offobj;

	if (f->f_fp == NULL)
		return err_closed();
	whence = 0;
	if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &whence))
		return NULL;
#if !defined(HAVE_LARGEFILE_SUPPORT)
	offset = PyInt_AsLong(offobj);
#else
	offset = PyLong_Check(offobj) ?
		PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
#endif
	if (PyErr_Occurred())
		return NULL;

	Py_BEGIN_ALLOW_THREADS
	errno = 0;
	ret = _portable_fseek(f->f_fp, offset, whence);
	Py_END_ALLOW_THREADS

	if (ret != 0) {
		PyErr_SetFromErrno(PyExc_IOError);
		clearerr(f->f_fp);
		return NULL;
	}
	Py_INCREF(Py_None);
	return Py_None;
}


#ifdef HAVE_FTRUNCATE
static PyObject *
file_truncate(PyFileObject *f, PyObject *args)
{
	int ret;
	Py_off_t newsize;
	PyObject *newsizeobj;

	if (f->f_fp == NULL)
		return err_closed();
	newsizeobj = NULL;
	if (!PyArg_ParseTuple(args, "|O:truncate", &newsizeobj))
		return NULL;
	if (newsizeobj != NULL) {
#if !defined(HAVE_LARGEFILE_SUPPORT)
		newsize = PyInt_AsLong(newsizeobj);
#else
		newsize = PyLong_Check(newsizeobj) ?
				PyLong_AsLongLong(newsizeobj) :
				PyInt_AsLong(newsizeobj);
#endif
		if (PyErr_Occurred())
			return NULL;
	} else {
		/* Default to current position*/
		Py_BEGIN_ALLOW_THREADS
		errno = 0;
		newsize = _portable_ftell(f->f_fp);
		Py_END_ALLOW_THREADS
		if (newsize == -1) {
		        PyErr_SetFromErrno(PyExc_IOError);
			clearerr(f->f_fp);
			return NULL;
		}
	}
	Py_BEGIN_ALLOW_THREADS
	errno = 0;
	ret = fflush(f->f_fp);
	Py_END_ALLOW_THREADS
	if (ret != 0) goto onioerror;

#ifdef MS_WIN32
	/* can use _chsize; if, however, the newsize overflows 32-bits then
	   _chsize is *not* adequate; in this case, an OverflowError is raised */
	if (newsize > LONG_MAX) {
		PyErr_SetString(PyExc_OverflowError,
			"the new size is too long for _chsize (it is limited to 32-bit values)");
		return NULL;
	} else {
		Py_BEGIN_ALLOW_THREADS
		errno = 0;
		ret = _chsize(fileno(f->f_fp), (long)newsize);
		Py_END_ALLOW_THREADS
		if (ret != 0) goto onioerror;
	}
#else
	Py_BEGIN_ALLOW_THREADS
	errno = 0;
	ret = ftruncate(fileno(f->f_fp), newsize);
	Py_END_ALLOW_THREADS
	if (ret != 0) goto onioerror;
#endif /* !MS_WIN32 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -