diff options
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r-- | Modules/posixmodule.c | 534 |
1 files changed, 376 insertions, 158 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index b854caf..10d6bcb 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -32,6 +32,12 @@ #include "winreparse.h" #endif +/* On android API level 21, 'AT_EACCESS' is not declared although + * HAVE_FACCESSAT is defined. */ +#ifdef __ANDROID__ +#undef HAVE_FACCESSAT +#endif + #include <stdio.h> /* needed for ctermid() */ #ifdef __cplusplus @@ -671,21 +677,20 @@ _Py_Dev_Converter(PyObject *obj, void *p) #endif static int -_fd_converter(PyObject *o, int *p, const char *allowed) +_fd_converter(PyObject *o, int *p) { int overflow; long long_value; PyObject *index = PyNumber_Index(o); if (index == NULL) { - PyErr_Format(PyExc_TypeError, - "argument should be %s, not %.200s", - allowed, Py_TYPE(o)->tp_name); return 0; } + assert(PyLong_Check(index)); long_value = PyLong_AsLongAndOverflow(index, &overflow); Py_DECREF(index); + assert(!PyErr_Occurred()); if (overflow > 0 || long_value > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "fd is greater than maximum"); @@ -708,7 +713,15 @@ dir_fd_converter(PyObject *o, void *p) *(int *)p = DEFAULT_DIR_FD; return 1; } - return _fd_converter(o, (int *)p, "integer"); + else if (PyIndex_Check(o)) { + return _fd_converter(o, (int *)p); + } + else { + PyErr_Format(PyExc_TypeError, + "argument should be integer or None, not %.200s", + Py_TYPE(o)->tp_name); + return 0; + } } @@ -799,8 +812,8 @@ typedef struct { const char *argument_name; int nullable; int allow_fd; - wchar_t *wide; - char *narrow; + const wchar_t *wide; + const char *narrow; int fd; Py_ssize_t length; PyObject *object; @@ -818,11 +831,12 @@ path_cleanup(path_t *path) { } static int -path_converter(PyObject *o, void *p) { +path_converter(PyObject *o, void *p) +{ path_t *path = (path_t *)p; - PyObject *unicode, *bytes; + PyObject *bytes; Py_ssize_t length; - char *narrow; + const char *narrow; #define FORMAT_EXCEPTION(exc, fmt) \ PyErr_Format(exc, "%s%s" fmt, \ @@ -839,12 +853,7 @@ path_converter(PyObject *o, void *p) { /* ensure it's always safe to call path_cleanup() */ path->cleanup = NULL; - if (o == Py_None) { - if (!path->nullable) { - FORMAT_EXCEPTION(PyExc_TypeError, - "can't specify None for %s argument"); - return 0; - } + if ((o == Py_None) && path->nullable) { path->wide = NULL; path->narrow = NULL; path->length = 0; @@ -853,24 +862,20 @@ path_converter(PyObject *o, void *p) { return 1; } - unicode = PyUnicode_FromObject(o); - if (unicode) { + if (PyUnicode_Check(o)) { #ifdef MS_WINDOWS - wchar_t *wide; + const wchar_t *wide; - wide = PyUnicode_AsUnicodeAndSize(unicode, &length); + wide = PyUnicode_AsUnicodeAndSize(o, &length); if (!wide) { - Py_DECREF(unicode); return 0; } if (length > 32767) { FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - Py_DECREF(unicode); return 0; } if (wcslen(wide) != length) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character"); - Py_DECREF(unicode); + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); return 0; } @@ -879,51 +884,67 @@ path_converter(PyObject *o, void *p) { path->length = length; path->object = o; path->fd = -1; - path->cleanup = unicode; - return Py_CLEANUP_SUPPORTED; + return 1; #else - int converted = PyUnicode_FSConverter(unicode, &bytes); - Py_DECREF(unicode); - if (!converted) - bytes = NULL; + if (!PyUnicode_FSConverter(o, &bytes)) { + return 0; + } #endif } - else { - PyErr_Clear(); - if (PyObject_CheckBuffer(o)) - bytes = PyBytes_FromObject(o); - else - bytes = NULL; + else if (PyBytes_Check(o)) { +#ifdef MS_WINDOWS + if (win32_warn_bytes_api()) { + return 0; + } +#endif + bytes = o; + Py_INCREF(bytes); + } + else if (PyObject_CheckBuffer(o)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "%s%s%s should be %s, not %.200s", + path->function_name ? path->function_name : "", + path->function_name ? ": " : "", + path->argument_name ? path->argument_name : "path", + path->allow_fd && path->nullable ? "string, bytes, integer or None" : + path->allow_fd ? "string, bytes or integer" : + path->nullable ? "string, bytes or None" : + "string or bytes", + Py_TYPE(o)->tp_name)) { + return 0; + } +#ifdef MS_WINDOWS + if (win32_warn_bytes_api()) { + return 0; + } +#endif + bytes = PyBytes_FromObject(o); if (!bytes) { - PyErr_Clear(); - if (path->allow_fd) { - int fd; - int result = _fd_converter(o, &fd, - "string, bytes or integer"); - if (result) { - path->wide = NULL; - path->narrow = NULL; - path->length = 0; - path->object = o; - path->fd = fd; - return result; - } - } + return 0; } } - - if (!bytes) { - if (!PyErr_Occurred()) - FORMAT_EXCEPTION(PyExc_TypeError, "illegal type for %s parameter"); - return 0; + else if (path->allow_fd && PyIndex_Check(o)) { + if (!_fd_converter(o, &path->fd)) { + return 0; + } + path->wide = NULL; + path->narrow = NULL; + path->length = 0; + path->object = o; + return 1; } - -#ifdef MS_WINDOWS - if (win32_warn_bytes_api()) { - Py_DECREF(bytes); + else { + PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s", + path->function_name ? path->function_name : "", + path->function_name ? ": " : "", + path->argument_name ? path->argument_name : "path", + path->allow_fd && path->nullable ? "string, bytes, integer or None" : + path->allow_fd ? "string, bytes or integer" : + path->nullable ? "string, bytes or None" : + "string or bytes", + Py_TYPE(o)->tp_name); return 0; } -#endif length = PyBytes_GET_SIZE(bytes); #ifdef MS_WINDOWS @@ -946,12 +967,19 @@ path_converter(PyObject *o, void *p) { path->length = length; path->object = o; path->fd = -1; - path->cleanup = bytes; - return Py_CLEANUP_SUPPORTED; + if (bytes == o) { + Py_DECREF(bytes); + return 1; + } + else { + path->cleanup = bytes; + return Py_CLEANUP_SUPPORTED; + } } static void -argument_unavailable_error(char *function_name, char *argument_name) { +argument_unavailable_error(const char *function_name, const char *argument_name) +{ PyErr_Format(PyExc_NotImplementedError, "%s%s%s unavailable on this platform", (function_name != NULL) ? function_name : "", @@ -974,7 +1002,8 @@ dir_fd_unavailable(PyObject *o, void *p) } static int -fd_specified(char *function_name, int fd) { +fd_specified(const char *function_name, int fd) +{ if (fd == -1) return 0; @@ -983,7 +1012,8 @@ fd_specified(char *function_name, int fd) { } static int -follow_symlinks_specified(char *function_name, int follow_symlinks) { +follow_symlinks_specified(const char *function_name, int follow_symlinks) +{ if (follow_symlinks) return 0; @@ -992,7 +1022,8 @@ follow_symlinks_specified(char *function_name, int follow_symlinks) { } static int -path_and_dir_fd_invalid(char *function_name, path_t *path, int dir_fd) { +path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd) +{ if (!path->narrow && !path->wide && (dir_fd != DEFAULT_DIR_FD)) { PyErr_Format(PyExc_ValueError, "%s: can't specify dir_fd without matching path", @@ -1003,7 +1034,8 @@ path_and_dir_fd_invalid(char *function_name, path_t *path, int dir_fd) { } static int -dir_fd_and_fd_invalid(char *function_name, int dir_fd, int fd) { +dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) +{ if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) { PyErr_Format(PyExc_ValueError, "%s: can't specify both dir_fd and fd", @@ -1014,8 +1046,9 @@ dir_fd_and_fd_invalid(char *function_name, int dir_fd, int fd) { } static int -fd_and_follow_symlinks_invalid(char *function_name, int fd, - int follow_symlinks) { +fd_and_follow_symlinks_invalid(const char *function_name, int fd, + int follow_symlinks) +{ if ((fd > 0) && (!follow_symlinks)) { PyErr_Format(PyExc_ValueError, "%s: cannot use fd and follow_symlinks together", @@ -1026,8 +1059,9 @@ fd_and_follow_symlinks_invalid(char *function_name, int fd, } static int -dir_fd_and_follow_symlinks_invalid(char *function_name, int dir_fd, - int follow_symlinks) { +dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, + int follow_symlinks) +{ if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { PyErr_Format(PyExc_ValueError, "%s: cannot use dir_fd and follow_symlinks together", @@ -1099,8 +1133,8 @@ _PyVerify_fd_dup2(int fd1, int fd2) static int win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) { - char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; + char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; DWORD n_bytes_returned; if (0 == DeviceIoControl( @@ -1159,7 +1193,7 @@ convertenviron(void) for (e = _wenviron; *e != NULL; e++) { PyObject *k; PyObject *v; - wchar_t *p = wcschr(*e, L'='); + const wchar_t *p = wcschr(*e, L'='); if (p == NULL) continue; k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e)); @@ -1187,7 +1221,7 @@ convertenviron(void) for (e = environ; *e != NULL; e++) { PyObject *k; PyObject *v; - char *p = strchr(*e, '='); + const char *p = strchr(*e, '='); if (p == NULL) continue; k = PyBytes_FromStringAndSize(*e, (int)(p-*e)); @@ -1222,7 +1256,7 @@ posix_error(void) #ifdef MS_WINDOWS static PyObject * -win32_error(char* function, const char* filename) +win32_error(const char* function, const char* filename) { /* XXX We should pass the function name along in the future. (winreg.c also wants to pass the function name.) @@ -1237,7 +1271,7 @@ win32_error(char* function, const char* filename) } static PyObject * -win32_error_object(char* function, PyObject* filename) +win32_error_object(const char* function, PyObject* filename) { /* XXX - see win32_error for comments on 'function' */ errno = GetLastError(); @@ -1458,7 +1492,7 @@ get_target_path(HANDLE hdl, wchar_t **target_path) if(!buf_size) return FALSE; - buf = PyMem_New(wchar_t, buf_size+1); + buf = (wchar_t *)PyMem_RawMalloc((buf_size + 1) * sizeof(wchar_t)); if (!buf) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; @@ -1468,12 +1502,12 @@ get_target_path(HANDLE hdl, wchar_t **target_path) buf, buf_size, VOLUME_NAME_DOS); if(!result_length) { - PyMem_Free(buf); + PyMem_RawFree(buf); return FALSE; } if(!CloseHandle(hdl)) { - PyMem_Free(buf); + PyMem_RawFree(buf); return FALSE; } @@ -1558,7 +1592,7 @@ win32_xstat_impl(const char *path, struct _Py_stat_struct *result, return -1; code = win32_xstat_impl_w(target_path, result, FALSE); - PyMem_Free(target_path); + PyMem_RawFree(target_path); return code; } } else @@ -1648,7 +1682,7 @@ win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, return -1; code = win32_xstat_impl_w(target_path, result, FALSE); - PyMem_Free(target_path); + PyMem_RawFree(target_path); return code; } } else @@ -2102,7 +2136,7 @@ _pystat_fromstructstat(STRUCT_STAT *st) static PyObject * -posix_do_stat(char *function_name, path_t *path, +posix_do_stat(const char *function_name, path_t *path, int dir_fd, int follow_symlinks) { STRUCT_STAT st; @@ -3314,12 +3348,22 @@ posix_getcwd(int use_bytes) Py_BEGIN_ALLOW_THREADS do { buflen += chunk; +#ifdef MS_WINDOWS + if (buflen > INT_MAX) { + PyErr_NoMemory(); + break; + } +#endif tmpbuf = PyMem_RawRealloc(buf, buflen); if (tmpbuf == NULL) break; buf = tmpbuf; +#ifdef MS_WINDOWS + cwd = getcwd(buf, (int)buflen); +#else cwd = getcwd(buf, buflen); +#endif } while (cwd == NULL && errno == ERANGE); Py_END_ALLOW_THREADS @@ -3461,15 +3505,13 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) BOOL result; WIN32_FIND_DATA FileData; char namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ - char *bufptr = namebuf; /* only claim to have space for MAX_PATH */ Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; - PyObject *po = NULL; wchar_t *wnamebuf = NULL; if (!path->narrow) { WIN32_FIND_DATAW wFileData; - wchar_t *po_wchars; + const wchar_t *po_wchars; if (!path->wide) { /* Default arg: "." */ po_wchars = L"."; @@ -3635,7 +3677,7 @@ _posix_listdir(path_t *path, PyObject *list) else #endif { - char *name; + const char *name; if (path->narrow) { name = path->narrow; /* only return bytes if they specified a bytes object */ @@ -3817,7 +3859,7 @@ os__getfinalpathname_impl(PyObject *module, PyObject *path) wchar_t *target_path; int result_length; PyObject *result; - wchar_t *path_wchar; + const wchar_t *path_wchar; path_wchar = PyUnicode_AsUnicode(path); if (path_wchar == NULL) @@ -3908,7 +3950,8 @@ os__getvolumepathname_impl(PyObject *module, PyObject *path) /*[clinic end generated code: output=cbdcbd1059ceef4c input=7eacadc40acbda6b]*/ { PyObject *result; - wchar_t *path_wchar, *mountpath=NULL; + const wchar_t *path_wchar; + wchar_t *mountpath=NULL; size_t buflen; BOOL ret; @@ -4106,7 +4149,7 @@ os_setpriority_impl(PyObject *module, int which, int who, int priority) static PyObject * internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace) { - char *function_name = is_replace ? "replace" : "rename"; + const char *function_name = is_replace ? "replace" : "rename"; int dir_fd_specified; #ifdef MS_WINDOWS @@ -4286,7 +4329,7 @@ os_system_impl(PyObject *module, PyObject *command) /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/ { long result; - char *bytes = PyBytes_AsString(command); + const char *bytes = PyBytes_AsString(command); Py_BEGIN_ALLOW_THREADS result = system(bytes); Py_END_ALLOW_THREADS @@ -4566,7 +4609,7 @@ typedef struct { #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) static int -utime_dir_fd(utime_t *ut, int dir_fd, char *path, int follow_symlinks) +utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) { #ifdef HAVE_UTIMENSAT int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; @@ -4608,14 +4651,14 @@ utime_fd(utime_t *ut, int fd) #define PATH_UTIME_HAVE_FD 0 #endif +#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES) +# define UTIME_HAVE_NOFOLLOW_SYMLINKS +#endif -#define UTIME_HAVE_NOFOLLOW_SYMLINKS \ - (defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)) - -#if UTIME_HAVE_NOFOLLOW_SYMLINKS +#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS static int -utime_nofollow_symlinks(utime_t *ut, char *path) +utime_nofollow_symlinks(utime_t *ut, const char *path) { #ifdef HAVE_UTIMENSAT UTIME_TO_TIMESPEC; @@ -4631,7 +4674,7 @@ utime_nofollow_symlinks(utime_t *ut, char *path) #ifndef MS_WINDOWS static int -utime_default(utime_t *ut, char *path) +utime_default(utime_t *ut, const char *path) { #ifdef HAVE_UTIMENSAT UTIME_TO_TIMESPEC; @@ -4774,7 +4817,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, utime.now = 1; } -#if !UTIME_HAVE_NOFOLLOW_SYMLINKS +#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS) if (follow_symlinks_specified("utime", follow_symlinks)) goto exit; #endif @@ -4828,7 +4871,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS -#if UTIME_HAVE_NOFOLLOW_SYMLINKS +#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) result = utime_nofollow_symlinks(&utime, path->narrow); else @@ -4925,7 +4968,8 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) Py_ssize_t i, pos, envc; PyObject *keys=NULL, *vals=NULL; PyObject *key, *val, *key2, *val2; - char *p, *k, *v; + char *p; + const char *k, *v; size_t len; i = PyMapping_Size(env); @@ -5040,7 +5084,7 @@ static PyObject * os_execv_impl(PyObject *module, PyObject *path, PyObject *argv) /*[clinic end generated code: output=b21dc34deeb5b004 input=96041559925e5229]*/ { - char *path_char; + const char *path_char; char **argvlist; Py_ssize_t argc; @@ -5160,7 +5204,7 @@ static PyObject * os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv) /*[clinic end generated code: output=c427c0ce40f10638 input=042c91dfc1e6debc]*/ { - char *path_char; + const char *path_char; char **argvlist; int i; Py_ssize_t argc; @@ -5238,7 +5282,7 @@ os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv, PyObject *env) /*[clinic end generated code: output=ebcfa5f7ba2f4219 input=02362fd937963f8f]*/ { - char *path_char; + const char *path_char; char **argvlist; char **envlist; PyObject *res = NULL; @@ -5758,14 +5802,14 @@ os.sched_getaffinity pid: pid_t / -Return the affinity of the process identified by pid. +Return the affinity of the process identified by pid (or the current process if zero). The affinity is returned as a set of CPU identifiers. [clinic start generated code]*/ static PyObject * os_sched_getaffinity_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=f726f2c193c17a4f input=eaf161936874b8a1]*/ +/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/ { int cpu, ncpus, count; size_t setsize; @@ -5926,7 +5970,7 @@ os_openpty_impl(PyObject *module) if (_Py_set_inheritable(master_fd, 0, NULL) < 0) goto posix_error; -#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) +#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC) ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ #ifndef __hpux @@ -6251,7 +6295,7 @@ static PyObject * posix_initgroups(PyObject *self, PyObject *args) { PyObject *oname; - char *username; + const char *username; int res; #ifdef __APPLE__ int gid; @@ -7125,16 +7169,16 @@ exit: static PyObject * win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) { - wchar_t *path; + const wchar_t *path; DWORD n_bytes_returned; DWORD io_result; PyObject *po, *result; - int dir_fd; + int dir_fd; HANDLE reparse_point_handle; - char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; - wchar_t *print_name; + char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; + const wchar_t *print_name; static char *keywords[] = {"path", "dir_fd", NULL}; @@ -7202,8 +7246,8 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) #if defined(MS_WINDOWS) /* Grab CreateSymbolicLinkW dynamically from kernel32 */ -static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD) = NULL; -static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPSTR, LPSTR, DWORD) = NULL; +static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD) = NULL; +static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPCSTR, LPCSTR, DWORD) = NULL; static int check_CreateSymbolicLink(void) @@ -7308,7 +7352,7 @@ _joinA(char *dest_path, const char *root, const char *rest) /* Return True if the path at src relative to dest is a directory */ static int -_check_dirW(WCHAR *src, WCHAR *dest) +_check_dirW(LPCWSTR src, LPCWSTR dest) { WIN32_FILE_ATTRIBUTE_DATA src_info; WCHAR dest_parent[MAX_PATH]; @@ -7327,7 +7371,7 @@ _check_dirW(WCHAR *src, WCHAR *dest) /* Return True if the path at src relative to dest is a directory */ static int -_check_dirA(char *src, char *dest) +_check_dirA(LPCSTR src, LPCSTR dest) { WIN32_FILE_ATTRIBUTE_DATA src_info; char dest_parent[MAX_PATH]; @@ -9015,7 +9059,7 @@ static PyObject * os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/ { - wchar_t *env; + const wchar_t *env; PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value); if (unicode == NULL) { @@ -9061,8 +9105,8 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) { PyObject *bytes = NULL; char *env; - char *name_string = PyBytes_AsString(name); - char *value_string = PyBytes_AsString(value); + const char *name_string = PyBytes_AsString(name); + const char *value_string = PyBytes_AsString(value); bytes = PyBytes_FromFormat("%s=%s", name_string, value_string); if (bytes == NULL) { @@ -9481,8 +9525,8 @@ os__getdiskusage_impl(PyObject *module, Py_UNICODE *path) * sufficiently pervasive that it's not worth the loss of readability. */ struct constdef { - char *name; - long value; + const char *name; + int value; }; static int @@ -9490,7 +9534,10 @@ conv_confname(PyObject *arg, int *valuep, struct constdef *table, size_t tablesize) { if (PyLong_Check(arg)) { - *valuep = PyLong_AS_LONG(arg); + int value = _PyLong_AsInt(arg); + if (value == -1 && PyErr_Occurred()) + return 0; + *valuep = value; return 1; } else { @@ -10451,7 +10498,7 @@ cmp_constdefs(const void *v1, const void *v2) static int setup_confname_table(struct constdef *table, size_t tablesize, - char *tablename, PyObject *module) + const char *tablename, PyObject *module) { PyObject *d = NULL; size_t i; @@ -10578,9 +10625,9 @@ static PyObject * win32_startfile(PyObject *self, PyObject *args) { PyObject *ofilepath; - char *filepath; - char *operation = NULL; - wchar_t *wpath, *woperation; + const char *filepath; + const char *operation = NULL; + const wchar_t *wpath, *woperation; HINSTANCE rc; PyObject *unipath, *uoperation = NULL; @@ -10821,7 +10868,7 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, for (i = 0; ; i++) { void *ptr; ssize_t result; - static Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; + static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; Py_ssize_t buffer_size = buffer_sizes[i]; if (!buffer_size) { path_error(path); @@ -10985,9 +11032,9 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) name = path->narrow ? path->narrow : "."; for (i = 0; ; i++) { - char *start, *trace, *end; + const char *start, *trace, *end; ssize_t length; - static Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; + static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; Py_ssize_t buffer_size = buffer_sizes[i]; if (!buffer_size) { /* ERANGE */ @@ -11199,11 +11246,15 @@ get_terminal_size(PyObject *self, PyObject *args) os.cpu_count Return the number of CPUs in the system; return None if indeterminable. + +This number is not equivalent to the number of CPUs the current process can +use. The number of usable CPUs can be obtained with +``len(os.sched_getaffinity(0))`` [clinic start generated code]*/ static PyObject * os_cpu_count_impl(PyObject *module) -/*[clinic end generated code: output=5fc29463c3936a9c input=d55e2f8f3823a628]*/ +/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/ { int ncpu = 0; #ifdef MS_WINDOWS @@ -11460,7 +11511,7 @@ DirEntry_fetch_stat(DirEntry *self, int follow_symlinks) struct _Py_stat_struct st; #ifdef MS_WINDOWS - wchar_t *path; + const wchar_t *path; path = PyUnicode_AsUnicode(self->path); if (!path) @@ -11477,7 +11528,7 @@ DirEntry_fetch_stat(DirEntry *self, int follow_symlinks) } #else /* POSIX */ PyObject *bytes; - char *path; + const char *path; if (!PyUnicode_FSConverter(self->path, &bytes)) return NULL; @@ -11661,7 +11712,7 @@ DirEntry_inode(DirEntry *self) { #ifdef MS_WINDOWS if (!self->got_file_index) { - wchar_t *path; + const wchar_t *path; struct _Py_stat_struct stat; path = PyUnicode_AsUnicode(self->path); @@ -11692,6 +11743,13 @@ DirEntry_repr(DirEntry *self) return PyUnicode_FromFormat("<DirEntry %R>", self->name); } +static PyObject * +DirEntry_fspath(DirEntry *self) +{ + Py_INCREF(self->path); + return self->path; +} + static PyMemberDef DirEntry_members[] = { {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, "the entry's base filename, relative to scandir() \"path\" argument"}, @@ -11716,6 +11774,9 @@ static PyMethodDef DirEntry_methods[] = { {"inode", (PyCFunction)DirEntry_inode, METH_NOARGS, "return inode of the entry; cached per entry", }, + {"__fspath__", (PyCFunction)DirEntry_fspath, METH_NOARGS, + "returns the path for the entry", + }, {NULL} }; @@ -11755,7 +11816,7 @@ static PyTypeObject DirEntryType = { #ifdef MS_WINDOWS static wchar_t * -join_path_filenameW(wchar_t *path_wide, wchar_t* filename) +join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename) { Py_ssize_t path_len; Py_ssize_t size; @@ -11830,7 +11891,7 @@ error: #else /* POSIX */ static char * -join_path_filename(char *path_narrow, char* filename, Py_ssize_t filename_len) +join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len) { Py_ssize_t path_len; Py_ssize_t size; @@ -11862,7 +11923,7 @@ join_path_filename(char *path_narrow, char* filename, Py_ssize_t filename_len) } static PyObject * -DirEntry_from_posix_info(path_t *path, char *name, Py_ssize_t name_len, +DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len, ino_t d_ino #ifdef HAVE_DIRENT_D_TYPE , unsigned char d_type @@ -11925,8 +11986,14 @@ typedef struct { #ifdef MS_WINDOWS +static int +ScandirIterator_is_closed(ScandirIterator *iterator) +{ + return iterator->handle == INVALID_HANDLE_VALUE; +} + static void -ScandirIterator_close(ScandirIterator *iterator) +ScandirIterator_closedir(ScandirIterator *iterator) { HANDLE handle = iterator->handle; @@ -11946,7 +12013,7 @@ ScandirIterator_iternext(ScandirIterator *iterator) BOOL success; PyObject *entry; - /* Happens if the iterator is iterated twice */ + /* Happens if the iterator is iterated twice, or closed explicitly */ if (iterator->handle == INVALID_HANDLE_VALUE) return NULL; @@ -11977,14 +12044,20 @@ ScandirIterator_iternext(ScandirIterator *iterator) } /* Error or no more files */ - ScandirIterator_close(iterator); + ScandirIterator_closedir(iterator); return NULL; } #else /* POSIX */ +static int +ScandirIterator_is_closed(ScandirIterator *iterator) +{ + return !iterator->dirp; +} + static void -ScandirIterator_close(ScandirIterator *iterator) +ScandirIterator_closedir(ScandirIterator *iterator) { DIR *dirp = iterator->dirp; @@ -12006,7 +12079,7 @@ ScandirIterator_iternext(ScandirIterator *iterator) int is_dot; PyObject *entry; - /* Happens if the iterator is iterated twice */ + /* Happens if the iterator is iterated twice, or closed explicitly */ if (!iterator->dirp) return NULL; @@ -12043,21 +12116,76 @@ ScandirIterator_iternext(ScandirIterator *iterator) } /* Error or no more files */ - ScandirIterator_close(iterator); + ScandirIterator_closedir(iterator); return NULL; } #endif +static PyObject * +ScandirIterator_close(ScandirIterator *self, PyObject *args) +{ + ScandirIterator_closedir(self); + Py_RETURN_NONE; +} + +static PyObject * +ScandirIterator_enter(PyObject *self, PyObject *args) +{ + Py_INCREF(self); + return self; +} + +static PyObject * +ScandirIterator_exit(ScandirIterator *self, PyObject *args) +{ + ScandirIterator_closedir(self); + Py_RETURN_NONE; +} + static void -ScandirIterator_dealloc(ScandirIterator *iterator) +ScandirIterator_finalize(ScandirIterator *iterator) { - ScandirIterator_close(iterator); - Py_XDECREF(iterator->path.object); + PyObject *error_type, *error_value, *error_traceback; + + /* Save the current exception, if any. */ + PyErr_Fetch(&error_type, &error_value, &error_traceback); + + if (!ScandirIterator_is_closed(iterator)) { + ScandirIterator_closedir(iterator); + + if (PyErr_ResourceWarning((PyObject *)iterator, 1, + "unclosed scandir iterator %R", iterator)) { + /* Spurious errors can appear at shutdown */ + if (PyErr_ExceptionMatches(PyExc_Warning)) { + PyErr_WriteUnraisable((PyObject *) iterator); + } + } + } + + Py_CLEAR(iterator->path.object); path_cleanup(&iterator->path); + + /* Restore the saved exception. */ + PyErr_Restore(error_type, error_value, error_traceback); +} + +static void +ScandirIterator_dealloc(ScandirIterator *iterator) +{ + if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0) + return; + Py_TYPE(iterator)->tp_free((PyObject *)iterator); } +static PyMethodDef ScandirIterator_methods[] = { + {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS}, + {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS}, + {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS}, + {NULL} +}; + static PyTypeObject ScandirIteratorType = { PyVarObject_HEAD_INIT(NULL, 0) MODNAME ".ScandirIterator", /* tp_name */ @@ -12079,7 +12207,8 @@ static PyTypeObject ScandirIteratorType = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT + | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -12087,6 +12216,27 @@ static PyTypeObject ScandirIteratorType = { 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)ScandirIterator_iternext, /* tp_iternext */ + ScandirIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ + (destructor)ScandirIterator_finalize, /* tp_finalize */ }; static PyObject * @@ -12097,7 +12247,7 @@ posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs) #ifdef MS_WINDOWS wchar_t *path_strW; #else - char *path; + const char *path; #endif iterator = PyObject_New(ScandirIterator, &ScandirIteratorType); @@ -12169,6 +12319,69 @@ error: return NULL; } +/* + Return the file system path representation of the object. + + If the object is str or bytes, then allow it to pass through with + an incremented refcount. If the object defines __fspath__(), then + return the result of that method. All other types raise a TypeError. +*/ +PyObject * +PyOS_FSPath(PyObject *path) +{ + _Py_IDENTIFIER(__fspath__); + PyObject *func = NULL; + PyObject *path_repr = NULL; + + if (PyUnicode_Check(path) || PyBytes_Check(path)) { + Py_INCREF(path); + return path; + } + + func = _PyObject_LookupSpecial(path, &PyId___fspath__); + if (NULL == func) { + return PyErr_Format(PyExc_TypeError, + "expected str, bytes or os.PathLike object, " + "not %.200s", + Py_TYPE(path)->tp_name); + } + + path_repr = PyObject_CallFunctionObjArgs(func, NULL); + Py_DECREF(func); + if (NULL == path_repr) { + return NULL; + } + + if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) { + PyErr_Format(PyExc_TypeError, + "expected %.200s.__fspath__() to return str or bytes, " + "not %.200s", Py_TYPE(path)->tp_name, + Py_TYPE(path_repr)->tp_name); + Py_DECREF(path_repr); + return NULL; + } + + return path_repr; +} + +/*[clinic input] +os.fspath + + path: object + +Return the file system path representation of the object. + +If the object is str or bytes, then allow it to pass through as-is. If the +object defines __fspath__(), then return the result of that method. All other +types raise a TypeError. +[clinic start generated code]*/ + +static PyObject * +os_fspath_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/ +{ + return PyOS_FSPath(path); +} #include "clinic/posixmodule.c.h" @@ -12369,6 +12582,7 @@ static PyMethodDef posix_methods[] = { {"scandir", (PyCFunction)posix_scandir, METH_VARARGS | METH_KEYWORDS, posix_scandir__doc__}, + OS_FSPATH_METHODDEF {NULL, NULL} /* Sentinel */ }; @@ -12380,7 +12594,6 @@ enable_symlink() HANDLE tok; TOKEN_PRIVILEGES tok_priv; LUID luid; - int meth_idx = 0; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok)) return 0; @@ -12483,12 +12696,14 @@ all_ins(PyObject *m) #ifdef O_LARGEFILE if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1; #endif +#ifndef __GNU__ #ifdef O_SHLOCK if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1; #endif #ifdef O_EXLOCK if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1; #endif +#endif #ifdef O_EXEC if (PyModule_AddIntMacro(m, O_EXEC)) return -1; #endif @@ -12791,25 +13006,25 @@ all_ins(PyObject *m) if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1; #endif -#ifdef RTLD_LAZY +#if HAVE_DECL_RTLD_LAZY if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1; #endif -#ifdef RTLD_NOW +#if HAVE_DECL_RTLD_NOW if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1; #endif -#ifdef RTLD_GLOBAL +#if HAVE_DECL_RTLD_GLOBAL if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1; #endif -#ifdef RTLD_LOCAL +#if HAVE_DECL_RTLD_LOCAL if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1; #endif -#ifdef RTLD_NODELETE +#if HAVE_DECL_RTLD_NODELETE if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1; #endif -#ifdef RTLD_NOLOAD +#if HAVE_DECL_RTLD_NOLOAD if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1; #endif -#ifdef RTLD_DEEPBIND +#if HAVE_DECL_RTLD_DEEPBIND if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1; #endif @@ -12830,7 +13045,7 @@ static struct PyModuleDef posixmodule = { }; -static char *have_functions[] = { +static const char * const have_functions[] = { #ifdef HAVE_FACCESSAT "HAVE_FACCESSAT", @@ -12965,7 +13180,7 @@ INITFUNC(void) { PyObject *m, *v; PyObject *list; - char **trace; + const char * const *trace; #if defined(HAVE_SYMLINK) && defined(MS_WINDOWS) win32_can_symlink = enable_symlink(); @@ -13141,6 +13356,9 @@ INITFUNC(void) } PyModule_AddObject(m, "_have_functions", list); + Py_INCREF((PyObject *) &DirEntryType); + PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType); + initialized = 1; return m; |