Commit 67c36059 authored by Tobias Klauser's avatar Tobias Klauser Committed by Ian Lance Taylor

syscall: add utimensat and use it for UtimesNano on BSD and Solaris

All the BSDs and Solaris support the utimensat syscall, but Darwin
doesn't. Account for that by adding the //sys lines not to
syscall_bsd.go but the individual OS's syscall_*.go files and implement
utimensat on Darwin as just returning ENOSYS, such that UtimesNano will
fall back to use utimes as it currently does unconditionally.

This also adds the previously missing utimensat syscall number for
FreeBSD and Dragonfly.

Fixes #16480

Change-Id: I367454c6168eb1f7150b988fa16cf02abff42f34
Reviewed-on: https://go-review.googlesource.com/55130Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
parent 6203a79b
......@@ -507,11 +507,13 @@ func Utimes(path string, tv []Timeval) (err error) {
}
func UtimesNano(path string, ts []Timespec) error {
// TODO: The BSDs can do utimensat with SYS_UTIMENSAT but it
// isn't supported by darwin so this uses utimes instead
if len(ts) != 2 {
return EINVAL
}
err := utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])))
if err != ENOSYS {
return err
}
// Not as efficient as it could be because Timespec and
// Timeval have different types in the different OSes
tv := [2]Timeval{
......
......@@ -186,6 +186,11 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
return
}
func utimensat(dirfd int, path string, times *[2]Timespec) error {
// Darwin doesn't support SYS_UTIMENSAT
return ENOSYS
}
/*
* Wrapped
*/
......
......@@ -211,6 +211,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
//sys accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error)
//sys utimensat(dirfd int, path string, times *[2]Timespec) (err error)
/*
* Unimplemented
......
......@@ -222,6 +222,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
//sys accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error)
//sys utimensat(dirfd int, path string, times *[2]Timespec) (err error)
/*
* Unimplemented
......
......@@ -202,6 +202,7 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys munmap(addr uintptr, length uintptr) (err error)
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
//sys utimensat(dirfd int, path string, times *[2]Timespec) (err error)
/*
* Unimplemented
......
......@@ -183,6 +183,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
//sys munmap(addr uintptr, length uintptr) (err error)
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
//sys utimensat(dirfd int, path string, times *[2]Timespec) (err error)
/*
* Unimplemented
......@@ -278,6 +279,5 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
// thrsleep
// thrwakeup
// unlinkat
// utimensat
// vfork
// writev
......@@ -510,6 +510,7 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
//sys getexecname() (path unsafe.Pointer, err error) = libc.getexecname
//sys utimensat(dirfd int, path string, times *[2]Timespec) (err error)
func Getexecname() (path string, err error) {
ptr, err := getexecname()
......
......@@ -238,6 +238,12 @@ type BpfInsn C.struct_bpf_insn
type BpfHdr C.struct_bpf_hdr
// Misc
const (
_AT_FDCWD = C.AT_FDCWD
)
// Terminal handling
type Termios C.struct_termios
......@@ -237,6 +237,12 @@ type BpfInsn C.struct_bpf_insn
type BpfHdr C.struct_bpf_hdr
// Misc
const (
_AT_FDCWD = C.AT_FDCWD
)
// Terminal handling
type Termios C.struct_termios
......@@ -337,6 +337,12 @@ type BpfHdr C.struct_bpf_hdr
type BpfZbufHeader C.struct_bpf_zbuf_header
// Misc
const (
_AT_FDCWD = C.AT_FDCWD
)
// Terminal handling
type Termios C.struct_termios
......@@ -223,6 +223,12 @@ type BpfHdr C.struct_bpf_hdr
type BpfTimeval C.struct_bpf_timeval
// Misc
const (
_AT_FDCWD = C.AT_FDCWD
)
// Terminal handling
type Termios C.struct_termios
......
......@@ -239,6 +239,12 @@ type BpfHdr C.struct_bpf_hdr
type BpfTimeval C.struct_bpf_timeval
// Misc
const (
_AT_FDCWD = C.AT_FDCWD
)
// Terminal handling
type Termios C.struct_termios
......@@ -224,6 +224,12 @@ type BpfTimeval C.struct_bpf_timeval
type BpfHdr C.struct_bpf_hdr
// Misc
const (
_AT_FDCWD = C.AT_FDCWD
)
// Terminal handling
type Termios C.struct_termios
......@@ -1298,3 +1298,18 @@ func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -1308,3 +1308,18 @@ func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -1308,3 +1308,18 @@ func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -1308,3 +1308,18 @@ func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -1224,3 +1224,18 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -1224,3 +1224,18 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// mksyscall.pl -l32 -arm -tags netbsd,arm syscall_bsd.go syscall_netbsd.go syscall_netbsd_arm.go
// mksyscall.pl -l32 -netbsd -arm -tags netbsd,arm syscall_bsd.go syscall_netbsd.go syscall_netbsd_arm.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// +build netbsd,arm
......@@ -1224,3 +1224,18 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -1262,3 +1262,18 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -1262,3 +1262,18 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -1262,3 +1262,18 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -90,6 +90,7 @@ import "unsafe"
//go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so"
//go:cgo_import_dynamic libc___xnet_recvmsg __xnet_recvmsg "libsocket.so"
//go:cgo_import_dynamic libc_getexecname getexecname "libc.so"
//go:cgo_import_dynamic libc_utimensat utimensat "libc.so"
//go:linkname libc_Getcwd libc_Getcwd
//go:linkname libc_getgroups libc_getgroups
......@@ -174,6 +175,7 @@ import "unsafe"
//go:linkname libc_recvfrom libc_recvfrom
//go:linkname libc___xnet_recvmsg libc___xnet_recvmsg
//go:linkname libc_getexecname libc_getexecname
//go:linkname libc_utimensat libc_utimensat
type libcFunc uintptr
......@@ -260,7 +262,8 @@ var (
libc_setsockopt,
libc_recvfrom,
libc___xnet_recvmsg,
libc_getexecname libcFunc
libc_getexecname,
libc_utimensat libcFunc
)
func Getcwd(buf []byte) (n int, err error) {
......@@ -1084,3 +1087,16 @@ func getexecname() (path unsafe.Pointer, err error) {
}
return
}
func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_utimensat)), 3, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0, 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
......@@ -301,5 +301,6 @@ const (
SYS_LPATHCONF = 533 // { int lpathconf(char *path, int name); }
SYS_VMM_GUEST_CTL = 534 // { int vmm_guest_ctl(int op, struct vmm_guest_options *options); }
SYS_VMM_GUEST_SYNC_ADDR = 535 // { int vmm_guest_sync_addr(long *dstaddr, long *srcaddr); }
SYS_UTIMENSAT = 539 // { int utimensat(int fd, const char *path, const struct timespec *ts, int flags); }
SYS_ACCEPT4 = 541 // { int accept4(int s, caddr_t name, int *anamelen, int flags); }
)
......@@ -347,4 +347,5 @@ const (
SYS_ACCEPT4 = 541 // { int accept4(int s, \
SYS_PIPE2 = 542 // { int pipe2(int *fildes, int flags); }
SYS_PROCCTL = 544 // { int procctl(idtype_t idtype, id_t id, \
SYS_UTIMENSAT = 547 // { int utimensat(int fd, \
)
......@@ -347,4 +347,5 @@ const (
SYS_ACCEPT4 = 541 // { int accept4(int s, \
SYS_PIPE2 = 542 // { int pipe2(int *fildes, int flags); }
SYS_PROCCTL = 544 // { int procctl(idtype_t idtype, id_t id, \
SYS_UTIMENSAT = 547 // { int utimensat(int fd, \
)
......@@ -347,4 +347,5 @@ const (
SYS_ACCEPT4 = 541 // { int accept4(int s, \
SYS_PIPE2 = 542 // { int pipe2(int *fildes, int flags); }
SYS_PROCCTL = 544 // { int procctl(idtype_t idtype, id_t id, \
SYS_UTIMENSAT = 547 // { int utimensat(int fd, \
)
......@@ -437,6 +437,10 @@ type BpfHdr struct {
Pad_cgo_0 [2]byte
}
const (
_AT_FDCWD = -0x2
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -446,6 +446,10 @@ type BpfHdr struct {
Pad_cgo_0 [2]byte
}
const (
_AT_FDCWD = -0x2
)
type Termios struct {
Iflag uint64
Oflag uint64
......
......@@ -438,6 +438,10 @@ type BpfHdr struct {
Pad_cgo_0 [2]byte
}
const (
_AT_FDCWD = -0x2
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -446,6 +446,10 @@ type BpfHdr struct {
Pad_cgo_0 [2]byte
}
const (
_AT_FDCWD = -0x2
)
type Termios struct {
Iflag uint64
Oflag uint64
......
......@@ -432,6 +432,10 @@ type BpfHdr struct {
Pad_cgo_0 [6]byte
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -483,6 +483,10 @@ type BpfZbufHeader struct {
X_bzh_pad [5]uint32
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -486,6 +486,10 @@ type BpfZbufHeader struct {
X_bzh_pad [5]uint32
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -486,6 +486,10 @@ type BpfZbufHeader struct {
X_bzh_pad [5]uint32
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -372,6 +372,10 @@ type BpfTimeval struct {
Usec int32
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -379,6 +379,10 @@ type BpfTimeval struct {
Usec int64
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -377,6 +377,10 @@ type BpfTimeval struct {
Usec int32
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -430,6 +430,10 @@ type BpfTimeval struct {
Usec uint32
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -437,6 +437,10 @@ type BpfTimeval struct {
Usec uint32
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -423,6 +423,10 @@ type BpfTimeval struct {
Usec uint32
}
const (
_AT_FDCWD = -0x64
)
type Termios struct {
Iflag uint32
Oflag uint32
......
......@@ -358,6 +358,10 @@ type BpfHdr struct {
Pad_cgo_0 [2]byte
}
const (
_AT_FDCWD = 0xffd19553
)
type Termios struct {
Iflag uint32
Oflag uint32
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment