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 Antony.Lee, eryksun, paul.moore, steve.dower, tim.golden, zach.ware
Date 2022-02-18.11:00:44
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1645182044.64.0.667681143691.issue46785@roundup.psfhosted.org>
In-reply-to
Content
Windows filesystems disallow new opens for a file that has its delete disposition set (i.e. the file is marked for deletion). For example, CreateFileW() fails with ERROR_ACCESS_DENIED (5) in this case. A file with its delete disposition set is still visibly linked in its parent directory. 

The trigger to unlink a file that's marked for deletion depends on the delete mode. In Windows 10, DeleteFileW() uses a POSIX delete if it's supported by the filesystem (e.g. NTFS). This delete mode unlinks the file as soon the file object that was used to set the delete disposition is closed. There's still a small window of time, however, in which attempts to open the file will fail with an access-denied error.

In os.stat(), if CreateFileW() fails with access denied, FindFirstFileW() is called to try to get the stat data from the file's parent directory. But in this case it's likely that the file has been unlinked from the directory by the time FindFirstFileW() is called.

The original error code from CreateFileW() gets restored if FindFirstFileW() fails. This is generally the right thing to do. However, if FindFirstFileW() fails with ERROR_FILE_NOT_FOUND (2) or ERROR_PATH_NOT_FOUND (3), then I suggest that the previous error code should not be restored.

For example:

        switch (error) {
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
            /* Try reading the parent directory. */
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
                /* Cannot read the parent directory. */
                DWORD dir_error = GetLastError();
                if (dir_error != ERROR_FILE_NOT_FOUND &&
                      dir_error != ERROR_PATH_NOT_FOUND) {
                    SetLastError(error);
                }
                return -1;
            }
History
Date User Action Args
2022-02-18 11:00:44eryksunsetrecipients: + eryksun, paul.moore, tim.golden, zach.ware, Antony.Lee, steve.dower
2022-02-18 11:00:44eryksunsetmessageid: <1645182044.64.0.667681143691.issue46785@roundup.psfhosted.org>
2022-02-18 11:00:44eryksunlinkissue46785 messages
2022-02-18 11:00:44eryksuncreate