fileobject.c 22.8 KB
Newer Older
1
/***********************************************************
2 3
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.
4 5 6

                        All Rights Reserved

7 8
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
9
provided that the above copyright notice appear in all copies and that
10
both that copyright notice and this permission notice appear in
11
supporting documentation, and that the names of Stichting Mathematisch
12 13 14 15
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
16

17 18 19 20 21 22 23 24 25 26 27 28
While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
29 30 31

******************************************************************/

Guido van Rossum's avatar
Guido van Rossum committed
32 33
/* File object implementation */

34
#include "Python.h"
35
#include "structmember.h"
Guido van Rossum's avatar
Guido van Rossum committed
36

37 38
#include <sys/types.h>

Guido van Rossum's avatar
Guido van Rossum committed
39 40 41 42
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

43 44 45 46 47 48
#ifdef MS_WIN32
#define ftruncate _chsize
#define fileno _fileno
#define HAVE_FTRUNCATE
#endif

49 50 51 52 53 54
#ifdef macintosh
#ifdef USE_GUSI
#define HAVE_FTRUNCATE
#endif
#endif

55 56 57
#ifdef THINK_C
#define HAVE_FOPENRF
#endif
58 59 60 61
#ifdef __MWERKS__
/* Mwerks fopen() doesn't always set errno */
#define NO_FOPEN_ERRNO
#endif
62

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

65
#include <errno.h>
Guido van Rossum's avatar
Guido van Rossum committed
66 67

typedef struct {
68
	PyObject_HEAD
Guido van Rossum's avatar
Guido van Rossum committed
69
	FILE *f_fp;
70 71 72
	PyObject *f_name;
	PyObject *f_mode;
	int (*f_close) Py_PROTO((FILE *));
73
	int f_softspace; /* Flag used by 'print' command */
74
} PyFileObject;
Guido van Rossum's avatar
Guido van Rossum committed
75 76

FILE *
77 78
PyFile_AsFile(f)
	PyObject *f;
Guido van Rossum's avatar
Guido van Rossum committed
79
{
80
	if (f == NULL || !PyFile_Check(f))
Guido van Rossum's avatar
Guido van Rossum committed
81
		return NULL;
82
	else
83
		return ((PyFileObject *)f)->f_fp;
Guido van Rossum's avatar
Guido van Rossum committed
84 85
}

86 87 88
PyObject *
PyFile_Name(f)
	PyObject *f;
89
{
90
	if (f == NULL || !PyFile_Check(f))
91 92
		return NULL;
	else
93
		return ((PyFileObject *)f)->f_name;
94 95
}

96 97
PyObject *
PyFile_FromFile(fp, name, mode, close)
Guido van Rossum's avatar
Guido van Rossum committed
98 99 100
	FILE *fp;
	char *name;
	char *mode;
101
	int (*close) Py_FPROTO((FILE *));
Guido van Rossum's avatar
Guido van Rossum committed
102
{
103
	PyFileObject *f = PyObject_NEW(PyFileObject, &PyFile_Type);
Guido van Rossum's avatar
Guido van Rossum committed
104 105 106
	if (f == NULL)
		return NULL;
	f->f_fp = NULL;
107 108
	f->f_name = PyString_FromString(name);
	f->f_mode = PyString_FromString(mode);
109
	f->f_close = close;
110
	f->f_softspace = 0;
Guido van Rossum's avatar
Guido van Rossum committed
111
	if (f->f_name == NULL || f->f_mode == NULL) {
112
		Py_DECREF(f);
Guido van Rossum's avatar
Guido van Rossum committed
113 114 115
		return NULL;
	}
	f->f_fp = fp;
116
	return (PyObject *) f;
Guido van Rossum's avatar
Guido van Rossum committed
117 118
}

119 120
PyObject *
PyFile_FromString(name, mode)
Guido van Rossum's avatar
Guido van Rossum committed
121 122
	char *name, *mode;
{
123 124 125
	extern int fclose Py_PROTO((FILE *));
	PyFileObject *f;
	f = (PyFileObject *) PyFile_FromFile((FILE *)NULL, name, mode, fclose);
Guido van Rossum's avatar
Guido van Rossum committed
126 127
	if (f == NULL)
		return NULL;
128
#ifdef HAVE_FOPENRF
129 130 131 132 133 134
	if (*mode == '*') {
		FILE *fopenRF();
		f->f_fp = fopenRF(name, mode+1);
	}
	else
#endif
Guido van Rossum's avatar
Guido van Rossum committed
135
	{
136
		Py_BEGIN_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
137
		f->f_fp = fopen(name, mode);
138
		Py_END_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
139
	}
140
	if (f->f_fp == NULL) {
141
#ifdef NO_FOPEN_ERRNO
142
		/* Metroworks only, not testable, so unchanged */
143
		if ( errno == 0 ) {
144 145
			PyErr_SetString(PyExc_IOError, "Cannot open file");
			Py_DECREF(f);
146 147 148
			return NULL;
		}
#endif
149
		PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
150
		Py_DECREF(f);
Guido van Rossum's avatar
Guido van Rossum committed
151 152
		return NULL;
	}
153
	return (PyObject *)f;
Guido van Rossum's avatar
Guido van Rossum committed
154 155
}

