mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[release-branch.go1.24] syscall: don't truncate newly created files on Windows
There is no need for syscall.OpenFile to truncate newly created files.
Some special Windows files, like the NUL device, can't be
truncated, so we should avoid truncating unless it is really necessary.
For #71752
Fixes #71836
Change-Id: I8238048594f706f6a5281053d55cfe3dc898828d
Reviewed-on: https://go-review.googlesource.com/c/go/+/650276
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
(cherry picked from commit 4267fd389e)
Reviewed-on: https://go-review.googlesource.com/c/go/+/650597
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Commit-Queue: Ian Lance Taylor <iant@google.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
This commit is contained in:
parent
bb0e5c2045
commit
30f4d9e117
3 changed files with 30 additions and 7 deletions
|
|
@ -3848,3 +3848,14 @@ func TestRemoveReadOnlyFile(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestOpenFileDevNull(t *testing.T) {
|
||||
// See https://go.dev/issue/71752.
|
||||
t.Parallel()
|
||||
|
||||
f, err := OpenFile(DevNull, O_WRONLY|O_CREATE|O_TRUNC, 0o644)
|
||||
if err != nil {
|
||||
t.Fatalf("OpenFile(DevNull): %v", err)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ func NewCallbackCDecl(fn any) uintptr {
|
|||
//sys GetVersion() (ver uint32, err error)
|
||||
//sys formatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
|
||||
//sys ExitProcess(exitcode uint32)
|
||||
//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
|
||||
//sys createFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval == InvalidHandle || e1 == ERROR_ALREADY_EXISTS ] = CreateFileW
|
||||
//sys readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = ReadFile
|
||||
//sys writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = WriteFile
|
||||
//sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff]
|
||||
|
|
@ -404,8 +404,8 @@ func Open(name string, flag int, perm uint32) (fd Handle, err error) {
|
|||
const _FILE_FLAG_WRITE_THROUGH = 0x80000000
|
||||
attrs |= _FILE_FLAG_WRITE_THROUGH
|
||||
}
|
||||
h, err := CreateFile(namep, access, sharemode, sa, createmode, attrs, 0)
|
||||
if err != nil {
|
||||
h, err := createFile(namep, access, sharemode, sa, createmode, attrs, 0)
|
||||
if h == InvalidHandle {
|
||||
if err == ERROR_ACCESS_DENIED && (flag&O_WRONLY != 0 || flag&O_RDWR != 0) {
|
||||
// We should return EISDIR when we are trying to open a directory with write access.
|
||||
fa, e1 := GetFileAttributes(namep)
|
||||
|
|
@ -413,9 +413,11 @@ func Open(name string, flag int, perm uint32) (fd Handle, err error) {
|
|||
err = EISDIR
|
||||
}
|
||||
}
|
||||
return InvalidHandle, err
|
||||
return h, err
|
||||
}
|
||||
if flag&O_TRUNC == O_TRUNC {
|
||||
// Ignore O_TRUNC if the file has just been created.
|
||||
if flag&O_TRUNC == O_TRUNC &&
|
||||
(createmode == OPEN_EXISTING || (createmode == OPEN_ALWAYS && err == ERROR_ALREADY_EXISTS)) {
|
||||
err = Ftruncate(h, 0)
|
||||
if err != nil {
|
||||
CloseHandle(h)
|
||||
|
|
@ -1454,3 +1456,13 @@ func GetStartupInfo(startupInfo *StartupInfo) error {
|
|||
getStartupInfo(startupInfo)
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) {
|
||||
handle, err = createFile(name, access, mode, sa, createmode, attrs, templatefile)
|
||||
if handle != InvalidHandle {
|
||||
// CreateFileW can return ERROR_ALREADY_EXISTS with a valid handle.
|
||||
// We only want to return an error if the handle is invalid.
|
||||
err = nil
|
||||
}
|
||||
return handle, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,10 +502,10 @@ func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxS
|
|||
return
|
||||
}
|
||||
|
||||
func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) {
|
||||
func createFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) {
|
||||
r0, _, e1 := Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||
handle = Handle(r0)
|
||||
if handle == InvalidHandle {
|
||||
if handle == InvalidHandle || e1 == ERROR_ALREADY_EXISTS {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue