Eryk Sun <eryk...@gmail.com> added the comment:

> 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 Windo
 ws 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.

----------
nosy: +eryksun

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue36656>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to