156
void
157 158
PyFile_SetBufSize(f, bufsize)
	PyObject *f;
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
	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;
		}
175 176
		setvbuf(((PyFileObject *)f)->f_fp, (char *)NULL,
			type, bufsize);
177 178 179 180
#else /* !HAVE_SETVBUF */
		if (bufsize <= 1)
			setbuf(((PyFileObject *)f)->f_fp, (char *)NULL);
#endif /* !HAVE_SETVBUF */
181 182 183
	}
}

184
static PyObject *
185 186
err_closed()
{
187
	PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
188 189 190
	return NULL;
}

Guido van Rossum's avatar
Guido van Rossum committed
191 192 193
/* Methods */

static void
Guido van Rossum's avatar
Guido van Rossum committed
194
file_dealloc(f)
195
	PyFileObject *f;
Guido van Rossum's avatar
Guido van Rossum committed
196
{
Guido van Rossum's avatar
Guido van Rossum committed
197
	if (f->f_fp != NULL && f->f_close != NULL) {
198
		Py_BEGIN_ALLOW_THREADS
199
		(*f->f_close)(f->f_fp);
200
		Py_END_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
201
	}
202
	if (f->f_name != NULL) {
203
		Py_DECREF(f->f_name);
204 205
	}
	if (f->f_mode != NULL) {
206
		Py_DECREF(f->f_mode);
207
	}
Guido van Rossum's avatar
Guido van Rossum committed
208 209 210
	free((char *)f);
}

211
static PyObject *
Guido van Rossum's avatar
Guido van Rossum committed
212
file_repr(f)
213
	PyFileObject *f;
Guido van Rossum's avatar
Guido van Rossum committed
214 215
{
	char buf[300];
216
	sprintf(buf, "<%s file '%.256s', mode '%.10s' at %lx>",
Guido van Rossum's avatar
Guido van Rossum committed
217
		f->f_fp == NULL ? "closed" : "open",
218 219
		PyString_AsString(f->f_name),
		PyString_AsString(f->f_mode),
220
		(long)f);
221
	return PyString_FromString(buf);
Guido van Rossum's avatar
Guido van Rossum committed
222 223
}

224
static PyObject *
Guido van Rossum's avatar
Guido van Rossum committed
225
file_close(f, args)
226 227
	PyFileObject *f;
	PyObject *args;
Guido van Rossum's avatar
Guido van Rossum committed
228
{
229
	int sts = 0;
230
	if (!PyArg_NoArgs(args))
Guido van Rossum's avatar
Guido van Rossum committed
231 232
		return NULL;
	if (f->f_fp != NULL) {
Guido van Rossum's avatar
Guido van Rossum committed
233
		if (f->f_close != NULL) {
234
			Py_BEGIN_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
235
			errno = 0;
236
			sts = (*f->f_close)(f->f_fp);
237
			Py_END_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
238
		}
Guido van Rossum's avatar
Guido van Rossum committed
239 240
		f->f_fp = NULL;
	}
241
	if (sts == EOF)
242
		return PyErr_SetFromErrno(PyExc_IOError);
243
	if (sts != 0)
244 245 246
		return PyInt_FromLong((long)sts);
	Py_INCREF(Py_None);
	return Py_None;
Guido van Rossum's avatar
Guido van Rossum committed
247 248
}

249
static PyObject *
250
file_seek(f, args)
251 252
	PyFileObject *f;
	PyObject *args;
Guido van Rossum's avatar
Guido van Rossum committed
253
{
254
	int whence;
Guido van Rossum's avatar
Guido van Rossum committed
255
	int ret;
256 257
	off_t offset;
	PyObject *offobj;
258
	
259 260 261
	if (f->f_fp == NULL)
		return err_closed();
	whence = 0;
262 263 264 265 266 267 268 269 270
	if (!PyArg_ParseTuple(args, "O|i", &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())
271
		return NULL;
272
	Py_BEGIN_ALLOW_THREADS
273
	errno = 0;
274 275 276 277 278
#if defined(HAVE_FSEEKO)
	ret = fseeko(f->f_fp, offset, whence);
#elif defined(HAVE_FSEEK64)
	ret = fseek64(f->f_fp, offset, whence);
#else
Guido van Rossum's avatar
Guido van Rossum committed
279
	ret = fseek(f->f_fp, offset, whence);
280
#endif
281
	Py_END_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
282
	if (ret != 0) {
283
		PyErr_SetFromErrno(PyExc_IOError);
284 285
		clearerr(f->f_fp);
		return NULL;
286
	}
287 288
	Py_INCREF(Py_None);
	return Py_None;
289 290
}

291
#ifdef HAVE_FTRUNCATE
292
static PyObject *
293
file_truncate(f, args)
294 295
	PyFileObject *f;
	PyObject *args;
296 297
{
	int ret;
298 299
	off_t newsize;
	PyObject *newsizeobj;
300 301 302
	
	if (f->f_fp == NULL)
		return err_closed();
303 304
	newsizeobj = NULL;
	if (!PyArg_ParseTuple(args, "|O", &newsizeobj))
305
		return NULL;
306 307 308 309 310 311 312 313 314 315 316 317
	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*/
318
		Py_BEGIN_ALLOW_THREADS
319
		errno = 0;
320 321 322 323 324 325 326
#if defined(HAVE_FTELLO) && defined(HAVE_LARGEFILE_SUPPORT)
		newsize =  ftello(f->f_fp);
#elif defined(HAVE_FTELL64) && defined(HAVE_LARGEFILE_SUPPORT)
		newsize =  ftell64(f->f_fp);
#else
		newsize =  ftell(f->f_fp);
#endif
327
		Py_END_ALLOW_THREADS
328
		if (newsize == -1) {
329
		        PyErr_SetFromErrno(PyExc_IOError);
330 331 332 333
			clearerr(f->f_fp);
			return NULL;
		}
	}
334
	Py_BEGIN_ALLOW_THREADS
335 336
	errno = 0;
	ret = fflush(f->f_fp);
337
	Py_END_ALLOW_THREADS
338
	if (ret == 0) {
339
	        Py_BEGIN_ALLOW_THREADS
340 341
		errno = 0;
		ret = ftruncate(fileno(f->f_fp), newsize);
342
		Py_END_ALLOW_THREADS
343 344
	}
	if (ret != 0) {
345
		PyErr_SetFromErrno(PyExc_IOError);
346 347 348
		clearerr(f->f_fp);
		return NULL;
	}
349 350
	Py_INCREF(Py_None);
	return Py_None;
351 352 353
}
#endif /* HAVE_FTRUNCATE */

354
static PyObject *
355
file_tell(f, args)
356 357
	PyFileObject *f;
	PyObject *args;
358
{
359
	off_t offset;
360 361
	if (f->f_fp == NULL)
		return err_closed();
362
	if (!PyArg_NoArgs(args))
Guido van Rossum's avatar
Guido van Rossum committed
363
		return NULL;
364
	Py_BEGIN_ALLOW_THREADS
365
	errno = 0;
366 367 368 369 370
#if defined(HAVE_FTELLO) && defined(HAVE_LARGEFILE_SUPPORT)
	offset = ftello(f->f_fp);
#elif defined(HAVE_FTELL64) && defined(HAVE_LARGEFILE_SUPPORT)
	offset = ftell64(f->f_fp);
#else
371
	offset = ftell(f->f_fp);
372
#endif
373
	Py_END_ALLOW_THREADS
374
	if (offset == -1) {
375
		PyErr_SetFromErrno(PyExc_IOError);
376 377
		clearerr(f->f_fp);
		return NULL;
378
	}
379
#if !defined(HAVE_LARGEFILE_SUPPORT)
380
	return PyInt_FromLong(offset);
381 382 383
#else
	return PyLong_FromLongLong(offset);
#endif
384 385
}

386
static PyObject *
387
file_fileno(f, args)
388 389
	PyFileObject *f;
	PyObject *args;
390
{
391 392
	if (f->f_fp == NULL)
		return err_closed();
393
	if (!PyArg_NoArgs(args))
394
		return NULL;
395
	return PyInt_FromLong((long) fileno(f->f_fp));
396 397
}

398
static PyObject *
399
file_flush(f, args)
400 401
	PyFileObject *f;
	PyObject *args;
402
{
Guido van Rossum's avatar
Guido van Rossum committed
403 404
	int res;
	
405 406
	if (f->f_fp == NULL)
		return err_closed();
407
	if (!PyArg_NoArgs(args))
408
		return NULL;
409
	Py_BEGIN_ALLOW_THREADS
410
	errno = 0;
Guido van Rossum's avatar
Guido van Rossum committed
411
	res = fflush(f->f_fp);
412
	Py_END_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
413
	if (res != 0) {
414
		PyErr_SetFromErrno(PyExc_IOError);
415 416
		clearerr(f->f_fp);
		return NULL;
417
	}
418 419
	Py_INCREF(Py_None);
	return Py_None;
420 421
}

