mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
gh-104803: Implement ntpath.isdevdrive for checking whether a path is on a Windows Dev Drive (GH-104805)
(cherry picked from commit bfd20d257e
)
Co-authored-by: Steve Dower <steve.dower@python.org>
This commit is contained in:
parent
5dc6b18cb0
commit
635ce29257
6 changed files with 216 additions and 1 deletions
|
@ -4530,6 +4530,95 @@ exit:
|
|||
}
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
os._path_isdevdrive
|
||||
|
||||
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, path_t *path)
|
||||
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
|
||||
{
|
||||
#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
|
||||
after release, and will be available in the latest WinSDK.
|
||||
We include the flag to avoid a specific version dependency
|
||||
on the latest WinSDK. */
|
||||
const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
|
||||
#endif
|
||||
int err = 0;
|
||||
PyObject *r = NULL;
|
||||
wchar_t volume[MAX_PATH];
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
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
|
||||
and problematic for other reasons, so a (soft) failure in this
|
||||
check seems okay. */
|
||||
err = GetLastError();
|
||||
} else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
|
||||
/* only care about local dev drives */
|
||||
r = Py_False;
|
||||
} else {
|
||||
HANDLE hVolume = CreateFileW(
|
||||
volume,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
NULL
|
||||
);
|
||||
if (hVolume == INVALID_HANDLE_VALUE) {
|
||||
err = GetLastError();
|
||||
} else {
|
||||
FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
|
||||
volumeState.Version = 1;
|
||||
volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
|
||||
if (!DeviceIoControl(
|
||||
hVolume,
|
||||
FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
|
||||
&volumeState,
|
||||
sizeof(volumeState),
|
||||
&volumeState,
|
||||
sizeof(volumeState),
|
||||
NULL,
|
||||
NULL
|
||||
)) {
|
||||
err = GetLastError();
|
||||
}
|
||||
CloseHandle(hVolume);
|
||||
if (err == ERROR_INVALID_PARAMETER) {
|
||||
/* not supported on this platform */
|
||||
r = Py_False;
|
||||
} else if (!err) {
|
||||
r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
|
||||
? Py_True : Py_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (err) {
|
||||
PyErr_SetFromWindowsErr(err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (r) {
|
||||
return Py_NewRef(r);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
|
||||
{
|
||||
|
@ -15797,6 +15886,7 @@ static PyMethodDef posix_methods[] = {
|
|||
OS_SETNS_METHODDEF
|
||||
OS_UNSHARE_METHODDEF
|
||||
|
||||
OS__PATH_ISDEVDRIVE_METHODDEF
|
||||
OS__PATH_ISDIR_METHODDEF
|
||||
OS__PATH_ISFILE_METHODDEF
|
||||
OS__PATH_ISLINK_METHODDEF
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue