diff options
Diffstat (limited to 'src/internal/syscall/windows/at_windows.go')
| -rw-r--r-- | src/internal/syscall/windows/at_windows.go | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/src/internal/syscall/windows/at_windows.go b/src/internal/syscall/windows/at_windows.go index de733c523c..81361c98e4 100644 --- a/src/internal/syscall/windows/at_windows.go +++ b/src/internal/syscall/windows/at_windows.go @@ -246,14 +246,31 @@ func Deleteat(dirfd syscall.Handle, name string, options uint32) error { var h syscall.Handle err := NtOpenFile( &h, - SYNCHRONIZE|FILE_READ_ATTRIBUTES|DELETE, + FILE_READ_ATTRIBUTES|DELETE, objAttrs, &IO_STATUS_BLOCK{}, FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN_REPARSE_POINT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_SYNCHRONOUS_IO_NONALERT|options, + FILE_OPEN_REPARSE_POINT|FILE_OPEN_FOR_BACKUP_INTENT|options, ) if err != nil { - return ntCreateFileError(err, 0) + if ntStatus, ok := err.(NTStatus); !ok || ntStatus != STATUS_ACCESS_DENIED { + return ntCreateFileError(err, 0) + } + + // Access denied, try opening with DELETE only. + // This may succeed if the file has restrictive permissions + // but the caller has delete child permission on the parent directory. + err = NtOpenFile( + &h, + DELETE, + objAttrs, + &IO_STATUS_BLOCK{}, + FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN_REPARSE_POINT|FILE_OPEN_FOR_BACKUP_INTENT|options, + ) + if err != nil { + return ntCreateFileError(err, 0) + } } defer syscall.CloseHandle(h) |
