unix: add utimensat libc wrapper on darwin

Direct syscalls are no longer supported on darwin (CL 250437), so
utimensat can be implemented as a wrapper around the libc function.
The utimensat function was added in macOS 10.13 and Go 1.17 dropped
support for macOS 10.12.

This also allows to drop the fallback to setattrlistTimes which was
used to set timestamps with nanosecond resolution before utimensat could
be used, see golang/go#22528 and CL 74952.

Change-Id: I206291277e6f7200ca7a659e29075968647779a6
Reviewed-on: https://go-review.googlesource.com/c/sys/+/251737
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matt Layher <mdlayher@gmail.com>
This commit is contained in:
Tobias Klauser
2022-02-19 12:41:11 +01:00
committed by Tobias Klauser
parent 36772127a2
commit 530d0810a4
12 changed files with 30 additions and 88 deletions

View File

@@ -118,7 +118,6 @@ var darwinTests = [...]darwinTest{
{"sendfile", libc_sendfile_trampoline_addr},
{"sendmsg", libc_sendmsg_trampoline_addr},
{"sendto", libc_sendto_trampoline_addr},
{"setattrlist", libc_setattrlist_trampoline_addr},
{"setegid", libc_setegid_trampoline_addr},
{"seteuid", libc_seteuid_trampoline_addr},
{"setgid", libc_setgid_trampoline_addr},
@@ -154,6 +153,7 @@ var darwinTests = [...]darwinTest{
{"unlink", libc_unlink_trampoline_addr},
{"unlinkat", libc_unlinkat_trampoline_addr},
{"unmount", libc_unmount_trampoline_addr},
{"utimensat", libc_utimensat_trampoline_addr},
{"utimes", libc_utimes_trampoline_addr},
{"wait4", libc_wait4_trampoline_addr},
{"write", libc_write_trampoline_addr},

View File

@@ -118,7 +118,6 @@ var darwinTests = [...]darwinTest{
{"sendfile", libc_sendfile_trampoline_addr},
{"sendmsg", libc_sendmsg_trampoline_addr},
{"sendto", libc_sendto_trampoline_addr},
{"setattrlist", libc_setattrlist_trampoline_addr},
{"setegid", libc_setegid_trampoline_addr},
{"seteuid", libc_seteuid_trampoline_addr},
{"setgid", libc_setgid_trampoline_addr},
@@ -154,6 +153,7 @@ var darwinTests = [...]darwinTest{
{"unlink", libc_unlink_trampoline_addr},
{"unlinkat", libc_unlinkat_trampoline_addr},
{"unmount", libc_unmount_trampoline_addr},
{"utimensat", libc_utimensat_trampoline_addr},
{"utimes", libc_utimes_trampoline_addr},
{"wait4", libc_wait4_trampoline_addr},
{"write", libc_write_trampoline_addr},

View File

@@ -553,12 +553,7 @@ func UtimesNano(path string, ts []Timespec) error {
if len(ts) != 2 {
return EINVAL
}
// Darwin setattrlist can set nanosecond timestamps
err := setattrlistTimes(path, ts, 0)
if err != ENOSYS {
return err
}
err = utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
if err != ENOSYS {
return err
}
@@ -578,10 +573,6 @@ func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
if len(ts) != 2 {
return EINVAL
}
err := setattrlistTimes(path, ts, flags)
if err != ENOSYS {
return err
}
return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
}

View File

@@ -141,16 +141,6 @@ func direntNamlen(buf []byte) (uint64, bool) {
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
type attrList struct {
bitmapCount uint16
_ uint16
CommonAttr uint32
VolAttr uint32
DirAttr uint32
FileAttr uint32
Forkattr uint32
}
//sysnb pipe(p *[2]int32) (err error)
func Pipe(p []int) (err error) {
@@ -282,36 +272,7 @@ func Flistxattr(fd int, dest []byte) (sz int, err error) {
return flistxattr(fd, xattrPointer(dest), len(dest), 0)
}
func setattrlistTimes(path string, times []Timespec, flags int) error {
_p0, err := BytePtrFromString(path)
if err != nil {
return err
}
var attrList attrList
attrList.bitmapCount = ATTR_BIT_MAP_COUNT
attrList.CommonAttr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME
// order is mtime, atime: the opposite of Chtimes
attributes := [2]Timespec{times[1], times[0]}
options := 0
if flags&AT_SYMLINK_NOFOLLOW != 0 {
options |= FSOPT_NOFOLLOW
}
return setattrlist(
_p0,
unsafe.Pointer(&attrList),
unsafe.Pointer(&attributes),
unsafe.Sizeof(attributes),
options)
}
//sys setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error)
func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error {
// Darwin doesn't support SYS_UTIMENSAT
return ENOSYS
}
//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
/*
* Wrapped

View File

@@ -169,11 +169,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
return
}
func setattrlistTimes(path string, times []Timespec, flags int) error {
// used on Darwin for UtimesNano
return ENOSYS
}
//sys ioctl(fd int, req uint, arg uintptr) (err error)
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL

View File

@@ -194,11 +194,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
return
}
func setattrlistTimes(path string, times []Timespec, flags int) error {
// used on Darwin for UtimesNano
return ENOSYS
}
//sys ioctl(fd int, req uint, arg uintptr) (err error)
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL

View File

@@ -163,11 +163,6 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
return -1, ENOSYS
}
func setattrlistTimes(path string, times []Timespec, flags int) error {
// used on Darwin for UtimesNano
return ENOSYS
}
//sys ioctl(fd int, req uint, arg uintptr) (err error)
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL

View File

@@ -149,11 +149,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
return
}
func setattrlistTimes(path string, times []Timespec, flags int) error {
// used on Darwin for UtimesNano
return ENOSYS
}
//sys ioctl(fd int, req uint, arg uintptr) (err error)
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL

View File

@@ -643,17 +643,22 @@ var libc_flistxattr_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
_, _, e1 := syscall_syscall6(libc_setattrlist_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setattrlist_trampoline_addr uintptr
var libc_utimensat_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_utimensat utimensat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT

View File

@@ -228,11 +228,11 @@ TEXT libc_flistxattr_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_flistxattr_trampoline_addr(SB), RODATA, $8
DATA ·libc_flistxattr_trampoline_addr(SB)/8, $libc_flistxattr_trampoline<>(SB)
TEXT libc_setattrlist_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setattrlist(SB)
TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_utimensat(SB)
GLOBL ·libc_setattrlist_trampoline_addr(SB), RODATA, $8
DATA ·libc_setattrlist_trampoline_addr(SB)/8, $libc_setattrlist_trampoline<>(SB)
GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8
DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB)
TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_fcntl(SB)

View File

@@ -643,17 +643,22 @@ var libc_flistxattr_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
_, _, e1 := syscall_syscall6(libc_setattrlist_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setattrlist_trampoline_addr uintptr
var libc_utimensat_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_utimensat utimensat "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT

View File

@@ -228,11 +228,11 @@ TEXT libc_flistxattr_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_flistxattr_trampoline_addr(SB), RODATA, $8
DATA ·libc_flistxattr_trampoline_addr(SB)/8, $libc_flistxattr_trampoline<>(SB)
TEXT libc_setattrlist_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setattrlist(SB)
TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_utimensat(SB)
GLOBL ·libc_setattrlist_trampoline_addr(SB), RODATA, $8
DATA ·libc_setattrlist_trampoline_addr(SB)/8, $libc_setattrlist_trampoline<>(SB)
GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8
DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB)
TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_fcntl(SB)