422
static PyObject *
423
file_isatty(f, args)
424 425
	PyFileObject *f;
	PyObject *args;
426
{
Guido van Rossum's avatar
Guido van Rossum committed
427
	long res;
428 429
	if (f->f_fp == NULL)
		return err_closed();
430
	if (!PyArg_NoArgs(args))
431
		return NULL;
432
	Py_BEGIN_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
433
	res = isatty((int)fileno(f->f_fp));
434 435
	Py_END_ALLOW_THREADS
	return PyInt_FromLong(res);
436 437
}

438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
/* We expect that fstat exists on most systems.
   It's confirmed on Unix, Mac and Windows.
   If you don't have it, add #define DONT_HAVE_FSTAT to your config.h. */
#ifndef DONT_HAVE_FSTAT
#define HAVE_FSTAT

#include <sys/types.h>
#include <sys/stat.h>

#endif

#if BUFSIZ < 8192
#define SMALLCHUNK 8192
#else
#define SMALLCHUNK BUFSIZ
#endif

455 456 457 458 459
#if SIZEOF_INT < 4
#define BIGCHUNK  (512 * 32)
#else
#define BIGCHUNK  (512 * 1024)
#endif
460 461 462 463 464 465 466 467 468 469 470

static size_t
new_buffersize(f, currentsize)
	PyFileObject *f;
	size_t currentsize;
{
#ifdef HAVE_FSTAT
	long pos, end;
	struct stat st;
	if (fstat(fileno(f->f_fp), &st) == 0) {
		end = st.st_size;
471 472 473 474 475 476 477 478 479
		/* 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. :-) */
480 481 482
		pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR);
		if (pos >= 0)
			pos = ftell(f->f_fp);
483 484
		if (pos < 0)
			clearerr(f->f_fp);
485
		if (end > pos && pos >= 0)
486
			return currentsize + end - pos + 1;
487
		/* Add 1 so if the file were to grow we'd notice. */
488 489 490 491 492 493 494 495 496 497 498 499 500
	}
#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;
}

501
static PyObject *
502
file_read(f, args)
503 504
	PyFileObject *f;
	PyObject *args;
505
{
506
	long bytesrequested = -1;
507
	size_t bytesread, buffersize, chunksize;
508
	PyObject *v;
509
	
510 511
	if (f->f_fp == NULL)
		return err_closed();
512 513
	if (!PyArg_ParseTuple(args, "|l", &bytesrequested))
		return NULL;
514
	if (bytesrequested < 0)
515
		buffersize = new_buffersize(f, (size_t)0);
516 517 518
	else
		buffersize = bytesrequested;
	v = PyString_FromStringAndSize((char *)NULL, buffersize);
Guido van Rossum's avatar
Guido van Rossum committed
519
	if (v == NULL)
Guido van Rossum's avatar
Guido van Rossum committed
520
		return NULL;
521
	bytesread = 0;
522
	for (;;) {
523 524
		Py_BEGIN_ALLOW_THREADS
		errno = 0;
525 526
		chunksize = fread(BUF(v) + bytesread, 1,
				  buffersize - bytesread, f->f_fp);
527 528 529 530 531 532 533 534 535
		Py_END_ALLOW_THREADS
		if (chunksize == 0) {
			if (!ferror(f->f_fp))
				break;
			PyErr_SetFromErrno(PyExc_IOError);
			clearerr(f->f_fp);
			Py_DECREF(v);
			return NULL;
		}
536 537
		bytesread += chunksize;
		if (bytesread < buffersize)
538
			break;
539
		if (bytesrequested < 0) {
540
			buffersize = new_buffersize(f, buffersize);
541
			if (_PyString_Resize(&v, buffersize) < 0)
542 543 544
				return NULL;
		}
	}
545 546
	if (bytesread != buffersize)
		_PyString_Resize(&v, bytesread);
Guido van Rossum's avatar
Guido van Rossum committed
547 548 549
	return v;
}

550 551 552 553 554 555 556 557 558 559 560 561 562
static PyObject *
file_readinto(f, args)
	PyFileObject *f;
	PyObject *args;
{
	char *ptr;
	int ntodo, ndone, nnow;
	
	if (f->f_fp == NULL)
		return err_closed();
	if (!PyArg_Parse(args, "w#", &ptr, &ntodo))
		return NULL;
	ndone = 0;
563 564 565
	while (ntodo > 0) {
		Py_BEGIN_ALLOW_THREADS
		errno = 0;
566
		nnow = fread(ptr+ndone, 1, ntodo, f->f_fp);
567 568 569 570
		Py_END_ALLOW_THREADS
		if (nnow == 0) {
			if (!ferror(f->f_fp))
				break;
571 572 573 574 575 576 577 578 579 580 581
			PyErr_SetFromErrno(PyExc_IOError);
			clearerr(f->f_fp);
			return NULL;
		}
		ndone += nnow;
		ntodo -= nnow;
	}
	return PyInt_FromLong(ndone);
}


582 583 584 585 586
/* Internal routine to get a line.
   Size argument interpretation:
   > 0: max length;
   = 0: read arbitrary line;
   < 0: strip trailing '\n', raise EOFError if EOF reached immediately
587 588
*/

589
static PyObject *
590
getline(f, n)
591
	PyFileObject *f;
592
	int n;
Guido van Rossum's avatar
Guido van Rossum committed
593
{
594 595 596
	register FILE *fp;
	register int c;
	register char *buf, *end;
597
	int n1, n2;
598
	PyObject *v;
599

600
	fp = f->f_fp;
601
	n2 = n > 0 ? n : 100;
602
	v = PyString_FromStringAndSize((char *)NULL, n2);
Guido van Rossum's avatar
Guido van Rossum committed
603
	if (v == NULL)
Guido van Rossum's avatar
Guido van Rossum committed
604
		return NULL;
605 606
	buf = BUF(v);
	end = buf + n2;
607

608
	Py_BEGIN_ALLOW_THREADS
609
	for (;;) {
610
		if ((c = getc(fp)) == EOF) {
611
			clearerr(fp);
612
			Py_BLOCK_THREADS
613 614
			if (PyErr_CheckSignals()) {
				Py_DECREF(v);
615 616 617
				return NULL;
			}
			if (n < 0 && buf == BUF(v)) {
618 619
				Py_DECREF(v);
				PyErr_SetString(PyExc_EOFError,
620
					   "EOF when reading a line");
621 622
				return NULL;
			}
623
			Py_UNBLOCK_THREADS
624
			break;
625 626 627 628 629 630
		}
		if ((*buf++ = c) == '\n') {
			if (n < 0)
				buf--;
			break;
		}
631
		if (buf == end) {
632
			if (n > 0)
633 634 635
				break;
			n1 = n2;
			n2 += 1000;
636 637
			Py_BLOCK_THREADS
			if (_PyString_Resize(&v, n2) < 0)
638
				return NULL;
639
			Py_UNBLOCK_THREADS
640 641 642
			buf = BUF(v) + n1;
			end = BUF(v) + n2;
		}
Guido van Rossum's avatar
Guido van Rossum committed
643
	}
644
	Py_END_ALLOW_THREADS
645

646 647
	n1 = buf - BUF(v);
	if (n1 != n2)
648
		_PyString_Resize(&v, n1);
Guido van Rossum's avatar
Guido van Rossum committed
649 650 651
	return v;
}

652 653
/* External C interface */

654 655 656
PyObject *
PyFile_GetLine(f, n)
	PyObject *f;
657 658
	int n;
{
659
	if (f == NULL) {
660
		PyErr_BadInternalCall();
661 662
		return NULL;
	}
663 664 665 666 667
	if (!PyFile_Check(f)) {
		PyObject *reader;
		PyObject *args;
		PyObject *result;
		reader = PyObject_GetAttrString(f, "readline");
668 669 670
		if (reader == NULL)
			return NULL;
		if (n <= 0)
671
			args = Py_BuildValue("()");
672
		else
673
			args = Py_BuildValue("(i)", n);
674
		if (args == NULL) {
675
			Py_DECREF(reader);
676 677
			return NULL;
		}
678 679 680 681 682
		result = PyEval_CallObject(reader, args);
		Py_DECREF(reader);
		Py_DECREF(args);
		if (result != NULL && !PyString_Check(result)) {
			Py_DECREF(result);
683
			result = NULL;
684
			PyErr_SetString(PyExc_TypeError,
685 686 687
				   "object.readline() returned non-string");
		}
		if (n < 0 && result != NULL) {
688 689
			char *s = PyString_AsString(result);
			int len = PyString_Size(result);
690
			if (len == 0) {
691
				Py_DECREF(result);
692
				result = NULL;
693
				PyErr_SetString(PyExc_EOFError,
694 695 696 697
					   "EOF when reading a line");
			}
			else if (s[len-1] == '\n') {
				if (result->ob_refcnt == 1)
698
					_PyString_Resize(&result, len-1);
699
				else {
700 701 702 703
					PyObject *v;
					v = PyString_FromStringAndSize(s,
								       len-1);
					Py_DECREF(result);
704 705 706 707 708 709
					result = v;
				}
			}
		}
		return result;
	}
710
	if (((PyFileObject*)f)->f_fp == NULL)
711
		return err_closed();
712
	return getline((PyFileObject *)f, n);
713 714 715 716
}

