2487 lines · 62.3 KB · C
RawDownload
		/* 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();	drop_readahead(f);	whence = 0;	if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &whence))		return NULL;#if !defined(HAVE_LARGEFILE_SUPPORT)	offset = PyInt_AsLong(offobj);#else	if(PyLong_Check(offobj))		offset = PyLong_AsLongLong(offobj);	else		offset = 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;	}	f->f_skipnextlf = 0;	Py_INCREF(Py_None);	return Py_None;}  #ifdef HAVE_FTRUNCATEstatic PyObject *file_truncate(PyFileObject *f, PyObject *args){	Py_off_t newsize;	PyObject *newsizeobj = NULL;	Py_off_t initialpos;	int ret; 	if (f->f_fp == NULL)		return err_closed();	if (!PyArg_UnpackTuple(args, "truncate", 0, 1, &newsizeobj))		return NULL; 	/* Get current file position.  If the file happens to be open for	 * update and the last operation was an input operation, C doesn't	 * define what the later fflush() will do, but we promise truncate()	 * won't change the current position (and fflush() *does* change it	 * then at least on Windows).  The easiest thing is to capture	 * current pos now and seek back to it at the end.	 */	Py_BEGIN_ALLOW_THREADS	errno = 0;	initialpos = _portable_ftell(f->f_fp);	Py_END_ALLOW_THREADS	if (initialpos == -1)		goto onioerror; 	/* Set newsize to current postion if newsizeobj NULL, else to the	 * specified value.	 */	if (newsizeobj != NULL) {#if !defined(HAVE_LARGEFILE_SUPPORT)		newsize = PyInt_AsLong(newsizeobj);#else		if(PyLong_Check(newsizeobj))			newsize = PyLong_AsLongLong(newsizeobj);		else			newsize = PyInt_AsLong(newsizeobj);#endif		if (PyErr_Occurred())			return NULL;	}	else /* default to current position */		newsize = initialpos; 	/* Flush the stream.  We're mixing stream-level I/O with lower-level	 * I/O, and a flush may be necessary to synch both platform views	 * of the current file state.	 */	Py_BEGIN_ALLOW_THREADS	errno = 0;	ret = fflush(f->f_fp);	Py_END_ALLOW_THREADS	if (ret != 0)		goto onioerror; #ifdef MS_WINDOWS	/* MS _chsize doesn't work if newsize doesn't fit in 32 bits,	   so don't even try using it. */	{		HANDLE hFile; 		/* Have to move current pos to desired endpoint on Windows. */		Py_BEGIN_ALLOW_THREADS		errno = 0;		ret = _portable_fseek(f->f_fp, newsize, SEEK_SET) != 0;		Py_END_ALLOW_THREADS		if (ret)			goto onioerror; 		/* Truncate.  Note that this may grow the file! */		Py_BEGIN_ALLOW_THREADS		errno = 0;		hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp));		ret = hFile == (HANDLE)-1;		if (ret == 0) {			ret = SetEndOfFile(hFile) == 0;			if (ret)				errno = EACCES;		}		Py_END_ALLOW_THREADS		if (ret)			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_WINDOWS */ 	/* Restore original file position. */	Py_BEGIN_ALLOW_THREADS	errno = 0;	ret = _portable_fseek(f->f_fp, initialpos, SEEK_SET) != 0;	Py_END_ALLOW_THREADS	if (ret)		goto onioerror; 	Py_INCREF(Py_None);	return Py_None; onioerror:	PyErr_SetFromErrno(PyExc_IOError);	clearerr(f->f_fp);	return NULL;}#endif /* HAVE_FTRUNCATE */ static PyObject *file_tell(PyFileObject *f){	Py_off_t pos; 	if (f->f_fp == NULL)		return err_closed();	Py_BEGIN_ALLOW_THREADS	errno = 0;	pos = _portable_ftell(f->f_fp);	Py_END_ALLOW_THREADS	if (pos == -1) {		PyErr_SetFromErrno(PyExc_IOError);		clearerr(f->f_fp);		return NULL;	}	if (f->f_skipnextlf) {		int c;		c = GETC(f->f_fp);		if (c == '\n') {			pos++;			f->f_skipnextlf = 0;		} else if (c != EOF) ungetc(c, f->f_fp);	}#if !defined(HAVE_LARGEFILE_SUPPORT)	return PyInt_FromLong(pos);#else	return PyLong_FromLongLong(pos);#endif} static PyObject *file_fileno(PyFileObject *f){	if (f->f_fp == NULL)		return err_closed();	return PyInt_FromLong((long) fileno(f->f_fp));} static PyObject *file_flush(PyFileObject *f){	int res; 	if (f->f_fp == NULL)		return err_closed();	Py_BEGIN_ALLOW_THREADS	errno = 0;	res = fflush(f->f_fp);	Py_END_ALLOW_THREADS	if (res != 0) {		PyErr_SetFromErrno(PyExc_IOError);		clearerr(f->f_fp);		return NULL;	}	Py_INCREF(Py_None);	return Py_None;} static PyObject *file_isatty(PyFileObject *f){	long res;	if (f->f_fp == NULL)		return err_closed();	Py_BEGIN_ALLOW_THREADS	res = isatty((int)fileno(f->f_fp));	Py_END_ALLOW_THREADS	return PyBool_FromLong(res);}  #if BUFSIZ < 8192#define SMALLCHUNK 8192#else#define SMALLCHUNK BUFSIZ#endif #if SIZEOF_INT < 4#define BIGCHUNK  (512 * 32)#else#define BIGCHUNK  (512 * 1024)#endif static size_tnew_buffersize(PyFileObject *f, size_t currentsize){#ifdef HAVE_FSTAT	off_t pos, end;	struct stat st;	if (fstat(fileno(f->f_fp), &st) == 0) {		end = st.st_size;		/* The following is not a bug: we really need to call lseek()		   *and* ftell().  The reason is that some stdio libraries		   mistakenly flush their buffer when ftell() is called and		   the lseek() call it makes fails, thereby throwing away		   data that cannot be recovered in any way.  To avoid this,		   we first test lseek(), and only call ftell() if lseek()		   works.  We can't use the lseek() value either, because we		   need to take the amount of buffered data into account.		   (Yet another reason why stdio stinks. :-) */		pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR);		if (pos >= 0) {			pos = ftell(f->f_fp);		}		if (pos < 0)			clearerr(f->f_fp);		if (end > pos && pos >= 0)			return currentsize + end - pos + 1;		/* Add 1 so if the file were to grow we'd notice. */	}#endif	if (currentsize > SMALLCHUNK) {		/* Keep doubling until we reach BIGCHUNK;		   then keep adding BIGCHUNK. */		if (currentsize <= BIGCHUNK)			return currentsize + currentsize;		else			return currentsize + BIGCHUNK;	}	return currentsize + SMALLCHUNK;} #if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK || (x) == EAGAIN)#else#ifdef EWOULDBLOCK#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK)#else#ifdef EAGAIN#define BLOCKED_ERRNO(x) ((x) == EAGAIN)#else#define BLOCKED_ERRNO(x) 0#endif#endif#endif static PyObject *file_read(PyFileObject *f, PyObject *args){	long bytesrequested = -1;	size_t bytesread, buffersize, chunksize;	PyObject *v; 	if (f->f_fp == NULL)		return err_closed();	/* refuse to mix with f.next() */	if (f->f_buf != NULL &&	    (f->f_bufend - f->f_bufptr) > 0 &&	    f->f_buf[0] != '\0')		return err_iterbuffered();	if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))		return NULL;	if (bytesrequested < 0)		buffersize = new_buffersize(f, (size_t)0);	else		buffersize = bytesrequested;	if (buffersize > PY_SSIZE_T_MAX) {		PyErr_SetString(PyExc_OverflowError,	"requested number of bytes is more than a Python string can hold");		return NULL;	}	v = PyString_FromStringAndSize((char *)NULL, buffersize);	if (v == NULL)		return NULL;	bytesread = 0;	for (;;) {		Py_BEGIN_ALLOW_THREADS		errno = 0;		chunksize = Py_UniversalNewlineFread(BUF(v) + bytesread,			  buffersize - bytesread, f->f_fp, (PyObject *)f);		Py_END_ALLOW_THREADS		if (chunksize == 0) {			if (!ferror(f->f_fp))				break;			clearerr(f->f_fp);			/* When in non-blocking mode, data shouldn't			 * be discarded if a blocking signal was			 * received. That will also happen if			 * chunksize != 0, but bytesread < buffersize. */			if (bytesread > 0 && BLOCKED_ERRNO(errno))				break;			PyErr_SetFromErrno(PyExc_IOError);			Py_DECREF(v);			return NULL;		}		bytesread += chunksize;		if (bytesread < buffersize) {			clearerr(f->f_fp);			break;		}		if (bytesrequested < 0) {			buffersize = new_buffersize(f, buffersize);			if (_PyString_Resize(&v, buffersize) < 0)				return NULL;		} else {			/* Got what was requested. */			break;		}	}	if (bytesread != buffersize)		_PyString_Resize(&v, bytesread);	return v;} static PyObject *file_readinto(PyFileObject *f, PyObject *args){	char *ptr;	Py_ssize_t ntodo;	Py_ssize_t ndone, nnow; 	if (f->f_fp == NULL)		return err_closed();	/* refuse to mix with f.next() */	if (f->f_buf != NULL &&	    (f->f_bufend - f->f_bufptr) > 0 &&	    f->f_buf[0] != '\0')		return err_iterbuffered();	if (!PyArg_ParseTuple(args, "w#", &ptr, &ntodo))		return NULL;	ndone = 0;	while (ntodo > 0) {		Py_BEGIN_ALLOW_THREADS		errno = 0;		nnow = Py_UniversalNewlineFread(ptr+ndone, ntodo, f->f_fp,						(PyObject *)f);		Py_END_ALLOW_THREADS		if (nnow == 0) {			if (!ferror(f->f_fp))				break;			PyErr_SetFromErrno(PyExc_IOError);			clearerr(f->f_fp);			return NULL;		}		ndone += nnow;		ntodo -= nnow;	}	return PyInt_FromSsize_t(ndone);} /**************************************************************************Routine to get next line using platform fgets(). Under MSVC 6: + MS threadsafe getc is very slow (multiple layers of function calls before+  after each character, to lock+unlock the stream).+ The stream-locking functions are MS-internal -- can't access them from user  code.+ There's nothing Tim could find in the MS C or platform SDK libraries that  can worm around this.+ MS fgets locks/unlocks only once per line; it's the only hook we have. So we use fgets for speed(!), despite that it's painful. MS realloc is also slow. Reports from other platforms on this method vs getc_unlocked (which MS doesn'thave):	Linux		a wash	Solaris		a wash	Tru64 Unix	getline_via_fgets significantly faster CAUTION:  The C std isn't clear about this:  in those cases where fgetswrites something into the buffer, can it write into any position beyond therequired trailing null byte?  MSVC 6 fgets does not, and no platform is (yet)known on which it does; and it would be a strange way to code fgets. Still,getline_via_fgets may not work correctly if it does.  The std testtest_bufio.py should fail if platform fgets() routinely writes beyond thetrailing null byte.  #define DONT_USE_FGETS_IN_GETLINE to disable this code.**************************************************************************/ /* Use this routine if told to, or by default on non-get_unlocked() * platforms unless told not to.  Yikes!  Let's spell that out: * On a platform with getc_unlocked(): *     By default, use getc_unlocked(). *     If you want to use fgets() instead, #define USE_FGETS_IN_GETLINE. * On a platform without getc_unlocked(): *     By default, use fgets(). *     If you don't want to use fgets(), #define DONT_USE_FGETS_IN_GETLINE. */#if !defined(USE_FGETS_IN_GETLINE) && !defined(HAVE_GETC_UNLOCKED)#define USE_FGETS_IN_GETLINE#endif #if defined(DONT_USE_FGETS_IN_GETLINE) && defined(USE_FGETS_IN_GETLINE)#undef USE_FGETS_IN_GETLINE#endif #ifdef USE_FGETS_IN_GETLINEstatic PyObject*getline_via_fgets(FILE *fp){/* INITBUFSIZE is the maximum line length that lets us get away with the fast * no-realloc, one-fgets()-call path.  Boosting it isn't free, because we have * to fill this much of the buffer with a known value in order to figure out * how much of the buffer fgets() overwrites.  So if INITBUFSIZE is larger * than "most" lines, we waste time filling unused buffer slots.  100 is * surely adequate for most peoples' email archives, chewing over source code, * etc -- "regular old text files". * MAXBUFSIZE is the maximum line length that lets us get away with the less * fast (but still zippy) no-realloc, two-fgets()-call path.  See above for * cautions about boosting that.  300 was chosen because the worst real-life * text-crunching job reported on Python-Dev was a mail-log crawler where over * half the lines were 254 chars. */#define INITBUFSIZE 100#define MAXBUFSIZE 300

Lines 501–1000 of 2487. Previous lines