bpo-29176 Use tmpfile() in curses module (#235)

The curses module used mkstemp() + fopen() to create a temporary file in
/tmp. The /tmp directory does not exist on Android. The tmpfile()
function simplifies the task a lot. It creates a temporary file in a
correct directory, takes care of cleanup and returns FILE*.

tmpfile is supported on all platforms (C89, POSIX 2001, Android,
Windows).

Signed-off-by: Christian Heimes <christian@python.org>
This commit is contained in:
Christian Heimes 2017-03-02 11:09:01 +01:00 committed by Victor Stinner
parent cb90f26122
commit 2b221b78d6
1 changed files with 15 additions and 37 deletions

View File

@ -1720,22 +1720,14 @@ PyCursesWindow_PutWin(PyCursesWindowObject *self, PyObject *stream)
{ {
/* We have to simulate this by writing to a temporary FILE*, /* We have to simulate this by writing to a temporary FILE*,
then reading back, then writing to the argument stream. */ then reading back, then writing to the argument stream. */
char fn[100]; FILE *fp;
int fd = -1;
FILE *fp = NULL;
PyObject *res = NULL; PyObject *res = NULL;
strcpy(fn, "/tmp/py.curses.putwin.XXXXXX"); fp = tmpfile();
fd = mkstemp(fn); if (fp == NULL)
if (fd < 0) return PyErr_SetFromErrno(PyExc_OSError);
return PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn); if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
if (_Py_set_inheritable(fd, 0, NULL) < 0)
goto exit; goto exit;
fp = fdopen(fd, "wb+");
if (fp == NULL) {
PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn);
goto exit;
}
res = PyCursesCheckERR(putwin(self->win, fp), "putwin"); res = PyCursesCheckERR(putwin(self->win, fp), "putwin");
if (res == NULL) if (res == NULL)
goto exit; goto exit;
@ -1754,11 +1746,7 @@ PyCursesWindow_PutWin(PyCursesWindowObject *self, PyObject *stream)
} }
exit: exit:
if (fp != NULL) fclose(fp);
fclose(fp);
else if (fd != -1)
close(fd);
remove(fn);
return res; return res;
} }
@ -2278,9 +2266,7 @@ PyCurses_UngetMouse(PyObject *self, PyObject *args)
static PyObject * static PyObject *
PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream) PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream)
{ {
char fn[100]; FILE *fp;
int fd = -1;
FILE *fp = NULL;
PyObject *data; PyObject *data;
size_t datalen; size_t datalen;
WINDOW *win; WINDOW *win;
@ -2289,17 +2275,13 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream)
PyCursesInitialised; PyCursesInitialised;
strcpy(fn, "/tmp/py.curses.getwin.XXXXXX"); fp = tmpfile();
fd = mkstemp(fn); if (fp == NULL)
if (fd < 0) return PyErr_SetFromErrno(PyExc_OSError);
return PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn);
if (_Py_set_inheritable(fd, 0, NULL) < 0) if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
goto error; goto error;
fp = fdopen(fd, "wb+");
if (fp == NULL) {
PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn);
goto error;
}
data = _PyObject_CallMethodId(stream, &PyId_read, NULL); data = _PyObject_CallMethodId(stream, &PyId_read, NULL);
if (data == NULL) if (data == NULL)
@ -2314,7 +2296,7 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream)
datalen = PyBytes_GET_SIZE(data); datalen = PyBytes_GET_SIZE(data);
if (fwrite(PyBytes_AS_STRING(data), 1, datalen, fp) != datalen) { if (fwrite(PyBytes_AS_STRING(data), 1, datalen, fp) != datalen) {
Py_DECREF(data); Py_DECREF(data);
PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn); PyErr_SetFromErrno(PyExc_OSError);
goto error; goto error;
} }
Py_DECREF(data); Py_DECREF(data);
@ -2328,11 +2310,7 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream)
res = PyCursesWindow_New(win, NULL); res = PyCursesWindow_New(win, NULL);
error: error:
if (fp != NULL) fclose(fp);
fclose(fp);
else if (fd != -1)
close(fd);
remove(fn);
return res; return res;
} }