diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 95b0c5ec7da3d1..b2f3e1b1049464 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -933,7 +933,19 @@ def commonpath(paths): from nt import _path_isfile as isfile from nt import _path_islink as islink from nt import _path_exists as exists - from nt import _path_isdevdrive as isdevdrive except ImportError: # Use genericpath.* as imported above pass + + +try: + from nt import _path_isdevdrive + def isdevdrive(path): + """Determines whether the specified path is on a Windows Dev Drive.""" + try: + return _path_isdevdrive(abspath(path)) + except OSError: + return False +except ImportError: + # Use genericpath.isdevdrive as imported above + pass diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index ddad3900f6a088..47c189e87f0f06 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -1135,8 +1135,6 @@ def test_fast_paths_in_use(self): self.assertFalse(inspect.isfunction(os.path.islink)) self.assertTrue(os.path.exists is nt._path_exists) self.assertFalse(inspect.isfunction(os.path.exists)) - self.assertTrue(os.path.isdevdrive is nt._path_isdevdrive) - self.assertFalse(inspect.isfunction(os.path.isdevdrive)) @unittest.skipIf(os.name != 'nt', "Dev Drives only exist on Win32") def test_isdevdrive(self): diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 675d4d938a1e87..7fdad8af7dff82 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1731,7 +1731,7 @@ PyDoc_STRVAR(os__path_isdevdrive__doc__, {"_path_isdevdrive", _PyCFunction_CAST(os__path_isdevdrive), METH_FASTCALL|METH_KEYWORDS, os__path_isdevdrive__doc__}, static PyObject * -os__path_isdevdrive_impl(PyObject *module, PyObject *path); +os__path_isdevdrive_impl(PyObject *module, path_t *path); static PyObject * os__path_isdevdrive(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1763,16 +1763,21 @@ os__path_isdevdrive(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P }; #undef KWTUPLE PyObject *argsbuf[1]; - PyObject *path; + path_t path = PATH_T_INITIALIZE("_path_isdevdrive", "path", 0, 0); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); if (!args) { goto exit; } - path = args[0]; - return_value = os__path_isdevdrive_impl(module, path); + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_isdevdrive_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -12647,4 +12652,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=412b4e312064330d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a5c86cf571db8e59 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 016df7c42d5457..2c20b561cce935 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -4723,38 +4723,16 @@ os_listmounts_impl(PyObject *module, path_t *volume) /*[clinic input] os._path_isdevdrive - path: object + path: path_t Determines whether the specified path is on a Windows Dev Drive. [clinic start generated code]*/ static PyObject * -os__path_isdevdrive_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=4f5a02fe80648dab input=cb26f0f438f49cb6]*/ +os__path_isdevdrive_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/ { - path_t _path = PATH_T_INITIALIZE("isdevdrive", "path", 0, 0); - if (!path_converter(path, &_path)) { - path_cleanup(&_path); - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; - } - - PyObject *abs_obj = posix_abspath((wchar_t *)_path.wide, _path.length, 0); - if (!abs_obj) { - path_cleanup(&_path); - return NULL; - } - wchar_t *abs_buf = PyUnicode_AsWideCharString(abs_obj, NULL); - Py_DECREF(abs_obj); - if (!abs_buf) { - path_cleanup(&_path); - return NULL; - } - #ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME /* This flag will be documented at https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information @@ -4768,7 +4746,7 @@ os__path_isdevdrive_impl(PyObject *module, PyObject *path) wchar_t volume[MAX_PATH]; Py_BEGIN_ALLOW_THREADS - if (!GetVolumePathNameW(abs_buf, volume, MAX_PATH)) { + if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) { /* invalid path of some kind */ /* Note that this also includes the case where a volume is mounted in a path longer than 260 characters. This is likely to be rare @@ -4818,8 +4796,6 @@ os__path_isdevdrive_impl(PyObject *module, PyObject *path) } Py_END_ALLOW_THREADS - path_cleanup(&_path); - PyMem_RawFree(abs_buf); if (err) { PyErr_SetFromWindowsErr(err); return NULL; @@ -5532,158 +5508,38 @@ os__path_normpath_impl(PyObject *module, PyObject *path) return result; } -#ifdef MS_WINDOWS - -/* We centralise SECURITY_ATTRIBUTE initialization based around -templates that will probably mostly match common POSIX mode settings. -The _Py_SECURITY_ATTRIBUTE_DATA structure contains temporary data, as -a constructed SECURITY_ATTRIBUTE structure typically refers to memory -that has to be alive while it's being used. - -Typical use will look like: - SECURITY_ATTRIBUTES *pSecAttr = NULL; - struct _Py_SECURITY_ATTRIBUTE_DATA secAttrData; - int error, error2; - - Py_BEGIN_ALLOW_THREADS - switch (mode) { - case 0x1C0: // 0o700 - error = initializeMkdir700SecurityAttributes(&pSecAttr, &secAttrData); - break; - ... - default: - error = initializeDefaultSecurityAttributes(&pSecAttr, &secAttrData); - break; - } - - if (!error) { - // do operation, passing pSecAttr - } - - // Unconditionally clear secAttrData. - error2 = clearSecurityAttributes(&pSecAttr, &secAttrData); - if (!error) { - error = error2; - } - Py_END_ALLOW_THREADS - - if (error) { - PyErr_SetFromWindowsErr(error); - return NULL; - } -*/ - -struct _Py_SECURITY_ATTRIBUTE_DATA { - SECURITY_ATTRIBUTES securityAttributes; - PACL acl; - SECURITY_DESCRIPTOR sd; - EXPLICIT_ACCESS_W ea[4]; - char sid[64]; -}; - -static int -initializeDefaultSecurityAttributes( - PSECURITY_ATTRIBUTES *securityAttributes, - struct _Py_SECURITY_ATTRIBUTE_DATA *data -) { - assert(securityAttributes); - assert(data); - *securityAttributes = NULL; - memset(data, 0, sizeof(*data)); - return 0; -} - -static int -initializeMkdir700SecurityAttributes( - PSECURITY_ATTRIBUTES *securityAttributes, - struct _Py_SECURITY_ATTRIBUTE_DATA *data -) { - assert(securityAttributes); - assert(data); - *securityAttributes = NULL; - memset(data, 0, sizeof(*data)); - - if (!InitializeSecurityDescriptor(&data->sd, SECURITY_DESCRIPTOR_REVISION) - || !SetSecurityDescriptorGroup(&data->sd, NULL, TRUE)) { - return GetLastError(); - } - - int use_alias = 0; - DWORD cbSid = sizeof(data->sid); - if (!CreateWellKnownSid(WinCreatorOwnerRightsSid, NULL, (PSID)data->sid, &cbSid)) { - use_alias = 1; - } - - data->securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); - data->ea[0].grfAccessPermissions = GENERIC_ALL; - data->ea[0].grfAccessMode = SET_ACCESS; - data->ea[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; - if (use_alias) { - data->ea[0].Trustee.TrusteeForm = TRUSTEE_IS_NAME; - data->ea[0].Trustee.TrusteeType = TRUSTEE_IS_ALIAS; - data->ea[0].Trustee.ptstrName = L"CURRENT_USER"; - } else { - data->ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; - data->ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; - data->ea[0].Trustee.ptstrName = (LPWCH)(SID*)data->sid; - } - - data->ea[1].grfAccessPermissions = GENERIC_ALL; - data->ea[1].grfAccessMode = SET_ACCESS; - data->ea[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; - data->ea[1].Trustee.TrusteeForm = TRUSTEE_IS_NAME; - data->ea[1].Trustee.TrusteeType = TRUSTEE_IS_ALIAS; - data->ea[1].Trustee.ptstrName = L"SYSTEM"; - - data->ea[2].grfAccessPermissions = GENERIC_ALL; - data->ea[2].grfAccessMode = SET_ACCESS; - data->ea[2].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; - data->ea[2].Trustee.TrusteeForm = TRUSTEE_IS_NAME; - data->ea[2].Trustee.TrusteeType = TRUSTEE_IS_ALIAS; - data->ea[2].Trustee.ptstrName = L"ADMINISTRATORS"; - - int r = SetEntriesInAclW(3, data->ea, NULL, &data->acl); - if (r) { - return r; - } - if (!SetSecurityDescriptorDacl(&data->sd, TRUE, data->acl, FALSE)) { - return GetLastError(); - } - data->securityAttributes.lpSecurityDescriptor = &data->sd; - *securityAttributes = &data->securityAttributes; - return 0; -} +/*[clinic input] +os._path_abspath -static int -clearSecurityAttributes( - PSECURITY_ATTRIBUTES *securityAttributes, - struct _Py_SECURITY_ATTRIBUTE_DATA *data -) { - assert(securityAttributes); - assert(data); - *securityAttributes = NULL; - if (data->acl) { - if (LocalFree((void *)data->acl)) { - return GetLastError(); - } - } - return 0; -} + path: unicode + / -#endif +Make path absolute. +[clinic start generated code]*/ static PyObject * -posix_abspath(wchar_t *path_buf, Py_ssize_t path_len, int use_bytes) +os__path_abspath_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=b58956d662b60be0 input=577ecb3473d22113]*/ { - Py_ssize_t abs_len; + Py_ssize_t path_len, abs_len; wchar_t *abs, *abs_buf = NULL, *cwd_buf = NULL; PyObject *result = NULL; + wchar_t *path_buf = PyUnicode_AsWideCharString(path, &path_len); + if (!path_buf) { + goto exit; + } + #ifdef MS_WINDOWS + if (wcslen(path_buf) != path_len) { + PyErr_Format(PyExc_ValueError, + "_path_abspath: embedded null character in path"); + goto exit; + } // Preserve `.\` for qualified referencing abs = _Py_normpath_and_size(path_buf, path_len, 0, &abs_len, 1); if (abs_len == 0 || (abs_len == 1 && abs[0] == L'.')) { - result = posix_getcwd(use_bytes); + result = posix_getcwd(0); goto exit; } if (_PyOS_getfullpathname(abs, &abs_buf) < 0) { @@ -5694,7 +5550,7 @@ posix_abspath(wchar_t *path_buf, Py_ssize_t path_len, int use_bytes) abs_len = wcslen(abs_buf); #else if (path_len == 0 || (path_len == 1 && path_buf[0] == L'.')) { - result = posix_getcwd(use_bytes); + result = posix_getcwd(0); goto exit; } @@ -5741,53 +5597,14 @@ posix_abspath(wchar_t *path_buf, Py_ssize_t path_len, int use_bytes) #endif result = PyUnicode_FromWideChar(abs, abs_len); - if (use_bytes) { - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); - } exit: + PyMem_Free(path_buf); PyMem_Free(cwd_buf); PyMem_RawFree(abs_buf); return result; } - -/*[clinic input] -os._path_abspath - - path: unicode - / - -Make path absolute. -[clinic start generated code]*/ - -static PyObject * -os__path_abspath_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=b58956d662b60be0 input=577ecb3473d22113]*/ -{ - Py_ssize_t path_len; - PyObject *result = NULL; - - wchar_t *path_buf = PyUnicode_AsWideCharString(path, &path_len); - if (!path_buf) { - goto exit; - } - -#ifdef MS_WINDOWS - if (wcslen(path_buf) != path_len) { - PyErr_Format(PyExc_ValueError, - "_path_abspath: embedded null character in path"); - goto exit; - } -#endif - - result = posix_abspath(path_buf, path_len, 0); - -exit: - PyMem_Free(path_buf); - return result; -} - /*[clinic input] os.mkdir