/* Python method */

717
static PyObject *
718
file_readline(f, args)
719 720
	PyFileObject *f;
	PyObject *args;
721
{
722
	int n = -1;
723

724 725
	if (f->f_fp == NULL)
		return err_closed();
726 727 728 729 730 731
	if (!PyArg_ParseTuple(args, "|i", &n))
		return NULL;
	if (n == 0)
		return PyString_FromString("");
	if (n < 0)
		n = 0;
Guido van Rossum's avatar
Guido van Rossum committed
732
	return getline(f, n);
733 734
}

735
static PyObject *
736
file_readlines(f, args)
737 738
	PyFileObject *f;
	PyObject *args;
739
{
740
	long sizehint = 0;
741 742
	PyObject *list;
	PyObject *line;
743 744 745 746 747 748
	char small_buffer[SMALLCHUNK];
	char *buffer = small_buffer;
	size_t buffersize = SMALLCHUNK;
	PyObject *big_buffer = NULL;
	size_t nfilled = 0;
	size_t nread;
749
	size_t totalread = 0;
750 751
	char *p, *q, *end;
	int err;
752

753 754
	if (f->f_fp == NULL)
		return err_closed();
755
	if (!PyArg_ParseTuple(args, "|l", &sizehint))
756
		return NULL;
757
	if ((list = PyList_New(0)) == NULL)
758 759
		return NULL;
	for (;;) {
760 761 762 763 764
		Py_BEGIN_ALLOW_THREADS
		errno = 0;
		nread = fread(buffer+nfilled, 1, buffersize-nfilled, f->f_fp);
		Py_END_ALLOW_THREADS
		if (nread == 0) {
765
			sizehint = 0;
766
			if (!ferror(f->f_fp))
767 768 769 770
				break;
			PyErr_SetFromErrno(PyExc_IOError);
			clearerr(f->f_fp);
		  error:
771
			Py_DECREF(list);
772 773 774
			list = NULL;
			goto cleanup;
		}
775
		totalread += nread;
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
		p = memchr(buffer+nfilled, '\n', nread);
		if (p == NULL) {
			/* Need a larger buffer to fit this line */
			nfilled += nread;
			buffersize *= 2;
			if (big_buffer == NULL) {
				/* Create the big buffer */
				big_buffer = PyString_FromStringAndSize(
					NULL, buffersize);
				if (big_buffer == NULL)
					goto error;
				buffer = PyString_AS_STRING(big_buffer);
				memcpy(buffer, small_buffer, nfilled);
			}
			else {
				/* Grow the big buffer */
				_PyString_Resize(&big_buffer, buffersize);
				buffer = PyString_AS_STRING(big_buffer);
			}
			continue;
796
		}
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
		end = buffer+nfilled+nread;
		q = buffer;
		do {
			/* Process complete lines */
			p++;
			line = PyString_FromStringAndSize(q, p-q);
			if (line == NULL)
				goto error;
			err = PyList_Append(list, line);
			Py_DECREF(line);
			if (err != 0)
				goto error;
			q = p;
			p = memchr(q, '\n', end-q);
		} while (p != NULL);
		/* Move the remaining incomplete line to the start */
		nfilled = end-q;
		memmove(buffer, q, nfilled);
815 816 817
		if (sizehint > 0)
			if (totalread >= (size_t)sizehint)
				break;
818 819 820 821 822 823
	}
	if (nfilled != 0) {
		/* Partial last line */
		line = PyString_FromStringAndSize(buffer, nfilled);
		if (line == NULL)
			goto error;
824 825 826 827 828 829 830 831 832 833 834 835
		if (sizehint > 0) {
			/* Need to complete the last line */
			PyObject *rest = getline(f, 0);
			if (rest == NULL) {
				Py_DECREF(line);
				goto error;
			}
			PyString_Concat(&line, rest);
			Py_DECREF(rest);
			if (line == NULL)
				goto error;
		}
836
		err = PyList_Append(list, line);
837
		Py_DECREF(line);
838 839
		if (err != 0)
			goto error;
840
	}
841
  cleanup:
842
	if (big_buffer) {
843
		Py_DECREF(big_buffer);
844
	}
845 846 847
	return list;
}

848
static PyObject *
Guido van Rossum's avatar
Guido van Rossum committed
849
file_write(f, args)
850 851
	PyFileObject *f;
	PyObject *args;
