From ae2e171f2a9e79db9f31547f2c8163f8b7c497b9 Mon Sep 17 00:00:00 2001 From: nineteendo Date: Sat, 27 Apr 2024 22:28:52 +0200 Subject: [PATCH 01/26] Add `null_embeddable` --- Include/unicodeobject.h | 1 + Modules/clinic/posixmodule.c.h | 168 ++++++++++++++++++--------------- Modules/posixmodule.c | 145 ++++++++++++---------------- Objects/unicodeobject.c | 10 +- 4 files changed, 165 insertions(+), 159 deletions(-) diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index dee00715b3c51d..cdeabee9d7aa68 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -740,6 +740,7 @@ PyAPI_FUNC(PyObject*) PyUnicode_EncodeLocale( /* ParseTuple converter: encode str objects to bytes using PyUnicode_EncodeFSDefault(); bytes objects are output as-is. */ +extern int _PyUnicode_FSConverter(PyObject*, void*, int); PyAPI_FUNC(int) PyUnicode_FSConverter(PyObject*, void*); /* ParseTuple converter: decode bytes objects to unicode using diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index a0d1f3238a6733..b6a582f6e81cfa 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -72,7 +72,7 @@ os_stat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("stat", "path", 0, 1); + path_t path = PATH_T_INITIALIZE("stat", "path", 0, 0, 1); int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; @@ -154,7 +154,7 @@ os_lstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -250,7 +250,7 @@ os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("access", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("access", "path", 0, 0, 0); int mode; int dir_fd = DEFAULT_DIR_FD; int effective_ids = 0; @@ -409,7 +409,7 @@ os_chdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chdir", "path", 0, PATH_HAVE_FCHDIR); + path_t path = PATH_T_INITIALIZE("chdir", "path", 0, 0, PATH_HAVE_FCHDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -560,7 +560,7 @@ os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chmod", "path", 0, PATH_HAVE_FCHMOD); + path_t path = PATH_T_INITIALIZE("chmod", "path", 0, 0, PATH_HAVE_FCHMOD); int mode; int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = CHMOD_DEFAULT_FOLLOW_SYMLINKS; @@ -725,7 +725,7 @@ os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0, 0); int mode; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -802,7 +802,7 @@ os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0, 0); unsigned long flags; int follow_symlinks = 1; @@ -884,7 +884,7 @@ os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0, 0); unsigned long flags; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -954,7 +954,7 @@ os_chroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1190,7 +1190,7 @@ os_chown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("chown", "path", 0, PATH_HAVE_FCHOWN); + path_t path = PATH_T_INITIALIZE("chown", "path", 0, 0, PATH_HAVE_FCHOWN); uid_t uid; gid_t gid; int dir_fd = DEFAULT_DIR_FD; @@ -1355,7 +1355,7 @@ os_lchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0, 0); uid_t uid; gid_t gid; @@ -1476,8 +1476,8 @@ os_link(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("link", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0); + path_t src = PATH_T_INITIALIZE("link", "src", 0, 0, 0); + path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; @@ -1583,7 +1583,7 @@ os_listdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listdir", "path", 1, PATH_HAVE_FDOPENDIR); + path_t path = PATH_T_INITIALIZE("listdir", "path", 1, 0, PATH_HAVE_FDOPENDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); if (!args) { @@ -1699,7 +1699,7 @@ os_listmounts(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t volume = PATH_T_INITIALIZE("listmounts", "volume", 0, 0); + path_t volume = PATH_T_INITIALIZE("listmounts", "volume", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1763,7 +1763,7 @@ os__path_isdevdrive(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_isdevdrive", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("_path_isdevdrive", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1800,7 +1800,7 @@ static PyObject * os__getfullpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1834,7 +1834,7 @@ static PyObject * os__getfinalpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1868,7 +1868,7 @@ static PyObject * os__findfirstfile(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_findfirstfile", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("_findfirstfile", "path", 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1928,7 +1928,7 @@ os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1992,7 +1992,7 @@ os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_splitroot", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("_path_splitroot", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -2024,7 +2024,7 @@ PyDoc_STRVAR(os__path_isdir__doc__, {"_path_isdir", _PyCFunction_CAST(os__path_isdir), METH_FASTCALL|METH_KEYWORDS, os__path_isdir__doc__}, static PyObject * -os__path_isdir_impl(PyObject *module, PyObject *s); +os__path_isdir_impl(PyObject *module, path_t *path); static PyObject * os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2056,16 +2056,21 @@ os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *s; + path_t path = PATH_T_INITIALIZE("_path_isdir", "path", 0, 1, 1); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - s = args[0]; - return_value = os__path_isdir_impl(module, s); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_isdir_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2083,7 +2088,7 @@ PyDoc_STRVAR(os__path_isfile__doc__, {"_path_isfile", _PyCFunction_CAST(os__path_isfile), METH_FASTCALL|METH_KEYWORDS, os__path_isfile__doc__}, static PyObject * -os__path_isfile_impl(PyObject *module, PyObject *path); +os__path_isfile_impl(PyObject *module, path_t *path); static PyObject * os__path_isfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2115,16 +2120,21 @@ os__path_isfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + path_t path = PATH_T_INITIALIZE("_path_isfile", "path", 0, 1, 1); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - path = args[0]; - return_value = os__path_isfile_impl(module, path); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_isfile_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2142,7 +2152,7 @@ PyDoc_STRVAR(os__path_exists__doc__, {"_path_exists", _PyCFunction_CAST(os__path_exists), METH_FASTCALL|METH_KEYWORDS, os__path_exists__doc__}, static PyObject * -os__path_exists_impl(PyObject *module, PyObject *path); +os__path_exists_impl(PyObject *module, path_t *path); static PyObject * os__path_exists(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2174,16 +2184,21 @@ os__path_exists(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + path_t path = PATH_T_INITIALIZE("_path_exists", "path", 0, 1, 1); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - path = args[0]; - return_value = os__path_exists_impl(module, path); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_exists_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2201,7 +2216,7 @@ PyDoc_STRVAR(os__path_islink__doc__, {"_path_islink", _PyCFunction_CAST(os__path_islink), METH_FASTCALL|METH_KEYWORDS, os__path_islink__doc__}, static PyObject * -os__path_islink_impl(PyObject *module, PyObject *path); +os__path_islink_impl(PyObject *module, path_t *path); static PyObject * os__path_islink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2233,16 +2248,21 @@ os__path_islink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + path_t path = PATH_T_INITIALIZE("_path_islink", "path", 0, 1, 1); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - path = args[0]; - return_value = os__path_islink_impl(module, path); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_islink_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2412,7 +2432,7 @@ os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0, 0); int mode = 511; int dir_fd = DEFAULT_DIR_FD; @@ -2673,8 +2693,8 @@ os_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0); + path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0, 0); + path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; @@ -2764,8 +2784,8 @@ os_replace(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0); + path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0, 0); + path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; @@ -2853,7 +2873,7 @@ os_rmdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3102,7 +3122,7 @@ os_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3176,7 +3196,7 @@ os_remove(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3294,7 +3314,7 @@ os_utime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("utime", "path", 0, PATH_UTIME_HAVE_FD); + path_t path = PATH_T_INITIALIZE("utime", "path", 0, 0, PATH_UTIME_HAVE_FD); PyObject *times = Py_None; PyObject *ns = NULL; int dir_fd = DEFAULT_DIR_FD; @@ -3429,7 +3449,7 @@ static PyObject * os_execv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0, 0); PyObject *argv; if (!_PyArg_CheckPositional("execv", nargs, 2, 2)) { @@ -3501,7 +3521,7 @@ os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("execve", "path", 0, PATH_HAVE_FEXECVE); + path_t path = PATH_T_INITIALIZE("execve", "path", 0, 0, PATH_HAVE_FEXECVE); PyObject *argv; PyObject *env; @@ -3597,7 +3617,7 @@ os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #undef KWTUPLE PyObject *argsbuf[10]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0, 0); PyObject *argv; PyObject *env; PyObject *file_actions = NULL; @@ -3747,7 +3767,7 @@ os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj #undef KWTUPLE PyObject *argsbuf[10]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawnp", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("posix_spawnp", "path", 0, 0, 0); PyObject *argv; PyObject *env; PyObject *file_actions = NULL; @@ -3851,7 +3871,7 @@ os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; - path_t path = PATH_T_INITIALIZE("spawnv", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("spawnv", "path", 0, 0, 0); PyObject *argv; if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { @@ -3905,7 +3925,7 @@ os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; - path_t path = PATH_T_INITIALIZE("spawnve", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("spawnve", "path", 0, 0, 0); PyObject *argv; PyObject *env; @@ -6081,7 +6101,7 @@ os_readlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -6165,8 +6185,8 @@ os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0); + path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0, 0); + path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0, 0); int target_is_directory = 0; int dir_fd = DEFAULT_DIR_FD; @@ -6808,7 +6828,7 @@ os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("open", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("open", "path", 0, 0, 0); int flags; int mode = 511; int dir_fd = DEFAULT_DIR_FD; @@ -8396,7 +8416,7 @@ os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0, 0); int mode = 438; int dir_fd = DEFAULT_DIR_FD; @@ -8496,7 +8516,7 @@ os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0, 0); int mode = 384; dev_t device = 0; int dir_fd = DEFAULT_DIR_FD; @@ -8750,7 +8770,7 @@ os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE); + path_t path = PATH_T_INITIALIZE("truncate", "path", 0, 0, PATH_HAVE_FTRUNCATE); Py_off_t length; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -9649,7 +9669,7 @@ os_statvfs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS); + path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, 0, PATH_HAVE_FSTATVFS); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -9713,7 +9733,7 @@ os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -9827,7 +9847,7 @@ os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF); + path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, 0, PATH_HAVE_FPATHCONF); int name; long _return_value; @@ -10017,10 +10037,10 @@ os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0); + path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0, 0); const wchar_t *operation = NULL; const wchar_t *arguments = NULL; - path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0); + path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0, 0); int show_cmd = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf); @@ -10355,8 +10375,8 @@ os_getxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0); + path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0, 0); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -10442,8 +10462,8 @@ os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0); + path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0, 0); Py_buffer value = {NULL, NULL}; int flags = 0; int follow_symlinks = 1; @@ -10550,8 +10570,8 @@ os_removexattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0); + path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0, 0); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -10636,7 +10656,7 @@ os_listxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 1); + path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 0, 1); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); @@ -11613,7 +11633,7 @@ os_scandir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("scandir", "path", 1, PATH_HAVE_FDOPENDIR); + path_t path = PATH_T_INITIALIZE("scandir", "path", 1, 0, PATH_HAVE_FDOPENDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); if (!args) { @@ -11825,7 +11845,7 @@ os__add_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_add_dll_directory", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("_add_dll_directory", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -12660,4 +12680,4 @@ os__supports_virtual_terminal(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */ -/*[clinic end generated code: output=c4698b47007cd6eb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=83770b03eff7f115 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index c9d67ccbb8c908..59cc7784268d29 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1108,6 +1108,8 @@ get_posix_state(PyObject *module) * Input fields: * path.nullable * If nonzero, the path is permitted to be None. + * path.null_embeddable + * If nonzero, the path is permitted to contain embedded null characters. * path.allow_fd * If nonzero, the path is permitted to be a file handle * (a signed int) instead of a string. @@ -1170,10 +1172,13 @@ get_posix_state(PyObject *module) * path_cleanup(). However it is safe to do so.) */ typedef struct { + // Input fields const char *function_name; const char *argument_name; int nullable; + int null_embeddable; int allow_fd; + // Output fields const wchar_t *wide; #ifdef MS_WINDOWS BOOL narrow; @@ -1187,11 +1192,11 @@ typedef struct { } path_t; #ifdef MS_WINDOWS -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ - {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, null_embeddable, allow_fd) \ + {function_name, argument_name, nullable, null_embeddable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} #else -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ - {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, null_embeddable, allow_fd) \ + {function_name, argument_name, nullable, null_embeddable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} #endif static void @@ -1293,7 +1298,7 @@ path_converter(PyObject *o, void *p) FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); goto error_exit; } - if (wcslen(wide) != length) { + if (!path->null_embeddable && wcslen(wide) != length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; } @@ -1304,7 +1309,7 @@ path_converter(PyObject *o, void *p) wide = NULL; goto success_exit; #else - if (!PyUnicode_FSConverter(o, &bytes)) { + if (!_PyUnicode_FSConverter(o, &bytes, path->null_embeddable)) { goto error_exit; } #endif @@ -1341,7 +1346,7 @@ path_converter(PyObject *o, void *p) length = PyBytes_GET_SIZE(bytes); narrow = PyBytes_AS_STRING(bytes); - if ((size_t)length != strlen(narrow)) { + if (!path->null_embeddable && (size_t)length != strlen(narrow)) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; } @@ -1364,7 +1369,7 @@ path_converter(PyObject *o, void *p) FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); goto error_exit; } - if (wcslen(wide) != length) { + if (!path->null_embeddable && wcslen(wide) != length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; } @@ -2911,7 +2916,7 @@ class path_t_converter(CConverter): converter = 'path_converter' - def converter_init(self, *, allow_fd=False, nullable=False): + def converter_init(self, *, allow_fd=False, nullable=False, null_embeddable=False): # right now path_t doesn't support default values. # to support a default value, you'll need to override initialize(). if self.default not in (unspecified, None): @@ -2921,6 +2926,7 @@ class path_t_converter(CConverter): raise RuntimeError("Can't specify a c_default to the path_t converter!") self.nullable = nullable + self.null_embeddable = null_embeddable self.allow_fd = allow_fd def pre_render(self): @@ -2930,10 +2936,11 @@ class path_t_converter(CConverter): return str(int(bool(value))) # add self.py_name here when merging with posixmodule conversion - self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( + self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {})'.format( self.function.name, self.name, strify(self.nullable), + strify(self.null_embeddable), strify(self.allow_fd), ) @@ -3014,7 +3021,7 @@ class sysconf_confname_converter(path_confname_converter): converter="conv_sysconf_confname" [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=f1a792e1921bd863]*/ /*[clinic input] @@ -5089,36 +5096,30 @@ os__path_splitroot_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isdir - s: 'O' + s as path: path_t(null_embeddable=True, allow_fd=True) Return true if the pathname refers to an existing directory. [clinic start generated code]*/ static PyObject * -os__path_isdir_impl(PyObject *module, PyObject *s) -/*[clinic end generated code: output=9d87ab3c8b8a4e61 input=c17f7ef21d22d64e]*/ +os__path_isdir_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=0adeafd60704f710 input=ea7242408dd79e95]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_BASIC_INFO info; - path_t _path = PATH_T_INITIALIZE("isdir", "s", 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (!path_converter(s, &_path)) { - path_cleanup(&_path); - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; + if (path->wide && wcslen(path->wide) != path->length) { + Py_RETURN_FALSE; } Py_BEGIN_ALLOW_THREADS - if (_path.wide) { - if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, + if (path->wide) { + if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (!(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { slow_path = FALSE; @@ -5133,12 +5134,12 @@ os__path_isdir_impl(PyObject *module, PyObject *s) } } if (slow_path) { - if (_path.fd != -1) { - hfile = _Py_get_osfhandle_noraise(_path.fd); + if (path->fd != -1) { + hfile = _Py_get_osfhandle_noraise(path->fd); close_file = FALSE; } else { - hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hfile != INVALID_HANDLE_VALUE) { @@ -5161,7 +5162,7 @@ os__path_isdir_impl(PyObject *module, PyObject *s) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (STAT(_path.wide, &st)) { + if (STAT(path->wide, &st)) { result = 0; } else { @@ -5175,7 +5176,6 @@ os__path_isdir_impl(PyObject *module, PyObject *s) } Py_END_ALLOW_THREADS - path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5186,36 +5186,30 @@ os__path_isdir_impl(PyObject *module, PyObject *s) /*[clinic input] os._path_isfile - path: 'O' + path: path_t(null_embeddable=True, allow_fd=True) Test whether a path is a regular file [clinic start generated code]*/ static PyObject * -os__path_isfile_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=2394ed7c4b5cfd85 input=de22d74960ade365]*/ +os__path_isfile_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=4f72e7b1ada002da input=4ab9dca4fbc441b1]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_BASIC_INFO info; - path_t _path = PATH_T_INITIALIZE("isfile", "path", 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (!path_converter(path, &_path)) { - path_cleanup(&_path); - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; + if (path->wide && wcslen(path->wide) != path->length) { + Py_RETURN_FALSE; } Py_BEGIN_ALLOW_THREADS - if (_path.wide) { - if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, + if (path->wide) { + if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (!(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { slow_path = FALSE; @@ -5230,12 +5224,12 @@ os__path_isfile_impl(PyObject *module, PyObject *path) } } if (slow_path) { - if (_path.fd != -1) { - hfile = _Py_get_osfhandle_noraise(_path.fd); + if (path->fd != -1) { + hfile = _Py_get_osfhandle_noraise(path->fd); close_file = FALSE; } else { - hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hfile != INVALID_HANDLE_VALUE) { @@ -5258,7 +5252,7 @@ os__path_isfile_impl(PyObject *module, PyObject *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (STAT(_path.wide, &st)) { + if (STAT(path->wide, &st)) { result = 0; } else { @@ -5272,7 +5266,6 @@ os__path_isfile_impl(PyObject *module, PyObject *path) } Py_END_ALLOW_THREADS - path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5283,35 +5276,29 @@ os__path_isfile_impl(PyObject *module, PyObject *path) /*[clinic input] os._path_exists - path: 'O' + path: path_t(null_embeddable=True, allow_fd=True) Test whether a path exists. Returns False for broken symbolic links [clinic start generated code]*/ static PyObject * -os__path_exists_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=f508c3b35e13a249 input=380f77cdfa0f7ae8]*/ +os__path_exists_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=69e6089df1fe463a input=bfd8cf0f7e09722f]*/ { HANDLE hfile; BOOL close_file = TRUE; - path_t _path = PATH_T_INITIALIZE("exists", "path", 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (!path_converter(path, &_path)) { - path_cleanup(&_path); - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; + if (path->wide && wcslen(path->wide) != path->length) { + Py_RETURN_FALSE; } Py_BEGIN_ALLOW_THREADS - if (_path.wide) { - if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, + if (path->wide) { + if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (!(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { slow_path = FALSE; @@ -5323,12 +5310,12 @@ os__path_exists_impl(PyObject *module, PyObject *path) } } if (slow_path) { - if (_path.fd != -1) { - hfile = _Py_get_osfhandle_noraise(_path.fd); + if (path->fd != -1) { + hfile = _Py_get_osfhandle_noraise(path->fd); close_file = FALSE; } else { - hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hfile != INVALID_HANDLE_VALUE) { @@ -5344,7 +5331,7 @@ os__path_exists_impl(PyObject *module, PyObject *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (STAT(_path.wide, &st)) { + if (STAT(path->wide, &st)) { result = 0; } else { @@ -5358,7 +5345,6 @@ os__path_exists_impl(PyObject *module, PyObject *path) } Py_END_ALLOW_THREADS - path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5369,36 +5355,30 @@ os__path_exists_impl(PyObject *module, PyObject *path) /*[clinic input] os._path_islink - path: 'O' + path: path_t(null_embeddable=True, allow_fd=True) Test whether a path is a symbolic link [clinic start generated code]*/ static PyObject * -os__path_islink_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=6d8640b1a390c054 input=38a3cb937ccf59bf]*/ +os__path_islink_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=109ad77ec747b3b7 input=380264532e0862a3]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_ATTRIBUTE_TAG_INFO info; - path_t _path = PATH_T_INITIALIZE("islink", "path", 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (!path_converter(path, &_path)) { - path_cleanup(&_path); - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; + if (path->wide && wcslen(path->wide) != path->length) { + Py_RETURN_FALSE; } Py_BEGIN_ALLOW_THREADS - if (_path.wide) { - if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, + if (path->wide) { + if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { slow_path = FALSE; if (statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { @@ -5413,12 +5393,12 @@ os__path_islink_impl(PyObject *module, PyObject *path) } } if (slow_path) { - if (_path.fd != -1) { - hfile = _Py_get_osfhandle_noraise(_path.fd); + if (path->fd != -1) { + hfile = _Py_get_osfhandle_noraise(path->fd); close_file = FALSE; } else { - hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); @@ -5443,7 +5423,7 @@ os__path_islink_impl(PyObject *module, PyObject *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (LSTAT(_path.wide, &st)) { + if (LSTAT(path->wide, &st)) { result = 0; } else { @@ -5457,7 +5437,6 @@ os__path_islink_impl(PyObject *module, PyObject *path) } Py_END_ALLOW_THREADS - path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 2c259b7e869efe..d100376bdb136c 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3790,7 +3790,7 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) int -PyUnicode_FSConverter(PyObject* arg, void* addr) +_PyUnicode_FSConverter(PyObject* arg, void* addr, int null_embeddable) { PyObject *path = NULL; PyObject *output = NULL; @@ -3819,7 +3819,7 @@ PyUnicode_FSConverter(PyObject* arg, void* addr) size = PyBytes_GET_SIZE(output); data = PyBytes_AS_STRING(output); - if ((size_t)size != strlen(data)) { + if (!null_embeddable && (size_t)size != strlen(data)) { PyErr_SetString(PyExc_ValueError, "embedded null byte"); Py_DECREF(output); return 0; @@ -3828,6 +3828,12 @@ PyUnicode_FSConverter(PyObject* arg, void* addr) return Py_CLEANUP_SUPPORTED; } +int +PyUnicode_FSConverter(PyObject* arg, void* addr) +{ + return _PyUnicode_FSConverter(arg, addr, 0); +} + int PyUnicode_FSDecoder(PyObject* arg, void* addr) From 0625bf1785bf218a91ff77e9369483d04c42a530 Mon Sep 17 00:00:00 2001 From: nineteendo Date: Sun, 28 Apr 2024 21:48:57 +0200 Subject: [PATCH 02/26] Add `make_wide` --- Lib/ntpath.py | 28 +-- Lib/posixpath.py | 28 +-- Modules/clinic/posixmodule.c.h | 201 ++++++++++----------- Modules/posixmodule.c | 319 +++++++++++++++++++-------------- 4 files changed, 286 insertions(+), 290 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index e810b655e5ac85..9375b05d7027ee 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -168,7 +168,7 @@ def splitdrive(p): try: - from nt import _path_splitroot_ex + from nt import _path_splitroot_ex as splitroot except ImportError: def splitroot(p): """Split a pathname into drive, root and tail. The drive is defined @@ -220,23 +220,7 @@ def splitroot(p): else: # Relative path, e.g. Windows return empty, empty, p -else: - def splitroot(p): - """Split a pathname into drive, root and tail. The drive is defined - exactly as in splitdrive(). On Windows, the root may be a single path - separator or an empty string. The tail contains anything after the root. - For example: - splitroot('//server/share/') == ('//server/share', '/', '') - splitroot('C:/Users/Barney') == ('C:', '/', 'Users/Barney') - splitroot('C:///spam///ham') == ('C:', '/', '//spam///ham') - splitroot('Windows/notepad') == ('', '', 'Windows/notepad') - """ - p = os.fspath(p) - if isinstance(p, bytes): - drive, root, tail = _path_splitroot_ex(os.fsdecode(p)) - return os.fsencode(drive), os.fsencode(root), os.fsencode(tail) - return _path_splitroot_ex(p) # Split a path in head (everything up to the last '/') and tail (the @@ -553,7 +537,7 @@ def expandvars(path): # Previously, this function also truncated pathnames to 8+3 format, # but as this module is called "ntpath", that's obviously wrong! try: - from nt import _path_normpath + from nt import _path_normpath as normpath except ImportError: def normpath(path): @@ -592,14 +576,6 @@ def normpath(path): comps.append(curdir) return prefix + sep.join(comps) -else: - def normpath(path): - """Normalize path, eliminating double slashes, etc.""" - path = os.fspath(path) - if isinstance(path, bytes): - return os.fsencode(_path_normpath(os.fsdecode(path))) or b"." - return _path_normpath(path) or "." - def _abspath_fallback(path): """Return the absolute version of a path as a fallback function in case diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 56b7915826daf4..bad1746ccb4f19 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -135,7 +135,7 @@ def splitdrive(p): try: - from posix import _path_splitroot_ex + from posix import _path_splitroot_ex as splitroot except ImportError: def splitroot(p): """Split a pathname into drive, root and tail. On Posix, drive is always @@ -164,23 +164,7 @@ def splitroot(p): # Precisely two leading slashes, e.g.: '//foo'. Implementation defined per POSIX, see # https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13 return empty, p[:2], p[2:] -else: - def splitroot(p): - """Split a pathname into drive, root and tail. On Posix, drive is always - empty; the root may be empty, a single slash, or two slashes. The tail - contains anything after the root. For example: - splitroot('foo/bar') == ('', '', 'foo/bar') - splitroot('/foo/bar') == ('', '/', 'foo/bar') - splitroot('//foo/bar') == ('', '//', 'foo/bar') - splitroot('///foo/bar') == ('', '/', '//foo/bar') - """ - p = os.fspath(p) - if isinstance(p, bytes): - # Optimisation: the drive is always empty - _, root, tail = _path_splitroot_ex(os.fsdecode(p)) - return b'', os.fsencode(root), os.fsencode(tail) - return _path_splitroot_ex(p) # Return the tail (basename) part of a path, same as split(path)[1]. @@ -366,7 +350,7 @@ def expandvars(path): # if it contains symbolic links! try: - from posix import _path_normpath + from posix import _path_normpath as normpath except ImportError: def normpath(path): @@ -397,14 +381,6 @@ def normpath(path): path = initial_slashes + sep.join(comps) return path or dot -else: - def normpath(path): - """Normalize path, eliminating double slashes, etc.""" - path = os.fspath(path) - if isinstance(path, bytes): - return os.fsencode(_path_normpath(os.fsdecode(path))) or b"." - return _path_normpath(path) or "." - def abspath(path): """Return an absolute path.""" diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index b6a582f6e81cfa..5015e65b6f2e2a 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -72,7 +72,7 @@ os_stat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("stat", "path", 0, 0, 1); + path_t path = PATH_T_INITIALIZE("stat", "path", 0, 0, 0, 1); int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; @@ -154,7 +154,7 @@ os_lstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -250,7 +250,7 @@ os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("access", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("access", "path", 0, 0, 0, 0); int mode; int dir_fd = DEFAULT_DIR_FD; int effective_ids = 0; @@ -409,7 +409,7 @@ os_chdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chdir", "path", 0, 0, PATH_HAVE_FCHDIR); + path_t path = PATH_T_INITIALIZE("chdir", "path", 0, 0, 0, PATH_HAVE_FCHDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -560,7 +560,7 @@ os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chmod", "path", 0, 0, PATH_HAVE_FCHMOD); + path_t path = PATH_T_INITIALIZE("chmod", "path", 0, 0, 0, PATH_HAVE_FCHMOD); int mode; int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = CHMOD_DEFAULT_FOLLOW_SYMLINKS; @@ -725,7 +725,7 @@ os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0, 0, 0); int mode; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -802,7 +802,7 @@ os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0, 0, 0); unsigned long flags; int follow_symlinks = 1; @@ -884,7 +884,7 @@ os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0, 0, 0); unsigned long flags; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -954,7 +954,7 @@ os_chroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1190,7 +1190,7 @@ os_chown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("chown", "path", 0, 0, PATH_HAVE_FCHOWN); + path_t path = PATH_T_INITIALIZE("chown", "path", 0, 0, 0, PATH_HAVE_FCHOWN); uid_t uid; gid_t gid; int dir_fd = DEFAULT_DIR_FD; @@ -1355,7 +1355,7 @@ os_lchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0, 0, 0); uid_t uid; gid_t gid; @@ -1476,8 +1476,8 @@ os_link(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("link", "src", 0, 0, 0); - path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0, 0); + path_t src = PATH_T_INITIALIZE("link", "src", 0, 0, 0, 0); + path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; @@ -1583,7 +1583,7 @@ os_listdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listdir", "path", 1, 0, PATH_HAVE_FDOPENDIR); + path_t path = PATH_T_INITIALIZE("listdir", "path", 1, 0, 0, PATH_HAVE_FDOPENDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); if (!args) { @@ -1699,7 +1699,7 @@ os_listmounts(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t volume = PATH_T_INITIALIZE("listmounts", "volume", 0, 0, 0); + path_t volume = PATH_T_INITIALIZE("listmounts", "volume", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1763,7 +1763,7 @@ os__path_isdevdrive(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_isdevdrive", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("_path_isdevdrive", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1800,7 +1800,7 @@ static PyObject * os__getfullpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1834,7 +1834,7 @@ static PyObject * os__getfinalpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1868,7 +1868,7 @@ static PyObject * os__findfirstfile(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_findfirstfile", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("_findfirstfile", "path", 0, 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1928,7 +1928,7 @@ os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1992,7 +1992,7 @@ os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_splitroot", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("_path_splitroot", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -2024,7 +2024,7 @@ PyDoc_STRVAR(os__path_isdir__doc__, {"_path_isdir", _PyCFunction_CAST(os__path_isdir), METH_FASTCALL|METH_KEYWORDS, os__path_isdir__doc__}, static PyObject * -os__path_isdir_impl(PyObject *module, path_t *path); +os__path_isdir_impl(PyObject *module, PyObject *s); static PyObject * os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2056,21 +2056,16 @@ os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_isdir", "path", 0, 1, 1); + PyObject *s; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__path_isdir_impl(module, &path); + s = args[0]; + return_value = os__path_isdir_impl(module, s); exit: - /* Cleanup for path */ - path_cleanup(&path); - return return_value; } @@ -2088,7 +2083,7 @@ PyDoc_STRVAR(os__path_isfile__doc__, {"_path_isfile", _PyCFunction_CAST(os__path_isfile), METH_FASTCALL|METH_KEYWORDS, os__path_isfile__doc__}, static PyObject * -os__path_isfile_impl(PyObject *module, path_t *path); +os__path_isfile_impl(PyObject *module, PyObject *path); static PyObject * os__path_isfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2120,21 +2115,16 @@ os__path_isfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_isfile", "path", 0, 1, 1); + PyObject *path; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__path_isfile_impl(module, &path); + path = args[0]; + return_value = os__path_isfile_impl(module, path); exit: - /* Cleanup for path */ - path_cleanup(&path); - return return_value; } @@ -2152,7 +2142,7 @@ PyDoc_STRVAR(os__path_exists__doc__, {"_path_exists", _PyCFunction_CAST(os__path_exists), METH_FASTCALL|METH_KEYWORDS, os__path_exists__doc__}, static PyObject * -os__path_exists_impl(PyObject *module, path_t *path); +os__path_exists_impl(PyObject *module, PyObject *path); static PyObject * os__path_exists(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2184,21 +2174,16 @@ os__path_exists(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_exists", "path", 0, 1, 1); + PyObject *path; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__path_exists_impl(module, &path); + path = args[0]; + return_value = os__path_exists_impl(module, path); exit: - /* Cleanup for path */ - path_cleanup(&path); - return return_value; } @@ -2216,7 +2201,7 @@ PyDoc_STRVAR(os__path_islink__doc__, {"_path_islink", _PyCFunction_CAST(os__path_islink), METH_FASTCALL|METH_KEYWORDS, os__path_islink__doc__}, static PyObject * -os__path_islink_impl(PyObject *module, path_t *path); +os__path_islink_impl(PyObject *module, PyObject *path); static PyObject * os__path_islink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2248,21 +2233,16 @@ os__path_islink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_islink", "path", 0, 1, 1); + PyObject *path; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__path_islink_impl(module, &path); + path = args[0]; + return_value = os__path_islink_impl(module, path); exit: - /* Cleanup for path */ - path_cleanup(&path); - return return_value; } @@ -2271,13 +2251,16 @@ os__path_islink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj PyDoc_STRVAR(os__path_splitroot_ex__doc__, "_path_splitroot_ex($module, /, path)\n" "--\n" -"\n"); +"\n" +"Split a pathname into drive, root and tail.\n" +"\n" +"The tail contains anything after the root."); #define OS__PATH_SPLITROOT_EX_METHODDEF \ {"_path_splitroot_ex", _PyCFunction_CAST(os__path_splitroot_ex), METH_FASTCALL|METH_KEYWORDS, os__path_splitroot_ex__doc__}, static PyObject * -os__path_splitroot_ex_impl(PyObject *module, PyObject *path); +os__path_splitroot_ex_impl(PyObject *module, path_t *path); static PyObject * os__path_splitroot_ex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2309,20 +2292,21 @@ os__path_splitroot_ex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + path_t path = PATH_T_INITIALIZE("_path_splitroot_ex", "path", 0, 1, 1, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("_path_splitroot_ex", "argument 'path'", "str", args[0]); + if (!path_converter(args[0], &path)) { goto exit; } - path = args[0]; - return_value = os__path_splitroot_ex_impl(module, path); + return_value = os__path_splitroot_ex_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2330,13 +2314,13 @@ PyDoc_STRVAR(os__path_normpath__doc__, "_path_normpath($module, /, path)\n" "--\n" "\n" -"Basic path normalization."); +"Normalize path, eliminating double slashes, etc."); #define OS__PATH_NORMPATH_METHODDEF \ {"_path_normpath", _PyCFunction_CAST(os__path_normpath), METH_FASTCALL|METH_KEYWORDS, os__path_normpath__doc__}, static PyObject * -os__path_normpath_impl(PyObject *module, PyObject *path); +os__path_normpath_impl(PyObject *module, path_t *path); static PyObject * os__path_normpath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2368,16 +2352,21 @@ os__path_normpath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + path_t path = PATH_T_INITIALIZE("_path_normpath", "path", 0, 1, 1, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - path = args[0]; - return_value = os__path_normpath_impl(module, path); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_normpath_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2432,7 +2421,7 @@ os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0, 0, 0); int mode = 511; int dir_fd = DEFAULT_DIR_FD; @@ -2693,8 +2682,8 @@ os_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0, 0); - path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0, 0); + path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0, 0, 0); + path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; @@ -2784,8 +2773,8 @@ os_replace(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0, 0); - path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0, 0); + path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0, 0, 0); + path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; @@ -2873,7 +2862,7 @@ os_rmdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3122,7 +3111,7 @@ os_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3196,7 +3185,7 @@ os_remove(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3314,7 +3303,7 @@ os_utime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("utime", "path", 0, 0, PATH_UTIME_HAVE_FD); + path_t path = PATH_T_INITIALIZE("utime", "path", 0, 0, 0, PATH_UTIME_HAVE_FD); PyObject *times = Py_None; PyObject *ns = NULL; int dir_fd = DEFAULT_DIR_FD; @@ -3449,7 +3438,7 @@ static PyObject * os_execv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0, 0, 0); PyObject *argv; if (!_PyArg_CheckPositional("execv", nargs, 2, 2)) { @@ -3521,7 +3510,7 @@ os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("execve", "path", 0, 0, PATH_HAVE_FEXECVE); + path_t path = PATH_T_INITIALIZE("execve", "path", 0, 0, 0, PATH_HAVE_FEXECVE); PyObject *argv; PyObject *env; @@ -3617,7 +3606,7 @@ os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #undef KWTUPLE PyObject *argsbuf[10]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0, 0, 0); PyObject *argv; PyObject *env; PyObject *file_actions = NULL; @@ -3767,7 +3756,7 @@ os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj #undef KWTUPLE PyObject *argsbuf[10]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawnp", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("posix_spawnp", "path", 0, 0, 0, 0); PyObject *argv; PyObject *env; PyObject *file_actions = NULL; @@ -3871,7 +3860,7 @@ os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; - path_t path = PATH_T_INITIALIZE("spawnv", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("spawnv", "path", 0, 0, 0, 0); PyObject *argv; if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { @@ -3925,7 +3914,7 @@ os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; - path_t path = PATH_T_INITIALIZE("spawnve", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("spawnve", "path", 0, 0, 0, 0); PyObject *argv; PyObject *env; @@ -6101,7 +6090,7 @@ os_readlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -6185,8 +6174,8 @@ os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0, 0); - path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0, 0); + path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0, 0, 0); + path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0, 0, 0); int target_is_directory = 0; int dir_fd = DEFAULT_DIR_FD; @@ -6828,7 +6817,7 @@ os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("open", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("open", "path", 0, 0, 0, 0); int flags; int mode = 511; int dir_fd = DEFAULT_DIR_FD; @@ -8416,7 +8405,7 @@ os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0, 0, 0); int mode = 438; int dir_fd = DEFAULT_DIR_FD; @@ -8516,7 +8505,7 @@ os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0, 0, 0); int mode = 384; dev_t device = 0; int dir_fd = DEFAULT_DIR_FD; @@ -8770,7 +8759,7 @@ os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("truncate", "path", 0, 0, PATH_HAVE_FTRUNCATE); + path_t path = PATH_T_INITIALIZE("truncate", "path", 0, 0, 0, PATH_HAVE_FTRUNCATE); Py_off_t length; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -9669,7 +9658,7 @@ os_statvfs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, 0, PATH_HAVE_FSTATVFS); + path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, 0, 0, PATH_HAVE_FSTATVFS); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -9733,7 +9722,7 @@ os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -9847,7 +9836,7 @@ os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, 0, PATH_HAVE_FPATHCONF); + path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, 0, 0, PATH_HAVE_FPATHCONF); int name; long _return_value; @@ -10037,10 +10026,10 @@ os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0, 0); + path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0, 0, 0); const wchar_t *operation = NULL; const wchar_t *arguments = NULL; - path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0, 0); + path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0, 0, 0); int show_cmd = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf); @@ -10375,8 +10364,8 @@ os_getxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 0, 1); - path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0, 0, 0); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -10462,8 +10451,8 @@ os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 0, 1); - path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0, 0, 0); Py_buffer value = {NULL, NULL}; int flags = 0; int follow_symlinks = 1; @@ -10570,8 +10559,8 @@ os_removexattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 0, 1); - path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0, 0, 0); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -10656,7 +10645,7 @@ os_listxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 0, 1); + path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 0, 0, 1); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); @@ -11633,7 +11622,7 @@ os_scandir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("scandir", "path", 1, 0, PATH_HAVE_FDOPENDIR); + path_t path = PATH_T_INITIALIZE("scandir", "path", 1, 0, 0, PATH_HAVE_FDOPENDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); if (!args) { @@ -11845,7 +11834,7 @@ os__add_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_add_dll_directory", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE("_add_dll_directory", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -12680,4 +12669,4 @@ os__supports_virtual_terminal(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */ -/*[clinic end generated code: output=83770b03eff7f115 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bfd2d2216e6079a8 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 59cc7784268d29..69db201b64b2d9 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1110,6 +1110,8 @@ get_posix_state(PyObject *module) * If nonzero, the path is permitted to be None. * path.null_embeddable * If nonzero, the path is permitted to contain embedded null characters. + * path.make_wide + * If zero, the path is encoded to bytes. (Argument is ignored on Windows) * path.allow_fd * If nonzero, the path is permitted to be a file handle * (a signed int) instead of a string. @@ -1125,7 +1127,7 @@ get_posix_state(PyObject *module) * Output fields: * path.wide * Points to the path if it was expressed as Unicode - * and was not encoded. (Only used on Windows.) + * and was not encoded. * path.narrow * Points to the path if it was expressed as bytes, * or it was Unicode and was encoded to bytes. (On Windows, @@ -1177,6 +1179,7 @@ typedef struct { const char *argument_name; int nullable; int null_embeddable; + int make_wide; int allow_fd; // Output fields const wchar_t *wide; @@ -1192,11 +1195,15 @@ typedef struct { } path_t; #ifdef MS_WINDOWS -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, null_embeddable, allow_fd) \ - {function_name, argument_name, nullable, null_embeddable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, \ + null_embeddable, make_wide, allow_fd) \ + {function_name, argument_name, nullable, null_embeddable, make_wide, \ + allow_fd, NULL, FALSE, -1, 0, NULL, NULL} #else -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, null_embeddable, allow_fd) \ - {function_name, argument_name, nullable, null_embeddable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, \ + null_embeddable, make_wide, allow_fd) \ + {function_name, argument_name, nullable, null_embeddable, make_wide, \ + allow_fd, NULL, NULL, -1, 0, NULL, NULL} #endif static void @@ -1217,10 +1224,8 @@ path_converter(PyObject *o, void *p) Py_ssize_t length = 0; int is_index, is_bytes, is_unicode; const char *narrow; -#ifdef MS_WINDOWS PyObject *wo = NULL; wchar_t *wide = NULL; -#endif #define FORMAT_EXCEPTION(exc, fmt) \ PyErr_Format(exc, "%s%s" fmt, \ @@ -1289,26 +1294,36 @@ path_converter(PyObject *o, void *p) } if (is_unicode) { +#ifndef MS_WINDOWS + if (path->make_wide) { +#endif + wide = PyUnicode_AsWideCharString(o, &length); + if (!wide) { + goto error_exit; + } #ifdef MS_WINDOWS - wide = PyUnicode_AsWideCharString(o, &length); - if (!wide) { - goto error_exit; - } - if (length > 32767) { - FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - goto error_exit; - } - if (!path->null_embeddable && wcslen(wide) != length) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto error_exit; - } + if (length > 32767) { + FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); + goto error_exit; + } +#endif + if (!path->null_embeddable && wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_ValueError, + "embedded null character in %s"); + goto error_exit; + } - path->wide = wide; - path->narrow = FALSE; - path->fd = -1; - wide = NULL; - goto success_exit; + path->wide = wide; +#ifdef MS_WINDOWS + path->narrow = FALSE; #else + path->narrow = NULL; +#endif + path->fd = -1; + wide = NULL; + goto success_exit; +#ifndef MS_WINDOWS + } if (!_PyUnicode_FSConverter(o, &bytes, path->null_embeddable)) { goto error_exit; } @@ -1351,42 +1366,51 @@ path_converter(PyObject *o, void *p) goto error_exit; } -#ifdef MS_WINDOWS - wo = PyUnicode_DecodeFSDefaultAndSize( - narrow, - length - ); - if (!wo) { - goto error_exit; - } +#ifndef MS_WINDOWS + if (path->make_wide) { +#endif + wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length); + if (!wo) { + goto error_exit; + } - wide = PyUnicode_AsWideCharString(wo, &length); - Py_DECREF(wo); - if (!wide) { - goto error_exit; - } - if (length > 32767) { - FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - goto error_exit; - } - if (!path->null_embeddable && wcslen(wide) != length) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto error_exit; - } - path->wide = wide; - path->narrow = TRUE; - Py_DECREF(bytes); - wide = NULL; + wide = PyUnicode_AsWideCharString(wo, &length); + Py_DECREF(wo); + if (!wide) { + goto error_exit; + } +#ifdef MS_WINDOWS + if (length > 32767) { + FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); + goto error_exit; + } +#endif + if (!path->null_embeddable && wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_ValueError, + "embedded null character in %s"); + goto error_exit; + } + path->wide = wide; +#ifdef MS_WINDOWS + path->narrow = TRUE; #else - path->wide = NULL; - path->narrow = narrow; - if (bytes == o) { - /* Still a reference owned by path->object, don't have to - worry about path->narrow is used after free. */ + path->narrow = narrow +#endif Py_DECREF(bytes); + wide = NULL; +#ifndef MS_WINDOWS } else { - path->cleanup = bytes; + path->wide = NULL; + path->narrow = narrow; + if (bytes == o) { + /* Still a reference owned by path->object, don't have to + worry about path->narrow is used after free. */ + Py_DECREF(bytes); + } + else { + path->cleanup = bytes; + } } #endif path->fd = -1; @@ -1399,9 +1423,7 @@ path_converter(PyObject *o, void *p) error_exit: Py_XDECREF(o); Py_XDECREF(bytes); -#ifdef MS_WINDOWS PyMem_Free(wide); -#endif return 0; } @@ -2916,7 +2938,8 @@ class path_t_converter(CConverter): converter = 'path_converter' - def converter_init(self, *, allow_fd=False, nullable=False, null_embeddable=False): + def converter_init(self, *, allow_fd=False, make_wide=False, + nullable=False, null_embeddable=False): # right now path_t doesn't support default values. # to support a default value, you'll need to override initialize(). if self.default not in (unspecified, None): @@ -2927,6 +2950,7 @@ class path_t_converter(CConverter): self.nullable = nullable self.null_embeddable = null_embeddable + self.make_wide = make_wide self.allow_fd = allow_fd def pre_render(self): @@ -2936,11 +2960,12 @@ class path_t_converter(CConverter): return str(int(bool(value))) # add self.py_name here when merging with posixmodule conversion - self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {})'.format( + self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {})'.format( self.function.name, self.name, strify(self.nullable), strify(self.null_embeddable), + strify(self.make_wide), strify(self.allow_fd), ) @@ -3021,7 +3046,7 @@ class sysconf_confname_converter(path_confname_converter): converter="conv_sysconf_confname" [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=f1a792e1921bd863]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=b9dc54246b32902c]*/ /*[clinic input] @@ -5096,30 +5121,36 @@ os__path_splitroot_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isdir - s as path: path_t(null_embeddable=True, allow_fd=True) + s: object Return true if the pathname refers to an existing directory. [clinic start generated code]*/ static PyObject * -os__path_isdir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=0adeafd60704f710 input=ea7242408dd79e95]*/ +os__path_isdir_impl(PyObject *module, PyObject *s) +/*[clinic end generated code: output=9d87ab3c8b8a4e61 input=6e8f9d9f66f85cbc]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_BASIC_INFO info; + path_t _path = PATH_T_INITIALIZE("isdir", "s", 0, 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (path->wide && wcslen(path->wide) != path->length) { - Py_RETURN_FALSE; + if (!path_converter(s, &_path)) { + path_cleanup(&_path); + if (PyErr_ExceptionMatches(PyExc_ValueError)) { + PyErr_Clear(); + Py_RETURN_FALSE; + } + return NULL; } Py_BEGIN_ALLOW_THREADS - if (path->wide) { - if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, + if (_path.wide) { + if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (!(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { slow_path = FALSE; @@ -5134,12 +5165,12 @@ os__path_isdir_impl(PyObject *module, path_t *path) } } if (slow_path) { - if (path->fd != -1) { - hfile = _Py_get_osfhandle_noraise(path->fd); + if (_path.fd != -1) { + hfile = _Py_get_osfhandle_noraise(_path.fd); close_file = FALSE; } else { - hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hfile != INVALID_HANDLE_VALUE) { @@ -5162,7 +5193,7 @@ os__path_isdir_impl(PyObject *module, path_t *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (STAT(path->wide, &st)) { + if (STAT(_path.wide, &st)) { result = 0; } else { @@ -5176,6 +5207,7 @@ os__path_isdir_impl(PyObject *module, path_t *path) } Py_END_ALLOW_THREADS + path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5186,30 +5218,36 @@ os__path_isdir_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isfile - path: path_t(null_embeddable=True, allow_fd=True) + path: object Test whether a path is a regular file [clinic start generated code]*/ static PyObject * -os__path_isfile_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=4f72e7b1ada002da input=4ab9dca4fbc441b1]*/ +os__path_isfile_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=2394ed7c4b5cfd85 input=b37b8017895208b2]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_BASIC_INFO info; + path_t _path = PATH_T_INITIALIZE("isfile", "path", 0, 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (path->wide && wcslen(path->wide) != path->length) { - Py_RETURN_FALSE; + if (!path_converter(path, &_path)) { + path_cleanup(&_path); + if (PyErr_ExceptionMatches(PyExc_ValueError)) { + PyErr_Clear(); + Py_RETURN_FALSE; + } + return NULL; } Py_BEGIN_ALLOW_THREADS - if (path->wide) { - if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, + if (_path.wide) { + if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (!(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { slow_path = FALSE; @@ -5224,12 +5262,12 @@ os__path_isfile_impl(PyObject *module, path_t *path) } } if (slow_path) { - if (path->fd != -1) { - hfile = _Py_get_osfhandle_noraise(path->fd); + if (_path.fd != -1) { + hfile = _Py_get_osfhandle_noraise(_path.fd); close_file = FALSE; } else { - hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hfile != INVALID_HANDLE_VALUE) { @@ -5252,7 +5290,7 @@ os__path_isfile_impl(PyObject *module, path_t *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (STAT(path->wide, &st)) { + if (STAT(_path.wide, &st)) { result = 0; } else { @@ -5266,6 +5304,7 @@ os__path_isfile_impl(PyObject *module, path_t *path) } Py_END_ALLOW_THREADS + path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5276,29 +5315,35 @@ os__path_isfile_impl(PyObject *module, path_t *path) /*[clinic input] os._path_exists - path: path_t(null_embeddable=True, allow_fd=True) + path: object Test whether a path exists. Returns False for broken symbolic links [clinic start generated code]*/ static PyObject * -os__path_exists_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=69e6089df1fe463a input=bfd8cf0f7e09722f]*/ +os__path_exists_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=f508c3b35e13a249 input=d0e5ab7388302942]*/ { HANDLE hfile; BOOL close_file = TRUE; + path_t _path = PATH_T_INITIALIZE("exists", "path", 0, 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (path->wide && wcslen(path->wide) != path->length) { - Py_RETURN_FALSE; + if (!path_converter(path, &_path)) { + path_cleanup(&_path); + if (PyErr_ExceptionMatches(PyExc_ValueError)) { + PyErr_Clear(); + Py_RETURN_FALSE; + } + return NULL; } Py_BEGIN_ALLOW_THREADS - if (path->wide) { - if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, + if (_path.wide) { + if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (!(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { slow_path = FALSE; @@ -5310,12 +5355,12 @@ os__path_exists_impl(PyObject *module, path_t *path) } } if (slow_path) { - if (path->fd != -1) { - hfile = _Py_get_osfhandle_noraise(path->fd); + if (_path.fd != -1) { + hfile = _Py_get_osfhandle_noraise(_path.fd); close_file = FALSE; } else { - hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hfile != INVALID_HANDLE_VALUE) { @@ -5331,7 +5376,7 @@ os__path_exists_impl(PyObject *module, path_t *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (STAT(path->wide, &st)) { + if (STAT(_path.wide, &st)) { result = 0; } else { @@ -5345,6 +5390,7 @@ os__path_exists_impl(PyObject *module, path_t *path) } Py_END_ALLOW_THREADS + path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5355,30 +5401,36 @@ os__path_exists_impl(PyObject *module, path_t *path) /*[clinic input] os._path_islink - path: path_t(null_embeddable=True, allow_fd=True) + path: object Test whether a path is a symbolic link [clinic start generated code]*/ static PyObject * -os__path_islink_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=109ad77ec747b3b7 input=380264532e0862a3]*/ +os__path_islink_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=6d8640b1a390c054 input=1a7c08fbe89b1ed6]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_ATTRIBUTE_TAG_INFO info; + path_t _path = PATH_T_INITIALIZE("islink", "path", 0, 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (path->wide && wcslen(path->wide) != path->length) { - Py_RETURN_FALSE; + if (!path_converter(path, &_path)) { + path_cleanup(&_path); + if (PyErr_ExceptionMatches(PyExc_ValueError)) { + PyErr_Clear(); + Py_RETURN_FALSE; + } + return NULL; } Py_BEGIN_ALLOW_THREADS - if (path->wide) { - if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, + if (_path.wide) { + if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { slow_path = FALSE; if (statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { @@ -5393,12 +5445,12 @@ os__path_islink_impl(PyObject *module, path_t *path) } } if (slow_path) { - if (path->fd != -1) { - hfile = _Py_get_osfhandle_noraise(path->fd); + if (_path.fd != -1) { + hfile = _Py_get_osfhandle_noraise(_path.fd); close_file = FALSE; } else { - hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); @@ -5423,7 +5475,7 @@ os__path_islink_impl(PyObject *module, path_t *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (LSTAT(path->wide, &st)) { + if (LSTAT(_path.wide, &st)) { result = 0; } else { @@ -5437,6 +5489,7 @@ os__path_islink_impl(PyObject *module, path_t *path) } Py_END_ALLOW_THREADS + path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5449,23 +5502,22 @@ os__path_islink_impl(PyObject *module, path_t *path) /*[clinic input] os._path_splitroot_ex - path: unicode + path: path_t(null_embeddable=True, make_wide=True) + +Split a pathname into drive, root and tail. +The tail contains anything after the root. [clinic start generated code]*/ static PyObject * -os__path_splitroot_ex_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=de97403d3dfebc40 input=f1470e12d899f9ac]*/ +os__path_splitroot_ex_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=4b0072b6cdf4b611 input=fa388b51979a2f57]*/ { - Py_ssize_t len, drvsize, rootsize; + Py_ssize_t drvsize, rootsize; PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL; - wchar_t *buffer = PyUnicode_AsWideCharString(path, &len); - if (!buffer) { - goto exit; - } - - _Py_skiproot(buffer, len, &drvsize, &rootsize); + const wchar_t *buffer = path->wide; + _Py_skiproot(buffer, path->length, &drvsize, &rootsize); drv = PyUnicode_FromWideChar(buffer, drvsize); if (drv == NULL) { goto exit; @@ -5475,13 +5527,17 @@ os__path_splitroot_ex_impl(PyObject *module, PyObject *path) goto exit; } tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize], - len - drvsize - rootsize); + path->length - drvsize - rootsize); if (tail == NULL) { goto exit; } + if (PyBytes_Check(path->object)) { + Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv)); + Py_SETREF(root, PyUnicode_EncodeFSDefault(root)); + Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail)); + } result = Py_BuildValue("(OOO)", drv, root, tail); exit: - PyMem_Free(buffer); Py_XDECREF(drv); Py_XDECREF(root); Py_XDECREF(tail); @@ -5492,29 +5548,28 @@ os__path_splitroot_ex_impl(PyObject *module, PyObject *path) /*[clinic input] os._path_normpath - path: object + path: path_t(null_embeddable=True, make_wide=True) -Basic path normalization. +Normalize path, eliminating double slashes, etc. [clinic start generated code]*/ static PyObject * -os__path_normpath_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/ +os__path_normpath_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=d353e7ed9410c044 input=4842c54b2fbdfc83]*/ { - if (!PyUnicode_Check(path)) { - PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'", - Py_TYPE(path)->tp_name); - return NULL; + PyObject *result; + Py_ssize_t norm_len; + wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide, + path->length, &norm_len); + if (!norm_len) { + result = PyUnicode_FromOrdinal('.'); } - Py_ssize_t len; - wchar_t *buffer = PyUnicode_AsWideCharString(path, &len); - if (!buffer) { - return NULL; + else { + result = PyUnicode_FromWideChar(norm_path, norm_len); + } + if (PyBytes_Check(path->object)) { + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); } - Py_ssize_t norm_len; - wchar_t *norm_path = _Py_normpath_and_size(buffer, len, &norm_len); - PyObject *result = PyUnicode_FromWideChar(norm_path, norm_len); - PyMem_Free(buffer); return result; } From 28b4b6e8f00def8c44c164167d4c0eb7c532baa3 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:51:01 +0000 Subject: [PATCH 03/26] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2024-04-28-19-51-00.gh-issue-118263.Gaap3S.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-28-19-51-00.gh-issue-118263.Gaap3S.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-28-19-51-00.gh-issue-118263.Gaap3S.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-28-19-51-00.gh-issue-118263.Gaap3S.rst new file mode 100644 index 00000000000000..165a1ba69a811b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-28-19-51-00.gh-issue-118263.Gaap3S.rst @@ -0,0 +1 @@ +Speed up :func:`os.path.splitroot` & :func:`os.path.normpath` with a direct C call. From 19209c69bc67f363276ea3bb73980a688f902430 Mon Sep 17 00:00:00 2001 From: nineteendo Date: Sun, 28 Apr 2024 21:59:50 +0200 Subject: [PATCH 04/26] Fix typo & add type casts --- Modules/posixmodule.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 69db201b64b2d9..e3236a566ae116 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1307,7 +1307,7 @@ path_converter(PyObject *o, void *p) goto error_exit; } #endif - if (!path->null_embeddable && wcslen(wide) != length) { + if (!path->null_embeddable && wcslen(wide) != (size_t)length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; @@ -1361,7 +1361,7 @@ path_converter(PyObject *o, void *p) length = PyBytes_GET_SIZE(bytes); narrow = PyBytes_AS_STRING(bytes); - if (!path->null_embeddable && (size_t)length != strlen(narrow)) { + if (!path->null_embeddable && strlen(narrow) != (size_t)length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; } @@ -1385,7 +1385,7 @@ path_converter(PyObject *o, void *p) goto error_exit; } #endif - if (!path->null_embeddable && wcslen(wide) != length) { + if (!path->null_embeddable && wcslen(wide) != (size_t)length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; @@ -1394,7 +1394,7 @@ path_converter(PyObject *o, void *p) #ifdef MS_WINDOWS path->narrow = TRUE; #else - path->narrow = narrow + path->narrow = narrow; #endif Py_DECREF(bytes); wide = NULL; From 7ca6036a05f26bdb811ea7e2b83056eb1e19688c Mon Sep 17 00:00:00 2001 From: nineteendo Date: Sun, 28 Apr 2024 23:16:45 +0200 Subject: [PATCH 05/26] Add test for fast paths --- Lib/test/test_ntpath.py | 4 ++++ Lib/test/test_posixpath.py | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 7f91bf1c2b837a..9a3d8d6392302f 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -1108,6 +1108,10 @@ def test_fast_paths_in_use(self): # There are fast paths of these functions implemented in posixmodule.c. # Confirm that they are being used, and not the Python fallbacks in # genericpath.py. + self.assertTrue(os.path.splitroot is nt._path_splitroot_ex) + self.assertFalse(inspect.isfunction(os.path.splitroot)) + self.assertTrue(os.path.normpath is nt._path_normpath) + self.assertFalse(inspect.isfunction(os.path.normpath)) self.assertTrue(os.path.isdir is nt._path_isdir) self.assertFalse(inspect.isfunction(os.path.isdir)) self.assertTrue(os.path.isfile is nt._path_isfile) diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py index 32a20efbb64e1d..137bbb7f945aac 100644 --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -1,3 +1,4 @@ +import inspect import os import posixpath import sys @@ -5,7 +6,7 @@ from posixpath import realpath, abspath, dirname, basename from test import test_genericpath from test.support import import_helper -from test.support import os_helper +from test.support import cpython_only, os_helper from test.support.os_helper import FakePath from unittest import mock @@ -283,6 +284,16 @@ def fake_lstat(path): def test_isjunction(self): self.assertFalse(posixpath.isjunction(ABSTFN)) + @unittest.skipIf(sys.platform == 'win32', "Fast paths are not for win32") + @cpython_only + def test_fast_paths_in_use(self): + # There are fast paths of these functions implemented in posixmodule.c. + # Confirm that they are being used, and not the Python fallbacks + self.assertTrue(os.path.splitroot is posix._path_splitroot_ex) + self.assertFalse(inspect.isfunction(os.path.splitroot)) + self.assertTrue(os.path.normpath is posix._path_normpath) + self.assertFalse(inspect.isfunction(os.path.normpath)) + def test_expanduser(self): self.assertEqual(posixpath.expanduser("foo"), "foo") self.assertEqual(posixpath.expanduser(b"foo"), b"foo") From 55c188324b59954b1945a286392aba2a943b39dd Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Mon, 29 Apr 2024 09:36:39 +0200 Subject: [PATCH 06/26] Build tuple faster --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e3236a566ae116..68aeaa206b0e5a 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5536,7 +5536,7 @@ os__path_splitroot_ex_impl(PyObject *module, path_t *path) Py_SETREF(root, PyUnicode_EncodeFSDefault(root)); Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail)); } - result = Py_BuildValue("(OOO)", drv, root, tail); + result = PyTuple_Pack(3, drv, root, tail); exit: Py_XDECREF(drv); Py_XDECREF(root); From 1c93617f36e264537e5d3c6298571e8df67d3b10 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Fri, 3 May 2024 21:39:34 +0200 Subject: [PATCH 07/26] Support `make_wide=False` on Windows --- Modules/clinic/posixmodule.c.h | 116 ++++++++++++++++----------------- Modules/posixmodule.c | 83 ++++++++++------------- 2 files changed, 91 insertions(+), 108 deletions(-) diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 5015e65b6f2e2a..9bbb8da2982932 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -72,7 +72,7 @@ os_stat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("stat", "path", 0, 0, 0, 1); + path_t path = PATH_T_INITIALIZE_P("stat", "path", 0, 0, 1); int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; @@ -154,7 +154,7 @@ os_lstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("lstat", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -250,7 +250,7 @@ os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("access", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("access", "path", 0, 0, 0); int mode; int dir_fd = DEFAULT_DIR_FD; int effective_ids = 0; @@ -409,7 +409,7 @@ os_chdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chdir", "path", 0, 0, 0, PATH_HAVE_FCHDIR); + path_t path = PATH_T_INITIALIZE_P("chdir", "path", 0, 0, PATH_HAVE_FCHDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -560,7 +560,7 @@ os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chmod", "path", 0, 0, 0, PATH_HAVE_FCHMOD); + path_t path = PATH_T_INITIALIZE_P("chmod", "path", 0, 0, PATH_HAVE_FCHMOD); int mode; int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = CHMOD_DEFAULT_FOLLOW_SYMLINKS; @@ -725,7 +725,7 @@ os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("lchmod", "path", 0, 0, 0); int mode; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -802,7 +802,7 @@ os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("chflags", "path", 0, 0, 0); unsigned long flags; int follow_symlinks = 1; @@ -884,7 +884,7 @@ os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("lchflags", "path", 0, 0, 0); unsigned long flags; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -954,7 +954,7 @@ os_chroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("chroot", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1190,7 +1190,7 @@ os_chown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("chown", "path", 0, 0, 0, PATH_HAVE_FCHOWN); + path_t path = PATH_T_INITIALIZE_P("chown", "path", 0, 0, PATH_HAVE_FCHOWN); uid_t uid; gid_t gid; int dir_fd = DEFAULT_DIR_FD; @@ -1355,7 +1355,7 @@ os_lchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("lchown", "path", 0, 0, 0); uid_t uid; gid_t gid; @@ -1476,8 +1476,8 @@ os_link(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("link", "src", 0, 0, 0, 0); - path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0, 0, 0); + path_t src = PATH_T_INITIALIZE_P("link", "src", 0, 0, 0); + path_t dst = PATH_T_INITIALIZE_P("link", "dst", 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; @@ -1583,7 +1583,7 @@ os_listdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listdir", "path", 1, 0, 0, PATH_HAVE_FDOPENDIR); + path_t path = PATH_T_INITIALIZE_P("listdir", "path", 1, 0, PATH_HAVE_FDOPENDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); if (!args) { @@ -1699,7 +1699,7 @@ os_listmounts(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t volume = PATH_T_INITIALIZE("listmounts", "volume", 0, 0, 0, 0); + path_t volume = PATH_T_INITIALIZE_P("listmounts", "volume", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1763,7 +1763,7 @@ os__path_isdevdrive(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_isdevdrive", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_path_isdevdrive", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1800,7 +1800,7 @@ static PyObject * os__getfullpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_getfullpathname", "path", 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1834,7 +1834,7 @@ static PyObject * os__getfinalpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_getfinalpathname", "path", 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1868,7 +1868,7 @@ static PyObject * os__findfirstfile(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_findfirstfile", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_findfirstfile", "path", 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1928,7 +1928,7 @@ os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_getvolumepathname", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1992,7 +1992,7 @@ os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_splitroot", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_path_splitroot", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -2421,7 +2421,7 @@ os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("mkdir", "path", 0, 0, 0); int mode = 511; int dir_fd = DEFAULT_DIR_FD; @@ -2682,8 +2682,8 @@ os_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0, 0, 0); - path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0, 0, 0); + path_t src = PATH_T_INITIALIZE_P("rename", "src", 0, 0, 0); + path_t dst = PATH_T_INITIALIZE_P("rename", "dst", 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; @@ -2773,8 +2773,8 @@ os_replace(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0, 0, 0); - path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0, 0, 0); + path_t src = PATH_T_INITIALIZE_P("replace", "src", 0, 0, 0); + path_t dst = PATH_T_INITIALIZE_P("replace", "dst", 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; @@ -2862,7 +2862,7 @@ os_rmdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("rmdir", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3111,7 +3111,7 @@ os_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("unlink", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3185,7 +3185,7 @@ os_remove(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("remove", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3303,7 +3303,7 @@ os_utime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("utime", "path", 0, 0, 0, PATH_UTIME_HAVE_FD); + path_t path = PATH_T_INITIALIZE_P("utime", "path", 0, 0, PATH_UTIME_HAVE_FD); PyObject *times = Py_None; PyObject *ns = NULL; int dir_fd = DEFAULT_DIR_FD; @@ -3438,7 +3438,7 @@ static PyObject * os_execv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("execv", "path", 0, 0, 0); PyObject *argv; if (!_PyArg_CheckPositional("execv", nargs, 2, 2)) { @@ -3510,7 +3510,7 @@ os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("execve", "path", 0, 0, 0, PATH_HAVE_FEXECVE); + path_t path = PATH_T_INITIALIZE_P("execve", "path", 0, 0, PATH_HAVE_FEXECVE); PyObject *argv; PyObject *env; @@ -3606,7 +3606,7 @@ os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #undef KWTUPLE PyObject *argsbuf[10]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("posix_spawn", "path", 0, 0, 0); PyObject *argv; PyObject *env; PyObject *file_actions = NULL; @@ -3756,7 +3756,7 @@ os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj #undef KWTUPLE PyObject *argsbuf[10]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawnp", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("posix_spawnp", "path", 0, 0, 0); PyObject *argv; PyObject *env; PyObject *file_actions = NULL; @@ -3860,7 +3860,7 @@ os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; - path_t path = PATH_T_INITIALIZE("spawnv", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("spawnv", "path", 0, 0, 0); PyObject *argv; if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { @@ -3914,7 +3914,7 @@ os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; - path_t path = PATH_T_INITIALIZE("spawnve", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("spawnve", "path", 0, 0, 0); PyObject *argv; PyObject *env; @@ -6090,7 +6090,7 @@ os_readlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("readlink", "path", 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -6174,8 +6174,8 @@ os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0, 0, 0); - path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0, 0, 0); + path_t src = PATH_T_INITIALIZE_P("symlink", "src", 0, 0, 0); + path_t dst = PATH_T_INITIALIZE_P("symlink", "dst", 0, 0, 0); int target_is_directory = 0; int dir_fd = DEFAULT_DIR_FD; @@ -6817,7 +6817,7 @@ os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("open", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("open", "path", 0, 0, 0); int flags; int mode = 511; int dir_fd = DEFAULT_DIR_FD; @@ -8405,7 +8405,7 @@ os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("mkfifo", "path", 0, 0, 0); int mode = 438; int dir_fd = DEFAULT_DIR_FD; @@ -8505,7 +8505,7 @@ os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("mknod", "path", 0, 0, 0); int mode = 384; dev_t device = 0; int dir_fd = DEFAULT_DIR_FD; @@ -8759,7 +8759,7 @@ os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("truncate", "path", 0, 0, 0, PATH_HAVE_FTRUNCATE); + path_t path = PATH_T_INITIALIZE_P("truncate", "path", 0, 0, PATH_HAVE_FTRUNCATE); Py_off_t length; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -9658,7 +9658,7 @@ os_statvfs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, 0, 0, PATH_HAVE_FSTATVFS); + path_t path = PATH_T_INITIALIZE_P("statvfs", "path", 0, 0, PATH_HAVE_FSTATVFS); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -9722,7 +9722,7 @@ os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_getdiskusage", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -9836,7 +9836,7 @@ os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, 0, 0, PATH_HAVE_FPATHCONF); + path_t path = PATH_T_INITIALIZE_P("pathconf", "path", 0, 0, PATH_HAVE_FPATHCONF); int name; long _return_value; @@ -10026,10 +10026,10 @@ os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0, 0, 0); + path_t filepath = PATH_T_INITIALIZE_P("startfile", "filepath", 0, 0, 0); const wchar_t *operation = NULL; const wchar_t *arguments = NULL; - path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0, 0, 0); + path_t cwd = PATH_T_INITIALIZE_P("startfile", "cwd", 1, 0, 0); int show_cmd = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf); @@ -10364,8 +10364,8 @@ os_getxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 0, 0, 1); - path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("getxattr", "path", 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE_P("getxattr", "attribute", 0, 0, 0); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -10451,8 +10451,8 @@ os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 0, 0, 1); - path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("setxattr", "path", 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE_P("setxattr", "attribute", 0, 0, 0); Py_buffer value = {NULL, NULL}; int flags = 0; int follow_symlinks = 1; @@ -10559,8 +10559,8 @@ os_removexattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 0, 0, 1); - path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("removexattr", "path", 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE_P("removexattr", "attribute", 0, 0, 0); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -10645,7 +10645,7 @@ os_listxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 0, 0, 1); + path_t path = PATH_T_INITIALIZE_P("listxattr", "path", 1, 0, 1); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); @@ -11622,7 +11622,7 @@ os_scandir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("scandir", "path", 1, 0, 0, PATH_HAVE_FDOPENDIR); + path_t path = PATH_T_INITIALIZE_P("scandir", "path", 1, 0, PATH_HAVE_FDOPENDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); if (!args) { @@ -11834,7 +11834,7 @@ os__add_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_add_dll_directory", "path", 0, 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_add_dll_directory", "path", 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -12669,4 +12669,4 @@ os__supports_virtual_terminal(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */ -/*[clinic end generated code: output=bfd2d2216e6079a8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fab60e954c4367e1 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 68aeaa206b0e5a..1de1125917c769 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1130,9 +1130,7 @@ get_posix_state(PyObject *module) * and was not encoded. * path.narrow * Points to the path if it was expressed as bytes, - * or it was Unicode and was encoded to bytes. (On Windows, - * is a non-zero integer if the path was expressed as bytes. - * The type is deliberately incompatible to prevent misuse.) + * or it was Unicode and was encoded to bytes. * path.fd * Contains a file descriptor if path.accept_fd was true * and the caller provided a signed integer instead of any @@ -1183,27 +1181,27 @@ typedef struct { int allow_fd; // Output fields const wchar_t *wide; -#ifdef MS_WINDOWS - BOOL narrow; -#else const char *narrow; -#endif int fd; Py_ssize_t length; PyObject *object; PyObject *cleanup; } path_t; -#ifdef MS_WINDOWS -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, \ - null_embeddable, make_wide, allow_fd) \ - {function_name, argument_name, nullable, null_embeddable, make_wide, \ - allow_fd, NULL, FALSE, -1, 0, NULL, NULL} -#else #define PATH_T_INITIALIZE(function_name, argument_name, nullable, \ null_embeddable, make_wide, allow_fd) \ {function_name, argument_name, nullable, null_embeddable, make_wide, \ allow_fd, NULL, NULL, -1, 0, NULL, NULL} +#ifdef MS_WINDOWS +#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ + null_embeddable, allow_fd) \ + PATH_T_INITIALIZE(function_name, argument_name, nullable, \ + null_embeddable, 1, allow_fd) +#else +#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ + null_embeddable, allow_fd) \ + PATH_T_INITIALIZE(function_name, argument_name, nullable, \ + null_embeddable, 0, allow_fd) #endif static void @@ -1246,11 +1244,7 @@ path_converter(PyObject *o, void *p) if ((o == Py_None) && path->nullable) { path->wide = NULL; -#ifdef MS_WINDOWS - path->narrow = FALSE; -#else path->narrow = NULL; -#endif path->fd = -1; goto success_exit; } @@ -1294,9 +1288,7 @@ path_converter(PyObject *o, void *p) } if (is_unicode) { -#ifndef MS_WINDOWS if (path->make_wide) { -#endif wide = PyUnicode_AsWideCharString(o, &length); if (!wide) { goto error_exit; @@ -1314,20 +1306,14 @@ path_converter(PyObject *o, void *p) } path->wide = wide; -#ifdef MS_WINDOWS - path->narrow = FALSE; -#else path->narrow = NULL; -#endif path->fd = -1; wide = NULL; goto success_exit; -#ifndef MS_WINDOWS } if (!_PyUnicode_FSConverter(o, &bytes, path->null_embeddable)) { goto error_exit; } -#endif } else if (is_bytes) { bytes = Py_NewRef(o); @@ -1337,11 +1323,7 @@ path_converter(PyObject *o, void *p) goto error_exit; } path->wide = NULL; -#ifdef MS_WINDOWS - path->narrow = FALSE; -#else path->narrow = NULL; -#endif goto success_exit; } else { @@ -1366,9 +1348,7 @@ path_converter(PyObject *o, void *p) goto error_exit; } -#ifndef MS_WINDOWS if (path->make_wide) { -#endif wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length); if (!wo) { goto error_exit; @@ -1391,14 +1371,9 @@ path_converter(PyObject *o, void *p) goto error_exit; } path->wide = wide; -#ifdef MS_WINDOWS - path->narrow = TRUE; -#else - path->narrow = narrow; -#endif + path->narrow = narrow; // TODO: replace by NULL Py_DECREF(bytes); wide = NULL; -#ifndef MS_WINDOWS } else { path->wide = NULL; @@ -1412,7 +1387,6 @@ path_converter(PyObject *o, void *p) path->cleanup = bytes; } } -#endif path->fd = -1; success_exit: @@ -2938,7 +2912,7 @@ class path_t_converter(CConverter): converter = 'path_converter' - def converter_init(self, *, allow_fd=False, make_wide=False, + def converter_init(self, *, allow_fd=False, make_wide=None, nullable=False, null_embeddable=False): # right now path_t doesn't support default values. # to support a default value, you'll need to override initialize(). @@ -2960,13 +2934,22 @@ class path_t_converter(CConverter): return str(int(bool(value))) # add self.py_name here when merging with posixmodule conversion - self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {})'.format( - self.function.name, - self.name, - strify(self.nullable), - strify(self.null_embeddable), - strify(self.make_wide), - strify(self.allow_fd), + if self.make_wide is None: + self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {})'.format( + self.function.name, + self.name, + strify(self.nullable), + strify(self.null_embeddable), + strify(self.allow_fd), + ) + else: + self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {})'.format( + self.function.name, + self.name, + strify(self.nullable), + strify(self.null_embeddable), + strify(self.make_wide), + strify(self.allow_fd), ) def cleanup(self): @@ -5134,7 +5117,7 @@ os__path_isdir_impl(PyObject *module, PyObject *s) HANDLE hfile; BOOL close_file = TRUE; FILE_BASIC_INFO info; - path_t _path = PATH_T_INITIALIZE("isdir", "s", 0, 0, 0, 1); + path_t _path = PATH_T_INITIALIZE_P("isdir", "s", 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; @@ -5231,7 +5214,7 @@ os__path_isfile_impl(PyObject *module, PyObject *path) HANDLE hfile; BOOL close_file = TRUE; FILE_BASIC_INFO info; - path_t _path = PATH_T_INITIALIZE("isfile", "path", 0, 0, 0, 1); + path_t _path = PATH_T_INITIALIZE_P("isfile", "path", 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; @@ -5327,7 +5310,7 @@ os__path_exists_impl(PyObject *module, PyObject *path) { HANDLE hfile; BOOL close_file = TRUE; - path_t _path = PATH_T_INITIALIZE("exists", "path", 0, 0, 0, 1); + path_t _path = PATH_T_INITIALIZE_P("exists", "path", 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; @@ -5414,7 +5397,7 @@ os__path_islink_impl(PyObject *module, PyObject *path) HANDLE hfile; BOOL close_file = TRUE; FILE_ATTRIBUTE_TAG_INFO info; - path_t _path = PATH_T_INITIALIZE("islink", "path", 0, 0, 0, 1); + path_t _path = PATH_T_INITIALIZE_P("islink", "path", 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; From dc36f2e7fe4451f34a13b6be467755c7990ddcef Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Fri, 3 May 2024 21:44:22 +0200 Subject: [PATCH 08/26] Update generated code --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 1de1125917c769..d34e14681ee96e 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3029,7 +3029,7 @@ class sysconf_confname_converter(path_confname_converter): converter="conv_sysconf_confname" [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=b9dc54246b32902c]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=fe32fef4a3a19fe5]*/ /*[clinic input] From 0a9d497e672a7be1da91bedd0839c5a7ad220bca Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 07:29:53 +0200 Subject: [PATCH 09/26] Add `suppress` --- Modules/clinic/posixmodule.c.h | 172 ++++++++++++++++++--------------- Modules/posixmodule.c | 149 ++++++++++++++-------------- 2 files changed, 174 insertions(+), 147 deletions(-) diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 9bbb8da2982932..de6c9e2fbd07bb 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -72,7 +72,7 @@ os_stat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("stat", "path", 0, 0, 1); + path_t path = PATH_T_INITIALIZE_P("stat", "path", 0, 0, 0, 1); int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; @@ -154,7 +154,7 @@ os_lstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("lstat", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("lstat", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -250,7 +250,7 @@ os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE_P("access", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("access", "path", 0, 0, 0, 0); int mode; int dir_fd = DEFAULT_DIR_FD; int effective_ids = 0; @@ -409,7 +409,7 @@ os_chdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("chdir", "path", 0, 0, PATH_HAVE_FCHDIR); + path_t path = PATH_T_INITIALIZE_P("chdir", "path", 0, 0, 0, PATH_HAVE_FCHDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -560,7 +560,7 @@ os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE_P("chmod", "path", 0, 0, PATH_HAVE_FCHMOD); + path_t path = PATH_T_INITIALIZE_P("chmod", "path", 0, 0, 0, PATH_HAVE_FCHMOD); int mode; int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = CHMOD_DEFAULT_FOLLOW_SYMLINKS; @@ -725,7 +725,7 @@ os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE_P("lchmod", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("lchmod", "path", 0, 0, 0, 0); int mode; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -802,7 +802,7 @@ os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE_P("chflags", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("chflags", "path", 0, 0, 0, 0); unsigned long flags; int follow_symlinks = 1; @@ -884,7 +884,7 @@ os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE_P("lchflags", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("lchflags", "path", 0, 0, 0, 0); unsigned long flags; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -954,7 +954,7 @@ os_chroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("chroot", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("chroot", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1190,7 +1190,7 @@ os_chown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE_P("chown", "path", 0, 0, PATH_HAVE_FCHOWN); + path_t path = PATH_T_INITIALIZE_P("chown", "path", 0, 0, 0, PATH_HAVE_FCHOWN); uid_t uid; gid_t gid; int dir_fd = DEFAULT_DIR_FD; @@ -1355,7 +1355,7 @@ os_lchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE_P("lchown", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("lchown", "path", 0, 0, 0, 0); uid_t uid; gid_t gid; @@ -1476,8 +1476,8 @@ os_link(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE_P("link", "src", 0, 0, 0); - path_t dst = PATH_T_INITIALIZE_P("link", "dst", 0, 0, 0); + path_t src = PATH_T_INITIALIZE_P("link", "src", 0, 0, 0, 0); + path_t dst = PATH_T_INITIALIZE_P("link", "dst", 0, 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; @@ -1583,7 +1583,7 @@ os_listdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE_P("listdir", "path", 1, 0, PATH_HAVE_FDOPENDIR); + path_t path = PATH_T_INITIALIZE_P("listdir", "path", 1, 0, 0, PATH_HAVE_FDOPENDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); if (!args) { @@ -1699,7 +1699,7 @@ os_listmounts(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t volume = PATH_T_INITIALIZE_P("listmounts", "volume", 0, 0, 0); + path_t volume = PATH_T_INITIALIZE_P("listmounts", "volume", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1763,7 +1763,7 @@ os__path_isdevdrive(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("_path_isdevdrive", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_path_isdevdrive", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1800,7 +1800,7 @@ static PyObject * os__getfullpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE_P("_getfullpathname", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_getfullpathname", "path", 0, 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1834,7 +1834,7 @@ static PyObject * os__getfinalpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE_P("_getfinalpathname", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_getfinalpathname", "path", 0, 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1868,7 +1868,7 @@ static PyObject * os__findfirstfile(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE_P("_findfirstfile", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_findfirstfile", "path", 0, 0, 0, 0); if (!path_converter(arg, &path)) { goto exit; @@ -1928,7 +1928,7 @@ os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("_getvolumepathname", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_getvolumepathname", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -1992,7 +1992,7 @@ os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("_path_splitroot", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_path_splitroot", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -2024,7 +2024,7 @@ PyDoc_STRVAR(os__path_isdir__doc__, {"_path_isdir", _PyCFunction_CAST(os__path_isdir), METH_FASTCALL|METH_KEYWORDS, os__path_isdir__doc__}, static PyObject * -os__path_isdir_impl(PyObject *module, PyObject *s); +os__path_isdir_impl(PyObject *module, path_t *path); static PyObject * os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2056,16 +2056,21 @@ os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *s; + path_t path = PATH_T_INITIALIZE_P("_path_isdir", "path", 0, 0, 1, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - s = args[0]; - return_value = os__path_isdir_impl(module, s); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_isdir_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2083,7 +2088,7 @@ PyDoc_STRVAR(os__path_isfile__doc__, {"_path_isfile", _PyCFunction_CAST(os__path_isfile), METH_FASTCALL|METH_KEYWORDS, os__path_isfile__doc__}, static PyObject * -os__path_isfile_impl(PyObject *module, PyObject *path); +os__path_isfile_impl(PyObject *module, path_t *path); static PyObject * os__path_isfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2115,16 +2120,21 @@ os__path_isfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + path_t path = PATH_T_INITIALIZE_P("_path_isfile", "path", 0, 0, 1, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - path = args[0]; - return_value = os__path_isfile_impl(module, path); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_isfile_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2142,7 +2152,7 @@ PyDoc_STRVAR(os__path_exists__doc__, {"_path_exists", _PyCFunction_CAST(os__path_exists), METH_FASTCALL|METH_KEYWORDS, os__path_exists__doc__}, static PyObject * -os__path_exists_impl(PyObject *module, PyObject *path); +os__path_exists_impl(PyObject *module, path_t *path); static PyObject * os__path_exists(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2174,16 +2184,21 @@ os__path_exists(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + path_t path = PATH_T_INITIALIZE_P("_path_exists", "path", 0, 0, 1, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - path = args[0]; - return_value = os__path_exists_impl(module, path); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_exists_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2201,7 +2216,7 @@ PyDoc_STRVAR(os__path_islink__doc__, {"_path_islink", _PyCFunction_CAST(os__path_islink), METH_FASTCALL|METH_KEYWORDS, os__path_islink__doc__}, static PyObject * -os__path_islink_impl(PyObject *module, PyObject *path); +os__path_islink_impl(PyObject *module, path_t *path); static PyObject * os__path_islink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -2233,16 +2248,21 @@ os__path_islink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + path_t path = PATH_T_INITIALIZE_P("_path_islink", "path", 0, 0, 1, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - path = args[0]; - return_value = os__path_islink_impl(module, path); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_islink_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -2292,7 +2312,7 @@ os__path_splitroot_ex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_splitroot_ex", "path", 0, 1, 1, 0); + path_t path = PATH_T_INITIALIZE("_path_splitroot_ex", "path", 0, 1, 1, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -2352,7 +2372,7 @@ os__path_normpath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_normpath", "path", 0, 1, 1, 0); + path_t path = PATH_T_INITIALIZE("_path_normpath", "path", 0, 1, 1, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -2421,7 +2441,7 @@ os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("mkdir", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("mkdir", "path", 0, 0, 0, 0); int mode = 511; int dir_fd = DEFAULT_DIR_FD; @@ -2682,8 +2702,8 @@ os_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE_P("rename", "src", 0, 0, 0); - path_t dst = PATH_T_INITIALIZE_P("rename", "dst", 0, 0, 0); + path_t src = PATH_T_INITIALIZE_P("rename", "src", 0, 0, 0, 0); + path_t dst = PATH_T_INITIALIZE_P("rename", "dst", 0, 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; @@ -2773,8 +2793,8 @@ os_replace(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE_P("replace", "src", 0, 0, 0); - path_t dst = PATH_T_INITIALIZE_P("replace", "dst", 0, 0, 0); + path_t src = PATH_T_INITIALIZE_P("replace", "src", 0, 0, 0, 0); + path_t dst = PATH_T_INITIALIZE_P("replace", "dst", 0, 0, 0, 0); int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; @@ -2862,7 +2882,7 @@ os_rmdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("rmdir", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("rmdir", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3111,7 +3131,7 @@ os_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("unlink", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("unlink", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3185,7 +3205,7 @@ os_remove(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("remove", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("remove", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -3303,7 +3323,7 @@ os_utime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("utime", "path", 0, 0, PATH_UTIME_HAVE_FD); + path_t path = PATH_T_INITIALIZE_P("utime", "path", 0, 0, 0, PATH_UTIME_HAVE_FD); PyObject *times = Py_None; PyObject *ns = NULL; int dir_fd = DEFAULT_DIR_FD; @@ -3438,7 +3458,7 @@ static PyObject * os_execv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE_P("execv", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("execv", "path", 0, 0, 0, 0); PyObject *argv; if (!_PyArg_CheckPositional("execv", nargs, 2, 2)) { @@ -3510,7 +3530,7 @@ os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k }; #undef KWTUPLE PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE_P("execve", "path", 0, 0, PATH_HAVE_FEXECVE); + path_t path = PATH_T_INITIALIZE_P("execve", "path", 0, 0, 0, PATH_HAVE_FEXECVE); PyObject *argv; PyObject *env; @@ -3606,7 +3626,7 @@ os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #undef KWTUPLE PyObject *argsbuf[10]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE_P("posix_spawn", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("posix_spawn", "path", 0, 0, 0, 0); PyObject *argv; PyObject *env; PyObject *file_actions = NULL; @@ -3756,7 +3776,7 @@ os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj #undef KWTUPLE PyObject *argsbuf[10]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE_P("posix_spawnp", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("posix_spawnp", "path", 0, 0, 0, 0); PyObject *argv; PyObject *env; PyObject *file_actions = NULL; @@ -3860,7 +3880,7 @@ os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; - path_t path = PATH_T_INITIALIZE_P("spawnv", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("spawnv", "path", 0, 0, 0, 0); PyObject *argv; if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { @@ -3914,7 +3934,7 @@ os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int mode; - path_t path = PATH_T_INITIALIZE_P("spawnve", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("spawnve", "path", 0, 0, 0, 0); PyObject *argv; PyObject *env; @@ -6090,7 +6110,7 @@ os_readlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("readlink", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("readlink", "path", 0, 0, 0, 0); int dir_fd = DEFAULT_DIR_FD; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -6174,8 +6194,8 @@ os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE_P("symlink", "src", 0, 0, 0); - path_t dst = PATH_T_INITIALIZE_P("symlink", "dst", 0, 0, 0); + path_t src = PATH_T_INITIALIZE_P("symlink", "src", 0, 0, 0, 0); + path_t dst = PATH_T_INITIALIZE_P("symlink", "dst", 0, 0, 0, 0); int target_is_directory = 0; int dir_fd = DEFAULT_DIR_FD; @@ -6817,7 +6837,7 @@ os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE_P("open", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("open", "path", 0, 0, 0, 0); int flags; int mode = 511; int dir_fd = DEFAULT_DIR_FD; @@ -8405,7 +8425,7 @@ os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("mkfifo", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("mkfifo", "path", 0, 0, 0, 0); int mode = 438; int dir_fd = DEFAULT_DIR_FD; @@ -8505,7 +8525,7 @@ os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw #undef KWTUPLE PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE_P("mknod", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("mknod", "path", 0, 0, 0, 0); int mode = 384; dev_t device = 0; int dir_fd = DEFAULT_DIR_FD; @@ -8759,7 +8779,7 @@ os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE_P("truncate", "path", 0, 0, PATH_HAVE_FTRUNCATE); + path_t path = PATH_T_INITIALIZE_P("truncate", "path", 0, 0, 0, PATH_HAVE_FTRUNCATE); Py_off_t length; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -9658,7 +9678,7 @@ os_statvfs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("statvfs", "path", 0, 0, PATH_HAVE_FSTATVFS); + path_t path = PATH_T_INITIALIZE_P("statvfs", "path", 0, 0, 0, PATH_HAVE_FSTATVFS); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -9722,7 +9742,7 @@ os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("_getdiskusage", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_getdiskusage", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -9836,7 +9856,7 @@ os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject }; #undef KWTUPLE PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE_P("pathconf", "path", 0, 0, PATH_HAVE_FPATHCONF); + path_t path = PATH_T_INITIALIZE_P("pathconf", "path", 0, 0, 0, PATH_HAVE_FPATHCONF); int name; long _return_value; @@ -10026,10 +10046,10 @@ os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t filepath = PATH_T_INITIALIZE_P("startfile", "filepath", 0, 0, 0); + path_t filepath = PATH_T_INITIALIZE_P("startfile", "filepath", 0, 0, 0, 0); const wchar_t *operation = NULL; const wchar_t *arguments = NULL; - path_t cwd = PATH_T_INITIALIZE_P("startfile", "cwd", 1, 0, 0); + path_t cwd = PATH_T_INITIALIZE_P("startfile", "cwd", 1, 0, 0, 0); int show_cmd = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf); @@ -10364,8 +10384,8 @@ os_getxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE_P("getxattr", "path", 0, 0, 1); - path_t attribute = PATH_T_INITIALIZE_P("getxattr", "attribute", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("getxattr", "path", 0, 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE_P("getxattr", "attribute", 0, 0, 0, 0); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -10451,8 +10471,8 @@ os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE_P("setxattr", "path", 0, 0, 1); - path_t attribute = PATH_T_INITIALIZE_P("setxattr", "attribute", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("setxattr", "path", 0, 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE_P("setxattr", "attribute", 0, 0, 0, 0); Py_buffer value = {NULL, NULL}; int flags = 0; int follow_symlinks = 1; @@ -10559,8 +10579,8 @@ os_removexattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE_P("removexattr", "path", 0, 0, 1); - path_t attribute = PATH_T_INITIALIZE_P("removexattr", "attribute", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("removexattr", "path", 0, 0, 0, 1); + path_t attribute = PATH_T_INITIALIZE_P("removexattr", "attribute", 0, 0, 0, 0); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); @@ -10645,7 +10665,7 @@ os_listxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #undef KWTUPLE PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE_P("listxattr", "path", 1, 0, 1); + path_t path = PATH_T_INITIALIZE_P("listxattr", "path", 1, 0, 0, 1); int follow_symlinks = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); @@ -11622,7 +11642,7 @@ os_scandir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE_P("scandir", "path", 1, 0, PATH_HAVE_FDOPENDIR); + path_t path = PATH_T_INITIALIZE_P("scandir", "path", 1, 0, 0, PATH_HAVE_FDOPENDIR); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); if (!args) { @@ -11834,7 +11854,7 @@ os__add_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("_add_dll_directory", "path", 0, 0, 0); + path_t path = PATH_T_INITIALIZE_P("_add_dll_directory", "path", 0, 0, 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -12669,4 +12689,4 @@ os__supports_virtual_terminal(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */ -/*[clinic end generated code: output=fab60e954c4367e1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=68dd3493b6596cb4 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index d34e14681ee96e..211f1180785299 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1090,13 +1090,13 @@ get_posix_state(PyObject *module) * * path_converter accepts (Unicode) strings and their * subclasses, and bytes and their subclasses. What - * it does with the argument depends on the platform: + * it does with the argument depends on path.make_wide: * - * * On Windows, if we get a (Unicode) string we - * extract the wchar_t * and return it; if we get - * bytes we decode to wchar_t * and return that. + * * If path.make_wide is nonzero, if we get a (Unicode) + * string we extract the wchar_t * and return it; if we + * get bytes we decode to wchar_t * and return that. * - * * On all other platforms, strings are encoded + * * If path.make_wide is zero, strings are encoded * to bytes using PyUnicode_FSConverter, then we * extract the char * from the bytes object and * return that. @@ -1111,7 +1111,9 @@ get_posix_state(PyObject *module) * path.null_embeddable * If nonzero, the path is permitted to contain embedded null characters. * path.make_wide - * If zero, the path is encoded to bytes. (Argument is ignored on Windows) + * If nonzero, the path is decoded to Unicode, encoded to bytes otherwise. + * path.suppress + * If nonzero, errors are suppressed. * path.allow_fd * If nonzero, the path is permitted to be a file handle * (a signed int) instead of a string. @@ -1127,7 +1129,7 @@ get_posix_state(PyObject *module) * Output fields: * path.wide * Points to the path if it was expressed as Unicode - * and was not encoded. + * or it was bytes and was encoded to Unicode. * path.narrow * Points to the path if it was expressed as bytes, * or it was Unicode and was encoded to bytes. @@ -1140,6 +1142,8 @@ get_posix_state(PyObject *module) * unspecified, path_converter will never get called. * So if you set allow_fd, you *MUST* initialize path.fd = -1 * yourself! + * path.error + * If nonzero, an error occurred. * path.length * The length of the path in characters, if specified as * a string. @@ -1178,30 +1182,32 @@ typedef struct { int nullable; int null_embeddable; int make_wide; + int suppress; int allow_fd; // Output fields const wchar_t *wide; const char *narrow; int fd; + int error; Py_ssize_t length; PyObject *object; PyObject *cleanup; } path_t; #define PATH_T_INITIALIZE(function_name, argument_name, nullable, \ - null_embeddable, make_wide, allow_fd) \ + null_embeddable, make_wide, suppress, allow_fd) \ {function_name, argument_name, nullable, null_embeddable, make_wide, \ - allow_fd, NULL, NULL, -1, 0, NULL, NULL} + suppress, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL} #ifdef MS_WINDOWS #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ - null_embeddable, allow_fd) \ + null_embeddable, suppress, allow_fd) \ PATH_T_INITIALIZE(function_name, argument_name, nullable, \ - null_embeddable, 1, allow_fd) + null_embeddable, 1, suppress, allow_fd) #else #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ - null_embeddable, allow_fd) \ + null_embeddable, suppress, allow_fd) \ PATH_T_INITIALIZE(function_name, argument_name, nullable, \ - null_embeddable, 0, allow_fd) + null_embeddable, 0, suppress, allow_fd) #endif static void @@ -1390,6 +1396,7 @@ path_converter(PyObject *o, void *p) path->fd = -1; success_exit: + path->error = 0; path->length = length; path->object = o; return Py_CLEANUP_SUPPORTED; @@ -1398,7 +1405,16 @@ path_converter(PyObject *o, void *p) Py_XDECREF(o); Py_XDECREF(bytes); PyMem_Free(wide); - return 0; + if (!path->suppress) { + return 0; + } + path->wide = NULL; + path->narrow = NULL; + path->fd = -1; + path->error = 1; + path->length = 0; + path->object = NULL; + return Py_CLEANUP_SUPPORTED; } static void @@ -2912,8 +2928,8 @@ class path_t_converter(CConverter): converter = 'path_converter' - def converter_init(self, *, allow_fd=False, make_wide=None, - nullable=False, null_embeddable=False): + def converter_init(self, *, allow_fd=False, make_wide=None, nullable=False, + null_embeddable=False, suppress=False): # right now path_t doesn't support default values. # to support a default value, you'll need to override initialize(). if self.default not in (unspecified, None): @@ -2925,6 +2941,7 @@ class path_t_converter(CConverter): self.nullable = nullable self.null_embeddable = null_embeddable self.make_wide = make_wide + self.suppress = suppress self.allow_fd = allow_fd def pre_render(self): @@ -2935,20 +2952,22 @@ class path_t_converter(CConverter): # add self.py_name here when merging with posixmodule conversion if self.make_wide is None: - self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {})'.format( + self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format( self.function.name, self.name, strify(self.nullable), strify(self.null_embeddable), + strify(self.suppress), strify(self.allow_fd), ) else: - self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {})'.format( + self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format( self.function.name, self.name, strify(self.nullable), strify(self.null_embeddable), strify(self.make_wide), + strify(self.suppress), strify(self.allow_fd), ) @@ -3029,7 +3048,7 @@ class sysconf_confname_converter(path_confname_converter): converter="conv_sysconf_confname" [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=fe32fef4a3a19fe5]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=9bfc716d9f7ad345]*/ /*[clinic input] @@ -5104,26 +5123,24 @@ os__path_splitroot_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isdir - s: object + s as path: path_t(suppress=True) Return true if the pathname refers to an existing directory. [clinic start generated code]*/ static PyObject * -os__path_isdir_impl(PyObject *module, PyObject *s) -/*[clinic end generated code: output=9d87ab3c8b8a4e61 input=6e8f9d9f66f85cbc]*/ +os__path_isdir_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=0adeafd60704f710 input=945359aa5bde6f2e]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_BASIC_INFO info; - path_t _path = PATH_T_INITIALIZE_P("isdir", "s", 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (!path_converter(s, &_path)) { - path_cleanup(&_path); + if (path->error) { if (PyErr_ExceptionMatches(PyExc_ValueError)) { PyErr_Clear(); Py_RETURN_FALSE; @@ -5132,8 +5149,8 @@ os__path_isdir_impl(PyObject *module, PyObject *s) } Py_BEGIN_ALLOW_THREADS - if (_path.wide) { - if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, + if (path->wide) { + if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (!(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { slow_path = FALSE; @@ -5148,12 +5165,12 @@ os__path_isdir_impl(PyObject *module, PyObject *s) } } if (slow_path) { - if (_path.fd != -1) { - hfile = _Py_get_osfhandle_noraise(_path.fd); + if (path->fd != -1) { + hfile = _Py_get_osfhandle_noraise(path->fd); close_file = FALSE; } else { - hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hfile != INVALID_HANDLE_VALUE) { @@ -5176,7 +5193,7 @@ os__path_isdir_impl(PyObject *module, PyObject *s) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (STAT(_path.wide, &st)) { + if (STAT(path->wide, &st)) { result = 0; } else { @@ -5190,7 +5207,6 @@ os__path_isdir_impl(PyObject *module, PyObject *s) } Py_END_ALLOW_THREADS - path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5201,26 +5217,24 @@ os__path_isdir_impl(PyObject *module, PyObject *s) /*[clinic input] os._path_isfile - path: object + path: path_t(suppress=True) Test whether a path is a regular file [clinic start generated code]*/ static PyObject * -os__path_isfile_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=2394ed7c4b5cfd85 input=b37b8017895208b2]*/ +os__path_isfile_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=4f72e7b1ada002da input=f095340c0e8e84e9]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_BASIC_INFO info; - path_t _path = PATH_T_INITIALIZE_P("isfile", "path", 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (!path_converter(path, &_path)) { - path_cleanup(&_path); + if (path->error) { if (PyErr_ExceptionMatches(PyExc_ValueError)) { PyErr_Clear(); Py_RETURN_FALSE; @@ -5229,8 +5243,8 @@ os__path_isfile_impl(PyObject *module, PyObject *path) } Py_BEGIN_ALLOW_THREADS - if (_path.wide) { - if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, + if (path->wide) { + if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (!(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { slow_path = FALSE; @@ -5245,12 +5259,12 @@ os__path_isfile_impl(PyObject *module, PyObject *path) } } if (slow_path) { - if (_path.fd != -1) { - hfile = _Py_get_osfhandle_noraise(_path.fd); + if (path->fd != -1) { + hfile = _Py_get_osfhandle_noraise(path->fd); close_file = FALSE; } else { - hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hfile != INVALID_HANDLE_VALUE) { @@ -5273,7 +5287,7 @@ os__path_isfile_impl(PyObject *module, PyObject *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (STAT(_path.wide, &st)) { + if (STAT(path->wide, &st)) { result = 0; } else { @@ -5287,7 +5301,6 @@ os__path_isfile_impl(PyObject *module, PyObject *path) } Py_END_ALLOW_THREADS - path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5298,25 +5311,23 @@ os__path_isfile_impl(PyObject *module, PyObject *path) /*[clinic input] os._path_exists - path: object + path: path_t(suppress=True) Test whether a path exists. Returns False for broken symbolic links [clinic start generated code]*/ static PyObject * -os__path_exists_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=f508c3b35e13a249 input=d0e5ab7388302942]*/ +os__path_exists_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=69e6089df1fe463a input=ba8bbd209962ca90]*/ { HANDLE hfile; BOOL close_file = TRUE; - path_t _path = PATH_T_INITIALIZE_P("exists", "path", 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (!path_converter(path, &_path)) { - path_cleanup(&_path); + if (path->error) { if (PyErr_ExceptionMatches(PyExc_ValueError)) { PyErr_Clear(); Py_RETURN_FALSE; @@ -5325,8 +5336,8 @@ os__path_exists_impl(PyObject *module, PyObject *path) } Py_BEGIN_ALLOW_THREADS - if (_path.wide) { - if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, + if (path->wide) { + if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (!(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { slow_path = FALSE; @@ -5338,12 +5349,12 @@ os__path_exists_impl(PyObject *module, PyObject *path) } } if (slow_path) { - if (_path.fd != -1) { - hfile = _Py_get_osfhandle_noraise(_path.fd); + if (path->fd != -1) { + hfile = _Py_get_osfhandle_noraise(path->fd); close_file = FALSE; } else { - hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hfile != INVALID_HANDLE_VALUE) { @@ -5359,7 +5370,7 @@ os__path_exists_impl(PyObject *module, PyObject *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (STAT(_path.wide, &st)) { + if (STAT(path->wide, &st)) { result = 0; } else { @@ -5373,7 +5384,6 @@ os__path_exists_impl(PyObject *module, PyObject *path) } Py_END_ALLOW_THREADS - path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } @@ -5384,26 +5394,24 @@ os__path_exists_impl(PyObject *module, PyObject *path) /*[clinic input] os._path_islink - path: object + path: path_t(suppress=True) Test whether a path is a symbolic link [clinic start generated code]*/ static PyObject * -os__path_islink_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=6d8640b1a390c054 input=1a7c08fbe89b1ed6]*/ +os__path_islink_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=109ad77ec747b3b7 input=a59fe6ee2804173f]*/ { HANDLE hfile; BOOL close_file = TRUE; FILE_ATTRIBUTE_TAG_INFO info; - path_t _path = PATH_T_INITIALIZE_P("islink", "path", 0, 0, 1); int result; BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (!path_converter(path, &_path)) { - path_cleanup(&_path); + if (path->error) { if (PyErr_ExceptionMatches(PyExc_ValueError)) { PyErr_Clear(); Py_RETURN_FALSE; @@ -5412,8 +5420,8 @@ os__path_islink_impl(PyObject *module, PyObject *path) } Py_BEGIN_ALLOW_THREADS - if (_path.wide) { - if (_Py_GetFileInformationByName(_path.wide, FileStatBasicByNameInfo, + if (path->wide) { + if (_Py_GetFileInformationByName(path->wide, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { slow_path = FALSE; if (statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { @@ -5428,12 +5436,12 @@ os__path_islink_impl(PyObject *module, PyObject *path) } } if (slow_path) { - if (_path.fd != -1) { - hfile = _Py_get_osfhandle_noraise(_path.fd); + if (path->fd != -1) { + hfile = _Py_get_osfhandle_noraise(path->fd); close_file = FALSE; } else { - hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL, + hfile = CreateFileW(path->wide, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); @@ -5458,7 +5466,7 @@ os__path_islink_impl(PyObject *module, PyObject *path) case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: - if (LSTAT(_path.wide, &st)) { + if (LSTAT(path->wide, &st)) { result = 0; } else { @@ -5472,7 +5480,6 @@ os__path_islink_impl(PyObject *module, PyObject *path) } Py_END_ALLOW_THREADS - path_cleanup(&_path); if (result) { Py_RETURN_TRUE; } From 14d711e7bf386d3cfa1d8e2d7d529ae7a9830634 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 07:52:41 +0200 Subject: [PATCH 10/26] Fix `allow_fd` --- Modules/clinic/posixmodule.c.h | 10 +++++----- Modules/posixmodule.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index de6c9e2fbd07bb..a74f776a808e9b 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -2056,7 +2056,7 @@ os__path_isdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("_path_isdir", "path", 0, 0, 1, 0); + path_t path = PATH_T_INITIALIZE_P("_path_isdir", "path", 0, 0, 1, 1); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -2120,7 +2120,7 @@ os__path_isfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("_path_isfile", "path", 0, 0, 1, 0); + path_t path = PATH_T_INITIALIZE_P("_path_isfile", "path", 0, 0, 1, 1); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -2184,7 +2184,7 @@ os__path_exists(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("_path_exists", "path", 0, 0, 1, 0); + path_t path = PATH_T_INITIALIZE_P("_path_exists", "path", 0, 0, 1, 1); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -2248,7 +2248,7 @@ os__path_islink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj }; #undef KWTUPLE PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE_P("_path_islink", "path", 0, 0, 1, 0); + path_t path = PATH_T_INITIALIZE_P("_path_islink", "path", 0, 0, 1, 1); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { @@ -12689,4 +12689,4 @@ os__supports_virtual_terminal(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF #endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */ -/*[clinic end generated code: output=68dd3493b6596cb4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=056a1c20f0b1f39f input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 211f1180785299..63c8d6c483dd52 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5123,7 +5123,7 @@ os__path_splitroot_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isdir - s as path: path_t(suppress=True) + s as path: path_t(allow_fd=True, suppress=True) Return true if the pathname refers to an existing directory. @@ -5131,7 +5131,7 @@ Return true if the pathname refers to an existing directory. static PyObject * os__path_isdir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=0adeafd60704f710 input=945359aa5bde6f2e]*/ +/*[clinic end generated code: output=0adeafd60704f710 input=3f8bf1ea0cc77e0c]*/ { HANDLE hfile; BOOL close_file = TRUE; @@ -5217,7 +5217,7 @@ os__path_isdir_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isfile - path: path_t(suppress=True) + path: path_t(allow_fd=True, suppress=True) Test whether a path is a regular file @@ -5225,7 +5225,7 @@ Test whether a path is a regular file static PyObject * os__path_isfile_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=4f72e7b1ada002da input=f095340c0e8e84e9]*/ +/*[clinic end generated code: output=4f72e7b1ada002da input=b6c69c96e1722a27]*/ { HANDLE hfile; BOOL close_file = TRUE; @@ -5311,7 +5311,7 @@ os__path_isfile_impl(PyObject *module, path_t *path) /*[clinic input] os._path_exists - path: path_t(suppress=True) + path: path_t(allow_fd=True, suppress=True) Test whether a path exists. Returns False for broken symbolic links @@ -5319,7 +5319,7 @@ Test whether a path exists. Returns False for broken symbolic links static PyObject * os__path_exists_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=69e6089df1fe463a input=ba8bbd209962ca90]*/ +/*[clinic end generated code: output=69e6089df1fe463a input=3a73be0affbbe43c]*/ { HANDLE hfile; BOOL close_file = TRUE; @@ -5394,7 +5394,7 @@ os__path_exists_impl(PyObject *module, path_t *path) /*[clinic input] os._path_islink - path: path_t(suppress=True) + path: path_t(allow_fd=True, suppress=True) Test whether a path is a symbolic link @@ -5402,7 +5402,7 @@ Test whether a path is a symbolic link static PyObject * os__path_islink_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=109ad77ec747b3b7 input=a59fe6ee2804173f]*/ +/*[clinic end generated code: output=109ad77ec747b3b7 input=3937a93631697d6c]*/ { HANDLE hfile; BOOL close_file = TRUE; From 89e83fac23549a182af33c70ff8b0ddce7796ea4 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 09:20:40 +0200 Subject: [PATCH 11/26] Allow paths of any length --- Modules/posixmodule.c | 59 +++++++++++++++++++++-------------------- Objects/unicodeobject.c | 4 +-- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 63c8d6c483dd52..464d2f92530c05 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1108,8 +1108,9 @@ get_posix_state(PyObject *module) * Input fields: * path.nullable * If nonzero, the path is permitted to be None. - * path.null_embeddable - * If nonzero, the path is permitted to contain embedded null characters. + * path.nonstrict + * If nonzero, the path is permitted to contain + * embedded null characters and have any length. * path.make_wide * If nonzero, the path is decoded to Unicode, encoded to bytes otherwise. * path.suppress @@ -1180,7 +1181,7 @@ typedef struct { const char *function_name; const char *argument_name; int nullable; - int null_embeddable; + int nonstrict; int make_wide; int suppress; int allow_fd; @@ -1194,20 +1195,20 @@ typedef struct { PyObject *cleanup; } path_t; -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, \ - null_embeddable, make_wide, suppress, allow_fd) \ - {function_name, argument_name, nullable, null_embeddable, make_wide, \ - suppress, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL} +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \ + make_wide, suppress, allow_fd) \ + {function_name, argument_name, nullable, nonstrict, make_wide, suppress, \ + allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL} #ifdef MS_WINDOWS #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ - null_embeddable, suppress, allow_fd) \ - PATH_T_INITIALIZE(function_name, argument_name, nullable, \ - null_embeddable, 1, suppress, allow_fd) + nonstrict, suppress, allow_fd) \ + PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \ + suppress, allow_fd) #else #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ - null_embeddable, suppress, allow_fd) \ - PATH_T_INITIALIZE(function_name, argument_name, nullable, \ - null_embeddable, 0, suppress, allow_fd) + nonstrict, suppress, allow_fd) \ + PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \ + suppress, allow_fd) #endif static void @@ -1300,12 +1301,12 @@ path_converter(PyObject *o, void *p) goto error_exit; } #ifdef MS_WINDOWS - if (length > 32767) { + if (!path->nonstrict && length > 32767) { FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); goto error_exit; } #endif - if (!path->null_embeddable && wcslen(wide) != (size_t)length) { + if (!path->nonstrict && wcslen(wide) != (size_t)length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; @@ -1317,7 +1318,7 @@ path_converter(PyObject *o, void *p) wide = NULL; goto success_exit; } - if (!_PyUnicode_FSConverter(o, &bytes, path->null_embeddable)) { + if (!_PyUnicode_FSConverter(o, &bytes, path->nonstrict)) { goto error_exit; } } @@ -1349,7 +1350,7 @@ path_converter(PyObject *o, void *p) length = PyBytes_GET_SIZE(bytes); narrow = PyBytes_AS_STRING(bytes); - if (!path->null_embeddable && strlen(narrow) != (size_t)length) { + if (!path->nonstrict && strlen(narrow) != (size_t)length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; } @@ -1366,12 +1367,12 @@ path_converter(PyObject *o, void *p) goto error_exit; } #ifdef MS_WINDOWS - if (length > 32767) { + if (!path->nonstrict && length > 32767) { FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); goto error_exit; } #endif - if (!path->null_embeddable && wcslen(wide) != (size_t)length) { + if (!path->nonstrict && wcslen(wide) != (size_t)length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; @@ -2928,8 +2929,8 @@ class path_t_converter(CConverter): converter = 'path_converter' - def converter_init(self, *, allow_fd=False, make_wide=None, nullable=False, - null_embeddable=False, suppress=False): + def converter_init(self, *, allow_fd=False, make_wide=None, + nonstrict=False, nullable=False, suppress=False): # right now path_t doesn't support default values. # to support a default value, you'll need to override initialize(). if self.default not in (unspecified, None): @@ -2939,7 +2940,7 @@ class path_t_converter(CConverter): raise RuntimeError("Can't specify a c_default to the path_t converter!") self.nullable = nullable - self.null_embeddable = null_embeddable + self.nonstrict = nonstrict self.make_wide = make_wide self.suppress = suppress self.allow_fd = allow_fd @@ -2956,7 +2957,7 @@ class path_t_converter(CConverter): self.function.name, self.name, strify(self.nullable), - strify(self.null_embeddable), + strify(self.nonstrict), strify(self.suppress), strify(self.allow_fd), ) @@ -2965,7 +2966,7 @@ class path_t_converter(CConverter): self.function.name, self.name, strify(self.nullable), - strify(self.null_embeddable), + strify(self.nonstrict), strify(self.make_wide), strify(self.suppress), strify(self.allow_fd), @@ -3048,7 +3049,7 @@ class sysconf_confname_converter(path_confname_converter): converter="conv_sysconf_confname" [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=9bfc716d9f7ad345]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=e859625395de8933]*/ /*[clinic input] @@ -5492,7 +5493,7 @@ os__path_islink_impl(PyObject *module, path_t *path) /*[clinic input] os._path_splitroot_ex - path: path_t(null_embeddable=True, make_wide=True) + path: path_t(make_wide=True, nonstrict=True) Split a pathname into drive, root and tail. @@ -5501,7 +5502,7 @@ The tail contains anything after the root. static PyObject * os__path_splitroot_ex_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=4b0072b6cdf4b611 input=fa388b51979a2f57]*/ +/*[clinic end generated code: output=4b0072b6cdf4b611 input=8f29a719fd480028]*/ { Py_ssize_t drvsize, rootsize; PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL; @@ -5538,14 +5539,14 @@ os__path_splitroot_ex_impl(PyObject *module, path_t *path) /*[clinic input] os._path_normpath - path: path_t(null_embeddable=True, make_wide=True) + path: path_t(make_wide=True, nonstrict=True) Normalize path, eliminating double slashes, etc. [clinic start generated code]*/ static PyObject * os__path_normpath_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=d353e7ed9410c044 input=4842c54b2fbdfc83]*/ +/*[clinic end generated code: output=d353e7ed9410c044 input=b8d62d498aa0a8db]*/ { PyObject *result; Py_ssize_t norm_len; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index d100376bdb136c..f9e31a90a74432 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3790,7 +3790,7 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) int -_PyUnicode_FSConverter(PyObject* arg, void* addr, int null_embeddable) +_PyUnicode_FSConverter(PyObject* arg, void* addr, int nonstrict) { PyObject *path = NULL; PyObject *output = NULL; @@ -3819,7 +3819,7 @@ _PyUnicode_FSConverter(PyObject* arg, void* addr, int null_embeddable) size = PyBytes_GET_SIZE(output); data = PyBytes_AS_STRING(output); - if (!null_embeddable && (size_t)size != strlen(data)) { + if (!nonstrict && (size_t)size != strlen(data)) { PyErr_SetString(PyExc_ValueError, "embedded null byte"); Py_DECREF(output); return 0; From d6a174ee657b6d0a5a9920bcd2670344bbdc49ef Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 09:30:13 +0200 Subject: [PATCH 12/26] Update generated files --- Modules/posixmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 464d2f92530c05..4a20e6733f912b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5502,7 +5502,7 @@ The tail contains anything after the root. static PyObject * os__path_splitroot_ex_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=4b0072b6cdf4b611 input=8f29a719fd480028]*/ +/*[clinic end generated code: output=4b0072b6cdf4b611 input=6eb76e9173412c92]*/ { Py_ssize_t drvsize, rootsize; PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL; @@ -5546,7 +5546,7 @@ Normalize path, eliminating double slashes, etc. static PyObject * os__path_normpath_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=d353e7ed9410c044 input=b8d62d498aa0a8db]*/ +/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/ { PyObject *result; Py_ssize_t norm_len; From 4e8b7131c4c2b68bd3d5b1a66506e344bc1ac981 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 15:48:48 +0200 Subject: [PATCH 13/26] Simplify bytes conversion Co-authored-by: Eryk Sun --- Modules/posixmodule.c | 10 +++++----- Objects/unicodeobject.c | 10 ++-------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 4a20e6733f912b..c567b88a274fe2 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1096,10 +1096,9 @@ get_posix_state(PyObject *module) * string we extract the wchar_t * and return it; if we * get bytes we decode to wchar_t * and return that. * - * * If path.make_wide is zero, strings are encoded - * to bytes using PyUnicode_FSConverter, then we - * extract the char * from the bytes object and - * return that. + * * If path.make_wide is zero, if we get bytes we extract + * the char_t * and return it; if we get a (Unicode) + * string we encode to char_t * and return that. * * path_converter also optionally accepts signed * integers (representing open file descriptors) instead @@ -1318,7 +1317,8 @@ path_converter(PyObject *o, void *p) wide = NULL; goto success_exit; } - if (!_PyUnicode_FSConverter(o, &bytes, path->nonstrict)) { + bytes = PyUnicode_EncodeFSDefault(o); + if (!bytes) { goto error_exit; } } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index f9e31a90a74432..2c259b7e869efe 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3790,7 +3790,7 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) int -_PyUnicode_FSConverter(PyObject* arg, void* addr, int nonstrict) +PyUnicode_FSConverter(PyObject* arg, void* addr) { PyObject *path = NULL; PyObject *output = NULL; @@ -3819,7 +3819,7 @@ _PyUnicode_FSConverter(PyObject* arg, void* addr, int nonstrict) size = PyBytes_GET_SIZE(output); data = PyBytes_AS_STRING(output); - if (!nonstrict && (size_t)size != strlen(data)) { + if ((size_t)size != strlen(data)) { PyErr_SetString(PyExc_ValueError, "embedded null byte"); Py_DECREF(output); return 0; @@ -3828,12 +3828,6 @@ _PyUnicode_FSConverter(PyObject* arg, void* addr, int nonstrict) return Py_CLEANUP_SUPPORTED; } -int -PyUnicode_FSConverter(PyObject* arg, void* addr) -{ - return _PyUnicode_FSConverter(arg, addr, 0); -} - int PyUnicode_FSDecoder(PyObject* arg, void* addr) From 0777a315209dd14736287ecff98fe88353f7b43f Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 15:50:09 +0200 Subject: [PATCH 14/26] Remove leftovers --- Include/unicodeobject.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index cdeabee9d7aa68..dee00715b3c51d 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -740,7 +740,6 @@ PyAPI_FUNC(PyObject*) PyUnicode_EncodeLocale( /* ParseTuple converter: encode str objects to bytes using PyUnicode_EncodeFSDefault(); bytes objects are output as-is. */ -extern int _PyUnicode_FSConverter(PyObject*, void*, int); PyAPI_FUNC(int) PyUnicode_FSConverter(PyObject*, void*); /* ParseTuple converter: decode bytes objects to unicode using From 46059d15c5ab4fa590b54169f926e2b7e06364fc Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 16:33:19 +0200 Subject: [PATCH 15/26] Update conditions to use `PyBytes_Check()` --- Modules/posixmodule.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index c567b88a274fe2..390eceb58380eb 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1378,7 +1378,7 @@ path_converter(PyObject *o, void *p) goto error_exit; } path->wide = wide; - path->narrow = narrow; // TODO: replace by NULL + path->narrow = NULL; Py_DECREF(bytes); wide = NULL; } @@ -1465,11 +1465,7 @@ follow_symlinks_specified(const char *function_name, int follow_symlinks) static int path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd) { - if (!path->wide && (dir_fd != DEFAULT_DIR_FD) -#ifndef MS_WINDOWS - && !path->narrow -#endif - ) { + if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) { PyErr_Format(PyExc_ValueError, "%s: can't specify dir_fd without matching path", function_name); @@ -4361,13 +4357,14 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) Py_CLEAR(list); goto exit; } + int return_bytes = PyBytes_Check(path->object); do { /* Skip over . and .. */ if (wcscmp(wFileData.cFileName, L".") != 0 && wcscmp(wFileData.cFileName, L"..") != 0) { v = PyUnicode_FromWideChar(wFileData.cFileName, wcslen(wFileData.cFileName)); - if (path->narrow && v) { + if (return_bytes && v) { Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); } if (v == NULL) { @@ -4910,7 +4907,7 @@ os__getfullpathname_impl(PyObject *module, path_t *path) if (str == NULL) { return NULL; } - if (path->narrow) { + if (PyBytes_Check(path->object)) { Py_SETREF(str, PyUnicode_EncodeFSDefault(str)); } return str; @@ -4983,7 +4980,7 @@ os__getfinalpathname_impl(PyObject *module, path_t *path) } result = PyUnicode_FromWideChar(target_path, result_length); - if (result && path->narrow) { + if (result && PyBytes_Check(path->object)) { Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); } @@ -5066,7 +5063,7 @@ os__getvolumepathname_impl(PyObject *module, path_t *path) goto exit; } result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); - if (path->narrow) + if (PyBytes_Check(path->object)) Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); exit: @@ -10254,7 +10251,7 @@ os_readlink_impl(PyObject *module, path_t *path, int dir_fd) name[1] = L'\\'; } result = PyUnicode_FromWideChar(name, nameLen); - if (result && path->narrow) { + if (result && PyBytes_Check(path->object)) { Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); } } @@ -15875,7 +15872,8 @@ DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW) entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); if (!entry->name) goto error; - if (path->narrow) { + int return_bytes = PyBytes_Check(path->object); + if (return_bytes) { Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name)); if (!entry->name) goto error; @@ -15889,7 +15887,7 @@ DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW) PyMem_Free(joined_path); if (!entry->path) goto error; - if (path->narrow) { + if (return_bytes) { Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path)); if (!entry->path) goto error; @@ -15974,7 +15972,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, goto error; } - if (!path->narrow || !PyBytes_Check(path->object)) { + if (!PyBytes_Check(path->object)) { entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len); if (joined_path) entry->path = PyUnicode_DecodeFSDefault(joined_path); From f95da67c7820e9aa932be98ebffab432ec44399e Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 16:49:30 +0200 Subject: [PATCH 16/26] Fix access violation attempt 1 --- Modules/posixmodule.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 390eceb58380eb..6e76418814958f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -4314,7 +4314,7 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) { PyObject *v; HANDLE hFindFile = INVALID_HANDLE_VALUE; - BOOL result; + BOOL result, return_bytes; wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ /* only claim to have space for MAX_PATH */ Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; @@ -4326,9 +4326,11 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) if (!path->wide) { /* Default arg: "." */ po_wchars = L"."; len = 1; + return_bytes = 0; } else { po_wchars = path->wide; len = wcslen(path->wide); + return_bytes = PyBytes_Check(path->object); } /* The +5 is so we can append "\\*.*\0" */ wnamebuf = PyMem_New(wchar_t, len + 5); @@ -4357,7 +4359,6 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) Py_CLEAR(list); goto exit; } - int return_bytes = PyBytes_Check(path->object); do { /* Skip over . and .. */ if (wcscmp(wFileData.cFileName, L".") != 0 && From e8ab7d7fe60e74aaec0027f6f1058f6892f08bef Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 17:04:30 +0200 Subject: [PATCH 17/26] Fix segmentation fault --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 6e76418814958f..9c528a7040eb15 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -15973,7 +15973,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, goto error; } - if (!PyBytes_Check(path->object)) { + if (!name || !PyBytes_Check(path->object)) { entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len); if (joined_path) entry->path = PyUnicode_DecodeFSDefault(joined_path); From 3b21f5daf3fd0380c82e83f55bc3a9c446bd624b Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 17:17:28 +0200 Subject: [PATCH 18/26] Fix segmentation fault attempt 2 --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 9c528a7040eb15..9fb4b3cd2ce1b9 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -15973,7 +15973,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, goto error; } - if (!name || !PyBytes_Check(path->object)) { + if (!path->narrow || !PyBytes_Check(path->object)) { entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len); if (joined_path) entry->path = PyUnicode_DecodeFSDefault(joined_path); From 7b3a7853156978e11c3052b01233027d505f6dab Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 17:49:41 +0200 Subject: [PATCH 19/26] Fix access violation attempt 1 --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 9fb4b3cd2ce1b9..a1966246365f1e 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -15873,7 +15873,7 @@ DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW) entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); if (!entry->name) goto error; - int return_bytes = PyBytes_Check(path->object); + int return_bytes = path->wide && PyBytes_Check(path->object); if (return_bytes) { Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name)); if (!entry->name) From a94c852894a5c64219a819e1f867e9e6730f761f Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 17:57:32 +0200 Subject: [PATCH 20/26] Clear ValueError Co-authored-by: Eryk Sun --- Modules/posixmodule.c | 94 +++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 53 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index a1966246365f1e..6da26822e81b7f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1112,8 +1112,8 @@ get_posix_state(PyObject *module) * embedded null characters and have any length. * path.make_wide * If nonzero, the path is decoded to Unicode, encoded to bytes otherwise. - * path.suppress - * If nonzero, errors are suppressed. + * path.suppress_value_error + * If nonzero, ValueErrors are suppressed. * path.allow_fd * If nonzero, the path is permitted to be a file handle * (a signed int) instead of a string. @@ -1142,8 +1142,8 @@ get_posix_state(PyObject *module) * unspecified, path_converter will never get called. * So if you set allow_fd, you *MUST* initialize path.fd = -1 * yourself! - * path.error - * If nonzero, an error occurred. + * path.value_error + * If nonzero, a ValueError occurred. * path.length * The length of the path in characters, if specified as * a string. @@ -1182,32 +1182,32 @@ typedef struct { int nullable; int nonstrict; int make_wide; - int suppress; + int suppress_value_error; int allow_fd; // Output fields const wchar_t *wide; const char *narrow; int fd; - int error; + int value_error; Py_ssize_t length; PyObject *object; PyObject *cleanup; } path_t; #define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \ - make_wide, suppress, allow_fd) \ - {function_name, argument_name, nullable, nonstrict, make_wide, suppress, \ - allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL} + make_wide, suppress_value_error, allow_fd) \ + {function_name, argument_name, nullable, nonstrict, make_wide, \ + suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL} #ifdef MS_WINDOWS #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ - nonstrict, suppress, allow_fd) \ + nonstrict, suppress_value_error, allow_fd) \ PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \ - suppress, allow_fd) + suppress_value_error, allow_fd) #else #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ - nonstrict, suppress, allow_fd) \ + nonstrict, suppress_value_error, allow_fd) \ PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \ - suppress, allow_fd) + suppress_value_error, allow_fd) #endif static void @@ -1397,7 +1397,7 @@ path_converter(PyObject *o, void *p) path->fd = -1; success_exit: - path->error = 0; + path->value_error = 0; path->length = length; path->object = o; return Py_CLEANUP_SUPPORTED; @@ -1406,13 +1406,16 @@ path_converter(PyObject *o, void *p) Py_XDECREF(o); Py_XDECREF(bytes); PyMem_Free(wide); - if (!path->suppress) { + if (!path->suppress_value_error || + !PyErr_ExceptionMatches(PyExc_ValueError)) + { return 0; } + PyErr_Clear(); path->wide = NULL; path->narrow = NULL; path->fd = -1; - path->error = 1; + path->value_error = 1; path->length = 0; path->object = NULL; return Py_CLEANUP_SUPPORTED; @@ -2926,7 +2929,8 @@ class path_t_converter(CConverter): converter = 'path_converter' def converter_init(self, *, allow_fd=False, make_wide=None, - nonstrict=False, nullable=False, suppress=False): + nonstrict=False, nullable=False, + suppress_value_error=False): # right now path_t doesn't support default values. # to support a default value, you'll need to override initialize(). if self.default not in (unspecified, None): @@ -2938,7 +2942,7 @@ class path_t_converter(CConverter): self.nullable = nullable self.nonstrict = nonstrict self.make_wide = make_wide - self.suppress = suppress + self.suppress_value_error = suppress_value_error self.allow_fd = allow_fd def pre_render(self): @@ -2954,7 +2958,7 @@ class path_t_converter(CConverter): self.name, strify(self.nullable), strify(self.nonstrict), - strify(self.suppress), + strify(self.suppress_value_error), strify(self.allow_fd), ) else: @@ -2964,7 +2968,7 @@ class path_t_converter(CConverter): strify(self.nullable), strify(self.nonstrict), strify(self.make_wide), - strify(self.suppress), + strify(self.suppress_value_error), strify(self.allow_fd), ) @@ -3045,7 +3049,7 @@ class sysconf_confname_converter(path_confname_converter): converter="conv_sysconf_confname" [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=e859625395de8933]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=577cb476e5d64960]*/ /*[clinic input] @@ -5122,7 +5126,7 @@ os__path_splitroot_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isdir - s as path: path_t(allow_fd=True, suppress=True) + s as path: path_t(allow_fd=True, suppress_value_error=True) Return true if the pathname refers to an existing directory. @@ -5130,7 +5134,7 @@ Return true if the pathname refers to an existing directory. static PyObject * os__path_isdir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=0adeafd60704f710 input=3f8bf1ea0cc77e0c]*/ +/*[clinic end generated code: output=0adeafd60704f710 input=2d09b8801fd2f638]*/ { HANDLE hfile; BOOL close_file = TRUE; @@ -5139,12 +5143,8 @@ os__path_isdir_impl(PyObject *module, path_t *path) BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (path->error) { - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; + if (path->value_error) { + Py_RETURN_FALSE; } Py_BEGIN_ALLOW_THREADS @@ -5216,7 +5216,7 @@ os__path_isdir_impl(PyObject *module, path_t *path) /*[clinic input] os._path_isfile - path: path_t(allow_fd=True, suppress=True) + path: path_t(allow_fd=True, suppress_value_error=True) Test whether a path is a regular file @@ -5224,7 +5224,7 @@ Test whether a path is a regular file static PyObject * os__path_isfile_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=4f72e7b1ada002da input=b6c69c96e1722a27]*/ +/*[clinic end generated code: output=4f72e7b1ada002da input=c378f54b14ae878a]*/ { HANDLE hfile; BOOL close_file = TRUE; @@ -5233,12 +5233,8 @@ os__path_isfile_impl(PyObject *module, path_t *path) BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (path->error) { - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; + if (path->value_error) { + Py_RETURN_FALSE; } Py_BEGIN_ALLOW_THREADS @@ -5310,7 +5306,7 @@ os__path_isfile_impl(PyObject *module, path_t *path) /*[clinic input] os._path_exists - path: path_t(allow_fd=True, suppress=True) + path: path_t(allow_fd=True, suppress_value_error=True) Test whether a path exists. Returns False for broken symbolic links @@ -5318,7 +5314,7 @@ Test whether a path exists. Returns False for broken symbolic links static PyObject * os__path_exists_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=69e6089df1fe463a input=3a73be0affbbe43c]*/ +/*[clinic end generated code: output=69e6089df1fe463a input=a62c424c1784c43b]*/ { HANDLE hfile; BOOL close_file = TRUE; @@ -5326,12 +5322,8 @@ os__path_exists_impl(PyObject *module, path_t *path) BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (path->error) { - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; + if (path->value_error) { + Py_RETURN_FALSE; } Py_BEGIN_ALLOW_THREADS @@ -5393,7 +5385,7 @@ os__path_exists_impl(PyObject *module, path_t *path) /*[clinic input] os._path_islink - path: path_t(allow_fd=True, suppress=True) + path: path_t(allow_fd=True, suppress_value_error=True) Test whether a path is a symbolic link @@ -5401,7 +5393,7 @@ Test whether a path is a symbolic link static PyObject * os__path_islink_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=109ad77ec747b3b7 input=3937a93631697d6c]*/ +/*[clinic end generated code: output=109ad77ec747b3b7 input=80bd45abdecb418e]*/ { HANDLE hfile; BOOL close_file = TRUE; @@ -5410,12 +5402,8 @@ os__path_islink_impl(PyObject *module, path_t *path) BOOL slow_path = TRUE; FILE_STAT_BASIC_INFORMATION statInfo; - if (path->error) { - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; + if (path->value_error) { + Py_RETURN_FALSE; } Py_BEGIN_ALLOW_THREADS From 5f717c9f59637a91c53248cd48ce360d5867fcbe Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Sat, 4 May 2024 18:55:34 +0200 Subject: [PATCH 21/26] Apply suggestions from code review Co-authored-by: Eryk Sun --- Modules/posixmodule.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 6da26822e81b7f..52e83b49614d7f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1111,9 +1111,11 @@ get_posix_state(PyObject *module) * If nonzero, the path is permitted to contain * embedded null characters and have any length. * path.make_wide - * If nonzero, the path is decoded to Unicode, encoded to bytes otherwise. + * If nonzero, the converter always uses wide, decoding if necessary, else + * it always uses narrow, encoding if necessary. The default value is + * nonzero on Windows, else zero. * path.suppress_value_error - * If nonzero, ValueErrors are suppressed. + * If nonzero, raising ValueError is suppressed. * path.allow_fd * If nonzero, the path is permitted to be a file handle * (a signed int) instead of a string. @@ -1129,10 +1131,10 @@ get_posix_state(PyObject *module) * Output fields: * path.wide * Points to the path if it was expressed as Unicode - * or it was bytes and was encoded to Unicode. + * or if it was bytes and decoded to Unicode. * path.narrow * Points to the path if it was expressed as bytes, - * or it was Unicode and was encoded to bytes. + * or if it was Unicode and encoded to bytes. * path.fd * Contains a file descriptor if path.accept_fd was true * and the caller provided a signed integer instead of any @@ -1143,7 +1145,8 @@ get_posix_state(PyObject *module) * So if you set allow_fd, you *MUST* initialize path.fd = -1 * yourself! * path.value_error - * If nonzero, a ValueError occurred. + * If nonzero, then suppress_value_error was specified and a ValueError + * occurred. * path.length * The length of the path in characters, if specified as * a string. From b76774bbfb6774a487e6a34d32f78e3b45deb3fe Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 19:35:25 +0200 Subject: [PATCH 22/26] Same docstring for python fallback --- Lib/ntpath.py | 13 +++---------- Lib/posixpath.py | 12 +++--------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 9375b05d7027ee..1236730dd801f7 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -171,16 +171,9 @@ def splitdrive(p): from nt import _path_splitroot_ex as splitroot except ImportError: def splitroot(p): - """Split a pathname into drive, root and tail. The drive is defined - exactly as in splitdrive(). On Windows, the root may be a single path - separator or an empty string. The tail contains anything after the root. - For example: - - splitroot('//server/share/') == ('//server/share', '/', '') - splitroot('C:/Users/Barney') == ('C:', '/', 'Users/Barney') - splitroot('C:///spam///ham') == ('C:', '/', '//spam///ham') - splitroot('Windows/notepad') == ('', '', 'Windows/notepad') - """ + """Split a pathname into drive, root and tail. + + The tail contains anything after the root.""" p = os.fspath(p) if isinstance(p, bytes): sep = b'\\' diff --git a/Lib/posixpath.py b/Lib/posixpath.py index bad1746ccb4f19..01268e47543f2f 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -138,15 +138,9 @@ def splitdrive(p): from posix import _path_splitroot_ex as splitroot except ImportError: def splitroot(p): - """Split a pathname into drive, root and tail. On Posix, drive is always - empty; the root may be empty, a single slash, or two slashes. The tail - contains anything after the root. For example: - - splitroot('foo/bar') == ('', '', 'foo/bar') - splitroot('/foo/bar') == ('', '/', 'foo/bar') - splitroot('//foo/bar') == ('', '//', 'foo/bar') - splitroot('///foo/bar') == ('', '/', '//foo/bar') - """ + """Split a pathname into drive, root and tail. + + The tail contains anything after the root.""" p = os.fspath(p) if isinstance(p, bytes): sep = b'/' From f2537a12e880b557c70f1c340554b03ded18499a Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 4 May 2024 19:40:49 +0200 Subject: [PATCH 23/26] Revert newline --- Lib/ntpath.py | 1 - Lib/posixpath.py | 1 - 2 files changed, 2 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 1236730dd801f7..8f8dd8d408d66b 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -215,7 +215,6 @@ def splitroot(p): return empty, empty, p - # Split a path in head (everything up to the last '/') and tail (the # rest). After the trailing '/' is stripped, the invariant # join(head, tail) == p holds. diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 01268e47543f2f..3d67338ab275f6 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -160,7 +160,6 @@ def splitroot(p): return empty, p[:2], p[2:] - # Return the tail (basename) part of a path, same as split(path)[1]. def basename(p): From 360326d3848ecf2930271866f6b1e013977b618f Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Wed, 22 May 2024 09:55:44 +0200 Subject: [PATCH 24/26] Fix pointers --- Modules/posixmodule.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 27aa6a7a30e053..2be8962af96d96 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5371,7 +5371,7 @@ static int os__path_exists_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=8da13acf666e16ba input=29198507a6082a57]*/ { - return _testFileExists(&path, TRUE); + return _testFileExists(path, TRUE); } @@ -5389,7 +5389,7 @@ static int os__path_lexists_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=e7240ed5fc45bff3 input=03d9fed8bc6ce96f]*/ { - return _testFileExists(&path, FALSE); + return _testFileExists(path, FALSE); } @@ -5406,7 +5406,7 @@ static int os__path_isdir_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=d5786196f9e2fa7a input=132a3b5301aecf79]*/ { - return _testFileType(&path, PY_IFDIR); + return _testFileType(path, PY_IFDIR); } @@ -5423,7 +5423,7 @@ static int os__path_isfile_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/ { - return _testFileType(&path, PY_IFREG); + return _testFileType(path, PY_IFREG); } @@ -5440,7 +5440,7 @@ static int os__path_islink_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/ { - return _testFileType(&path, PY_IFLNK); + return _testFileType(path, PY_IFLNK); } @@ -5457,7 +5457,7 @@ static int os__path_isjunction_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/ { - return _testFileType(&path, PY_IFMNT); + return _testFileType(path, PY_IFMNT); } #undef PY_IFREG From 3514bdba1e0c3a2d7df2e5af48390102b323e525 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Wed, 22 May 2024 10:48:19 +0200 Subject: [PATCH 25/26] Return false in case of value error --- Modules/posixmodule.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 2be8962af96d96..9f0320aa4047e8 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5307,12 +5307,12 @@ _testFileExistsByName(LPCWSTR path, BOOL followLinks) } -static int +static BOOL _testFileExists(path_t *path, BOOL followLinks) { BOOL result = FALSE; if (path->value_error) { - return -1; + return FALSE; } Py_BEGIN_ALLOW_THREADS @@ -5333,12 +5333,12 @@ _testFileExists(path_t *path, BOOL followLinks) } -static int +static BOOL _testFileType(path_t *path, int testedType) { BOOL result = FALSE; if (path->value_error) { - return -1; + return FALSE; } Py_BEGIN_ALLOW_THREADS From e362054a2715defb44a86761502def0555b4c915 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Fri, 24 May 2024 16:08:24 +0200 Subject: [PATCH 26/26] Add null check --- Modules/posixmodule.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 9f0320aa4047e8..bb35cfd9cdb138 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5504,8 +5504,17 @@ os__path_splitroot_ex_impl(PyObject *module, path_t *path) } if (PyBytes_Check(path->object)) { Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv)); + if (drv == NULL) { + goto exit; + } Py_SETREF(root, PyUnicode_EncodeFSDefault(root)); + if (root == NULL) { + goto exit; + } Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail)); + if (tail == NULL) { + goto exit; + } } result = PyTuple_Pack(3, drv, root, tail); exit: