]> Cypherpunks repositories - gostls13.git/commitdiff
internal/syscall/unix: add Mkdirat and Readlinkat
authorDamien Neil <dneil@google.com>
Fri, 4 Oct 2024 21:19:05 +0000 (14:19 -0700)
committerDamien Neil <dneil@google.com>
Mon, 7 Oct 2024 19:24:54 +0000 (19:24 +0000)
For #67002

Change-Id: I460e02db33799c145c296bcf0668fa555199036e
Reviewed-on: https://go-review.googlesource.com/c/go/+/617376
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
23 files changed:
src/internal/syscall/unix/asm_darwin.s
src/internal/syscall/unix/asm_openbsd.s
src/internal/syscall/unix/at.go
src/internal/syscall/unix/at_aix.go
src/internal/syscall/unix/at_darwin.go [new file with mode: 0644]
src/internal/syscall/unix/at_libc.go
src/internal/syscall/unix/at_openbsd.go [new file with mode: 0644]
src/internal/syscall/unix/at_solaris.go
src/internal/syscall/unix/at_sysnum_dragonfly.go
src/internal/syscall/unix/at_sysnum_freebsd.go
src/internal/syscall/unix/at_sysnum_linux.go
src/internal/syscall/unix/at_sysnum_netbsd.go
src/internal/syscall/unix/at_sysnum_openbsd.go
src/internal/syscall/unix/at_wasip1.go
src/internal/syscall/unix/syscall.go [new file with mode: 0644]
src/internal/syscall/unix/sysnum_linux_386.go
src/internal/syscall/unix/sysnum_linux_amd64.go
src/internal/syscall/unix/sysnum_linux_arm.go
src/internal/syscall/unix/sysnum_linux_generic.go
src/internal/syscall/unix/sysnum_linux_mips64x.go
src/internal/syscall/unix/sysnum_linux_mipsx.go
src/internal/syscall/unix/sysnum_linux_ppc64x.go
src/internal/syscall/unix/sysnum_linux_s390x.go

index 99f28765fe0ccd053ace0f9bc45ca0c61abbded7..b96eb1e80752fa6dff1c23cc16f7089f4f0791de 100644 (file)
@@ -23,3 +23,5 @@ TEXT ·libc_getgrnam_r_trampoline(SB),NOSPLIT,$0-0; JMP libc_getgrnam_r(SB)
 TEXT ·libc_getgrgid_r_trampoline(SB),NOSPLIT,$0-0; JMP libc_getgrgid_r(SB)
 TEXT ·libc_sysconf_trampoline(SB),NOSPLIT,$0-0; JMP libc_sysconf(SB)
 TEXT ·libc_faccessat_trampoline(SB),NOSPLIT,$0-0; JMP libc_faccessat(SB)
+TEXT ·libc_readlinkat_trampoline(SB),NOSPLIT,$0-0; JMP libc_readlinkat(SB)
+TEXT ·libc_mkdirat_trampoline(SB),NOSPLIT,$0-0; JMP libc_mkdirat(SB)
index d6c43205396019145b5419e1dfada8f982cba2c0..90f6831e4e53dccb60f04912d6e5c70037605c6f 100644 (file)
@@ -10,3 +10,7 @@ TEXT ·libc_faccessat_trampoline(SB),NOSPLIT,$0-0
         JMP    libc_faccessat(SB)
 TEXT ·libc_arc4random_buf_trampoline(SB),NOSPLIT,$0-0
         JMP    libc_arc4random_buf(SB)
+TEXT ·libc_readlinkat_trampoline(SB),NOSPLIT,$0-0
+        JMP    libc_readlinkat(SB)
+TEXT ·libc_mkdirat_trampoline(SB),NOSPLIT,$0-0
+        JMP    libc_mkdirat(SB)
index cfb6e410b122a81a481a7831abc024d6dfc8f98b..27a798e0461d70d69441fd8a066eb3c7d87207ac 100644 (file)
@@ -38,3 +38,44 @@ func Openat(dirfd int, path string, flags int, perm uint32) (int, error) {
 
        return int(fd), nil
 }
+
+func Readlinkat(dirfd int, path string, buf []byte) (int, error) {
+       p0, err := syscall.BytePtrFromString(path)
+       if err != nil {
+               return 0, err
+       }
+       var p1 unsafe.Pointer
+       if len(buf) > 0 {
+               p1 = unsafe.Pointer(&buf[0])
+       } else {
+               p1 = unsafe.Pointer(&_zero)
+       }
+       n, _, errno := syscall.Syscall6(readlinkatTrap,
+               uintptr(dirfd),
+               uintptr(unsafe.Pointer(p0)),
+               uintptr(p1),
+               uintptr(len(buf)),
+               0, 0)
+       if errno != 0 {
+               return 0, errno
+       }
+
+       return int(n), nil
+}
+
+func Mkdirat(dirfd int, path string, mode uint32) error {
+       p, err := syscall.BytePtrFromString(path)
+       if err != nil {
+               return err
+       }
+
+       _, _, errno := syscall.Syscall6(mkdiratTrap,
+               uintptr(dirfd),
+               uintptr(unsafe.Pointer(p)),
+               uintptr(mode),
+               0, 0, 0)
+       if errno != 0 {
+               return errno
+       }
+       return nil
+}
index 04cacf7f30333c89924e3c4b1a72fcc5c45d1efc..5c2f00efe59cf3528e5a2df8c4cfd1261dd8bb25 100644 (file)
@@ -7,6 +7,8 @@ package unix
 //go:cgo_import_dynamic libc_fstatat fstatat "libc.a/shr_64.o"
 //go:cgo_import_dynamic libc_openat openat "libc.a/shr_64.o"
 //go:cgo_import_dynamic libc_unlinkat unlinkat "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.a/shr_64.o"
 
 const (
        AT_EACCESS          = 0x1
diff --git a/src/internal/syscall/unix/at_darwin.go b/src/internal/syscall/unix/at_darwin.go
new file mode 100644 (file)
index 0000000..dbcae5a
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build darwin
+
+package unix
+
+import (
+       "internal/abi"
+       "syscall"
+       "unsafe"
+)
+
+func libc_readlinkat_trampoline()
+
+//go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib"
+
+func Readlinkat(dirfd int, path string, buf []byte) (int, error) {
+       p0, err := syscall.BytePtrFromString(path)
+       if err != nil {
+               return 0, err
+       }
+       var p1 unsafe.Pointer
+       if len(buf) > 0 {
+               p1 = unsafe.Pointer(&buf[0])
+       } else {
+               p1 = unsafe.Pointer(&_zero)
+       }
+       n, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_readlinkat_trampoline),
+               uintptr(dirfd),
+               uintptr(unsafe.Pointer(p0)),
+               uintptr(p1),
+               uintptr(len(buf)),
+               0,
+               0)
+       if errno != 0 {
+               return 0, errno
+       }
+       return int(n), nil
+}
+
+func libc_mkdirat_trampoline()
+
+//go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib"
+
+func Mkdirat(dirfd int, path string, mode uint32) error {
+       p, err := syscall.BytePtrFromString(path)
+       if err != nil {
+               return err
+       }
+       _, _, errno := syscall_syscall(abi.FuncPCABI0(libc_mkdirat_trampoline),
+               uintptr(dirfd),
+               uintptr(unsafe.Pointer(p)),
+               uintptr(mode))
+       if errno != 0 {
+               return errno
+       }
+       return nil
+}
index f48d3791e370c83f2218007416f6be607a34c2dd..faf38be602af659cec8ab5f46d434ede97ca0298 100644 (file)
@@ -14,11 +14,15 @@ import (
 //go:linkname procFstatat libc_fstatat
 //go:linkname procOpenat libc_openat
 //go:linkname procUnlinkat libc_unlinkat
+//go:linkname procReadlinkat libc_readlinkat
+//go:linkname procMkdirat libc_mkdirat
 
 var (
        procFstatat,
        procOpenat,
-       procUnlinkat uintptr
+       procUnlinkat,
+       procReadlinkat,
+       procMkdirat uintptr
 )
 
 func Unlinkat(dirfd int, path string, flags int) error {
@@ -62,3 +66,44 @@ func Fstatat(dirfd int, path string, stat *syscall.Stat_t, flags int) error {
 
        return nil
 }
+
+func Readlinkat(dirfd int, path string, buf []byte) (int, error) {
+       p0, err := syscall.BytePtrFromString(path)
+       if err != nil {
+               return 0, err
+       }
+       var p1 unsafe.Pointer
+       if len(buf) > 0 {
+               p1 = unsafe.Pointer(&buf[0])
+       } else {
+               p1 = unsafe.Pointer(&_zero)
+       }
+       n, _, errno := syscall6(uintptr(unsafe.Pointer(&procReadlinkat)), 4,
+               uintptr(dirfd),
+               uintptr(unsafe.Pointer(p0)),
+               uintptr(p1),
+               uintptr(len(buf)),
+               0, 0)
+       if errno != 0 {
+               return 0, errno
+       }
+
+       return int(n), nil
+}
+
+func Mkdirat(dirfd int, path string, mode uint32) error {
+       p, err := syscall.BytePtrFromString(path)
+       if err != nil {
+               return err
+       }
+
+       _, _, errno := syscall6(uintptr(unsafe.Pointer(&procMkdirat)), 3,
+               uintptr(dirfd),
+               uintptr(unsafe.Pointer(p)),
+               uintptr(mode),
+               0, 0, 0)
+       if errno != 0 {
+               return errno
+       }
+       return nil
+}
diff --git a/src/internal/syscall/unix/at_openbsd.go b/src/internal/syscall/unix/at_openbsd.go
new file mode 100644 (file)
index 0000000..69463e0
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build openbsd && !mips64
+
+package unix
+
+import (
+       "internal/abi"
+       "syscall"
+       "unsafe"
+)
+
+//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.so"
+
+func libc_readlinkat_trampoline()
+
+func Readlinkat(dirfd int, path string, buf []byte) (int, error) {
+       p0, err := syscall.BytePtrFromString(path)
+       if err != nil {
+               return 0, err
+       }
+       var p1 unsafe.Pointer
+       if len(buf) > 0 {
+               p1 = unsafe.Pointer(&buf[0])
+       } else {
+               p1 = unsafe.Pointer(&_zero)
+       }
+       n, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_readlinkat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(p0)), uintptr(p1), uintptr(len(buf)), 0, 0)
+       if errno != 0 {
+               return 0, errno
+       }
+       return int(n), nil
+}
+
+//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.so"
+
+func libc_mkdirat_trampoline()
+
+func Mkdirat(dirfd int, path string, mode uint32) error {
+       p, err := syscall.BytePtrFromString(path)
+       if err != nil {
+               return err
+       }
+       _, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_mkdirat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(p)), 0, 0, 0, 0)
+       if errno != 0 {
+               return errno
+       }
+       return nil
+}
index 7a29eb309cc5c9bf773eac2468302e734999e007..fa65d9e8d95990e6d81146f6662aef85a9c2e259 100644 (file)
@@ -16,6 +16,8 @@ func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, e
 //go:cgo_import_dynamic libc_fstatat fstatat "libc.so"
 //go:cgo_import_dynamic libc_openat openat "libc.so"
 //go:cgo_import_dynamic libc_unlinkat unlinkat "libc.so"
