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.
5 // +build darwin freebsd linux
20 #include <sys/types.h>
24 static int mygetpwuid_r(int uid, struct passwd *pwd,
25 char *buf, size_t buflen, struct passwd **result) {
26 return getpwuid_r(uid, pwd, buf, buflen, result);
31 func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
34 func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
36 // bytePtrToString takes a NUL-terminated array of bytes and convert
38 func bytePtrToString(p *byte) string {
39 a := (*[10000]byte)(unsafe.Pointer(p))
47 // Current returns the current user.
48 func Current() (*User, error) {
49 return lookup(syscall.Getuid(), "", false)
52 // Lookup looks up a user by username. If the user cannot be found,
53 // the returned error is of type UnknownUserError.
54 func Lookup(username string) (*User, error) {
55 return lookup(-1, username, true)
58 // LookupId looks up a user by userid. If the user cannot be found,
59 // the returned error is of type UnknownUserIdError.
60 func LookupId(uid string) (*User, error) {
61 i, e := strconv.Atoi(uid)
65 return lookup(i, "", false)
68 func lookup(uid int, username string, lookupByName bool) (*User, error) {
69 var pwd syscall.Passwd
70 var result *syscall.Passwd
72 // FIXME: Should let buf grow if necessary.
74 buf := make([]byte, bufSize)
76 p := syscall.StringBytePtr(username)
77 syscall.Entersyscall()
78 rv := libc_getpwnam_r(p,
85 return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.GetErrno())
88 return nil, UnknownUserError(username)
91 syscall.Entersyscall()
92 rv := libc_getpwuid_r(syscall.Uid_t(uid),
99 return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.GetErrno())
102 return nil, UnknownUserIdError(uid)
106 Uid: strconv.Itoa(int(pwd.Pw_uid)),
107 Gid: strconv.Itoa(int(pwd.Pw_gid)),
108 Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
109 Name: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
110 HomeDir: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
112 // The pw_gecos field isn't quite standardized. Some docs
113 // say: "It is expected to be a comma separated list of
114 // personal data where the first item is the full name of the
116 if i := strings.Index(u.Name, ","); i >= 0 {