Guido van Rossum's avatar
Guido van Rossum committed
852
{
853
	char *s;
Guido van Rossum's avatar
Guido van Rossum committed
854
	int n, n2;
855 856
	if (f->f_fp == NULL)
		return err_closed();
857
	if (!PyArg_Parse(args, "s#", &s, &n))
Guido van Rossum's avatar
Guido van Rossum committed
858
		return NULL;
859
	f->f_softspace = 0;
860
	Py_BEGIN_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
861
	errno = 0;
862
	n2 = fwrite(s, 1, n, f->f_fp);
863
	Py_END_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
864
	if (n2 != n) {
865
		PyErr_SetFromErrno(PyExc_IOError);
866
		clearerr(f->f_fp);
Guido van Rossum's avatar
Guido van Rossum committed
867 868
		return NULL;
	}
869 870
	Py_INCREF(Py_None);
	return Py_None;
Guido van Rossum's avatar
Guido van Rossum committed
871 872
}

873
static PyObject *
874
file_writelines(f, args)
875 876
	PyFileObject *f;
	PyObject *args;
877 878 879 880
{
	int i, n;
	if (f->f_fp == NULL)
		return err_closed();
881 882
	if (args == NULL || !PyList_Check(args)) {
		PyErr_SetString(PyExc_TypeError,
883 884 885
			   "writelines() requires list of strings");
		return NULL;
	}
886
	n = PyList_Size(args);
887
	f->f_softspace = 0;
888
	Py_BEGIN_ALLOW_THREADS
889 890
	errno = 0;
	for (i = 0; i < n; i++) {
891
		PyObject *line = PyList_GetItem(args, i);
892 893
		int len;
		int nwritten;
894 895 896
		if (!PyString_Check(line)) {
			Py_BLOCK_THREADS
			PyErr_SetString(PyExc_TypeError,
897 898 899
				   "writelines() requires list of strings");
			return NULL;
		}
900 901
		len = PyString_Size(line);
		nwritten = fwrite(PyString_AsString(line), 1, len, f->f_fp);
902
		if (nwritten != len) {
903 904
			Py_BLOCK_THREADS
			PyErr_SetFromErrno(PyExc_IOError);
905 906 907 908
			clearerr(f->f_fp);
			return NULL;
		}
	}
909 910 911
	Py_END_ALLOW_THREADS
	Py_INCREF(Py_None);
	return Py_None;
912 913
}

914
static PyMethodDef file_methods[] = {
915
	{"readline",	(PyCFunction)file_readline, 1},
916 917 918
	{"read",	(PyCFunction)file_read, 1},
	{"write",	(PyCFunction)file_write, 0},
	{"fileno",	(PyCFunction)file_fileno, 0},
919
	{"seek",	(PyCFunction)file_seek, 1},
920
#ifdef HAVE_FTRUNCATE
921
	{"truncate",	(PyCFunction)file_truncate, 1},
922
#endif
923
	{"tell",	(PyCFunction)file_tell, 0},
924
	{"readinto",	(PyCFunction)file_readinto, 0},
925 926 927 928 929
	{"readlines",	(PyCFunction)file_readlines, 1},
	{"writelines",	(PyCFunction)file_writelines, 0},
	{"flush",	(PyCFunction)file_flush, 0},
	{"close",	(PyCFunction)file_close, 0},
	{"isatty",	(PyCFunction)file_isatty, 0},
Guido van Rossum's avatar
Guido van Rossum committed
930 931 932
	{NULL,		NULL}		/* sentinel */
};

933
#define OFF(x) offsetof(PyFileObject, x)
934 935 936 937 938 939 940 941 942 943

static struct memberlist file_memberlist[] = {
	{"softspace",	T_INT,		OFF(f_softspace)},
	{"mode",	T_OBJECT,	OFF(f_mode),	RO},
	{"name",	T_OBJECT,	OFF(f_name),	RO},
	/* getattr(f, "closed") is implemented without this table */
	{"closed",	T_INT,		0,		RO},
	{NULL}	/* Sentinel */
};

944
static PyObject *
Guido van Rossum's avatar
Guido van Rossum committed
945
file_getattr(f, name)
946
	PyFileObject *f;
Guido van Rossum's avatar
Guido van Rossum committed
947 948
	char *name;
{
949
	PyObject *res;
950

951
	res = Py_FindMethod(file_methods, (PyObject *)f, name);
952 953
	if (res != NULL)
		return res;
954
	PyErr_Clear();
955
	if (strcmp(name, "closed") == 0)
956 957
		return PyInt_FromLong((long)(f->f_fp == 0));
	return PyMember_Get((char *)f, file_memberlist, name);
958 959 960 961
}

static int
file_setattr(f, name, v)
962
	PyFileObject *f;
963
	char *name;
964
	PyObject *v;
965 966
{
	if (v == NULL) {
967 968
		PyErr_SetString(PyExc_AttributeError,
				"can't delete file attributes");
969 970
		return -1;
	}
971
	return PyMember_Set((char *)f, file_memberlist, name, v);
Guido van Rossum's avatar
Guido van Rossum committed
972 973
}

974 975
PyTypeObject PyFile_Type = {
	PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum's avatar
Guido van Rossum committed
976 977
	0,
	"file",
978
	sizeof(PyFileObject),
Guido van Rossum's avatar
Guido van Rossum committed
979
	0,
980
	(destructor)file_dealloc, /*tp_dealloc*/
981
	0,		/*tp_print*/
982 983
	(getattrfunc)file_getattr, /*tp_getattr*/
	(setattrfunc)file_setattr, /*tp_setattr*/
Guido van Rossum's avatar
Guido van Rossum committed
984
	0,		/*tp_compare*/
985
	(reprfunc)file_repr, /*tp_repr*/
Guido van Rossum's avatar
Guido van Rossum committed
986
};
987 988 989 990

/* Interface for the 'soft space' between print items. */

int
991 992
PyFile_SoftSpace(f, newflag)
	PyObject *f;
993 994 995
	int newflag;
{
	int oldflag = 0;
996 997 998
	if (f == NULL) {
		/* Do nothing */
	}
999 1000 1001
	else if (PyFile_Check(f)) {
		oldflag = ((PyFileObject *)f)->f_softspace;
		((PyFileObject *)f)->f_softspace = newflag;
1002
	}
1003
	else {
1004 1005
		PyObject *v;
		v = PyObject_GetAttrString(f, "softspace");
1006
		if (v == NULL)
1007
			PyErr_Clear();
1008
		else {
1009 1010 1011
			if (PyInt_Check(v))
				oldflag = PyInt_AsLong(v);
			Py_DECREF(v);
1012
		}
1013
		v = PyInt_FromLong((long)newflag);
1014
		if (v == NULL)
1015
			PyErr_Clear();
1016
		else {
1017 1018 1019
			if (PyObject_SetAttrString(f, "softspace", v) != 0)
				PyErr_Clear();
			Py_DECREF(v);
1020 1021
		}
	}
1022 1023
	return oldflag;
}
1024 1025 1026 1027

/* Interfaces to write objects/strings to file-like objects */

int
1028 1029 1030
PyFile_WriteObject(v, f, flags)
	PyObject *v;
	PyObject *f;
1031 1032
	int flags;
{
1033
	PyObject *writer, *value, *args, *result;
1034
	if (f == NULL) {
1035
		PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");
1036 1037
		return -1;
	}
1038 1039
	else if (PyFile_Check(f)) {
		FILE *fp = PyFile_AsFile(f);
1040 1041 1042 1043
		if (fp == NULL) {
			err_closed();
			return -1;
		}
1044
		return PyObject_Print(v, fp, flags);
1045
	}
1046
	writer = PyObject_GetAttrString(f, "write");
1047 1048
	if (writer == NULL)
		return -1;
1049 1050
	if (flags & Py_PRINT_RAW)
		value = PyObject_Str(v);
1051
	else
1052
		value = PyObject_Repr(v);
1053
	if (value == NULL) {
1054
		Py_DECREF(writer);
1055
		return -1;
1056
	}
1057
	args = Py_BuildValue("(O)", value);
1058
	if (args == NULL) {
1059 1060
		Py_DECREF(value);
		Py_DECREF(writer);
1061 1062
		return -1;
	}
1063 1064 1065 1066
	result = PyEval_CallObject(writer, args);
	Py_DECREF(args);
	Py_DECREF(value);
	Py_DECREF(writer);
1067 1068
	if (result == NULL)
		return -1;
1069
	Py_DECREF(result);
1070 1071 1072
	return 0;
}

1073
int
1074
PyFile_WriteString(s, f)
1075
	char *s;
1076
	PyObject *f;
1077 1078
{
	if (f == NULL) {
1079 1080 1081 1082 1083
		/* Should be caused by a pre-existing error */
		if(!PyErr_Occurred())
			PyErr_SetString(PyExc_SystemError,
					"null file for PyFile_WriteString");
		return -1;
1084
	}
1085 1086
	else if (PyFile_Check(f)) {
		FILE *fp = PyFile_AsFile(f);
1087 1088 1089 1090 1091 1092
		if (fp == NULL) {
			err_closed();
			return -1;
		}
		fputs(s, fp);
		return 0;
1093
	}
1094 1095
	else if (!PyErr_Occurred()) {
		PyObject *v = PyString_FromString(s);
1096 1097 1098 1099 1100 1101
		int err;
		if (v == NULL)
			return -1;
		err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
		Py_DECREF(v);
		return err;
1102
	}
1103 1104
	else
		return -1;
1105
}