implement futimens on Darwin and Linux (#1210)

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
This commit is contained in:
Edoardo Vacchi
2023-03-08 01:21:12 +01:00
committed by GitHub
parent 6626535f44
commit b16f74a86b
5 changed files with 62 additions and 2 deletions

View File

@@ -0,0 +1,34 @@
package platform
import (
"syscall"
"unsafe"
)
func futimens(fd uintptr, atimeNsec, mtimeNsec int64) error {
tv := []syscall.Timespec{
syscall.NsecToTimespec(atimeNsec),
syscall.NsecToTimespec(mtimeNsec),
}
// Warning: futimens only exists since High Sierra (10.13).
_, _, e1 := syscall_syscall6(libc_futimens_trampoline_addr, fd, uintptr(unsafe.Pointer(&tv[0])), 0, 0, 0, 0)
if e1 != 0 {
return e1
}
return nil
}
// libc_futimens_trampoline_addr is the address of the libc_futimens_trampoline symbol, defined in utimes_darwin.s
// we use this value to invoke the syscall through syscall_syscall6 imported below
var libc_futimens_trampoline_addr uintptr
// Imports the futimens symbol from libc as libc_futimens
//go:cgo_import_dynamic libc_futimens futimens "/usr/lib/libSystem.B.dylib"
// syscall_syscall6 is a private symbol that we link below. We need to use this instead of syscall.Syscall6
// because the public syscall.Syscall6 won't work when fn is an address
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
// Import syscall.syscall6 as syscall_syscall6.
//go:linkname syscall_syscall6 syscall.syscall6

View File

@@ -0,0 +1,8 @@
// lifted from golang.org/x/sys unix
#include "textflag.h"
TEXT libc_futimens_trampoline<>(SB), NOSPLIT, $0-0
JMP libc_futimens(SB)
GLOBL ·libc_futimens_trampoline_addr(SB), RODATA, $8
DATA ·libc_futimens_trampoline_addr(SB)/8, $libc_futimens_trampoline<>(SB)

View File

@@ -0,0 +1,18 @@
package platform
import (
"syscall"
"unsafe"
)
func futimens(fd uintptr, atimeNsec, mtimeNsec int64) error {
times := []syscall.Timespec{
syscall.NsecToTimespec(atimeNsec),
syscall.NsecToTimespec(mtimeNsec),
}
_, _, err := syscall.Syscall6(syscall.SYS_UTIMENSAT, fd, uintptr(0), uintptr(unsafe.Pointer(&times[0])), uintptr(0), 0, 0)
if err != 0 {
return err
}
return nil
}

View File

@@ -73,7 +73,7 @@ func TestUtimesNano(t *testing.T) {
}
func TestUtimesNanoFile(t *testing.T) {
if !(runtime.GOOS == "windows" && IsGo120) {
if !IsGo120 {
t.Skip("TODO: implement futimens on darwin, freebsd, linux w/o CGO")
}

View File

@@ -1,4 +1,4 @@
//go:build !windows
//go:build !windows && !linux && !darwin
package platform