diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-03-30 08:09:31 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-03-30 08:09:31 (GMT) |
commit | e134a7fe36652434c2ccffc4ebab2ec2031d1505 (patch) | |
tree | 9eea060bf19c856881f438860eb2abdbe41f2bdd /Python | |
parent | 2e1c4e5db2894ec4322f917e9babc4e37dca9244 (diff) | |
download | cpython-e134a7fe36652434c2ccffc4ebab2ec2031d1505.zip cpython-e134a7fe36652434c2ccffc4ebab2ec2031d1505.tar.gz cpython-e134a7fe36652434c2ccffc4ebab2ec2031d1505.tar.bz2 |
Issue #23752: _Py_fstat() is now responsible to raise the Python exception
Add _Py_fstat_noraise() function when a Python exception is not welcome.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/dynload_shlib.c | 14 | ||||
-rw-r--r-- | Python/fileutils.c | 58 | ||||
-rw-r--r-- | Python/marshal.c | 2 | ||||
-rw-r--r-- | Python/random.c | 3 | ||||
-rw-r--r-- | Python/sysmodule.c | 2 |
5 files changed, 56 insertions, 23 deletions
diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 659adac..1a467fd 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -71,22 +71,20 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, if (fp != NULL) { int i; - struct _Py_stat_struct statb; - if (_Py_fstat(fileno(fp), &statb) == -1) { - PyErr_SetFromErrno(PyExc_IOError); + struct _Py_stat_struct status; + if (_Py_fstat(fileno(fp), &status) == -1) return NULL; - } for (i = 0; i < nhandles; i++) { - if (statb.st_dev == handles[i].dev && - statb.st_ino == handles[i].ino) { + if (status.st_dev == handles[i].dev && + status.st_ino == handles[i].ino) { p = (dl_funcptr) dlsym(handles[i].handle, funcname); return p; } } if (nhandles < 128) { - handles[nhandles].dev = statb.st_dev; - handles[nhandles].ino = statb.st_ino; + handles[nhandles].dev = status.st_dev; + handles[nhandles].ino = status.st_ino; } } diff --git a/Python/fileutils.c b/Python/fileutils.c index e6d3154..daaad2a 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -565,7 +565,8 @@ attributes_to_mode(DWORD attr) } void -_Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, struct _Py_stat_struct *result) +_Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, + struct _Py_stat_struct *result) { memset(result, 0, sizeof(*result)); result->st_mode = attributes_to_mode(info->dwFileAttributes); @@ -595,9 +596,12 @@ _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, files larger than 2 GB. fstat() may fail with EOVERFLOW on files larger than 2 GB because the file size type is an signed 32-bit integer: see issue #23152. - */ + + On Windows, set the last Windows error and return nonzero on error. On + POSIX, set errno and return nonzero on error. Fill status and return 0 on + success. */ int -_Py_fstat(int fd, struct _Py_stat_struct *result) +_Py_fstat_noraise(int fd, struct _Py_stat_struct *status) { #ifdef MS_WINDOWS BY_HANDLE_FILE_INFORMATION info; @@ -619,22 +623,21 @@ _Py_fstat(int fd, struct _Py_stat_struct *result) SetLastError(ERROR_INVALID_HANDLE); return -1; } - memset(result, 0, sizeof(*result)); + memset(status, 0, sizeof(*status)); type = GetFileType(h); if (type == FILE_TYPE_UNKNOWN) { DWORD error = GetLastError(); - if (error != 0) { + if (error != 0) return -1; - } /* else: valid but unknown file */ } if (type != FILE_TYPE_DISK) { if (type == FILE_TYPE_CHAR) - result->st_mode = _S_IFCHR; + status->st_mode = _S_IFCHR; else if (type == FILE_TYPE_PIPE) - result->st_mode = _S_IFIFO; + status->st_mode = _S_IFIFO; return 0; } @@ -642,15 +645,48 @@ _Py_fstat(int fd, struct _Py_stat_struct *result) return -1; } - _Py_attribute_data_to_stat(&info, 0, result); + _Py_attribute_data_to_stat(&info, 0, status); /* specific to fstat() */ - result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow; + status->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow; return 0; #else - return fstat(fd, result); + return fstat(fd, status); #endif } +/* Return information about a file. + + On POSIX, use fstat(). + + On Windows, use GetFileType() and GetFileInformationByHandle() which support + files larger than 2 GB. fstat() may fail with EOVERFLOW on files larger + than 2 GB because the file size type is an signed 32-bit integer: see issue + #23152. + + Raise an exception and return -1 on error. On Windows, set the last Windows + error on error. On POSIX, set errno on error. Fill status and return 0 on + success. + + The GIL must be held. */ +int +_Py_fstat(int fd, struct _Py_stat_struct *status) +{ + int res; + + Py_BEGIN_ALLOW_THREADS + res = _Py_fstat_noraise(fd, status); + Py_END_ALLOW_THREADS + + if (res != 0) { +#ifdef MS_WINDOWS + PyErr_SetFromWindowsErr(0); +#else + PyErr_SetFromErrno(PyExc_OSError); +#endif + return -1; + } + return 0; +} /* Call _wstat() on Windows, or encode the path to the filesystem encoding and call stat() otherwise. Only fill st_mode attribute on Windows. diff --git a/Python/marshal.c b/Python/marshal.c index 3472882..f89cd04 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -1486,7 +1486,7 @@ static off_t getfilesize(FILE *fp) { struct _Py_stat_struct st; - if (_Py_fstat(fileno(fp), &st) != 0) + if (_Py_fstat_noraise(fileno(fp), &st) != 0) return -1; #if SIZEOF_OFF_T == 4 else if (st.st_size >= INT_MAX) diff --git a/Python/random.c b/Python/random.c index a281829..a4eba3c 100644 --- a/Python/random.c +++ b/Python/random.c @@ -221,7 +221,7 @@ dev_urandom_python(char *buffer, Py_ssize_t size) if (urandom_cache.fd >= 0) { /* Does the fd point to the same thing as before? (issue #21207) */ - if (_Py_fstat(urandom_cache.fd, &st) + if (_Py_fstat_noraise(urandom_cache.fd, &st) || st.st_dev != urandom_cache.st_dev || st.st_ino != urandom_cache.st_ino) { /* Something changed: forget the cached fd (but don't close it, @@ -250,7 +250,6 @@ dev_urandom_python(char *buffer, Py_ssize_t size) } else { if (_Py_fstat(fd, &st)) { - PyErr_SetFromErrno(PyExc_OSError); close(fd); return -1; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 471389c..9ec2521 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1690,7 +1690,7 @@ _PySys_Init(void) #if !defined(MS_WINDOWS) { struct _Py_stat_struct sb; - if (_Py_fstat(fileno(stdin), &sb) == 0 && + if (_Py_fstat_noraise(fileno(stdin), &sb) == 0 && S_ISDIR(sb.st_mode)) { /* There's nothing more we can do. */ /* Py_FatalError() will core dump, so just exit. */ |