+//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.so"
+//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.so"
 //go:cgo_import_dynamic libc_uname uname "libc.so"
 
 const (
index a8164dcc8ec7be3cb1e65013d9df11d49ab97fd3..d0ba12a78af0555e6fef14d6cc117ce2e3dd1117 100644 (file)
@@ -7,9 +7,11 @@ package unix
 import "syscall"
 
 const (
-       unlinkatTrap uintptr = syscall.SYS_UNLINKAT
-       openatTrap   uintptr = syscall.SYS_OPENAT
-       fstatatTrap  uintptr = syscall.SYS_FSTATAT
+       unlinkatTrap   uintptr = syscall.SYS_UNLINKAT
+       openatTrap     uintptr = syscall.SYS_OPENAT
+       fstatatTrap    uintptr = syscall.SYS_FSTATAT
+       readlinkatTrap uintptr = syscall.SYS_READLINKAT
+       mkdiratTrap    uintptr = syscall.SYS_MKDIRAT
 
        AT_EACCESS          = 0x4
        AT_FDCWD            = 0xfffafdcd
index f74961d508623d1bd3740601786adcab84d85bbc..0f3472243226530f9522c37b7218f752ba22e387 100644 (file)
@@ -17,4 +17,6 @@ const (
        unlinkatTrap       uintptr = syscall.SYS_UNLINKAT
        openatTrap         uintptr = syscall.SYS_OPENAT
        posixFallocateTrap uintptr = syscall.SYS_POSIX_FALLOCATE
+       readlinkatTrap     uintptr = syscall.SYS_READLINKAT
+       mkdiratTrap        uintptr = syscall.SYS_MKDIRAT
 )
index 7c3b15c30302c87252c4e6e24701b21fe20da2f9..2885c7c68106e9563926d57dbd05e582d4d68fac 100644 (file)
@@ -6,8 +6,12 @@ package unix
 
 import "syscall"
 
-const unlinkatTrap uintptr = syscall.SYS_UNLINKAT
-const openatTrap uintptr = syscall.SYS_OPENAT
+const (
+       unlinkatTrap   uintptr = syscall.SYS_UNLINKAT
+       openatTrap     uintptr = syscall.SYS_OPENAT
+       readlinkatTrap uintptr = syscall.SYS_READLINKAT
+       mkdiratTrap    uintptr = syscall.SYS_MKDIRAT
+)
 
 const (
        AT_EACCESS          = 0x200
index ffb1d2eaf8b1f47d080431e41520f75f6521f445..820b977436377fcf13a2a8ea1e8fd5c87ac3b06d 100644 (file)
@@ -6,9 +6,13 @@ package unix
 
 import "syscall"
 
-const unlinkatTrap uintptr = syscall.SYS_UNLINKAT
-const openatTrap uintptr = syscall.SYS_OPENAT
-const fstatatTrap uintptr = syscall.SYS_FSTATAT
+const (
+       unlinkatTrap   uintptr = syscall.SYS_UNLINKAT
+       openatTrap     uintptr = syscall.SYS_OPENAT
+       fstatatTrap    uintptr = syscall.SYS_FSTATAT
+       readlinkatTrap uintptr = syscall.SYS_READLINKAT
+       mkdiratTrap    uintptr = syscall.SYS_MKDIRAT
+)
 
 const (
        AT_EACCESS          = 0x100
index 3b0c0dbd19cc46482b05c4818d4ca4e7b9cb4932..7672414cf7690efb8811d3334ec7157eae22dbd4 100644 (file)
@@ -6,9 +6,13 @@ package unix
 
 import "syscall"
 
-const unlinkatTrap uintptr = syscall.SYS_UNLINKAT
-const openatTrap uintptr = syscall.SYS_OPENAT
-const fstatatTrap uintptr = syscall.SYS_FSTATAT
+const (
+       unlinkatTrap   uintptr = syscall.SYS_UNLINKAT
+       openatTrap     uintptr = syscall.SYS_OPENAT
+       fstatatTrap    uintptr = syscall.SYS_FSTATAT
+       readlinkatTrap uintptr = syscall.SYS_READLINKAT
+       mkdiratTrap    uintptr = syscall.SYS_MKDIRAT
+)
 
 const (
        AT_EACCESS          = 0x1
index 3d47d7ebe0b641304cc276666bc6b7649439f2c3..5cce1030f10d03653d1fbe00ce6c2e3923ac6207 100644 (file)
@@ -2,8 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build wasip1
+
 package unix
 
+import (
+       "syscall"
+       "unsafe"
+)
+
 const (
        // UTIME_OMIT is the sentinel value to indicate that a time value should not
        // be changed. It is useful for example to indicate for example with UtimesNano
@@ -11,3 +18,46 @@ const (
        // Its value must match syscall/fs_wasip1.go
        UTIME_OMIT = -0x2
 )
+
+func Readlinkat(dirfd int, path string, buf []byte) (int, error) {
+       var nwritten size
+       errno := path_readlink(
+               int32(dirfd),
+               unsafe.Pointer(unsafe.StringData(path)),
+               size(len(path)),
+               unsafe.Pointer(&buf[0]),
+               size(len(buf)),
+               unsafe.Pointer(&nwritten))
+       return int(nwritten), errnoErr(errno)
+
+}
+
+type (
+       size = uint32
+)
+
+//go:wasmimport wasi_snapshot_preview1 path_readlink
+//go:noescape
+func path_readlink(fd int32, path unsafe.Pointer, pathLen size, buf unsafe.Pointer, bufLen size, nwritten unsafe.Pointer) syscall.Errno
+
+func Mkdirat(dirfd int, path string, mode uint32) error {
+       if path == "" {
+               return syscall.EINVAL
+       }
+       return errnoErr(path_create_directory(
+               int32(dirfd),
+               unsafe.Pointer(unsafe.StringData(path)),
+               size(len(path)),
+       ))
+}
+
+//go:wasmimport wasi_snapshot_preview1 path_create_directory
+//go:noescape
+func path_create_directory(fd int32, path unsafe.Pointer, pathLen size) syscall.Errno
+
+func errnoErr(errno syscall.Errno) error {
+       if errno == 0 {
+               return nil
+       }
+       return errno
+}
diff --git a/src/internal/syscall/unix/syscall.go b/src/internal/syscall/unix/syscall.go
new file mode 100644 (file)
index 0000000..99805d9
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+// Single-word zero for use when we need a valid pointer to 0 bytes.
+var _zero uintptr
index be048bcf734b4bd006035ddfdebf49392adcaf55..c83beef74906bf596a68fa2990aff01d8339ef25 100644 (file)
@@ -9,4 +9,5 @@ const (
        copyFileRangeTrap   uintptr = 377
        pidfdSendSignalTrap uintptr = 424
        pidfdOpenTrap       uintptr = 434
+       openat2Trap         uintptr = 437
 )
index 525de9cbd8c1a230078077c2c89dae7ddd601517..098e3320a0c7edb083bfdd5c20136b7203d164c6 100644 (file)
@@ -9,4 +9,5 @@ const (
        copyFileRangeTrap   uintptr = 326
        pidfdSendSignalTrap uintptr = 424
        pidfdOpenTrap       uintptr = 434
+       openat2Trap         uintptr = 437
 )
index b80389227868281b9e2a05ef718dbd7b3b2f13ee..f0cd45f9b004896fd369f91e924a26d0cfe0c633 100644 (file)
@@ -9,4 +9,5 @@ const (
        copyFileRangeTrap   uintptr = 391
        pidfdSendSignalTrap uintptr = 424
        pidfdOpenTrap       uintptr = 434
+       openat2Trap         uintptr = 437
 )
index b06bf6927312dd1450f9c0916d24d694faed6aa0..ec622cff0d6ef69ff08af5dab2888d795be70233 100644 (file)
@@ -15,4 +15,5 @@ const (
        copyFileRangeTrap   uintptr = 285
        pidfdSendSignalTrap uintptr = 424
        pidfdOpenTrap       uintptr = 434
+       openat2Trap         uintptr = 437
 )
index 8764f5dc8fcf7df6adbd922193de7cc685662b0e..3875105d7de02ee9fd94c0e7a2d766bf62a283c5 100644 (file)
@@ -11,4 +11,5 @@ const (
        copyFileRangeTrap   uintptr = 5320
        pidfdSendSignalTrap uintptr = 5424
        pidfdOpenTrap       uintptr = 5434
+       openat2Trap         uintptr = 5437
 )
index 9b2e587ba55fbd21b30ab5a94fa97a11c8ab3cfe..bdd2fef2c30881e54235b2a4bf469a7ec0f2b726 100644 (file)
@@ -11,4 +11,5 @@ const (
        copyFileRangeTrap   uintptr = 4360
        pidfdSendSignalTrap uintptr = 4424
        pidfdOpenTrap       uintptr = 4434
+       openat2Trap         uintptr = 4437
 )
index 03e9c197433e1b064c8f0f95c018b15e51a7dfb3..9291d58f5de9e0b31141001697a65aebf9c6dc7e 100644 (file)
@@ -11,4 +11,5 @@ const (
        copyFileRangeTrap   uintptr = 379
        pidfdSendSignalTrap uintptr = 424
        pidfdOpenTrap       uintptr = 434
+       openat2Trap         uintptr = 437
 )
index c6e3e02e46e36c1c4a31f259902ecc8e4f19e25f..65a82d1c3d63689595c5c1753571750b9ac3461c 100644 (file)
@@ -9,4 +9,5 @@ const (
        copyFileRangeTrap   uintptr = 375
        pidfdSendSignalTrap uintptr = 424
        pidfdOpenTrap       uintptr = 434
+       openat2Trap         uintptr = 437
 )