This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eryksun
Recipients eryksun, mangrisano, paul.moore, serhiy.storchaka, steve.dower, tim.golden, zach.ware
Date 2019-05-28.14:10:09
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1559052609.91.0.368630295086.issue37074@roundup.psfhosted.org>
In-reply-to
Content
Opening "CON" (i.e. r"\\.\CON") fails with ERROR_INVALID_PARAMETER (87) because it has to be opened with either GENERIC_READ or GENERIC_WRITE data access in order to map it to either the console input buffer or active screen buffer. The CreateFileW call in stat() necessarily requests no data access.

Calling stat on "NUL" (among others such as "CONIN$", "//./C:", and "//./PhysicalDrive0") fails with ERROR_INVALID_FUNCTION (1) -- or possibly ERROR_INVALID_PARAMETER or ERROR_NOT_SUPPORTED (50), depending on the device. stat() calls GetFileInformationByHandle. This requests FileFsVolumeInformation and FileAllInformation, which commonly fail as unsupported or invalid requests for devices other than filesystem devices. Even volume and raw disk devices fail a FileAllInformation request. 

If we have a valid file handle, we can get the file type via GetFileType(hFile), as _Py_fstat_noraise does in Python/fileutils.c. If opening a handle fails with ERROR_INVALID_PARAMETER for a path that resolves to r"\\.\CON" or r"\\?\CON" via GetFullPathNameW, we can simply set st_mode to _S_IFCHR and return.

For example:

    if (hFile == INVALID_HANDLE_VALUE) {
        DWORD lastError = GetLastError();
        if (lastError == ERROR_INVALID_PARAMETER) {
            WCHAR fullPath[8];
            if (GetFullPathNameW(path, sizeof(fullPath),
                    fullPath, NULL) == 7 && (
                _wcsicmp(fullPath, L"\\\\.\\CON") == 0 ||
                _wcsicmp(fullPath, L"\\\\?\\CON") == 0)) {
                memset(result, 0, sizeof(*result));
                result->st_mode = _S_IFCHR;
                return 0;
            }
        }
        /*
            Existing error handling code.
        */
    } else {
        DWORD type = GetFileType(hFile);
        if (type != FILE_TYPE_DISK) {
            CloseHandle(hFile);
            if (type == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
                return -1;
            }
            memset(result, 0, sizeof(*result));
            if (type == FILE_TYPE_CHAR) { /* e.g. "//./NUL" */
                result->st_mode = _S_IFCHR;
            } else if (type == FILE_TYPE_PIPE) { /* e.g. "//./PIPE/Spam" */
                result->st_mode = _S_IFIFO;
            }
            return 0;
        } else if (!GetFileInformationByHandle(hFile, &info)) {
            DWORD lastError = GetLastError();
            CloseHandle(hFile);
            /* e.g. "//./C:" or "//./PhysicalDrive0" */
            if (lastError == ERROR_INVALID_FUNCTION ||
                lastError == ERROR_INVALID_PARAMETER ||
                lastError == ERROR_NOT_SUPPORTED) {
                memset(result, 0, sizeof(*result));
                result->st_mode = _S_IFREG;
                return 0;
            }
            return -1;
        }
    }
History
Date User Action Args
2019-05-28 14:10:09eryksunsetrecipients: + eryksun, paul.moore, tim.golden, zach.ware, serhiy.storchaka, steve.dower, mangrisano
2019-05-28 14:10:09eryksunsetmessageid: <1559052609.91.0.368630295086.issue37074@roundup.psfhosted.org>
2019-05-28 14:10:09eryksunlinkissue37074 messages
2019-05-28 14:10:09eryksuncreate