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 Tom Hale, a.badger, eryksun, rbcollins, serhiy.storchaka
Date 2019-06-04.14:14:41
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1559657682.07.0.9983508434.issue36656@roundup.psfhosted.org>
In-reply-to
Content
> I'd like to add a few notes; please do consider Windows interactions 
> here - Windows does not have the same model for inode replacement that 
> Posix has.

Certainly Windows doesn't have the same model for inode replacement since it doesn't have inodes. ;-)

Like POSIX, we can't create a symlink and replace it in one step in Windows. A reparse point can only be set on an existing file. WINAPI CreateSymbolicLink thus requires two system calls: NtCreateFile (file or directory) and NtFsControlFile: FSCTL_SET_REPARSE_POINT. Sensibly, CreateSymbolicLink does not support a flag to allow replacing an existing file or empty directory, since overall the operation isn't atomic.

Like POSIX, we can do an atomic rename within a volume device. This supports replacing an existing file, but, for backward compatibility, we can't implement the replace semantics in os.rename in Windows. Instead we have os.replace. This is a single NtSetInformatonFile: FileRenameInformation system call, with ReplaceIfExists enabled. An important caveat is that this request cannot replace an open file, even if it was opened with delete-access sharing, since that would leave the replaced file nameless. To partially address this, NTFS (but not FAT32) in Windows 10 1709 supports a new FileRenameInformationEx request. This request can combine the flags FILE_RENAME_REPLACE_IF_EXISTS and FILE_RENAME_POSIX_SEMANTICS to allow replacing an open file, if and only if it's opened with delete-access sharing. The replaced file is still accessible for read and write data operations until it's closed. The requirement for delete-access sharing means this is still not quite POSIX semantics. (Most Windows programs do not open files with delete sharing, except for temp files.) But at least it's possible for aware programs and environments to implement POSIX semantics. 

Regarding os.link, WINAPI CreateHardLink is implemented via NtSetInformationFile: FileLinkInformation. This system call also supports ReplaceIfExists, but CreateHardLink doesn't expose an option or flag for this capability. Even if we supported the system call directly (unprecedented in Windows Python), the same problem exists with open files. NTFS in Windows 10 1809 supports a new FileLinkInformationEx request. The flags FILE_LINK_REPLACE_IF_EXISTS and FILE_LINK_POSIX_SEMANTICS behave as the corresponding flags for FileRenameInformationEx.

It's unrelated, but just to round this discussion out, NTFS in Windows 10 1709 supports a new FileDispositionInformationEx request to set a file's delete disposition. With the flag FILE_DISPOSITION_POSIX_SEMANTICS, the deleted file is unlinked as soon as the requesting file reference is closed, even if the file has other references. This is in contrast to the classic FileDispositionInformation request for which the file is only unlinked once all references are closed. Again, it's not quit POSIX semantics overall since the shared delete access model still applies. But this new delete operation at least addresses the problem with malware scanners and similar programs that open files with shared delete access.
History
Date User Action Args
2019-06-04 14:14:42eryksunsetrecipients: + eryksun, rbcollins, a.badger, serhiy.storchaka, Tom Hale
2019-06-04 14:14:42eryksunsetmessageid: <1559657682.07.0.9983508434.issue36656@roundup.psfhosted.org>
2019-06-04 14:14:42eryksunlinkissue36656 messages
2019-06-04 14:14:41eryksuncreate