Skip to content

Commit

Permalink
Revert "Direct C call for nt.isdevdrive()"
Browse files Browse the repository at this point in the history
This reverts commit b3d04ac.
  • Loading branch information
nineteendo committed May 4, 2024
1 parent 415f831 commit 9c55537
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 217 deletions.
14 changes: 13 additions & 1 deletion Lib/ntpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 0 additions & 2 deletions Lib/test/test_ntpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
15 changes: 10 additions & 5 deletions Modules/clinic/posixmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

235 changes: 26 additions & 209 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 9c55537

Please sign in to comment.