153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* File object implementation */
253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define PY_SSIZE_T_CLEAN
453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include "Python.h"
553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include "structmember.h"
653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef HAVE_SYS_TYPES_H
853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include <sys/types.h>
953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif /* HAVE_SYS_TYPES_H */
1053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
1153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef MS_WINDOWS
1253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define fileno _fileno
1353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* can simulate truncate with Win32 API functions; see file_truncate */
1453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define HAVE_FTRUNCATE
1553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define WIN32_LEAN_AND_MEAN
1653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include <windows.h>
1753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
1853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
1953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if defined(PYOS_OS2) && defined(PYCC_GCC)
2053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include <io.h>
2153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
2253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
2353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define BUF(v) PyString_AS_STRING((PyStringObject *)v)
2453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
2553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef HAVE_ERRNO_H
2653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include <errno.h>
2753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
2853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
2953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef HAVE_GETC_UNLOCKED
3053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define GETC(f) getc_unlocked(f)
3153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define FLOCKFILE(f) flockfile(f)
3253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define FUNLOCKFILE(f) funlockfile(f)
3353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
3453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define GETC(f) getc(f)
3553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define FLOCKFILE(f)
3653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define FUNLOCKFILE(f)
3753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
3853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
3953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Bits in f_newlinetypes */
4053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define NEWLINE_UNKNOWN 0       /* No newline seen, yet */
4153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define NEWLINE_CR 1            /* \r newline seen */
4253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define NEWLINE_LF 2            /* \n newline seen */
4353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define NEWLINE_CRLF 4          /* \r\n newline seen */
4453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
4553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/*
4653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * These macros release the GIL while preventing the f_close() function being
4753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * called in the interval between them.  For that purpose, a running total of
4853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * the number of currently running unlocked code sections is kept in
4953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * the unlocked_count field of the PyFileObject. The close() method raises
5053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * an IOError if that field is non-zero.  See issue #815646, #595601.
5153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel */
5253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
5353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define FILE_BEGIN_ALLOW_THREADS(fobj) \
5453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ \
5553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    fobj->unlocked_count++; \
5653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_BEGIN_ALLOW_THREADS
5753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
5853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define FILE_END_ALLOW_THREADS(fobj) \
5953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_END_ALLOW_THREADS \
6053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    fobj->unlocked_count--; \
6153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(fobj->unlocked_count >= 0); \
6253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
6353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
6453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define FILE_ABORT_ALLOW_THREADS(fobj) \
6553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_BLOCK_THREADS \
6653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    fobj->unlocked_count--; \
6753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(fobj->unlocked_count >= 0);
6853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
6953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef __cplusplus
7053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielextern "C" {
7153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
7253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
7353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielFILE *
7453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_AsFile(PyObject *f)
7553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
7653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f == NULL || !PyFile_Check(f))
7753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
7853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else
7953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return ((PyFileObject *)f)->f_fp;
8053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
8153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
8253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielvoid PyFile_IncUseCount(PyFileObject *fobj)
8353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
8453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    fobj->unlocked_count++;
8553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
8653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
8753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielvoid PyFile_DecUseCount(PyFileObject *fobj)
8853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
8953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    fobj->unlocked_count--;
9053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(fobj->unlocked_count >= 0);
9153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
9253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
9353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyObject *
9453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_Name(PyObject *f)
9553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
9653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f == NULL || !PyFile_Check(f))
9753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
9853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else
9953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return ((PyFileObject *)f)->f_name;
10053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
10153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
10253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* This is a safe wrapper around PyObject_Print to print to the FILE
10353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   of a PyFileObject. PyObject_Print releases the GIL but knows nothing
10453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   about PyFileObject. */
10553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic int
10653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_PyObject_Print(PyObject *op, PyFileObject *f, int flags)
10753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
10853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int result;
10953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyFile_IncUseCount(f);
11053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    result = PyObject_Print(op, f->f_fp, flags);
11153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyFile_DecUseCount(f);
11253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return result;
11353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
11453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
11553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* On Unix, fopen will succeed for directories.
11653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   In Python, there should be no file objects referring to
11753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   directories, so we need a check.  */
11853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
11953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyFileObject*
12053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanieldircheck(PyFileObject* f)
12153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
12253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
12353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    struct stat buf;
12453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
12553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return f;
12653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (fstat(fileno(f->f_fp), &buf) == 0 &&
12753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        S_ISDIR(buf.st_mode)) {
12853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        char *msg = strerror(EISDIR);
12953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(isO)",
13053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                              EISDIR, msg, f->f_name);
13153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetObject(PyExc_IOError, exc);
13253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_XDECREF(exc);
13353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
13453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
13553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
13653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return f;
13753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
13853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
13953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
14053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
14153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfill_file_fields(PyFileObject *f, FILE *fp, PyObject *name, char *mode,
14253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 int (*close)(FILE *))
14353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
14453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(name != NULL);
14553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(f != NULL);
14653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(PyFile_Check(f));
14753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(f->f_fp == NULL);
14853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
14953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(f->f_name);
15053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(f->f_mode);
15153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(f->f_encoding);
15253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(f->f_errors);
15353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
15453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_INCREF(name);
15553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_name = name;
15653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
15753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_mode = PyString_FromString(mode);
15853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
15953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_close = close;
16053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_softspace = 0;
16153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_binary = strchr(mode,'b') != NULL;
16253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_buf = NULL;
16353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_univ_newline = (strchr(mode, 'U') != NULL);
16453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_newlinetypes = NEWLINE_UNKNOWN;
16553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_skipnextlf = 0;
16653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_INCREF(Py_None);
16753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_encoding = Py_None;
16853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_INCREF(Py_None);
16953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_errors = Py_None;
17053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->readable = f->writable = 0;
17153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (strchr(mode, 'r') != NULL || f->f_univ_newline)
17253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->readable = 1;
17353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (strchr(mode, 'w') != NULL || strchr(mode, 'a') != NULL)
17453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->writable = 1;
17553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (strchr(mode, '+') != NULL)
17653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->readable = f->writable = 1;
17753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
17853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_mode == NULL)
17953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
18053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_fp = fp;
18153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f = dircheck(f);
18253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return (PyObject *) f;
18353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
18453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
18553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
18653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define Py_VERIFY_WINNT
18753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* The CRT on windows compiled with Visual Studio 2005 and higher may
18853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * assert if given invalid mode strings.  This is all fine and well
18953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * in static languages like C where the mode string is typcially hard
19053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * coded.  But in Python, were we pass in the mode string from the user,
19153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * we need to verify it first manually
19253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel */
19353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic int _PyVerify_Mode_WINNT(const char *mode)
19453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
19553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* See if mode string is valid on Windows to avoid hard assertions */
19653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* remove leading spacese */
19753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int singles = 0;
19853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int pairs = 0;
19953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int encoding = 0;
20053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    const char *s, *c;
20153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
20253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    while(*mode == ' ') /* strip initial spaces */
20353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ++mode;
20453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!strchr("rwa", *mode)) /* must start with one of these */
20553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return 0;
20653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    while (*++mode) {
20753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (*mode == ' ' || *mode == 'N') /* ignore spaces and N */
20853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            continue;
20953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        s = "+TD"; /* each of this can appear only once */
21053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        c = strchr(s, *mode);
21153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (c) {
21253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ptrdiff_t idx = s-c;
21353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (singles & (1<<idx))
21453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return 0;
21553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            singles |= (1<<idx);
21653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            continue;
21753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
21853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        s = "btcnSR"; /* only one of each letter in the pairs allowed */
21953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        c = strchr(s, *mode);
22053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (c) {
22153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ptrdiff_t idx = (s-c)/2;
22253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (pairs & (1<<idx))
22353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return 0;
22453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            pairs |= (1<<idx);
22553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            continue;
22653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
22753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (*mode == ',') {
22853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            encoding = 1;
22953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
23053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
23153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return 0; /* found an invalid char */
23253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
23353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
23453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (encoding) {
23553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        char *e[] = {"UTF-8", "UTF-16LE", "UNICODE"};
23653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        while (*mode == ' ')
23753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ++mode;
23853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* find 'ccs =' */
23953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (strncmp(mode, "ccs", 3))
24053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return 0;
24153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        mode += 3;
24253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        while (*mode == ' ')
24353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ++mode;
24453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (*mode != '=')
24553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return 0;
24653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        while (*mode == ' ')
24753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ++mode;
24853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        for(encoding = 0; encoding<_countof(e); ++encoding) {
24953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            size_t l = strlen(e[encoding]);
25053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (!strncmp(mode, e[encoding], l)) {
25153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                mode += l; /* found a valid encoding */
25253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                break;
25353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
25453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
25553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (encoding == _countof(e))
25653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return 0;
25753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
25853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* skip trailing spaces */
25953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    while (*mode == ' ')
26053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ++mode;
26153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
26253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return *mode == '\0'; /* must be at the end of the string */
26353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
26453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
26553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
26653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* check for known incorrect mode strings - problem is, platforms are
26753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   free to accept any mode characters they like and are supposed to
26853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   ignore stuff they don't understand... write or append mode with
26953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   universal newline support is expressly forbidden by PEP 278.
27053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   Additionally, remove the 'U' from the mode string as platforms
27153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   won't know what it is. Non-zero return signals an exception */
27253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielint
27353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel_PyFile_SanitizeMode(char *mode)
27453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
27553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *upos;
27653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t len = strlen(mode);
27753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
27853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!len) {
27953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetString(PyExc_ValueError, "empty mode string");
28053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
28153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
28253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
28353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    upos = strchr(mode, 'U');
28453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (upos) {
28553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        memmove(upos, upos+1, len-(upos-mode)); /* incl null char */
28653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
28753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (mode[0] == 'w' || mode[0] == 'a') {
28853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_Format(PyExc_ValueError, "universal newline "
28953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                         "mode can only be used with modes "
29053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                         "starting with 'r'");
29153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
29253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
29353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
29453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (mode[0] != 'r') {
29553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            memmove(mode+1, mode, strlen(mode)+1);
29653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            mode[0] = 'r';
29753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
29853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
29953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!strchr(mode, 'b')) {
30053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            memmove(mode+2, mode+1, strlen(mode));
30153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            mode[1] = 'b';
30253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
30353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    } else if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') {
30453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_Format(PyExc_ValueError, "mode string must begin with "
30553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    "one of 'r', 'w', 'a' or 'U', not '%.200s'", mode);
30653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
30753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
30853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef Py_VERIFY_WINNT
30953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* additional checks on NT with visual studio 2005 and higher */
31053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!_PyVerify_Mode_WINNT(mode)) {
31153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_Format(PyExc_ValueError, "Invalid mode ('%.50s')", mode);
31253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
31353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
31453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
31553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return 0;
31653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
31753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
31853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
31953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielopen_the_file(PyFileObject *f, char *name, char *mode)
32053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
32153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *newmode;
32253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(f != NULL);
32353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(PyFile_Check(f));
32453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef MS_WINDOWS
32553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* windows ignores the passed name in order to support Unicode */
32653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(f->f_name != NULL);
32753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
32853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(name != NULL);
32953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
33053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(mode != NULL);
33153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(f->f_fp == NULL);
33253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
33353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* probably need to replace 'U' by 'rb' */
33453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    newmode = PyMem_MALLOC(strlen(mode) + 3);
33553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!newmode) {
33653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_NoMemory();
33753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
33853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
33953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    strcpy(newmode, mode);
34053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
34153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (_PyFile_SanitizeMode(newmode)) {
34253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f = NULL;
34353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        goto cleanup;
34453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
34553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
34653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* rexec.py can't stop a user from getting the file() constructor --
34753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel       all they have to do is get *any* file object f, and then do
34853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel       type(f).  Here we prevent them from doing damage with it. */
34953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyEval_GetRestricted()) {
35053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetString(PyExc_IOError,
35153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        "file() constructor not accessible in restricted mode");
35253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f = NULL;
35353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        goto cleanup;
35453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
35553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
35653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
35753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef MS_WINDOWS
35853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyUnicode_Check(f->f_name)) {
35953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *wmode;
36053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        wmode = PyUnicode_DecodeASCII(newmode, strlen(newmode), NULL);
36153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (f->f_name && wmode) {
36253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            FILE_BEGIN_ALLOW_THREADS(f)
36353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* PyUnicode_AS_UNICODE OK without thread
36453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel               lock as it is a simple dereference. */
36553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            f->f_fp = _wfopen(PyUnicode_AS_UNICODE(f->f_name),
36653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                              PyUnicode_AS_UNICODE(wmode));
36753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            FILE_END_ALLOW_THREADS(f)
36853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
36953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_XDECREF(wmode);
37053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
37153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
37253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (NULL == f->f_fp && NULL != name) {
37353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(f)
37453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_fp = fopen(name, newmode);
37553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(f)
37653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
37753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
37853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL) {
37953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if defined  _MSC_VER && (_MSC_VER < 1400 || !defined(__STDC_SECURE_LIB__))
38053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* MSVC 6 (Microsoft) leaves errno at 0 for bad mode strings,
38153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * across all Windows flavors.  When it sets EINVAL varies
38253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * across Windows flavors, the exact conditions aren't
38353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * documented, and the answer lies in the OS's implementation
38453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * of Win32's CreateFile function (whose source is secret).
38553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * Seems the best we can do is map EINVAL to ENOENT.
38653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * Starting with Visual Studio .NET 2005, EINVAL is correctly
38753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * set by our CRT error handler (set in exceptions.c.)
38853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         */
38953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (errno == 0)         /* bad mode string */
39053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            errno = EINVAL;
39153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else if (errno == EINVAL) /* unknown, but not a mode string */
39253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            errno = ENOENT;
39353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
39453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* EINVAL is returned when an invalid filename or
39553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * an invalid mode is supplied. */
39653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (errno == EINVAL) {
39753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyObject *v;
39853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            char message[100];
39953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyOS_snprintf(message, 100,
40053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                "invalid mode ('%.50s') or filename", mode);
40153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            v = Py_BuildValue("(isO)", errno, message, f->f_name);
40253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (v != NULL) {
40353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyErr_SetObject(PyExc_IOError, v);
40453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                Py_DECREF(v);
40553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
40653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
40753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else
40853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, f->f_name);
40953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f = NULL;
41053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
41153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f != NULL)
41253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f = dircheck(f);
41353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
41453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielcleanup:
41553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyMem_FREE(newmode);
41653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
41753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return (PyObject *)f;
41853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
41953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
42053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
42153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielclose_the_file(PyFileObject *f)
42253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
42353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int sts = 0;
42453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int (*local_close)(FILE *);
42553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE *local_fp = f->f_fp;
42653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *local_setbuf = f->f_setbuf;
42753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (local_fp != NULL) {
42853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        local_close = f->f_close;
42953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (local_close != NULL && f->unlocked_count > 0) {
43053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (f->ob_refcnt > 0) {
43153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyErr_SetString(PyExc_IOError,
43253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    "close() called during concurrent "
43353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    "operation on the same file object.");
43453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            } else {
43553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* This should not happen unless someone is
43653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * carelessly playing with the PyFileObject
43753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * struct fields and/or its associated FILE
43853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * pointer. */
43953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyErr_SetString(PyExc_SystemError,
44053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    "PyFileObject locking error in "
44153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    "destructor (refcnt <= 0 at close).");
44253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
44353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
44453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
44553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* NULL out the FILE pointer before releasing the GIL, because
44653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * it will not be valid anymore after the close() function is
44753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * called. */
44853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_fp = NULL;
44953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (local_close != NULL) {
45053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* Issue #9295: must temporarily reset f_setbuf so that another
45153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel               thread doesn't free it when running file_close() concurrently.
45253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel               Otherwise this close() will crash when flushing the buffer. */
45353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            f->f_setbuf = NULL;
45453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_BEGIN_ALLOW_THREADS
45553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            errno = 0;
45653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            sts = (*local_close)(local_fp);
45753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_END_ALLOW_THREADS
45853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            f->f_setbuf = local_setbuf;
45953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (sts == EOF)
46053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return PyErr_SetFromErrno(PyExc_IOError);
46153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (sts != 0)
46253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return PyInt_FromLong((long)sts);
46353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
46453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
46553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_RETURN_NONE;
46653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
46753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
46853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyObject *
46953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *))
47053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
47153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyFileObject *f;
47253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *o_name;
47353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
47453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type, NULL, NULL);
47553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f == NULL)
47653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
47753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    o_name = PyString_FromString(name);
47853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (o_name == NULL) {
47953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (close != NULL && fp != NULL)
48053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            close(fp);
48153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(f);
48253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
48353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
48453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (fill_file_fields(f, fp, o_name, mode, close) == NULL) {
48553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(f);
48653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(o_name);
48753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
48853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
48953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(o_name);
49053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return (PyObject *)f;
49153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
49253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
49353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyObject *
49453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_FromString(char *name, char *mode)
49553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
49653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    extern int fclose(FILE *);
49753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyFileObject *f;
49853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
49953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f = (PyFileObject *)PyFile_FromFile((FILE *)NULL, name, mode, fclose);
50053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f != NULL) {
50153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (open_the_file(f, name, mode) == NULL) {
50253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(f);
50353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            f = NULL;
50453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
50553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
50653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return (PyObject *)f;
50753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
50853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
50953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielvoid
51053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_SetBufSize(PyObject *f, int bufsize)
51153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
51253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyFileObject *file = (PyFileObject *)f;
51353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (bufsize >= 0) {
51453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        int type;
51553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        switch (bufsize) {
51653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        case 0:
51753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            type = _IONBF;
51853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
51953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef HAVE_SETVBUF
52053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        case 1:
52153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            type = _IOLBF;
52253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            bufsize = BUFSIZ;
52353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
52453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
52553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        default:
52653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            type = _IOFBF;
52753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifndef HAVE_SETVBUF
52853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            bufsize = BUFSIZ;
52953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
53053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
53153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
53253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        fflush(file->f_fp);
53353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (type == _IONBF) {
53453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyMem_Free(file->f_setbuf);
53553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            file->f_setbuf = NULL;
53653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } else {
53753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            file->f_setbuf = (char *)PyMem_Realloc(file->f_setbuf,
53853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                                    bufsize);
53953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
54053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef HAVE_SETVBUF
54153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        setvbuf(file->f_fp, file->f_setbuf, type, bufsize);
54253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else /* !HAVE_SETVBUF */
54353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        setbuf(file->f_fp, file->f_setbuf);
54453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif /* !HAVE_SETVBUF */
54553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
54653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
54753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
54853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Set the encoding used to output Unicode strings.
54953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   Return 1 on success, 0 on failure. */
55053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
55153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielint
55253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_SetEncoding(PyObject *f, const char *enc)
55353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
55453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return PyFile_SetEncodingAndErrors(f, enc, NULL);
55553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
55653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
55753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielint
55853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_SetEncodingAndErrors(PyObject *f, const char *enc, char* errors)
55953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
56053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyFileObject *file = (PyFileObject*)f;
56153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *str, *oerrors;
56253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
56353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(PyFile_Check(f));
56453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    str = PyString_FromString(enc);
56553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!str)
56653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return 0;
56753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (errors) {
56853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        oerrors = PyString_FromString(errors);
56953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!oerrors) {
57053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(str);
57153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return 0;
57253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
57353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    } else {
57453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        oerrors = Py_None;
57553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_INCREF(Py_None);
57653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
57753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(file->f_encoding);
57853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    file->f_encoding = str;
57953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(file->f_errors);
58053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    file->f_errors = oerrors;
58153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return 1;
58253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
58353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
58453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
58553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielerr_closed(void)
58653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
58753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
58853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return NULL;
58953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
59053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
59153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
59253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielerr_mode(char *action)
59353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
59453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyErr_Format(PyExc_IOError, "File not open for %s", action);
59553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return NULL;
59653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
59753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
59853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Refuse regular file I/O if there's data in the iteration-buffer.
59953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * Mixing them would cause data to arrive out of order, as the read*
60053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * methods don't use the iteration buffer. */
60153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
60253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielerr_iterbuffered(void)
60353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
60453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyErr_SetString(PyExc_ValueError,
60553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        "Mixing iteration and read methods would lose data");
60653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return NULL;
60753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
60853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
60953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic void drop_readahead(PyFileObject *);
61053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
61153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Methods */
61253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
61353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic void
61453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_dealloc(PyFileObject *f)
61553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
61653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *ret;
61753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->weakreflist != NULL)
61853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject_ClearWeakRefs((PyObject *) f);
61953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    ret = close_the_file(f);
62053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!ret) {
62153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PySys_WriteStderr("close failed in file object destructor:\n");
62253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_Print();
62353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
62453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else {
62553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(ret);
62653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
62753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyMem_Free(f->f_setbuf);
62853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_XDECREF(f->f_name);
62953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_XDECREF(f->f_mode);
63053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_XDECREF(f->f_encoding);
63153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_XDECREF(f->f_errors);
63253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    drop_readahead(f);
63353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_TYPE(f)->tp_free((PyObject *)f);
63453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
63553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
63653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
63753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_repr(PyFileObject *f)
63853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
63953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *ret = NULL;
64053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *name = NULL;
64153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyUnicode_Check(f->f_name)) {
64253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef Py_USING_UNICODE
64353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        const char *name_str;
64453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        name = PyUnicode_AsUnicodeEscapeString(f->f_name);
64553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        name_str = name ? PyString_AsString(name) : "?";
64653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ret = PyString_FromFormat("<%s file u'%s', mode '%s' at %p>",
64753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                           f->f_fp == NULL ? "closed" : "open",
64853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                           name_str,
64953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                           PyString_AsString(f->f_mode),
65053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                           f);
65153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_XDECREF(name);
65253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return ret;
65353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
65453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    } else {
65553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        name = PyObject_Repr(f->f_name);
65653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (name == NULL)
65753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
65853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ret = PyString_FromFormat("<%s file %s, mode '%s' at %p>",
65953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                           f->f_fp == NULL ? "closed" : "open",
66053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                           PyString_AsString(name),
66153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                           PyString_AsString(f->f_mode),
66253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                           f);
66353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_XDECREF(name);
66453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return ret;
66553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
66653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
66753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
66853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
66953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_close(PyFileObject *f)
67053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
67153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *sts = close_the_file(f);
67253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (sts) {
67353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyMem_Free(f->f_setbuf);
67453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_setbuf = NULL;
67553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
67653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return sts;
67753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
67853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
67953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
68053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Our very own off_t-like type, 64-bit if possible */
68153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if !defined(HAVE_LARGEFILE_SUPPORT)
68253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanieltypedef off_t Py_off_t;
68353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#elif SIZEOF_OFF_T >= 8
68453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanieltypedef off_t Py_off_t;
68553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#elif SIZEOF_FPOS_T >= 8
68653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanieltypedef fpos_t Py_off_t;
68753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
68853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#error "Large file support, but neither off_t nor fpos_t is large enough."
68953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
69053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
69153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
69253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* a portable fseek() function
69353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   return 0 on success, non-zero on failure (with errno set) */
69453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic int
69553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel_portable_fseek(FILE *fp, Py_off_t offset, int whence)
69653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
69753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if !defined(HAVE_LARGEFILE_SUPPORT)
69853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return fseek(fp, offset, whence);
69953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#elif defined(HAVE_FSEEKO) && SIZEOF_OFF_T >= 8
70053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return fseeko(fp, offset, whence);
70153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#elif defined(HAVE_FSEEK64)
70253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return fseek64(fp, offset, whence);
70353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#elif defined(__BEOS__)
70453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return _fseek(fp, offset, whence);
70553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#elif SIZEOF_FPOS_T >= 8
70653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* lacking a 64-bit capable fseek(), use a 64-bit capable fsetpos()
70753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel       and fgetpos() to implement fseek()*/
70853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    fpos_t pos;
70953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    switch (whence) {
71053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case SEEK_END:
71153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef MS_WINDOWS
71253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        fflush(fp);
71353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (_lseeki64(fileno(fp), 0, 2) == -1)
71453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
71553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
71653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (fseek(fp, 0, SEEK_END) != 0)
71753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
71853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
71953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* fall through */
72053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case SEEK_CUR:
72153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (fgetpos(fp, &pos) != 0)
72253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
72353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        offset += pos;
72453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        break;
72553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* case SEEK_SET: break; */
72653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
72753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return fsetpos(fp, &offset);
72853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
72953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#error "Large file support, but no way to fseek."
73053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
73153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
73253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
73353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
73453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* a portable ftell() function
73553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   Return -1 on failure with errno set appropriately, current file
73653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   position on success */
73753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic Py_off_t
73853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel_portable_ftell(FILE* fp)
73953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
74053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if !defined(HAVE_LARGEFILE_SUPPORT)
74153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return ftell(fp);
74253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#elif defined(HAVE_FTELLO) && SIZEOF_OFF_T >= 8
74353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return ftello(fp);
74453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#elif defined(HAVE_FTELL64)
74553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return ftell64(fp);
74653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#elif SIZEOF_FPOS_T >= 8
74753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    fpos_t pos;
74853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (fgetpos(fp, &pos) != 0)
74953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
75053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return pos;
75153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
75253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#error "Large file support, but no way to ftell."
75353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
75453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
75553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
75653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
75753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
75853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_seek(PyFileObject *f, PyObject *args)
75953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
76053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int whence;
76153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int ret;
76253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_off_t offset;
76353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *offobj, *off_index;
76453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
76553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
76653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
76753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    drop_readahead(f);
76853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    whence = 0;
76953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &whence))
77053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
77153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    off_index = PyNumber_Index(offobj);
77253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!off_index) {
77353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!PyFloat_Check(offobj))
77453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
77553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Deprecated in 2.6 */
77653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_Clear();
77753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (PyErr_WarnEx(PyExc_DeprecationWarning,
77853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                         "integer argument expected, got float",
77953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                         1) < 0)
78053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
78153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        off_index = offobj;
78253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_INCREF(offobj);
78353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
78453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if !defined(HAVE_LARGEFILE_SUPPORT)
78553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    offset = PyInt_AsLong(off_index);
78653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
78753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    offset = PyLong_Check(off_index) ?
78853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyLong_AsLongLong(off_index) : PyInt_AsLong(off_index);
78953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
79053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(off_index);
79153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyErr_Occurred())
79253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
79353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
79453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
79553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
79653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    ret = _portable_fseek(f->f_fp, offset, whence);
79753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
79853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
79953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (ret != 0) {
80053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetFromErrno(PyExc_IOError);
80153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        clearerr(f->f_fp);
80253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
80353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
80453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_skipnextlf = 0;
80553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_INCREF(Py_None);
80653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return Py_None;
80753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
80853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
80953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
81053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef HAVE_FTRUNCATE
81153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
81253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_truncate(PyFileObject *f, PyObject *args)
81353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
81453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_off_t newsize;
81553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *newsizeobj = NULL;
81653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_off_t initialpos;
81753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int ret;
81853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
81953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
82053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
82153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!f->writable)
82253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_mode("writing");
82353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!PyArg_UnpackTuple(args, "truncate", 0, 1, &newsizeobj))
82453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
82553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
82653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* Get current file position.  If the file happens to be open for
82753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * update and the last operation was an input operation, C doesn't
82853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * define what the later fflush() will do, but we promise truncate()
82953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * won't change the current position (and fflush() *does* change it
83053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * then at least on Windows).  The easiest thing is to capture
83153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * current pos now and seek back to it at the end.
83253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     */
83353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
83453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
83553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    initialpos = _portable_ftell(f->f_fp);
83653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
83753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (initialpos == -1)
83853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        goto onioerror;
83953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
84053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* Set newsize to current postion if newsizeobj NULL, else to the
84153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * specified value.
84253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     */
84353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (newsizeobj != NULL) {
84453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if !defined(HAVE_LARGEFILE_SUPPORT)
84553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        newsize = PyInt_AsLong(newsizeobj);
84653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
84753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        newsize = PyLong_Check(newsizeobj) ?
84853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        PyLong_AsLongLong(newsizeobj) :
84953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyInt_AsLong(newsizeobj);
85053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
85153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (PyErr_Occurred())
85253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
85353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
85453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else /* default to current position */
85553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        newsize = initialpos;
85653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
85753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* Flush the stream.  We're mixing stream-level I/O with lower-level
85853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * I/O, and a flush may be necessary to synch both platform views
85953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * of the current file state.
86053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     */
86153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
86253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
86353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    ret = fflush(f->f_fp);
86453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
86553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (ret != 0)
86653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        goto onioerror;
86753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
86853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef MS_WINDOWS
86953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
87053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel       so don't even try using it. */
87153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {
87253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        HANDLE hFile;
87353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
87453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Have to move current pos to desired endpoint on Windows. */
87553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(f)
87653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        errno = 0;
87753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ret = _portable_fseek(f->f_fp, newsize, SEEK_SET) != 0;
87853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(f)
87953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (ret)
88053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            goto onioerror;
88153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
88253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Truncate.  Note that this may grow the file! */
88353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(f)
88453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        errno = 0;
88553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp));
88653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ret = hFile == (HANDLE)-1;
88753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (ret == 0) {
88853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ret = SetEndOfFile(hFile) == 0;
88953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (ret)
89053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                errno = EACCES;
89153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
89253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(f)
89353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (ret)
89453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            goto onioerror;
89553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
89653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
89753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
89853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
89953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    ret = ftruncate(fileno(f->f_fp), newsize);
90053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
90153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (ret != 0)
90253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        goto onioerror;
90353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif /* !MS_WINDOWS */
90453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
90553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* Restore original file position. */
90653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
90753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
90853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    ret = _portable_fseek(f->f_fp, initialpos, SEEK_SET) != 0;
90953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
91053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (ret)
91153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        goto onioerror;
91253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
91353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_INCREF(Py_None);
91453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return Py_None;
91553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
91653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielonioerror:
91753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyErr_SetFromErrno(PyExc_IOError);
91853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    clearerr(f->f_fp);
91953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return NULL;
92053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
92153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif /* HAVE_FTRUNCATE */
92253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
92353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
92453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_tell(PyFileObject *f)
92553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
92653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_off_t pos;
92753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
92853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
92953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
93053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
93153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
93253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    pos = _portable_ftell(f->f_fp);
93353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
93453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
93553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (pos == -1) {
93653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetFromErrno(PyExc_IOError);
93753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        clearerr(f->f_fp);
93853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
93953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
94053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_skipnextlf) {
94153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        int c;
94253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        c = GETC(f->f_fp);
94353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (c == '\n') {
94453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            f->f_newlinetypes |= NEWLINE_CRLF;
94553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            pos++;
94653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            f->f_skipnextlf = 0;
94753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } else if (c != EOF) ungetc(c, f->f_fp);
94853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
94953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if !defined(HAVE_LARGEFILE_SUPPORT)
95053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return PyInt_FromLong(pos);
95153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
95253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return PyLong_FromLongLong(pos);
95353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
95453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
95553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
95653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
95753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_fileno(PyFileObject *f)
95853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
95953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
96053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
96153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return PyInt_FromLong((long) fileno(f->f_fp));
96253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
96353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
96453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
96553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_flush(PyFileObject *f)
96653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
96753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int res;
96853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
96953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
97053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
97153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
97253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
97353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    res = fflush(f->f_fp);
97453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
97553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (res != 0) {
97653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetFromErrno(PyExc_IOError);
97753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        clearerr(f->f_fp);
97853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
97953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
98053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_INCREF(Py_None);
98153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return Py_None;
98253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
98353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
98453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
98553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_isatty(PyFileObject *f)
98653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
98753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    long res;
98853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
98953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
99053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
99153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    res = isatty((int)fileno(f->f_fp));
99253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
99353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return PyBool_FromLong(res);
99453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
99553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
99653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
99753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if BUFSIZ < 8192
99853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define SMALLCHUNK 8192
99953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
100053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define SMALLCHUNK BUFSIZ
100153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
100253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
100353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic size_t
100453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielnew_buffersize(PyFileObject *f, size_t currentsize)
100553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
100653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef HAVE_FSTAT
100753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    off_t pos, end;
100853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    struct stat st;
100953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (fstat(fileno(f->f_fp), &st) == 0) {
101053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        end = st.st_size;
101153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* The following is not a bug: we really need to call lseek()
101253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           *and* ftell().  The reason is that some stdio libraries
101353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           mistakenly flush their buffer when ftell() is called and
101453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           the lseek() call it makes fails, thereby throwing away
101553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           data that cannot be recovered in any way.  To avoid this,
101653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           we first test lseek(), and only call ftell() if lseek()
101753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           works.  We can't use the lseek() value either, because we
101853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           need to take the amount of buffered data into account.
101953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           (Yet another reason why stdio stinks. :-) */
102053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR);
102153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (pos >= 0) {
102253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            pos = ftell(f->f_fp);
102353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
102453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (pos < 0)
102553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(f->f_fp);
102653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (end > pos && pos >= 0)
102753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return currentsize + end - pos + 1;
102853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Add 1 so if the file were to grow we'd notice. */
102953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
103053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
103153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* Expand the buffer by an amount proportional to the current size,
103253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel       giving us amortized linear-time behavior. Use a less-than-double
103353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel       growth factor to avoid excessive allocation. */
103453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return currentsize + (currentsize >> 3) + 6;
103553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
103653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
103753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN
103853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK || (x) == EAGAIN)
103953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
104053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef EWOULDBLOCK
104153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK)
104253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
104353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef EAGAIN
104453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define BLOCKED_ERRNO(x) ((x) == EAGAIN)
104553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
104653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define BLOCKED_ERRNO(x) 0
104753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
104853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
104953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
105053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
105153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
105253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_read(PyFileObject *f, PyObject *args)
105353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
105453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    long bytesrequested = -1;
105553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t bytesread, buffersize, chunksize;
105653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *v;
105753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
105853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
105953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
106053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!f->readable)
106153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_mode("reading");
106253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* refuse to mix with f.next() */
106353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_buf != NULL &&
106453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        (f->f_bufend - f->f_bufptr) > 0 &&
106553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_buf[0] != '\0')
106653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_iterbuffered();
106753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
106853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
106953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (bytesrequested < 0)
107053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        buffersize = new_buffersize(f, (size_t)0);
107153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else
107253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        buffersize = bytesrequested;
107353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (buffersize > PY_SSIZE_T_MAX) {
107453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetString(PyExc_OverflowError,
107553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    "requested number of bytes is more than a Python string can hold");
107653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
107753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
107853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    v = PyString_FromStringAndSize((char *)NULL, buffersize);
107953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (v == NULL)
108053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
108153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    bytesread = 0;
108253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    for (;;) {
108353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        int interrupted;
108453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(f)
108553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        errno = 0;
108653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        chunksize = Py_UniversalNewlineFread(BUF(v) + bytesread,
108753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                  buffersize - bytesread, f->f_fp, (PyObject *)f);
108853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        interrupted = ferror(f->f_fp) && errno == EINTR;
108953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(f)
109053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (interrupted) {
109153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(f->f_fp);
109253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (PyErr_CheckSignals()) {
109353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                Py_DECREF(v);
109453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return NULL;
109553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
109653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
109753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (chunksize == 0) {
109853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (interrupted)
109953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                continue;
110053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (!ferror(f->f_fp))
110153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                break;
110253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(f->f_fp);
110353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* When in non-blocking mode, data shouldn't
110453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             * be discarded if a blocking signal was
110553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             * received. That will also happen if
110653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             * chunksize != 0, but bytesread < buffersize. */
110753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (bytesread > 0 && BLOCKED_ERRNO(errno))
110853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                break;
110953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetFromErrno(PyExc_IOError);
111053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(v);
111153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
111253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
111353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        bytesread += chunksize;
111453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (bytesread < buffersize && !interrupted) {
111553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(f->f_fp);
111653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
111753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
111853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (bytesrequested < 0) {
111953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            buffersize = new_buffersize(f, buffersize);
112053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (_PyString_Resize(&v, buffersize) < 0)
112153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return NULL;
112253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } else {
112353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* Got what was requested. */
112453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
112553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
112653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
112753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (bytesread != buffersize && _PyString_Resize(&v, bytesread))
112853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
112953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return v;
113053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
113153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
113253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
113353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_readinto(PyFileObject *f, PyObject *args)
113453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
113553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *ptr;
113653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_ssize_t ntodo;
113753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_ssize_t ndone, nnow;
113853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_buffer pbuf;
113953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
114053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
114153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
114253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!f->readable)
114353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_mode("reading");
114453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* refuse to mix with f.next() */
114553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_buf != NULL &&
114653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        (f->f_bufend - f->f_bufptr) > 0 &&
114753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_buf[0] != '\0')
114853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_iterbuffered();
114953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!PyArg_ParseTuple(args, "w*", &pbuf))
115053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
115153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    ptr = pbuf.buf;
115253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    ntodo = pbuf.len;
115353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    ndone = 0;
115453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    while (ntodo > 0) {
115553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        int interrupted;
115653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(f)
115753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        errno = 0;
115853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        nnow = Py_UniversalNewlineFread(ptr+ndone, ntodo, f->f_fp,
115953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                        (PyObject *)f);
116053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        interrupted = ferror(f->f_fp) && errno == EINTR;
116153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(f)
116253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (interrupted) {
116353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(f->f_fp);
116453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (PyErr_CheckSignals()) {
116553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyBuffer_Release(&pbuf);
116653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return NULL;
116753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
116853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
116953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (nnow == 0) {
117053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (interrupted)
117153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                continue;
117253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (!ferror(f->f_fp))
117353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                break;
117453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetFromErrno(PyExc_IOError);
117553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(f->f_fp);
117653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyBuffer_Release(&pbuf);
117753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
117853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
117953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ndone += nnow;
118053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ntodo -= nnow;
118153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
118253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyBuffer_Release(&pbuf);
118353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return PyInt_FromSsize_t(ndone);
118453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
118553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
118653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/**************************************************************************
118753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielRoutine to get next line using platform fgets().
118853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
118953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielUnder MSVC 6:
119053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
119153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel+ MS threadsafe getc is very slow (multiple layers of function calls before+
119253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel  after each character, to lock+unlock the stream).
119353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel+ The stream-locking functions are MS-internal -- can't access them from user
119453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel  code.
119553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel+ There's nothing Tim could find in the MS C or platform SDK libraries that
119653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel  can worm around this.
119753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel+ MS fgets locks/unlocks only once per line; it's the only hook we have.
119853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
119953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielSo we use fgets for speed(!), despite that it's painful.
120053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
120153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielMS realloc is also slow.
120253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
120353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielReports from other platforms on this method vs getc_unlocked (which MS doesn't
120453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielhave):
120553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Linux               a wash
120653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Solaris             a wash
120753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Tru64 Unix          getline_via_fgets significantly faster
120853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
120953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielCAUTION:  The C std isn't clear about this:  in those cases where fgets
121053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielwrites something into the buffer, can it write into any position beyond the
121153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielrequired trailing null byte?  MSVC 6 fgets does not, and no platform is (yet)
121253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielknown on which it does; and it would be a strange way to code fgets. Still,
121353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgetline_via_fgets may not work correctly if it does.  The std test
121453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanieltest_bufio.py should fail if platform fgets() routinely writes beyond the
121553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanieltrailing null byte.  #define DONT_USE_FGETS_IN_GETLINE to disable this code.
121653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel**************************************************************************/
121753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
121853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Use this routine if told to, or by default on non-get_unlocked()
121953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * platforms unless told not to.  Yikes!  Let's spell that out:
122053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * On a platform with getc_unlocked():
122153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel *     By default, use getc_unlocked().
122253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel *     If you want to use fgets() instead, #define USE_FGETS_IN_GETLINE.
122353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * On a platform without getc_unlocked():
122453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel *     By default, use fgets().
122553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel *     If you don't want to use fgets(), #define DONT_USE_FGETS_IN_GETLINE.
122653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel */
122753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if !defined(USE_FGETS_IN_GETLINE) && !defined(HAVE_GETC_UNLOCKED)
122853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define USE_FGETS_IN_GETLINE
122953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
123053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
123153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if defined(DONT_USE_FGETS_IN_GETLINE) && defined(USE_FGETS_IN_GETLINE)
123253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#undef USE_FGETS_IN_GETLINE
123353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
123453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
123553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef USE_FGETS_IN_GETLINE
123653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject*
123753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgetline_via_fgets(PyFileObject *f, FILE *fp)
123853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
123953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* INITBUFSIZE is the maximum line length that lets us get away with the fast
124053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * no-realloc, one-fgets()-call path.  Boosting it isn't free, because we have
124153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * to fill this much of the buffer with a known value in order to figure out
124253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * how much of the buffer fgets() overwrites.  So if INITBUFSIZE is larger
124353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * than "most" lines, we waste time filling unused buffer slots.  100 is
124453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * surely adequate for most peoples' email archives, chewing over source code,
124553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * etc -- "regular old text files".
124653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * MAXBUFSIZE is the maximum line length that lets us get away with the less
124753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * fast (but still zippy) no-realloc, two-fgets()-call path.  See above for
124853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * cautions about boosting that.  300 was chosen because the worst real-life
124953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * text-crunching job reported on Python-Dev was a mail-log crawler where over
125053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * half the lines were 254 chars.
125153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel */
125253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define INITBUFSIZE 100
125353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define MAXBUFSIZE 300
125453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char* p;            /* temp */
125553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char buf[MAXBUFSIZE];
125653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject* v;        /* the string object result */
125753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char* pvfree;       /* address of next free slot */
125853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char* pvend;    /* address one beyond last free slot */
125953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t nfree;       /* # of free buffer slots; pvend-pvfree */
126053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t total_v_size;  /* total # of slots in buffer */
126153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t increment;           /* amount to increment the buffer */
126253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t prev_v_size;
126353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
126453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* Optimize for normal case:  avoid _PyString_Resize if at all
126553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * possible via first reading into stack buffer "buf".
126653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     */
126753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    total_v_size = INITBUFSIZE;         /* start small and pray */
126853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    pvfree = buf;
126953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    for (;;) {
127053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(f)
127153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        pvend = buf + total_v_size;
127253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        nfree = pvend - pvfree;
127353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        memset(pvfree, '\n', nfree);
127453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        assert(nfree < INT_MAX); /* Should be atmost MAXBUFSIZE */
127553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        p = fgets(pvfree, (int)nfree, fp);
127653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(f)
127753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
127853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (p == NULL) {
127953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(fp);
128053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (PyErr_CheckSignals())
128153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return NULL;
128253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            v = PyString_FromStringAndSize(buf, pvfree - buf);
128353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return v;
128453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
128553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* fgets read *something* */
128653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        p = memchr(pvfree, '\n', nfree);
128753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (p != NULL) {
128853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* Did the \n come from fgets or from us?
128953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             * Since fgets stops at the first \n, and then writes
129053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             * \0, if it's from fgets a \0 must be next.  But if
129153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             * that's so, it could not have come from us, since
129253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             * the \n's we filled the buffer with have only more
129353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             * \n's to the right.
129453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             */
129553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (p+1 < pvend && *(p+1) == '\0') {
129653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* It's from fgets:  we win!  In particular,
129753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * we haven't done any mallocs yet, and can
129853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * build the final result on the first try.
129953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 */
130053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                ++p;                    /* include \n from fgets */
130153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
130253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            else {
130353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* Must be from us:  fgets didn't fill the
130453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * buffer and didn't find a newline, so it
130553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * must be the last and newline-free line of
130653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * the file.
130753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 */
130853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                assert(p > pvfree && *(p-1) == '\0');
130953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                --p;                    /* don't include \0 from fgets */
131053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
131153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            v = PyString_FromStringAndSize(buf, p - buf);
131253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return v;
131353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
131453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* yuck:  fgets overwrote all the newlines, i.e. the entire
131553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * buffer.  So this line isn't over yet, or maybe it is but
131653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * we're exactly at EOF.  If we haven't already, try using the
131753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         * rest of the stack buffer.
131853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel         */
131953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        assert(*(pvend-1) == '\0');
132053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (pvfree == buf) {
132153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            pvfree = pvend - 1;                 /* overwrite trailing null */
132253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            total_v_size = MAXBUFSIZE;
132353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
132453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else
132553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
132653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
132753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
132853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* The stack buffer isn't big enough; malloc a string object and read
132953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * into its buffer.
133053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     */
133153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    total_v_size = MAXBUFSIZE << 1;
133253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    v = PyString_FromStringAndSize((char*)NULL, (int)total_v_size);
133353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (v == NULL)
133453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return v;
133553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* copy over everything except the last null byte */
133653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    memcpy(BUF(v), buf, MAXBUFSIZE-1);
133753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    pvfree = BUF(v) + MAXBUFSIZE - 1;
133853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
133953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* Keep reading stuff into v; if it ever ends successfully, break
134053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * after setting p one beyond the end of the line.  The code here is
134153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * very much like the code above, except reads into v's buffer; see
134253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * the code above for detailed comments about the logic.
134353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     */
134453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    for (;;) {
134553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(f)
134653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        pvend = BUF(v) + total_v_size;
134753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        nfree = pvend - pvfree;
134853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        memset(pvfree, '\n', nfree);
134953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        assert(nfree < INT_MAX);
135053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        p = fgets(pvfree, (int)nfree, fp);
135153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(f)
135253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
135353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (p == NULL) {
135453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(fp);
135553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (PyErr_CheckSignals()) {
135653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                Py_DECREF(v);
135753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return NULL;
135853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
135953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            p = pvfree;
136053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
136153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
136253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        p = memchr(pvfree, '\n', nfree);
136353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (p != NULL) {
136453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (p+1 < pvend && *(p+1) == '\0') {
136553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* \n came from fgets */
136653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                ++p;
136753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                break;
136853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
136953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* \n came from us; last line of file, no newline */
137053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            assert(p > pvfree && *(p-1) == '\0');
137153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            --p;
137253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
137353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
137453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* expand buffer and try again */
137553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        assert(*(pvend-1) == '\0');
137653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        increment = total_v_size >> 2;          /* mild exponential growth */
137753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        prev_v_size = total_v_size;
137853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        total_v_size += increment;
137953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* check for overflow */
138053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (total_v_size <= prev_v_size ||
138153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            total_v_size > PY_SSIZE_T_MAX) {
138253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetString(PyExc_OverflowError,
138353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                "line is longer than a Python string can hold");
138453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(v);
138553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
138653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
138753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (_PyString_Resize(&v, (int)total_v_size) < 0)
138853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
138953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* overwrite the trailing null byte */
139053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        pvfree = BUF(v) + (prev_v_size - 1);
139153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
139253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (BUF(v) + total_v_size != p && _PyString_Resize(&v, p - BUF(v)))
139353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
139453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return v;
139553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#undef INITBUFSIZE
139653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#undef MAXBUFSIZE
139753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
139853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif  /* ifdef USE_FGETS_IN_GETLINE */
139953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
140053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Internal routine to get a line.
140153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   Size argument interpretation:
140253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   > 0: max length;
140353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   <= 0: read arbitrary line
140453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel*/
140553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
140653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
140753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielget_line(PyFileObject *f, int n)
140853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
140953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE *fp = f->f_fp;
141053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int c;
141153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *buf, *end;
141253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t total_v_size;        /* total # of slots in buffer */
141353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t used_v_size;         /* # used slots in buffer */
141453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t increment;       /* amount to increment the buffer */
141553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *v;
141653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int newlinetypes = f->f_newlinetypes;
141753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int skipnextlf = f->f_skipnextlf;
141853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int univ_newline = f->f_univ_newline;
141953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
142053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#if defined(USE_FGETS_IN_GETLINE)
142153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (n <= 0 && !univ_newline )
142253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return getline_via_fgets(f, fp);
142353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
142453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    total_v_size = n > 0 ? n : 100;
142553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    v = PyString_FromStringAndSize((char *)NULL, total_v_size);
142653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (v == NULL)
142753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
142853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    buf = BUF(v);
142953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    end = buf + total_v_size;
143053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
143153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    for (;;) {
143253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(f)
143353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FLOCKFILE(fp);
143453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (univ_newline) {
143553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            c = 'x'; /* Shut up gcc warning */
143653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            while ( buf != end && (c = GETC(fp)) != EOF ) {
143753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (skipnextlf ) {
143853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    skipnextlf = 0;
143953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    if (c == '\n') {
144053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        /* Seeing a \n here with
144153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                         * skipnextlf true means we
144253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                         * saw a \r before.
144353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                         */
144453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        newlinetypes |= NEWLINE_CRLF;
144553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        c = GETC(fp);
144653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        if (c == EOF) break;
144753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    } else {
144853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        newlinetypes |= NEWLINE_CR;
144953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    }
145053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                }
145153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (c == '\r') {
145253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    skipnextlf = 1;
145353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    c = '\n';
145453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                } else if ( c == '\n')
145553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    newlinetypes |= NEWLINE_LF;
145653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                *buf++ = c;
145753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (c == '\n') break;
145853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
145953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (c == EOF) {
146053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (ferror(fp) && errno == EINTR) {
146153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    FUNLOCKFILE(fp);
146253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    FILE_ABORT_ALLOW_THREADS(f)
146353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    f->f_newlinetypes = newlinetypes;
146453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    f->f_skipnextlf = skipnextlf;
146553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
146653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    if (PyErr_CheckSignals()) {
146753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        Py_DECREF(v);
146853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        return NULL;
146953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    }
147053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    /* We executed Python signal handlers and got no exception.
147153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                     * Now back to reading the line where we left off. */
147253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    clearerr(fp);
147353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    continue;
147453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                }
147553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (skipnextlf)
147653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    newlinetypes |= NEWLINE_CR;
147753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
147853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } else /* If not universal newlines use the normal loop */
147953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        while ((c = GETC(fp)) != EOF &&
148053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel               (*buf++ = c) != '\n' &&
148153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            buf != end)
148253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ;
148353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FUNLOCKFILE(fp);
148453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(f)
148553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_newlinetypes = newlinetypes;
148653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_skipnextlf = skipnextlf;
148753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (c == '\n')
148853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
148953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (c == EOF) {
149053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (ferror(fp)) {
149153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (errno == EINTR) {
149253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    if (PyErr_CheckSignals()) {
149353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        Py_DECREF(v);
149453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        return NULL;
149553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    }
149653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    /* We executed Python signal handlers and got no exception.
149753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                     * Now back to reading the line where we left off. */
149853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    clearerr(fp);
149953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    continue;
150053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                }
150153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyErr_SetFromErrno(PyExc_IOError);
150253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                clearerr(fp);
150353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                Py_DECREF(v);
150453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return NULL;
150553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
150653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(fp);
150753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (PyErr_CheckSignals()) {
150853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                Py_DECREF(v);
150953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return NULL;
151053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
151153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
151253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
151353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Must be because buf == end */
151453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (n > 0)
151553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
151653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        used_v_size = total_v_size;
151753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        increment = total_v_size >> 2; /* mild exponential growth */
151853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        total_v_size += increment;
151953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (total_v_size > PY_SSIZE_T_MAX) {
152053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetString(PyExc_OverflowError,
152153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                "line is longer than a Python string can hold");
152253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(v);
152353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
152453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
152553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (_PyString_Resize(&v, total_v_size) < 0)
152653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
152753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        buf = BUF(v) + used_v_size;
152853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        end = BUF(v) + total_v_size;
152953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
153053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
153153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    used_v_size = buf - BUF(v);
153253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (used_v_size != total_v_size && _PyString_Resize(&v, used_v_size))
153353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
153453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return v;
153553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
153653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
153753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* External C interface */
153853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
153953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyObject *
154053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_GetLine(PyObject *f, int n)
154153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
154253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *result;
154353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
154453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f == NULL) {
154553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_BadInternalCall();
154653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
154753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
154853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
154953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyFile_Check(f)) {
155053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyFileObject *fo = (PyFileObject *)f;
155153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (fo->f_fp == NULL)
155253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return err_closed();
155353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!fo->readable)
155453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return err_mode("reading");
155553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* refuse to mix with f.next() */
155653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (fo->f_buf != NULL &&
155753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            (fo->f_bufend - fo->f_bufptr) > 0 &&
155853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            fo->f_buf[0] != '\0')
155953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return err_iterbuffered();
156053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        result = get_line(fo, n);
156153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
156253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else {
156353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *reader;
156453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *args;
156553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
156653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        reader = PyObject_GetAttrString(f, "readline");
156753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (reader == NULL)
156853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
156953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (n <= 0)
157053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            args = PyTuple_New(0);
157153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else
157253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            args = Py_BuildValue("(i)", n);
157353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (args == NULL) {
157453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(reader);
157553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
157653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
157753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        result = PyEval_CallObject(reader, args);
157853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(reader);
157953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(args);
158053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (result != NULL && !PyString_Check(result) &&
158153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            !PyUnicode_Check(result)) {
158253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(result);
158353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            result = NULL;
158453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetString(PyExc_TypeError,
158553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                       "object.readline() returned non-string");
158653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
158753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
158853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
158953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (n < 0 && result != NULL && PyString_Check(result)) {
159053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        char *s = PyString_AS_STRING(result);
159153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_ssize_t len = PyString_GET_SIZE(result);
159253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (len == 0) {
159353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(result);
159453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            result = NULL;
159553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetString(PyExc_EOFError,
159653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                            "EOF when reading a line");
159753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
159853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else if (s[len-1] == '\n') {
159953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (result->ob_refcnt == 1) {
160053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (_PyString_Resize(&result, len-1))
160153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    return NULL;
160253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
160353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            else {
160453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyObject *v;
160553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                v = PyString_FromStringAndSize(s, len-1);
160653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                Py_DECREF(result);
160753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                result = v;
160853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
160953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
161053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
161153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef Py_USING_UNICODE
161253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (n < 0 && result != NULL && PyUnicode_Check(result)) {
161353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_UNICODE *s = PyUnicode_AS_UNICODE(result);
161453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_ssize_t len = PyUnicode_GET_SIZE(result);
161553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (len == 0) {
161653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(result);
161753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            result = NULL;
161853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetString(PyExc_EOFError,
161953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                            "EOF when reading a line");
162053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
162153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else if (s[len-1] == '\n') {
162253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (result->ob_refcnt == 1)
162353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyUnicode_Resize(&result, len-1);
162453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            else {
162553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyObject *v;
162653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                v = PyUnicode_FromUnicode(s, len-1);
162753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                Py_DECREF(result);
162853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                result = v;
162953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
163053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
163153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
163253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
163353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return result;
163453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
163553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
163653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Python method */
163753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
163853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
163953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_readline(PyFileObject *f, PyObject *args)
164053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
164153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int n = -1;
164253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
164353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
164453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
164553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!f->readable)
164653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_mode("reading");
164753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* refuse to mix with f.next() */
164853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_buf != NULL &&
164953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        (f->f_bufend - f->f_bufptr) > 0 &&
165053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_buf[0] != '\0')
165153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_iterbuffered();
165253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!PyArg_ParseTuple(args, "|i:readline", &n))
165353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
165453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (n == 0)
165553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return PyString_FromString("");
165653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (n < 0)
165753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        n = 0;
165853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return get_line(f, n);
165953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
166053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
166153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
166253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_readlines(PyFileObject *f, PyObject *args)
166353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
166453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    long sizehint = 0;
166553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *list = NULL;
166653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *line;
166753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char small_buffer[SMALLCHUNK];
166853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *buffer = small_buffer;
166953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t buffersize = SMALLCHUNK;
167053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *big_buffer = NULL;
167153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t nfilled = 0;
167253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t nread;
167353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    size_t totalread = 0;
167453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *p, *q, *end;
167553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int err;
167653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int shortread = 0;  /* bool, did the previous read come up short? */
167753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
167853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
167953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
168053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!f->readable)
168153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_mode("reading");
168253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* refuse to mix with f.next() */
168353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_buf != NULL &&
168453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        (f->f_bufend - f->f_bufptr) > 0 &&
168553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_buf[0] != '\0')
168653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_iterbuffered();
168753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
168853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
168953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if ((list = PyList_New(0)) == NULL)
169053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
169153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    for (;;) {
169253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (shortread)
169353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            nread = 0;
169453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else {
169553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            FILE_BEGIN_ALLOW_THREADS(f)
169653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            errno = 0;
169753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            nread = Py_UniversalNewlineFread(buffer+nfilled,
169853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                buffersize-nfilled, f->f_fp, (PyObject *)f);
169953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            FILE_END_ALLOW_THREADS(f)
170053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            shortread = (nread < buffersize-nfilled);
170153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
170253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (nread == 0) {
170353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            sizehint = 0;
170453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (!ferror(f->f_fp))
170553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                break;
170653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (errno == EINTR) {
170753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (PyErr_CheckSignals()) {
170853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    goto error;
170953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                }
171053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                clearerr(f->f_fp);
171153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                shortread = 0;
171253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                continue;
171353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
171453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetFromErrno(PyExc_IOError);
171553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(f->f_fp);
171653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            goto error;
171753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
171853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        totalread += nread;
171953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        p = (char *)memchr(buffer+nfilled, '\n', nread);
172053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (p == NULL) {
172153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* Need a larger buffer to fit this line */
172253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            nfilled += nread;
172353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            buffersize *= 2;
172453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (buffersize > PY_SSIZE_T_MAX) {
172553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyErr_SetString(PyExc_OverflowError,
172653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                "line is longer than a Python string can hold");
172753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                goto error;
172853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
172953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (big_buffer == NULL) {
173053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* Create the big buffer */
173153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                big_buffer = PyString_FromStringAndSize(
173253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    NULL, buffersize);
173353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (big_buffer == NULL)
173453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    goto error;
173553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                buffer = PyString_AS_STRING(big_buffer);
173653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                memcpy(buffer, small_buffer, nfilled);
173753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
173853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            else {
173953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* Grow the big buffer */
174053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if ( _PyString_Resize(&big_buffer, buffersize) < 0 )
174153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    goto error;
174253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                buffer = PyString_AS_STRING(big_buffer);
174353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
174453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            continue;
174553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
174653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        end = buffer+nfilled+nread;
174753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        q = buffer;
174853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        do {
174953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* Process complete lines */
175053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            p++;
175153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            line = PyString_FromStringAndSize(q, p-q);
175253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (line == NULL)
175353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                goto error;
175453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            err = PyList_Append(list, line);
175553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(line);
175653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (err != 0)
175753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                goto error;
175853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            q = p;
175953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            p = (char *)memchr(q, '\n', end-q);
176053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } while (p != NULL);
176153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Move the remaining incomplete line to the start */
176253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        nfilled = end-q;
176353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        memmove(buffer, q, nfilled);
176453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (sizehint > 0)
176553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (totalread >= (size_t)sizehint)
176653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                break;
176753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
176853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (nfilled != 0) {
176953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Partial last line */
177053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        line = PyString_FromStringAndSize(buffer, nfilled);
177153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (line == NULL)
177253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            goto error;
177353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (sizehint > 0) {
177453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* Need to complete the last line */
177553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyObject *rest = get_line(f, 0);
177653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (rest == NULL) {
177753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                Py_DECREF(line);
177853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                goto error;
177953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
178053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyString_Concat(&line, rest);
178153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(rest);
178253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (line == NULL)
178353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                goto error;
178453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
178553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        err = PyList_Append(list, line);
178653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(line);
178753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (err != 0)
178853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            goto error;
178953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
179053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
179153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielcleanup:
179253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_XDECREF(big_buffer);
179353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return list;
179453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
179553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielerror:
179653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_CLEAR(list);
179753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    goto cleanup;
179853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
179953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
180053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
180153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_write(PyFileObject *f, PyObject *args)
180253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
180353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_buffer pbuf;
180453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    const char *s;
180553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_ssize_t n, n2;
180653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *encoded = NULL;
180753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int err_flag = 0, err;
180853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
180953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
181053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
181153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!f->writable)
181253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_mode("writing");
181353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_binary) {
181453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!PyArg_ParseTuple(args, "s*", &pbuf))
181553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
181653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        s = pbuf.buf;
181753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        n = pbuf.len;
181853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
181953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else {
182053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *text;
182153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!PyArg_ParseTuple(args, "O", &text))
182253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
182353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
182453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (PyString_Check(text)) {
182553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            s = PyString_AS_STRING(text);
182653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            n = PyString_GET_SIZE(text);
182753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef Py_USING_UNICODE
182853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } else if (PyUnicode_Check(text)) {
182953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            const char *encoding, *errors;
183053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (f->f_encoding != Py_None)
183153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                encoding = PyString_AS_STRING(f->f_encoding);
183253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            else
183353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                encoding = PyUnicode_GetDefaultEncoding();
183453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (f->f_errors != Py_None)
183553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                errors = PyString_AS_STRING(f->f_errors);
183653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            else
183753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                errors = "strict";
183853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            encoded = PyUnicode_AsEncodedString(text, encoding, errors);
183953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (encoded == NULL)
184053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return NULL;
184153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            s = PyString_AS_STRING(encoded);
184253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            n = PyString_GET_SIZE(encoded);
184353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
184453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } else {
184553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (PyObject_AsCharBuffer(text, &s, &n))
184653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return NULL;
184753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
184853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
184953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_softspace = 0;
185053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
185153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
185253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    n2 = fwrite(s, 1, n, f->f_fp);
185353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (n2 != n || ferror(f->f_fp)) {
185453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        err_flag = 1;
185553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        err = errno;
185653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
185753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
185853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_XDECREF(encoded);
185953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_binary)
186053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyBuffer_Release(&pbuf);
186153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (err_flag) {
186253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        errno = err;
186353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetFromErrno(PyExc_IOError);
186453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        clearerr(f->f_fp);
186553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
186653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
186753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_INCREF(Py_None);
186853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return Py_None;
186953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
187053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
187153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
187253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_writelines(PyFileObject *f, PyObject *seq)
187353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
187453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define CHUNKSIZE 1000
187553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *list, *line;
187653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *it;       /* iter(seq) */
187753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *result;
187853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int index, islist;
187953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_ssize_t i, j, nwritten, len;
188053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
188153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(seq != NULL);
188253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
188353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
188453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!f->writable)
188553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_mode("writing");
188653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
188753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    result = NULL;
188853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    list = NULL;
188953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    islist = PyList_Check(seq);
189053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if  (islist)
189153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        it = NULL;
189253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else {
189353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        it = PyObject_GetIter(seq);
189453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (it == NULL) {
189553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetString(PyExc_TypeError,
189653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                "writelines() requires an iterable argument");
189753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
189853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
189953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* From here on, fail by going to error, to reclaim "it". */
190053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        list = PyList_New(CHUNKSIZE);
190153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (list == NULL)
190253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            goto error;
190353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
190453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
190553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* Strategy: slurp CHUNKSIZE lines into a private list,
190653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel       checking that they are all strings, then write that list
190753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel       without holding the interpreter lock, then come back for more. */
190853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    for (index = 0; ; index += CHUNKSIZE) {
190953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (islist) {
191053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_XDECREF(list);
191153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
191253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (list == NULL)
191353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                goto error;
191453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            j = PyList_GET_SIZE(list);
191553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
191653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else {
191753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            for (j = 0; j < CHUNKSIZE; j++) {
191853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                line = PyIter_Next(it);
191953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (line == NULL) {
192053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    if (PyErr_Occurred())
192153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        goto error;
192253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    break;
192353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                }
192453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyList_SetItem(list, j, line);
192553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
192653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* The iterator might have closed the file on us. */
192753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (f->f_fp == NULL) {
192853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                err_closed();
192953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                goto error;
193053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
193153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
193253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (j == 0)
193353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
193453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
193553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Check that all entries are indeed strings. If not,
193653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           apply the same rules as for file.write() and
193753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           convert the results to strings. This is slow, but
193853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           seems to be the only way since all conversion APIs
193953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           could potentially execute Python code. */
194053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        for (i = 0; i < j; i++) {
194153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyObject *v = PyList_GET_ITEM(list, i);
194253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (!PyString_Check(v)) {
194353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                const char *buffer;
194453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                int res;
194553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (f->f_binary) {
194653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    res = PyObject_AsReadBuffer(v, (const void**)&buffer, &len);
194753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                } else {
194853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    res = PyObject_AsCharBuffer(v, &buffer, &len);
194953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                }
195053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (res) {
195153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    PyErr_SetString(PyExc_TypeError,
195253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            "writelines() argument must be a sequence of strings");
195353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                            goto error;
195453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                }
195553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                line = PyString_FromStringAndSize(buffer,
195653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                                  len);
195753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (line == NULL)
195853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    goto error;
195953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                Py_DECREF(v);
196053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyList_SET_ITEM(list, i, line);
196153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
196253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
196353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
196453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Since we are releasing the global lock, the
196553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           following code may *not* execute Python code. */
196653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_softspace = 0;
196753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(f)
196853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        errno = 0;
196953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        for (i = 0; i < j; i++) {
197053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            line = PyList_GET_ITEM(list, i);
197153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            len = PyString_GET_SIZE(line);
197253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            nwritten = fwrite(PyString_AS_STRING(line),
197353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                              1, len, f->f_fp);
197453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (nwritten != len) {
197553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                FILE_ABORT_ALLOW_THREADS(f)
197653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyErr_SetFromErrno(PyExc_IOError);
197753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                clearerr(f->f_fp);
197853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                goto error;
197953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
198053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
198153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(f)
198253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
198353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (j < CHUNKSIZE)
198453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
198553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
198653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
198753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_INCREF(Py_None);
198853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    result = Py_None;
198953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel  error:
199053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_XDECREF(list);
199153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_XDECREF(it);
199253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return result;
199353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#undef CHUNKSIZE
199453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
199553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
199653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
199753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_self(PyFileObject *f)
199853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
199953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
200053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
200153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_INCREF(f);
200253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return (PyObject *)f;
200353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
200453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
200553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
200653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_xreadlines(PyFileObject *f)
200753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
200853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyErr_WarnPy3k("f.xreadlines() not supported in 3.x, "
200953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                       "try 'for line in f' instead", 1) < 0)
201053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           return NULL;
201153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return file_self(f);
201253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
201353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
201453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
201553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_exit(PyObject *f, PyObject *args)
201653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
201753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *ret = PyObject_CallMethod(f, "close", NULL);
201853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!ret)
201953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* If error occurred, pass through */
202053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
202153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(ret);
202253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* We cannot return the result of close since a true
202353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * value will be interpreted as "yes, swallow the
202453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * exception if one was raised inside the with block". */
202553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_RETURN_NONE;
202653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
202753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
202853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(readline_doc,
202953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"readline([size]) -> next line from the file, as a string.\n"
203053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
203153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Retain newline.  A non-negative size argument limits the maximum\n"
203253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"number of bytes to return (an incomplete line may be returned then).\n"
203353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Return an empty string at EOF.");
203453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
203553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(read_doc,
203653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"read([size]) -> read at most size bytes, returned as a string.\n"
203753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
203853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"If the size argument is negative or omitted, read until EOF is reached.\n"
203953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Notice that when in non-blocking mode, less data than what was requested\n"
204053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"may be returned, even if no size parameter was given.");
204153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
204253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(write_doc,
204353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"write(str) -> None.  Write string str to file.\n"
204453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
204553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Note that due to buffering, flush() or close() may be needed before\n"
204653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"the file on disk reflects the data written.");
204753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
204853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(fileno_doc,
204953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"fileno() -> integer \"file descriptor\".\n"
205053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
205153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"This is needed for lower-level file interfaces, such os.read().");
205253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
205353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(seek_doc,
205453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"seek(offset[, whence]) -> None.  Move to new file position.\n"
205553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
205653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Argument offset is a byte count.  Optional argument whence defaults to\n"
205753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"0 (offset from start of file, offset should be >= 0); other values are 1\n"
205853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"(move relative to current position, positive or negative), and 2 (move\n"
205953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"relative to end of file, usually negative, although many platforms allow\n"
206053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"seeking beyond the end of a file).  If the file is opened in text mode,\n"
206153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"only offsets returned by tell() are legal.  Use of other offsets causes\n"
206253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"undefined behavior."
206353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
206453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Note that not all file objects are seekable.");
206553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
206653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef HAVE_FTRUNCATE
206753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(truncate_doc,
206853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"truncate([size]) -> None.  Truncate the file to at most size bytes.\n"
206953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
207053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Size defaults to the current file position, as returned by tell().");
207153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
207253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
207353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(tell_doc,
207453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"tell() -> current file position, an integer (may be a long integer).");
207553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
207653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(readinto_doc,
207753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"readinto() -> Undocumented.  Don't use this; it may go away.");
207853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
207953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(readlines_doc,
208053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"readlines([size]) -> list of strings, each a line from the file.\n"
208153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
208253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Call readline() repeatedly and return a list of the lines so read.\n"
208353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"The optional size argument, if given, is an approximate bound on the\n"
208453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"total number of bytes in the lines returned.");
208553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
208653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(xreadlines_doc,
208753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"xreadlines() -> returns self.\n"
208853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
208953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"For backward compatibility. File objects now include the performance\n"
209053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"optimizations previously implemented in the xreadlines module.");
209153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
209253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(writelines_doc,
209353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"writelines(sequence_of_strings) -> None.  Write the strings to the file.\n"
209453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
209553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Note that newlines are not added.  The sequence can be any iterable object\n"
209653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"producing strings. This is equivalent to calling write() for each string.");
209753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
209853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(flush_doc,
209953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"flush() -> None.  Flush the internal I/O buffer.");
210053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
210153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(close_doc,
210253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"close() -> None or (perhaps) an integer.  Close the file.\n"
210353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
210453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Sets data attribute .closed to True.  A closed file cannot be used for\n"
210553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"further I/O operations.  close() may be called more than once without\n"
210653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"error.  Some kinds of file objects (for example, opened by popen())\n"
210753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"may return an exit status upon closing.");
210853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
210953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(isatty_doc,
211053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"isatty() -> true or false.  True if the file is connected to a tty device.");
211153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
211253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(enter_doc,
211353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             "__enter__() -> self.");
211453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
211553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(exit_doc,
211653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel             "__exit__(*excinfo) -> None.  Closes the file.");
211753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
211853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyMethodDef file_methods[] = {
211953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"readline",  (PyCFunction)file_readline, METH_VARARGS, readline_doc},
212053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"read",      (PyCFunction)file_read,     METH_VARARGS, read_doc},
212153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"write",     (PyCFunction)file_write,    METH_VARARGS, write_doc},
212253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"fileno",    (PyCFunction)file_fileno,   METH_NOARGS,  fileno_doc},
212353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"seek",      (PyCFunction)file_seek,     METH_VARARGS, seek_doc},
212453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef HAVE_FTRUNCATE
212553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"truncate",  (PyCFunction)file_truncate, METH_VARARGS, truncate_doc},
212653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
212753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"tell",      (PyCFunction)file_tell,     METH_NOARGS,  tell_doc},
212853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"readinto",  (PyCFunction)file_readinto, METH_VARARGS, readinto_doc},
212953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"readlines", (PyCFunction)file_readlines, METH_VARARGS, readlines_doc},
213053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"xreadlines",(PyCFunction)file_xreadlines, METH_NOARGS, xreadlines_doc},
213153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"writelines",(PyCFunction)file_writelines, METH_O,     writelines_doc},
213253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"flush",     (PyCFunction)file_flush,    METH_NOARGS,  flush_doc},
213353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"close",     (PyCFunction)file_close,    METH_NOARGS,  close_doc},
213453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"isatty",    (PyCFunction)file_isatty,   METH_NOARGS,  isatty_doc},
213553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"__enter__", (PyCFunction)file_self,     METH_NOARGS,  enter_doc},
213653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"__exit__",  (PyCFunction)file_exit,     METH_VARARGS, exit_doc},
213753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {NULL,            NULL}             /* sentinel */
213853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel};
213953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
214053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define OFF(x) offsetof(PyFileObject, x)
214153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
214253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyMemberDef file_memberlist[] = {
214353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"mode",            T_OBJECT,       OFF(f_mode),    RO,
214453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     "file mode ('r', 'U', 'w', 'a', possibly with 'b' or '+' added)"},
214553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"name",            T_OBJECT,       OFF(f_name),    RO,
214653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     "file name"},
214753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"encoding",        T_OBJECT,       OFF(f_encoding),        RO,
214853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     "file encoding"},
214953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"errors",          T_OBJECT,       OFF(f_errors),  RO,
215053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     "Unicode error handler"},
215153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* getattr(f, "closed") is implemented without this table */
215253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {NULL}      /* Sentinel */
215353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel};
215453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
215553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
215653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielget_closed(PyFileObject *f, void *closure)
215753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
215853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return PyBool_FromLong((long)(f->f_fp == 0));
215953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
216053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
216153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielget_newlines(PyFileObject *f, void *closure)
216253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
216353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    switch (f->f_newlinetypes) {
216453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case NEWLINE_UNKNOWN:
216553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_INCREF(Py_None);
216653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return Py_None;
216753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case NEWLINE_CR:
216853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return PyString_FromString("\r");
216953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case NEWLINE_LF:
217053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return PyString_FromString("\n");
217153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case NEWLINE_CR|NEWLINE_LF:
217253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return Py_BuildValue("(ss)", "\r", "\n");
217353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case NEWLINE_CRLF:
217453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return PyString_FromString("\r\n");
217553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case NEWLINE_CR|NEWLINE_CRLF:
217653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return Py_BuildValue("(ss)", "\r", "\r\n");
217753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case NEWLINE_LF|NEWLINE_CRLF:
217853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return Py_BuildValue("(ss)", "\n", "\r\n");
217953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:
218053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return Py_BuildValue("(sss)", "\r", "\n", "\r\n");
218153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    default:
218253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_Format(PyExc_SystemError,
218353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                     "Unknown newlines value 0x%x\n",
218453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                     f->f_newlinetypes);
218553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
218653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
218753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
218853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
218953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
219053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielget_softspace(PyFileObject *f, void *closure)
219153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
219253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyErr_WarnPy3k("file.softspace not supported in 3.x", 1) < 0)
219353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
219453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return PyInt_FromLong(f->f_softspace);
219553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
219653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
219753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic int
219853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielset_softspace(PyFileObject *f, PyObject *value)
219953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
220053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int new;
220153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyErr_WarnPy3k("file.softspace not supported in 3.x", 1) < 0)
220253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
220353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
220453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (value == NULL) {
220553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetString(PyExc_TypeError,
220653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        "can't delete softspace attribute");
220753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
220853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
220953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
221053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    new = PyInt_AsLong(value);
221153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (new == -1 && PyErr_Occurred())
221253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
221353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_softspace = new;
221453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return 0;
221553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
221653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
221753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyGetSetDef file_getsetlist[] = {
221853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"closed", (getter)get_closed, NULL, "True if the file is closed"},
221953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"newlines", (getter)get_newlines, NULL,
222053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     "end-of-line convention used in this file"},
222153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {"softspace", (getter)get_softspace, (setter)set_softspace,
222253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     "flag indicating that a space needs to be printed; used by print"},
222353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {0},
222453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel};
222553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
222653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic void
222753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanieldrop_readahead(PyFileObject *f)
222853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
222953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_buf != NULL) {
223053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyMem_Free(f->f_buf);
223153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_buf = NULL;
223253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
223353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
223453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
223553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Make sure that file has a readahead buffer with at least one byte
223653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   (unless at EOF) and no more than bufsize.  Returns negative value on
223753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   error, will set MemoryError if bufsize bytes cannot be allocated. */
223853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic int
223953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielreadahead(PyFileObject *f, Py_ssize_t bufsize)
224053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
224153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_ssize_t chunksize;
224253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
224353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_buf != NULL) {
224453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if( (f->f_bufend - f->f_bufptr) >= 1)
224553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return 0;
224653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else
224753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            drop_readahead(f);
224853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
224953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if ((f->f_buf = (char *)PyMem_Malloc(bufsize)) == NULL) {
225053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_NoMemory();
225153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
225253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
225353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_BEGIN_ALLOW_THREADS(f)
225453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    errno = 0;
225553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    chunksize = Py_UniversalNewlineFread(
225653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_buf, bufsize, f->f_fp, (PyObject *)f);
225753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FILE_END_ALLOW_THREADS(f)
225853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (chunksize == 0) {
225953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (ferror(f->f_fp)) {
226053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetFromErrno(PyExc_IOError);
226153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            clearerr(f->f_fp);
226253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            drop_readahead(f);
226353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
226453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
226553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
226653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_bufptr = f->f_buf;
226753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_bufend = f->f_buf + chunksize;
226853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return 0;
226953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
227053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
227153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Used by file_iternext.  The returned string will start with 'skip'
227253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   uninitialized bytes followed by the remainder of the line. Don't be
227353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   horrified by the recursive call: maximum recursion depth is limited by
227453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   logarithmic buffer growth to about 50 even when reading a 1gb line. */
227553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
227653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyStringObject *
227753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielreadahead_get_line_skip(PyFileObject *f, Py_ssize_t skip, Py_ssize_t bufsize)
227853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
227953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyStringObject* s;
228053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *bufptr;
228153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *buf;
228253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_ssize_t len;
228353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
228453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_buf == NULL)
228553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (readahead(f, bufsize) < 0)
228653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
228753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
228853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    len = f->f_bufend - f->f_bufptr;
228953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (len == 0)
229053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return (PyStringObject *)
229153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyString_FromStringAndSize(NULL, skip);
229253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    bufptr = (char *)memchr(f->f_bufptr, '\n', len);
229353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (bufptr != NULL) {
229453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        bufptr++;                               /* Count the '\n' */
229553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        len = bufptr - f->f_bufptr;
229653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        s = (PyStringObject *)
229753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyString_FromStringAndSize(NULL, skip + len);
229853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (s == NULL)
229953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
230053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        memcpy(PyString_AS_STRING(s) + skip, f->f_bufptr, len);
230153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_bufptr = bufptr;
230253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (bufptr == f->f_bufend)
230353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            drop_readahead(f);
230453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    } else {
230553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        bufptr = f->f_bufptr;
230653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        buf = f->f_buf;
230753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        f->f_buf = NULL;                /* Force new readahead buffer */
230853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        assert(len <= PY_SSIZE_T_MAX - skip);
230953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        s = readahead_get_line_skip(f, skip + len, bufsize + (bufsize>>2));
231053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (s == NULL) {
231153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyMem_Free(buf);
231253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
231353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
231453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        memcpy(PyString_AS_STRING(s) + skip, bufptr, len);
231553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyMem_Free(buf);
231653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
231753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return s;
231853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
231953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
232053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* A larger buffer size may actually decrease performance. */
232153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#define READAHEAD_BUFSIZE 8192
232253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
232353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
232453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_iternext(PyFileObject *f)
232553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
232653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyStringObject* l;
232753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
232853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f->f_fp == NULL)
232953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_closed();
233053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!f->readable)
233153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err_mode("reading");
233253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
233353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    l = readahead_get_line_skip(f, 0, READAHEAD_BUFSIZE);
233453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (l == NULL || PyString_GET_SIZE(l) == 0) {
233553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_XDECREF(l);
233653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
233753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
233853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return (PyObject *)l;
233953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
234053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
234153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
234253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject *
234353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
234453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
234553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *self;
234653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    static PyObject *not_yet_string;
234753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
234853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(type != NULL && type->tp_alloc != NULL);
234953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
235053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (not_yet_string == NULL) {
235153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        not_yet_string = PyString_InternFromString("<uninitialized file>");
235253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (not_yet_string == NULL)
235353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
235453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
235553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
235653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    self = type->tp_alloc(type, 0);
235753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (self != NULL) {
235853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Always fill in the name and mode, so that nobody else
235953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           needs to special-case NULLs there. */
236053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_INCREF(not_yet_string);
236153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ((PyFileObject *)self)->f_name = not_yet_string;
236253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_INCREF(not_yet_string);
236353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ((PyFileObject *)self)->f_mode = not_yet_string;
236453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_INCREF(Py_None);
236553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ((PyFileObject *)self)->f_encoding = Py_None;
236653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_INCREF(Py_None);
236753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ((PyFileObject *)self)->f_errors = Py_None;
236853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ((PyFileObject *)self)->weakreflist = NULL;
236953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ((PyFileObject *)self)->unlocked_count = 0;
237053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
237153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return self;
237253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
237353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
237453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic int
237553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfile_init(PyObject *self, PyObject *args, PyObject *kwds)
237653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
237753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyFileObject *foself = (PyFileObject *)self;
237853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int ret = 0;
237953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    static char *kwlist[] = {"name", "mode", "buffering", 0};
238053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *name = NULL;
238153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *mode = "r";
238253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int bufsize = -1;
238353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int wideargument = 0;
238453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef MS_WINDOWS
238553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *po;
238653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
238753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
238853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(PyFile_Check(self));
238953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (foself->f_fp != NULL) {
239053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Have to close the existing file first. */
239153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *closeresult = file_close(foself);
239253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (closeresult == NULL)
239353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
239453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(closeresult);
239553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
239653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
239753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef MS_WINDOWS
239853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:file",
239953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                    kwlist, &po, &mode, &bufsize)) {
240053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        wideargument = 1;
240153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (fill_file_fields(foself, NULL, po, mode,
240253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                             fclose) == NULL)
240353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            goto Error;
240453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    } else {
240553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Drop the argument parsing error as narrow
240653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel           strings are also valid. */
240753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_Clear();
240853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
240953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
241053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
241153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!wideargument) {
241253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *o_name;
241353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
241453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,
241553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                         Py_FileSystemDefaultEncoding,
241653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                         &name,
241753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                         &mode, &bufsize))
241853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
241953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
242053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* We parse again to get the name as a PyObject */
242153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:file",
242253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                         kwlist, &o_name, &mode,
242353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                                         &bufsize))
242453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            goto Error;
242553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
242653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (fill_file_fields(foself, NULL, o_name, mode,
242753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                             fclose) == NULL)
242853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            goto Error;
242953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
243053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (open_the_file(foself, name, mode) == NULL)
243153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        goto Error;
243253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    foself->f_setbuf = NULL;
243353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyFile_SetBufSize(self, bufsize);
243453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    goto Done;
243553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
243653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielError:
243753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    ret = -1;
243853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* fall through */
243953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielDone:
244053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyMem_Free(name); /* free the encoded string */
244153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return ret;
244253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
244353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
244453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_VAR(file_doc) =
244553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STR(
244653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"file(name[, mode[, buffering]]) -> file object\n"
244753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
244853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Open a file.  The mode can be 'r', 'w' or 'a' for reading (default),\n"
244953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"writing or appending.  The file will be created if it doesn't exist\n"
245053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"when opened for writing or appending; it will be truncated when\n"
245153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"opened for writing.  Add a 'b' to the mode for binary files.\n"
245253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Add a '+' to the mode to allow simultaneous reading and writing.\n"
245353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"If the buffering argument is given, 0 means unbuffered, 1 means line\n"
245453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"buffered, and larger numbers specify the buffer size.  The preferred way\n"
245553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"to open a file is with the builtin open() function.\n"
245653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel)
245753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STR(
245853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Add a 'U' to mode to open the file for input with universal newline\n"
245953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"support.  Any line ending in the input file will be seen as a '\\n'\n"
246053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"in Python.  Also, a file so opened gains the attribute 'newlines';\n"
246153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"the value for this attribute is one of None (no newline read yet),\n"
246253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"'\\r', '\\n', '\\r\\n' or a tuple containing all the newline types seen.\n"
246353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"\n"
246453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"'U' cannot be combined with 'w' or '+' mode.\n"
246553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel);
246653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
246753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyTypeObject PyFile_Type = {
246853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyVarObject_HEAD_INIT(&PyType_Type, 0)
246953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    "file",
247053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    sizeof(PyFileObject),
247153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,
247253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    (destructor)file_dealloc,                   /* tp_dealloc */
247353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_print */
247453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_getattr */
247553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_setattr */
247653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_compare */
247753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    (reprfunc)file_repr,                        /* tp_repr */
247853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_as_number */
247953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_as_sequence */
248053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_as_mapping */
248153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_hash */
248253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_call */
248353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_str */
248453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject_GenericGetAttr,                    /* tp_getattro */
248553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* softspace is writable:  we must supply tp_setattro */
248653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject_GenericSetAttr,                    /* tp_setattro */
248753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_as_buffer */
248853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
248953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    file_doc,                                   /* tp_doc */
249053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_traverse */
249153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_clear */
249253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_richcompare */
249353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    offsetof(PyFileObject, weakreflist),        /* tp_weaklistoffset */
249453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    (getiterfunc)file_self,                     /* tp_iter */
249553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    (iternextfunc)file_iternext,                /* tp_iternext */
249653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    file_methods,                               /* tp_methods */
249753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    file_memberlist,                            /* tp_members */
249853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    file_getsetlist,                            /* tp_getset */
249953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_base */
250053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_dict */
250153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_descr_get */
250253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_descr_set */
250353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    0,                                          /* tp_dictoffset */
250453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    file_init,                                  /* tp_init */
250553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyType_GenericAlloc,                        /* tp_alloc */
250653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    file_new,                                   /* tp_new */
250753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject_Del,                           /* tp_free */
250853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel};
250953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
251053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Interface for the 'soft space' between print items. */
251153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
251253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielint
251353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_SoftSpace(PyObject *f, int newflag)
251453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
251553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    long oldflag = 0;
251653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f == NULL) {
251753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Do nothing */
251853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
251953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else if (PyFile_Check(f)) {
252053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        oldflag = ((PyFileObject *)f)->f_softspace;
252153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ((PyFileObject *)f)->f_softspace = newflag;
252253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
252353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else {
252453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *v;
252553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        v = PyObject_GetAttrString(f, "softspace");
252653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (v == NULL)
252753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_Clear();
252853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else {
252953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (PyInt_Check(v))
253053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                oldflag = PyInt_AsLong(v);
253153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            assert(oldflag < INT_MAX);
253253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(v);
253353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
253453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        v = PyInt_FromLong((long)newflag);
253553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (v == NULL)
253653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_Clear();
253753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else {
253853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (PyObject_SetAttrString(f, "softspace", v) != 0)
253953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                PyErr_Clear();
254053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(v);
254153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
254253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
254353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return (int)oldflag;
254453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
254553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
254653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Interfaces to write objects/strings to file-like objects */
254753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
254853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielint
254953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_WriteObject(PyObject *v, PyObject *f, int flags)
255053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
255153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *writer, *value, *args, *result;
255253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f == NULL) {
255353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");
255453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
255553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
255653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else if (PyFile_Check(f)) {
255753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyFileObject *fobj = (PyFileObject *) f;
255853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef Py_USING_UNICODE
255953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *enc = fobj->f_encoding;
256053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        int result;
256153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
256253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (fobj->f_fp == NULL) {
256353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            err_closed();
256453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
256553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
256653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef Py_USING_UNICODE
256753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if ((flags & Py_PRINT_RAW) &&
256853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyUnicode_Check(v) && enc != Py_None) {
256953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            char *cenc = PyString_AS_STRING(enc);
257053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            char *errors = fobj->f_errors == Py_None ?
257153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel              "strict" : PyString_AS_STRING(fobj->f_errors);
257253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            value = PyUnicode_AsEncodedString(v, cenc, errors);
257353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (value == NULL)
257453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                return -1;
257553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } else {
257653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            value = v;
257753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_INCREF(value);
257853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
257953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        result = file_PyObject_Print(value, fobj, flags);
258053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(value);
258153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return result;
258253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#else
258353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return file_PyObject_Print(v, fobj, flags);
258453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
258553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
258653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    writer = PyObject_GetAttrString(f, "write");
258753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (writer == NULL)
258853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
258953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (flags & Py_PRINT_RAW) {
259053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (PyUnicode_Check(v)) {
259153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            value = v;
259253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_INCREF(value);
259353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } else
259453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            value = PyObject_Str(v);
259553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
259653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else
259753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        value = PyObject_Repr(v);
259853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (value == NULL) {
259953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(writer);
260053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
260153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
260253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    args = PyTuple_Pack(1, value);
260353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (args == NULL) {
260453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(value);
260553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(writer);
260653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
260753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
260853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    result = PyEval_CallObject(writer, args);
260953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(args);
261053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(value);
261153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(writer);
261253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (result == NULL)
261353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
261453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    Py_DECREF(result);
261553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return 0;
261653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
261753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
261853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielint
261953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyFile_WriteString(const char *s, PyObject *f)
262053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
262153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
262253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (f == NULL) {
262353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* Should be caused by a pre-existing error */
262453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!PyErr_Occurred())
262553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetString(PyExc_SystemError,
262653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                            "null file for PyFile_WriteString");
262753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
262853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
262953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else if (PyFile_Check(f)) {
263053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyFileObject *fobj = (PyFileObject *) f;
263153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE *fp = PyFile_AsFile(f);
263253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (fp == NULL) {
263353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            err_closed();
263453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
263553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
263653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_BEGIN_ALLOW_THREADS(fobj)
263753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        fputs(s, fp);
263853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        FILE_END_ALLOW_THREADS(fobj)
263953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return 0;
264053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
264153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else if (!PyErr_Occurred()) {
264253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *v = PyString_FromString(s);
264353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        int err;
264453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (v == NULL)
264553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
264653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
264753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(v);
264853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return err;
264953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
265053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else
265153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
265253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
265353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
265453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Try to get a file-descriptor from a Python object.  If the object
265553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   is an integer or long integer, its value is returned.  If not, the
265653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   object's fileno() method is called if it exists; the method must return
265753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   an integer or long integer, which is returned as the file descriptor value.
265853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel   -1 is returned on failure.
265953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel*/
266053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
266153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielint PyObject_AsFileDescriptor(PyObject *o)
266253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
266353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int fd;
266453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyObject *meth;
266553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
266653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (PyInt_Check(o)) {
266753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        fd = _PyInt_AsInt(o);
266853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
266953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else if (PyLong_Check(o)) {
267053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        fd = _PyLong_AsInt(o);
267153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
267253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)
267353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    {
267453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyObject *fno = PyEval_CallObject(meth, NULL);
267553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        Py_DECREF(meth);
267653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (fno == NULL)
267753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
267853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
267953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (PyInt_Check(fno)) {
268053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            fd = _PyInt_AsInt(fno);
268153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(fno);
268253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
268353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else if (PyLong_Check(fno)) {
268453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            fd = _PyLong_AsInt(fno);
268553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(fno);
268653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
268753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        else {
268853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            PyErr_SetString(PyExc_TypeError,
268953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                            "fileno() returned a non-integer");
269053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            Py_DECREF(fno);
269153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return -1;
269253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
269353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
269453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    else {
269553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_SetString(PyExc_TypeError,
269653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                        "argument must be an int, or have a fileno() method.");
269753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
269853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
269953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
270053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (fd < 0) {
270153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        PyErr_Format(PyExc_ValueError,
270253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                     "file descriptor cannot be a negative integer (%i)",
270353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                     fd);
270453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return -1;
270553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
270653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return fd;
270753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
270853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
270953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* From here on we need access to the real fgets and fread */
271053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#undef fgets
271153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#undef fread
271253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
271353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/*
271453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** Py_UniversalNewlineFgets is an fgets variation that understands
271553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** all of \r, \n and \r\n conventions.
271653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** The stream should be opened in binary mode.
271753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** If fobj is NULL the routine always does newline conversion, and
271853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** it may peek one char ahead to gobble the second char in \r\n.
271953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** If fobj is non-NULL it must be a PyFileObject. In this case there
272053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** is no readahead but in stead a flag is used to skip a following
272153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** \n on the next read. Also, if the file is open in binary mode
272253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** the whole conversion is skipped. Finally, the routine keeps track of
272353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** the different types of newlines seen.
272453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** Note that we need no error handling: fgets() treats error and eof
272553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** identically.
272653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel*/
272753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielchar *
272853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPy_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
272953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
273053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *p = buf;
273153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int c;
273253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int newlinetypes = 0;
273353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int skipnextlf = 0;
273453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int univ_newline = 1;
273553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
273653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (fobj) {
273753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (!PyFile_Check(fobj)) {
273853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            errno = ENXIO;              /* What can you do... */
273953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return NULL;
274053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
274153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        univ_newline = ((PyFileObject *)fobj)->f_univ_newline;
274253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if ( !univ_newline )
274353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            return fgets(buf, n, stream);
274453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        newlinetypes = ((PyFileObject *)fobj)->f_newlinetypes;
274553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        skipnextlf = ((PyFileObject *)fobj)->f_skipnextlf;
274653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
274753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FLOCKFILE(stream);
274853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    c = 'x'; /* Shut up gcc warning */
274953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    while (--n > 0 && (c = GETC(stream)) != EOF ) {
275053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (skipnextlf ) {
275153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            skipnextlf = 0;
275253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (c == '\n') {
275353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* Seeing a \n here with skipnextlf true
275453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                ** means we saw a \r before.
275553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                */
275653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                newlinetypes |= NEWLINE_CRLF;
275753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                c = GETC(stream);
275853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (c == EOF) break;
275953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            } else {
276053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /*
276153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                ** Note that c == EOF also brings us here,
276253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                ** so we're okay if the last char in the file
276353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                ** is a CR.
276453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                */
276553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                newlinetypes |= NEWLINE_CR;
276653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
276753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
276853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (c == '\r') {
276953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* A \r is translated into a \n, and we skip
277053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ** an adjacent \n, if any. We don't set the
277153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ** newlinetypes flag until we've seen the next char.
277253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            */
277353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            skipnextlf = 1;
277453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            c = '\n';
277553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        } else if ( c == '\n') {
277653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            newlinetypes |= NEWLINE_LF;
277753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
277853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        *p++ = c;
277953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (c == '\n') break;
278053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
278153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if ( c == EOF && skipnextlf )
278253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        newlinetypes |= NEWLINE_CR;
278353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    FUNLOCKFILE(stream);
278453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    *p = '\0';
278553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (fobj) {
278653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ((PyFileObject *)fobj)->f_newlinetypes = newlinetypes;
278753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ((PyFileObject *)fobj)->f_skipnextlf = skipnextlf;
278853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    } else if ( skipnextlf ) {
278953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        /* If we have no file object we cannot save the
279053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ** skipnextlf flag. We have to readahead, which
279153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ** will cause a pause if we're reading from an
279253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ** interactive stream, but that is very unlikely
279353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ** unless we're doing something silly like
279453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        ** execfile("/dev/tty").
279553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        */
279653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        c = GETC(stream);
279753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if ( c != '\n' )
279853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            ungetc(c, stream);
279953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
280053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (p == buf)
280153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return NULL;
280253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return buf;
280353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
280453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
280553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/*
280653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** Py_UniversalNewlineFread is an fread variation that understands
280753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** all of \r, \n and \r\n conventions.
280853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** The stream should be opened in binary mode.
280953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** fobj must be a PyFileObject. In this case there
281053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** is no readahead but in stead a flag is used to skip a following
281153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** \n on the next read. Also, if the file is open in binary mode
281253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** the whole conversion is skipped. Finally, the routine keeps track of
281353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel** the different types of newlines seen.
281453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel*/
281553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielsize_t
281653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPy_UniversalNewlineFread(char *buf, size_t n,
281753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                         FILE *stream, PyObject *fobj)
281853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{
281953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    char *dst = buf;
282053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    PyFileObject *f = (PyFileObject *)fobj;
282153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    int newlinetypes, skipnextlf;
282253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
282353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(buf != NULL);
282453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    assert(stream != NULL);
282553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
282653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!fobj || !PyFile_Check(fobj)) {
282753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        errno = ENXIO;          /* What can you do... */
282853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return 0;
282953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
283053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    if (!f->f_univ_newline)
283153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        return fread(buf, 1, n, stream);
283253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    newlinetypes = f->f_newlinetypes;
283353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    skipnextlf = f->f_skipnextlf;
283453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    /* Invariant:  n is the number of bytes remaining to be filled
283553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     * in the buffer.
283653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel     */
283753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    while (n) {
283853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        size_t nread;
283953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        int shortread;
284053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        char *src = dst;
284153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
284253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        nread = fread(dst, 1, n, stream);
284353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        assert(nread <= n);
284453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (nread == 0)
284553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
284653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
284753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        n -= nread; /* assuming 1 byte out for each in; will adjust */
284853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        shortread = n != 0;             /* true iff EOF or error */
284953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        while (nread--) {
285053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            char c = *src++;
285153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (c == '\r') {
285253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* Save as LF and set flag to skip next LF. */
285353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                *dst++ = '\n';
285453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                skipnextlf = 1;
285553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
285653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            else if (skipnextlf && c == '\n') {
285753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* Skip LF, and remember we saw CR LF. */
285853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                skipnextlf = 0;
285953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                newlinetypes |= NEWLINE_CRLF;
286053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                ++n;
286153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
286253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            else {
286353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                /* Normal char to be stored in buffer.  Also
286453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * update the newlinetypes flag if either this
286553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 * is an LF or the previous char was a CR.
286653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                 */
286753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                if (c == '\n')
286853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    newlinetypes |= NEWLINE_LF;
286953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                else if (skipnextlf)
287053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                    newlinetypes |= NEWLINE_CR;
287153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                *dst++ = c;
287253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                skipnextlf = 0;
287353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            }
287453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
287553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        if (shortread) {
287653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            /* If this is EOF, update type flags. */
287753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            if (skipnextlf && feof(stream))
287853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel                newlinetypes |= NEWLINE_CR;
287953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel            break;
288053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel        }
288153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    }
288253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_newlinetypes = newlinetypes;
288353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    f->f_skipnextlf = skipnextlf;
288453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel    return dst - buf;
288553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
288653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel
288753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef __cplusplus
288853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}
288953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif
2890