mirror of
https://github.com/python/cpython.git
synced 2025-07-23 11:15:24 +00:00
gh-127350: Add Py_fopen() and Py_fclose() functions (#127821)
This commit is contained in:
parent
7e8c571604
commit
f89e5e20cb
18 changed files with 270 additions and 53 deletions
|
@ -1981,7 +1981,7 @@ _PyErr_ProgramDecodedTextObject(PyObject *filename, int lineno, const char* enco
|
|||
return NULL;
|
||||
}
|
||||
|
||||
FILE *fp = _Py_fopen_obj(filename, "r" PY_STDIOTEXTMODE);
|
||||
FILE *fp = Py_fopen(filename, "r" PY_STDIOTEXTMODE);
|
||||
if (fp == NULL) {
|
||||
PyErr_Clear();
|
||||
return NULL;
|
||||
|
|
|
@ -1748,8 +1748,10 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
|
|||
}
|
||||
|
||||
|
||||
/* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem
|
||||
encoding and call fopen() otherwise.
|
||||
/* Open a file.
|
||||
|
||||
On Windows, if 'path' is a Unicode string, call _wfopen(). Otherwise, encode
|
||||
the path to the filesystem encoding and call fopen().
|
||||
|
||||
Return the new file object on success. Raise an exception and return NULL
|
||||
on error.
|
||||
|
@ -1762,32 +1764,32 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
|
|||
Release the GIL to call _wfopen() or fopen(). The caller must hold
|
||||
the GIL. */
|
||||
FILE*
|
||||
_Py_fopen_obj(PyObject *path, const char *mode)
|
||||
Py_fopen(PyObject *path, const char *mode)
|
||||
{
|
||||
FILE *f;
|
||||
int async_err = 0;
|
||||
#ifdef MS_WINDOWS
|
||||
wchar_t wmode[10];
|
||||
int usize;
|
||||
|
||||
assert(PyGILState_Check());
|
||||
|
||||
if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!PyUnicode_Check(path)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"str file path expected under Windows, got %R",
|
||||
Py_TYPE(path));
|
||||
|
||||
FILE *f;
|
||||
int async_err = 0;
|
||||
int saved_errno;
|
||||
#ifdef MS_WINDOWS
|
||||
PyObject *unicode;
|
||||
if (!PyUnicode_FSDecoder(path, &unicode)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL);
|
||||
if (wpath == NULL)
|
||||
wchar_t *wpath = PyUnicode_AsWideCharString(unicode, NULL);
|
||||
Py_DECREF(unicode);
|
||||
if (wpath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
usize = MultiByteToWideChar(CP_ACP, 0, mode, -1,
|
||||
wmode, Py_ARRAY_LENGTH(wmode));
|
||||
wchar_t wmode[10];
|
||||
int usize = MultiByteToWideChar(CP_ACP, 0, mode, -1,
|
||||
wmode, Py_ARRAY_LENGTH(wmode));
|
||||
if (usize == 0) {
|
||||
PyErr_SetFromWindowsErr(0);
|
||||
PyMem_Free(wpath);
|
||||
|
@ -1796,26 +1798,20 @@ _Py_fopen_obj(PyObject *path, const char *mode)
|
|||
|
||||
do {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
_Py_BEGIN_SUPPRESS_IPH
|
||||
f = _wfopen(wpath, wmode);
|
||||
_Py_END_SUPPRESS_IPH
|
||||
Py_END_ALLOW_THREADS
|
||||
} while (f == NULL
|
||||
&& errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
int saved_errno = errno;
|
||||
saved_errno = errno;
|
||||
PyMem_Free(wpath);
|
||||
#else
|
||||
PyObject *bytes;
|
||||
const char *path_bytes;
|
||||
|
||||
assert(PyGILState_Check());
|
||||
|
||||
if (!PyUnicode_FSConverter(path, &bytes))
|
||||
return NULL;
|
||||
path_bytes = PyBytes_AS_STRING(bytes);
|
||||
|
||||
if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
|
||||
Py_DECREF(bytes);
|
||||
if (!PyUnicode_FSConverter(path, &bytes)) {
|
||||
return NULL;
|
||||
}
|
||||
const char *path_bytes = PyBytes_AS_STRING(bytes);
|
||||
|
||||
do {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
@ -1823,11 +1819,13 @@ _Py_fopen_obj(PyObject *path, const char *mode)
|
|||
Py_END_ALLOW_THREADS
|
||||
} while (f == NULL
|
||||
&& errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
int saved_errno = errno;
|
||||
saved_errno = errno;
|
||||
Py_DECREF(bytes);
|
||||
#endif
|
||||
if (async_err)
|
||||
|
||||
if (async_err) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (f == NULL) {
|
||||
errno = saved_errno;
|
||||
|
@ -1842,6 +1840,27 @@ _Py_fopen_obj(PyObject *path, const char *mode)
|
|||
return f;
|
||||
}
|
||||
|
||||
|
||||
// Deprecated alias to Py_fopen() kept for backward compatibility
|
||||
FILE*
|
||||
_Py_fopen_obj(PyObject *path, const char *mode)
|
||||
{
|
||||
return Py_fopen(path, mode);
|
||||
}
|
||||
|
||||
|
||||
// Call fclose().
|
||||
//
|
||||
// On Windows, files opened by Py_fopen() in the Python DLL must be closed by
|
||||
// the Python DLL to use the same C runtime version. Otherwise, calling
|
||||
// fclose() directly can cause undefined behavior.
|
||||
int
|
||||
Py_fclose(FILE *file)
|
||||
{
|
||||
return fclose(file);
|
||||
}
|
||||
|
||||
|
||||
/* Read count bytes from fd into buf.
|
||||
|
||||
On success, return the number of read bytes, it can be lower than count.
|
||||
|
|
|
@ -4688,7 +4688,7 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
|
|||
* code relies on fp still being open. */
|
||||
FILE *fp;
|
||||
if (file != NULL) {
|
||||
fp = _Py_fopen_obj(info.filename, "r");
|
||||
fp = Py_fopen(info.filename, "r");
|
||||
if (fp == NULL) {
|
||||
goto finally;
|
||||
}
|
||||
|
|
|
@ -467,7 +467,7 @@ _PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit,
|
|||
fclose(fp);
|
||||
}
|
||||
|
||||
pyc_fp = _Py_fopen_obj(filename, "rb");
|
||||
pyc_fp = Py_fopen(filename, "rb");
|
||||
if (pyc_fp == NULL) {
|
||||
fprintf(stderr, "python: Can't reopen .pyc file\n");
|
||||
goto done;
|
||||
|
|
|
@ -2356,7 +2356,7 @@ static PyObject *
|
|||
sys__dump_tracelets_impl(PyObject *module, PyObject *outpath)
|
||||
/*[clinic end generated code: output=a7fe265e2bc3b674 input=5bff6880cd28ffd1]*/
|
||||
{
|
||||
FILE *out = _Py_fopen_obj(outpath, "wb");
|
||||
FILE *out = Py_fopen(outpath, "wb");
|
||||
if (out == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue