Commit 1dd82a95 authored by Victor Stinner's avatar Victor Stinner

Issue #23694: Enhance _Py_fopen(), it now raises an exception on error

* If fopen() fails, OSError is raised with the original filename object.
* The GIL is now released while calling fopen()
parent 39710881
......@@ -2941,11 +2941,9 @@ load_dh_params(PySSLContext *self, PyObject *filepath)
DH *dh;
f = _Py_fopen_obj(filepath, "rb");
if (f == NULL) {
if (!PyErr_Occurred())
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath);
if (f == NULL)
return NULL;
}
errno = 0;
PySSL_BEGIN_ALLOW_THREADS
dh = PEM_read_DHparams(f, NULL, NULL, NULL);
......
......@@ -875,7 +875,7 @@ read_directory(PyObject *archive)
fp = _Py_fopen_obj(archive, "rb");
if (fp == NULL) {
if (!PyErr_Occurred())
if (PyErr_ExceptionMatches(PyExc_OSError))
PyErr_Format(ZipImportError, "can't open Zip file: %R", archive);
return NULL;
}
......@@ -1073,12 +1073,8 @@ get_data(PyObject *archive, PyObject *toc_entry)
}
fp = _Py_fopen_obj(archive, "rb");
if (!fp) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_IOError,
"zipimport: can not open file %U", archive);
if (!fp)
return NULL;
}
/* Check to make sure the local file header is correct */
if (fseek(fp, file_offset, 0) == -1) {
......
......@@ -1126,6 +1126,10 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno)
if (filename == NULL || lineno <= 0)
return NULL;
fp = _Py_fopen_obj(filename, "r" PY_STDIOTEXTMODE);
if (fp == NULL) {
PyErr_Clear();
return NULL;
}
return err_programtext(fp, lineno);
}
......
......@@ -957,7 +957,7 @@ _Py_open_impl(const char *pathname, int flags, int gil_held)
The file descriptor is created non-inheritable.
The GIL must be held. Use _Py_open_noraise() if the GIL cannot be held. */
The GIL must be held. */
int
_Py_open(const char *pathname, int flags)
{
......@@ -977,8 +977,9 @@ _Py_open_noraise(const char *pathname, int flags)
}
/* Open a file. Use _wfopen() on Windows, encode the path to the locale
encoding and use fopen() otherwise. The file descriptor is created
non-inheritable. */
encoding and use fopen() otherwise.
The file descriptor is created non-inheritable). */
FILE *
_Py_wfopen(const wchar_t *path, const wchar_t *mode)
{
......@@ -1009,7 +1010,9 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
return f;
}
/* Wrapper to fopen(). The file descriptor is created non-inheritable. */
/* Wrapper to fopen().
The file descriptor is created non-inheritable). */
FILE*
_Py_fopen(const char *pathname, const char *mode)
{
......@@ -1024,11 +1027,14 @@ _Py_fopen(const char *pathname, const char *mode)
}
/* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem
encoding and call fopen() otherwise. The file descriptor is created
non-inheritable.
encoding and call fopen() otherwise.
Return the new file object on success. Raise an exception and return NULL
on error.
Return the new file object on success, or NULL if the file cannot be open or
(if PyErr_Occurred()) on unicode error. */
The file descriptor is created non-inheritable.
The GIL must be held. */
FILE*
_Py_fopen_obj(PyObject *path, const char *mode)
{
......@@ -1038,6 +1044,8 @@ _Py_fopen_obj(PyObject *path, const char *mode)
wchar_t wmode[10];
int usize;
assert(PyGILState_Check());
if (!PyUnicode_Check(path)) {
PyErr_Format(PyExc_TypeError,
"str file path expected under Windows, got %R",
......@@ -1049,20 +1057,36 @@ _Py_fopen_obj(PyObject *path, const char *mode)
return NULL;
usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode));
if (usize == 0)
if (usize == 0) {
PyErr_SetFromWindowsErr(0);
return NULL;
}
Py_BEGIN_ALLOW_THREADS
f = _wfopen(wpath, wmode);
Py_END_ALLOW_THREADS
#else
PyObject *bytes;
char *path_bytes;
assert(PyGILState_Check());
if (!PyUnicode_FSConverter(path, &bytes))
return NULL;
f = fopen(PyBytes_AS_STRING(bytes), mode);
path_bytes = PyBytes_AS_STRING(bytes);
Py_BEGIN_ALLOW_THREADS
f = fopen(path_bytes, mode);
Py_END_ALLOW_THREADS
Py_DECREF(bytes);
#endif
if (f == NULL)
if (f == NULL) {
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
return NULL;
if (make_non_inheritable(fileno(f)) < 0) {
}
if (set_inheritable(fileno(f), 0, 1, NULL) < 0) {
fclose(f);
return NULL;
}
......
......@@ -1945,8 +1945,6 @@ _imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, PyOb
fp = _Py_fopen_obj(path, "r");
if (fp == NULL) {
Py_DECREF(path);
if (!PyErr_Occurred())
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment