Skip to content

Commit 185766d

Browse files
rscgopherbot
authored andcommitted
os/user: use libc (not cgo) on macOS
With net converted to libc, os/user is the last remaining cgo code in the standard libary on macOS. Convert it to libc too. Now only plugin remains as a cgo-using package on macOS. Change-Id: Ibb518b5c62ef9ec1e6ab6191f4b576f7c5a4501c Reviewed-on: https://go-review.googlesource.com/c/go/+/449316 Reviewed-by: Ian Lance Taylor <[email protected]> Auto-Submit: Russ Cox <[email protected]> Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent d62f8d5 commit 185766d

17 files changed

+407
-227
lines changed

src/internal/syscall/unix/asm_darwin.s

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,21 @@
44

55
#include "textflag.h"
66

7-
TEXT ·libc_getentropy_trampoline(SB),NOSPLIT,$0-0
8-
JMP libc_getentropy(SB)
9-
10-
TEXT ·libc_getaddrinfo_trampoline(SB),NOSPLIT,$0-0
11-
JMP libc_getaddrinfo(SB)
12-
13-
TEXT ·libc_freeaddrinfo_trampoline(SB),NOSPLIT,$0-0
14-
JMP libc_freeaddrinfo(SB)
15-
16-
TEXT ·libc_getnameinfo_trampoline(SB),NOSPLIT,$0-0
17-
JMP libc_getnameinfo(SB)
18-
19-
TEXT ·libc_gai_strerror_trampoline(SB),NOSPLIT,$0-0
20-
JMP libc_gai_strerror(SB)
21-
22-
TEXT ·libresolv_res_9_ninit_trampoline(SB),NOSPLIT,$0-0
23-
JMP libresolv_res_9_ninit(SB)
24-
25-
TEXT ·libresolv_res_9_nclose_trampoline(SB),NOSPLIT,$0-0
26-
JMP libresolv_res_9_nclose(SB)
27-
28-
TEXT ·libresolv_res_9_nsearch_trampoline(SB),NOSPLIT,$0-0
29-
JMP libresolv_res_9_nsearch(SB)
30-
31-
TEXT ·libc_grantpt_trampoline(SB),NOSPLIT,$0-0
32-
JMP libc_grantpt(SB)
33-
34-
TEXT ·libc_unlockpt_trampoline(SB),NOSPLIT,$0-0
35-
JMP libc_unlockpt(SB)
36-
37-
TEXT ·libc_ptsname_r_trampoline(SB),NOSPLIT,$0-0
38-
JMP libc_ptsname_r(SB)
39-
40-
TEXT ·libc_posix_openpt_trampoline(SB),NOSPLIT,$0-0
41-
JMP libc_posix_openpt(SB)
7+
TEXT ·libc_getentropy_trampoline(SB),NOSPLIT,$0-0; JMP libc_getentropy(SB)
8+
TEXT ·libc_getaddrinfo_trampoline(SB),NOSPLIT,$0-0; JMP libc_getaddrinfo(SB)
9+
TEXT ·libc_freeaddrinfo_trampoline(SB),NOSPLIT,$0-0; JMP libc_freeaddrinfo(SB)
10+
TEXT ·libc_getnameinfo_trampoline(SB),NOSPLIT,$0-0; JMP libc_getnameinfo(SB)
11+
TEXT ·libc_gai_strerror_trampoline(SB),NOSPLIT,$0-0; JMP libc_gai_strerror(SB)
12+
TEXT ·libresolv_res_9_ninit_trampoline(SB),NOSPLIT,$0-0; JMP libresolv_res_9_ninit(SB)
13+
TEXT ·libresolv_res_9_nclose_trampoline(SB),NOSPLIT,$0-0; JMP libresolv_res_9_nclose(SB)
14+
TEXT ·libresolv_res_9_nsearch_trampoline(SB),NOSPLIT,$0-0; JMP libresolv_res_9_nsearch(SB)
15+
TEXT ·libc_grantpt_trampoline(SB),NOSPLIT,$0-0; JMP libc_grantpt(SB)
16+
TEXT ·libc_unlockpt_trampoline(SB),NOSPLIT,$0-0; JMP libc_unlockpt(SB)
17+
TEXT ·libc_ptsname_r_trampoline(SB),NOSPLIT,$0-0; JMP libc_ptsname_r(SB)
18+
TEXT ·libc_posix_openpt_trampoline(SB),NOSPLIT,$0-0; JMP libc_posix_openpt(SB)
19+
TEXT ·libc_getgrouplist_trampoline(SB),NOSPLIT,$0-0; JMP libc_getgrouplist(SB)
20+
TEXT ·libc_getpwnam_r_trampoline(SB),NOSPLIT,$0-0; JMP libc_getpwnam_r(SB)
21+
TEXT ·libc_getpwuid_r_trampoline(SB),NOSPLIT,$0-0; JMP libc_getpwuid_r(SB)
22+
TEXT ·libc_getgrnam_r_trampoline(SB),NOSPLIT,$0-0; JMP libc_getgrnam_r(SB)
23+
TEXT ·libc_getgrgid_r_trampoline(SB),NOSPLIT,$0-0; JMP libc_getgrgid_r(SB)
24+
TEXT ·libc_sysconf_trampoline(SB),NOSPLIT,$0-0; JMP libc_sysconf(SB)

src/internal/syscall/unix/net_darwin.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,15 @@ func GoString(p *byte) string {
111111
//go:linkname syscall_syscall syscall.syscall
112112
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
113113

114+
//go:linkname syscall_syscallPtr syscall.syscallPtr
115+
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
116+
114117
//go:linkname syscall_syscall6 syscall.syscall6
115118
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
116119

120+
//go:linkname syscall_syscall6X syscall.syscall6X
121+
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
122+
117123
//go:linkname syscall_syscall9 syscall.syscall9
118124
func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
119125

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package unix
6+
7+
import (
8+
"internal/abi"
9+
"syscall"
10+
"unsafe"
11+
)
12+
13+
//go:cgo_import_dynamic libc_getgrouplist getgrouplist "/usr/lib/libSystem.B.dylib"
14+
func libc_getgrouplist_trampoline()
15+
16+
func Getgrouplist(name *byte, gid uint32, gids *uint32, n *int32) error {
17+
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getgrouplist_trampoline),
18+
uintptr(unsafe.Pointer(name)), uintptr(gid), uintptr(unsafe.Pointer(gids)),
19+
uintptr(unsafe.Pointer(n)), 0, 0)
20+
if errno != 0 {
21+
return errno
22+
}
23+
return nil
24+
}
25+
26+
const (
27+
SC_GETGR_R_SIZE_MAX = 0x46
28+
SC_GETPW_R_SIZE_MAX = 0x47
29+
)
30+
31+
type Passwd struct {
32+
Name *byte
33+
Passwd *byte
34+
Uid uint32 // uid_t
35+
Gid uint32 // gid_t
36+
Change int64 // time_t
37+
Class *byte
38+
Gecos *byte
39+
Dir *byte
40+
Shell *byte
41+
Expire int64 // time_t
42+
}
43+
44+
type Group struct {
45+
Name *byte
46+
Passwd *byte
47+
Gid uint32 // gid_t
48+
Mem **byte
49+
}
50+
51+
//go:cgo_import_dynamic libc_getpwnam_r getpwnam_r "/usr/lib/libSystem.B.dylib"
52+
func libc_getpwnam_r_trampoline()
53+
54+
func Getpwnam(name *byte, pwd *Passwd, buf *byte, size uintptr, result **Passwd) syscall.Errno {
55+
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getpwnam_r_trampoline),
56+
uintptr(unsafe.Pointer(name)),
57+
uintptr(unsafe.Pointer(pwd)),
58+
uintptr(unsafe.Pointer(buf)),
59+
size,
60+
uintptr(unsafe.Pointer(result)),
61+
0)
62+
return errno
63+
}
64+
65+
//go:cgo_import_dynamic libc_getpwuid_r getpwuid_r "/usr/lib/libSystem.B.dylib"
66+
func libc_getpwuid_r_trampoline()
67+
68+
func Getpwuid(uid uint32, pwd *Passwd, buf *byte, size uintptr, result **Passwd) syscall.Errno {
69+
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getpwuid_r_trampoline),
70+
uintptr(uid),
71+
uintptr(unsafe.Pointer(pwd)),
72+
uintptr(unsafe.Pointer(buf)),
73+
size,
74+
uintptr(unsafe.Pointer(result)),
75+
0)
76+
return errno
77+
}
78+
79+
//go:cgo_import_dynamic libc_getgrnam_r getgrnam_r "/usr/lib/libSystem.B.dylib"
80+
func libc_getgrnam_r_trampoline()
81+
82+
func Getgrnam(name *byte, grp *Group, buf *byte, size uintptr, result **Group) syscall.Errno {
83+
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getgrnam_r_trampoline),
84+
uintptr(unsafe.Pointer(name)),
85+
uintptr(unsafe.Pointer(grp)),
86+
uintptr(unsafe.Pointer(buf)),
87+
size,
88+
uintptr(unsafe.Pointer(result)),
89+
0)
90+
return errno
91+
}
92+
93+
//go:cgo_import_dynamic libc_getgrgid_r getgrgid_r "/usr/lib/libSystem.B.dylib"
94+
func libc_getgrgid_r_trampoline()
95+
96+
func Getgrgid(gid uint32, grp *Group, buf *byte, size uintptr, result **Group) syscall.Errno {
97+
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getgrgid_r_trampoline),
98+
uintptr(gid),
99+
uintptr(unsafe.Pointer(grp)),
100+
uintptr(unsafe.Pointer(buf)),
101+
size,
102+
uintptr(unsafe.Pointer(result)),
103+
0)
104+
return errno
105+
}
106+
107+
//go:cgo_import_dynamic libc_sysconf sysconf "/usr/lib/libSystem.B.dylib"
108+
func libc_sysconf_trampoline()
109+
110+
func Sysconf(key int32) int64 {
111+
val, _, errno := syscall_syscall6X(abi.FuncPCABI0(libc_sysconf_trampoline),
112+
uintptr(key), 0, 0, 0, 0, 0)
113+
if errno != 0 {
114+
return -1
115+
}
116+
return int64(val)
117+
}

src/os/user/cgo_listgroups_unix.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
//go:build (dragonfly || darwin || freebsd || (!android && linux) || netbsd || openbsd || (solaris && !illumos)) && cgo && !osusergo
5+
//go:build (cgo || darwin) && !osusergo && (darwin || dragonfly || freebsd || (linux && !android) || netbsd || openbsd || (solaris && !illumos))
66

77
package user
88

@@ -12,26 +12,20 @@ import (
1212
"unsafe"
1313
)
1414

15-
/*
16-
#include <unistd.h>
17-
#include <sys/types.h>
18-
*/
19-
import "C"
20-
2115
const maxGroups = 2048
2216

2317
func listGroups(u *User) ([]string, error) {
2418
ug, err := strconv.Atoi(u.Gid)
2519
if err != nil {
2620
return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid)
2721
}
28-
userGID := C.gid_t(ug)
22+
userGID := _C_gid_t(ug)
2923
nameC := make([]byte, len(u.Username)+1)
3024
copy(nameC, u.Username)
3125

32-
n := C.int(256)
33-
gidsC := make([]C.gid_t, n)
34-
rv := getGroupList((*C.char)(unsafe.Pointer(&nameC[0])), userGID, &gidsC[0], &n)
26+
n := _C_int(256)
27+
gidsC := make([]_C_gid_t, n)
28+
rv := getGroupList((*_C_char)(unsafe.Pointer(&nameC[0])), userGID, &gidsC[0], &n)
3529
if rv == -1 {
3630
// Mac is the only Unix that does not set n properly when rv == -1, so
3731
// we need to use different logic for Mac vs. the other OS's.
@@ -46,3 +40,18 @@ func listGroups(u *User) ([]string, error) {
4640
}
4741
return gids, nil
4842
}
43+
44+
// groupRetry retries getGroupList with much larger size for n. The result is
45+
// stored in gids.
46+
func groupRetry(username string, name []byte, userGID _C_gid_t, gids *[]_C_gid_t, n *_C_int) error {
47+
// More than initial buffer, but now n contains the correct size.
48+
if *n > maxGroups {
49+
return fmt.Errorf("user: %q is a member of more than %d groups", username, maxGroups)
50+
}
51+
*gids = make([]_C_gid_t, *n)
52+
rv := getGroupList((*_C_char)(unsafe.Pointer(&name[0])), userGID, &(*gids)[0], n)
53+
if rv == -1 {
54+
return fmt.Errorf("user: list groups for %s failed", username)
55+
}
56+
return nil
57+
}

src/os/user/cgo_lookup_cgo.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright 2011 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build cgo && !osusergo && unix && !android && !darwin
6+
7+
package user
8+
9+
import (
10+
"syscall"
11+
)
12+
13+
/*
14+
#cgo solaris CFLAGS: -D_POSIX_PTHREAD_SEMANTICS
15+
#include <unistd.h>
16+
#include <sys/types.h>
17+
#include <pwd.h>
18+
#include <grp.h>
19+
#include <stdlib.h>
20+
21+
static struct passwd mygetpwuid_r(int uid, char *buf, size_t buflen, int *found, int *perr) {
22+
struct passwd pwd;
23+
struct passwd *result;
24+
*perr = getpwuid_r(uid, &pwd, buf, buflen, &result);
25+
*found = result != NULL;
26+
return pwd;
27+
}
28+
29+
static struct passwd mygetpwnam_r(const char *name, char *buf, size_t buflen, int *found, int *perr) {
30+
struct passwd pwd;
31+
struct passwd *result;
32+
*perr = getpwnam_r(name, &pwd, buf, buflen, &result);
33+
*found = result != NULL;
34+
return pwd;
35+
}
36+
37+
static struct group mygetgrgid_r(int gid, char *buf, size_t buflen, int *found, int *perr) {
38+
struct group grp;
39+
struct group *result;
40+
*perr = getgrgid_r(gid, &grp, buf, buflen, &result);
41+
*found = result != NULL;
42+
return grp;
43+
}
44+
45+
static struct group mygetgrnam_r(const char *name, char *buf, size_t buflen, int *found, int *perr) {
46+
struct group grp;
47+
struct group *result;
48+
*perr = getgrnam_r(name, &grp, buf, buflen, &result);
49+
*found = result != NULL;
50+
return grp;
51+
}
52+
*/
53+
import "C"
54+
55+
type _C_char = C.char
56+
type _C_int = C.int
57+
type _C_gid_t = C.gid_t
58+
type _C_uid_t = C.uid_t
59+
type _C_size_t = C.size_t
60+
type _C_struct_group = C.struct_group
61+
type _C_struct_passwd = C.struct_passwd
62+
type _C_long = C.long
63+
64+
func _C_pw_uid(p *_C_struct_passwd) _C_uid_t { return p.pw_uid }
65+
func _C_pw_uidp(p *_C_struct_passwd) *_C_uid_t { return &p.pw_uid }
66+
func _C_pw_gid(p *_C_struct_passwd) _C_gid_t { return p.pw_gid }
67+
func _C_pw_gidp(p *_C_struct_passwd) *_C_gid_t { return &p.pw_gid }
68+
func _C_pw_name(p *_C_struct_passwd) *_C_char { return p.pw_name }
69+
func _C_pw_gecos(p *_C_struct_passwd) *_C_char { return p.pw_gecos }
70+
func _C_pw_dir(p *_C_struct_passwd) *_C_char { return p.pw_dir }
71+
72+
func _C_gr_gid(g *_C_struct_group) _C_gid_t { return g.gr_gid }
73+
func _C_gr_name(g *_C_struct_group) *_C_char { return g.gr_name }
74+
75+
func _C_GoString(p *_C_char) string { return C.GoString(p) }
76+
77+
func _C_getpwnam_r(name *_C_char, buf *_C_char, size _C_size_t) (pwd _C_struct_passwd, found bool, errno syscall.Errno) {
78+
var f, e _C_int
79+
pwd = C.mygetpwnam_r(name, buf, size, &f, &e)
80+
return pwd, f != 0, syscall.Errno(e)
81+
}
82+
83+
func _C_getpwuid_r(uid _C_uid_t, buf *_C_char, size _C_size_t) (pwd _C_struct_passwd, found bool, errno syscall.Errno) {
84+
var f, e _C_int
85+
pwd = C.mygetpwuid_r(_C_int(uid), buf, size, &f, &e)
86+
return pwd, f != 0, syscall.Errno(e)
87+
}
88+
89+
func _C_getgrnam_r(name *_C_char, buf *_C_char, size _C_size_t) (grp _C_struct_group, found bool, errno syscall.Errno) {
90+
var f, e _C_int
91+
grp = C.mygetgrnam_r(name, buf, size, &f, &e)
92+
return grp, f != 0, syscall.Errno(e)
93+
}
94+
95+
func _C_getgrgid_r(gid _C_gid_t, buf *_C_char, size _C_size_t) (grp _C_struct_group, found bool, errno syscall.Errno) {
96+
var f, e _C_int
97+
grp = C.mygetgrgid_r(_C_int(gid), buf, size, &f, &e)
98+
return grp, f != 0, syscall.Errno(e)
99+
}
100+
101+
const (
102+
_C__SC_GETPW_R_SIZE_MAX = C._SC_GETPW_R_SIZE_MAX
103+
_C__SC_GETGR_R_SIZE_MAX = C._SC_GETGR_R_SIZE_MAX
104+
)
105+
106+
func _C_sysconf(key _C_int) _C_long { return C.sysconf(key) }

0 commit comments

Comments
 (0)