@@ -22,24 +22,36 @@ import (
22
22
#include <grp.h>
23
23
#include <stdlib.h>
24
24
25
- static int mygetpwuid_r(int uid, struct passwd *pwd,
26
- char *buf, size_t buflen, struct passwd **result) {
27
- return getpwuid_r(uid, pwd, buf, buflen, result);
25
+ static struct passwd mygetpwuid_r(int uid, char *buf, size_t buflen, int *found, int *perr) {
26
+ struct passwd pwd;
27
+ struct passwd *result;
28
+ *perr = getpwuid_r(uid, &pwd, buf, buflen, &result);
29
+ *found = result != NULL;
30
+ return pwd;
28
31
}
29
32
30
- static int mygetpwnam_r(const char *name, struct passwd *pwd,
31
- char *buf, size_t buflen, struct passwd **result) {
32
- return getpwnam_r(name, pwd, buf, buflen, result);
33
+ static struct passwd mygetpwnam_r(const char *name, char *buf, size_t buflen, int *found, int *perr) {
34
+ struct passwd pwd;
35
+ struct passwd *result;
36
+ *perr = getpwnam_r(name, &pwd, buf, buflen, &result);
37
+ *found = result != NULL;
38
+ return pwd;
33
39
}
34
40
35
- static int mygetgrgid_r(int gid, struct group *grp,
36
- char *buf, size_t buflen, struct group **result) {
37
- return getgrgid_r(gid, grp, buf, buflen, result);
41
+ static struct group mygetgrgid_r(int gid, char *buf, size_t buflen, int *found, int *perr) {
42
+ struct group grp;
43
+ struct group *result;
44
+ *perr = getgrgid_r(gid, &grp, buf, buflen, &result);
45
+ *found = result != NULL;
46
+ return grp;
38
47
}
39
48
40
- static int mygetgrnam_r(const char *name, struct group *grp,
41
- char *buf, size_t buflen, struct group **result) {
42
- return getgrnam_r(name, grp, buf, buflen, result);
49
+ static struct group mygetgrnam_r(const char *name, char *buf, size_t buflen, int *found, int *perr) {
50
+ struct group grp;
51
+ struct group *result;
52
+ *perr = getgrnam_r(name, &grp, buf, buflen, &result);
53
+ *found = result != NULL;
54
+ return grp;
43
55
}
44
56
*/
45
57
import "C"
@@ -50,28 +62,22 @@ func current() (*User, error) {
50
62
51
63
func lookupUser (username string ) (* User , error ) {
52
64
var pwd C.struct_passwd
53
- var result * C. struct_passwd
65
+ var found bool
54
66
nameC := make ([]byte , len (username )+ 1 )
55
67
copy (nameC , username )
56
68
57
- buf := alloc (userBuffer )
58
- defer buf .free ()
59
-
60
- err := retryWithBuffer (buf , func () syscall.Errno {
61
- // mygetpwnam_r is a wrapper around getpwnam_r to avoid
62
- // passing a size_t to getpwnam_r, because for unknown
63
- // reasons passing a size_t to getpwnam_r doesn't work on
64
- // Solaris.
65
- return syscall .Errno (C .mygetpwnam_r ((* C .char )(unsafe .Pointer (& nameC [0 ])),
66
- & pwd ,
67
- (* C .char )(buf .ptr ),
68
- C .size_t (buf .size ),
69
- & result ))
69
+ err := retryWithBuffer (userBuffer , func (buf []byte ) syscall.Errno {
70
+ var cfound , cerr C.int
71
+ pwd = C .mygetpwnam_r ((* C .char )(unsafe .Pointer (& nameC [0 ])),
72
+ (* C .char )(unsafe .Pointer (& buf [0 ])), C .size_t (len (buf )),
73
+ & cfound , & cerr )
74
+ found = cfound != 0
75
+ return syscall .Errno (cerr )
70
76
})
71
77
if err != nil {
72
78
return nil , fmt .Errorf ("user: lookup username %s: %v" , username , err )
73
79
}
74
- if result == nil {
80
+ if ! found {
75
81
return nil , UnknownUserError (username )
76
82
}
77
83
return buildUser (& pwd ), err
@@ -87,24 +93,20 @@ func lookupUserId(uid string) (*User, error) {
87
93
88
94
func lookupUnixUid (uid int ) (* User , error ) {
89
95
var pwd C.struct_passwd
90
- var result * C.struct_passwd
91
-
92
- buf := alloc (userBuffer )
93
- defer buf .free ()
94
-
95
- err := retryWithBuffer (buf , func () syscall.Errno {
96
- // mygetpwuid_r is a wrapper around getpwuid_r to avoid using uid_t
97
- // because C.uid_t(uid) for unknown reasons doesn't work on linux.
98
- return syscall .Errno (C .mygetpwuid_r (C .int (uid ),
99
- & pwd ,
100
- (* C .char )(buf .ptr ),
101
- C .size_t (buf .size ),
102
- & result ))
96
+ var found bool
97
+
98
+ err := retryWithBuffer (userBuffer , func (buf []byte ) syscall.Errno {
99
+ var cfound , cerr C.int
100
+ pwd = C .mygetpwuid_r (C .int (uid ),
101
+ (* C .char )(unsafe .Pointer (& buf [0 ])), C .size_t (len (buf )),
102
+ & cfound , & cerr )
103
+ found = cfound != 0
104
+ return syscall .Errno (cerr )
103
105
})
104
106
if err != nil {
105
107
return nil , fmt .Errorf ("user: lookup userid %d: %v" , uid , err )
106
108
}
107
- if result == nil {
109
+ if ! found {
108
110
return nil , UnknownUserIdError (uid )
109
111
}
110
112
return buildUser (& pwd ), nil
@@ -128,24 +130,23 @@ func buildUser(pwd *C.struct_passwd) *User {
128
130
129
131
func lookupGroup (groupname string ) (* Group , error ) {
130
132
var grp C.struct_group
131
- var result * C. struct_group
133
+ var found bool
132
134
133
- buf := alloc (groupBuffer )
134
- defer buf .free ()
135
135
cname := make ([]byte , len (groupname )+ 1 )
136
136
copy (cname , groupname )
137
137
138
- err := retryWithBuffer (buf , func () syscall.Errno {
139
- return syscall .Errno (C .mygetgrnam_r ((* C .char )(unsafe .Pointer (& cname [0 ])),
140
- & grp ,
141
- (* C .char )(buf .ptr ),
142
- C .size_t (buf .size ),
143
- & result ))
138
+ err := retryWithBuffer (groupBuffer , func (buf []byte ) syscall.Errno {
139
+ var cfound , cerr C.int
140
+ grp = C .mygetgrnam_r ((* C .char )(unsafe .Pointer (& cname [0 ])),
141
+ (* C .char )(unsafe .Pointer (& buf [0 ])), C .size_t (len (buf )),
142
+ & cfound , & cerr )
143
+ found = cfound != 0
144
+ return syscall .Errno (cerr )
144
145
})
145
146
if err != nil {
146
147
return nil , fmt .Errorf ("user: lookup groupname %s: %v" , groupname , err )
147
148
}
148
- if result == nil {
149
+ if ! found {
149
150
return nil , UnknownGroupError (groupname )
150
151
}
151
152
return buildGroup (& grp ), nil
@@ -161,24 +162,20 @@ func lookupGroupId(gid string) (*Group, error) {
161
162
162
163
func lookupUnixGid (gid int ) (* Group , error ) {
163
164
var grp C.struct_group
164
- var result * C.struct_group
165
-
166
- buf := alloc (groupBuffer )
167
- defer buf .free ()
168
-
169
- err := retryWithBuffer (buf , func () syscall.Errno {
170
- // mygetgrgid_r is a wrapper around getgrgid_r to avoid using gid_t
171
- // because C.gid_t(gid) for unknown reasons doesn't work on linux.
172
- return syscall .Errno (C .mygetgrgid_r (C .int (gid ),
173
- & grp ,
174
- (* C .char )(buf .ptr ),
175
- C .size_t (buf .size ),
176
- & result ))
165
+ var found bool
166
+
167
+ err := retryWithBuffer (groupBuffer , func (buf []byte ) syscall.Errno {
168
+ var cfound , cerr C.int
169
+ grp = C .mygetgrgid_r (C .int (gid ),
170
+ (* C .char )(unsafe .Pointer (& buf [0 ])), C .size_t (len (buf )),
171
+ & cfound , & cerr )
172
+ found = cfound != 0
173
+ return syscall .Errno (cerr )
177
174
})
178
175
if err != nil {
179
176
return nil , fmt .Errorf ("user: lookup groupid %d: %v" , gid , err )
180
177
}
181
- if result == nil {
178
+ if ! found {
182
179
return nil , UnknownGroupIdError (strconv .Itoa (gid ))
183
180
}
184
181
return buildGroup (& grp ), nil
@@ -214,44 +211,23 @@ func (k bufferKind) initialSize() C.size_t {
214
211
return C .size_t (sz )
215
212
}
216
213
217
- type memBuffer struct {
218
- ptr unsafe.Pointer
219
- size C.size_t
220
- }
221
-
222
- func alloc (kind bufferKind ) * memBuffer {
223
- sz := kind .initialSize ()
224
- return & memBuffer {
225
- ptr : C .malloc (sz ),
226
- size : sz ,
227
- }
228
- }
229
-
230
- func (mb * memBuffer ) resize (newSize C.size_t ) {
231
- mb .ptr = C .realloc (mb .ptr , newSize )
232
- mb .size = newSize
233
- }
234
-
235
- func (mb * memBuffer ) free () {
236
- C .free (mb .ptr )
237
- }
238
-
239
214
// retryWithBuffer repeatedly calls f(), increasing the size of the
240
215
// buffer each time, until f succeeds, fails with a non-ERANGE error,
241
216
// or the buffer exceeds a reasonable limit.
242
- func retryWithBuffer (buf * memBuffer , f func () syscall.Errno ) error {
217
+ func retryWithBuffer (startSize bufferKind , f func ([]byte ) syscall.Errno ) error {
218
+ buf := make ([]byte , startSize )
243
219
for {
244
- errno := f ()
220
+ errno := f (buf )
245
221
if errno == 0 {
246
222
return nil
247
223
} else if errno != syscall .ERANGE {
248
224
return errno
249
225
}
250
- newSize := buf . size * 2
226
+ newSize := len ( buf ) * 2
251
227
if ! isSizeReasonable (int64 (newSize )) {
252
228
return fmt .Errorf ("internal buffer exceeds %d bytes" , maxBufferSize )
253
229
}
254
- buf . resize ( newSize )
230
+ buf = make ([] byte , newSize )
255
231
}
256
232
}
257
233
0 commit comments