Rebase.
[official-gcc.git] / libgo / go / os / user / lookup_unix.go
blob0db08067201f5167067268d5d72ba3ef9579103e
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 dragonfly freebsd linux netbsd openbsd solaris
6 // +build cgo
8 package user
10 import (
11 "fmt"
12 "strconv"
13 "strings"
14 "syscall"
15 "unsafe"
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <pwd.h>
22 #include <stdlib.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);
30 // bytePtrToString takes a NUL-terminated array of bytes and convert
31 // it to a Go string.
32 func bytePtrToString(p *byte) string {
33 a := (*[10000]byte)(unsafe.Pointer(p))
34 i := 0
35 for a[i] != 0 {
36 i++
38 return string(a[:i])
41 func current() (*User, error) {
42 return lookupUnix(syscall.Getuid(), "", false)
45 func lookup(username string) (*User, error) {
46 return lookupUnix(-1, username, true)
49 func lookupId(uid string) (*User, error) {
50 i, e := strconv.Atoi(uid)
51 if e != nil {
52 return nil, e
54 return lookupUnix(i, "", false)
57 func lookupUnix(uid int, username string, lookupByName bool) (*User, error) {
58 var pwd syscall.Passwd
59 var result *syscall.Passwd
61 // FIXME: Should let buf grow if necessary.
62 const bufSize = 1024
63 buf := make([]byte, bufSize)
64 if lookupByName {
65 p := syscall.StringBytePtr(username)
66 syscall.Entersyscall()
67 rv := libc_getpwnam_r(p,
68 &pwd,
69 &buf[0],
70 bufSize,
71 &result)
72 syscall.Exitsyscall()
73 if rv != 0 {
74 return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.GetErrno())
76 if result == nil {
77 return nil, UnknownUserError(username)
79 } else {
80 syscall.Entersyscall()
81 rv := libc_getpwuid_r(syscall.Uid_t(uid),
82 &pwd,
83 &buf[0],
84 bufSize,
85 &result)
86 syscall.Exitsyscall()
87 if rv != 0 {
88 return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.GetErrno())
90 if result == nil {
91 return nil, UnknownUserIdError(uid)
94 u := &User{
95 Uid: strconv.Itoa(int(pwd.Pw_uid)),
96 Gid: strconv.Itoa(int(pwd.Pw_gid)),
97 Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
98 Name: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
99 HomeDir: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
101 // The pw_gecos field isn't quite standardized. Some docs
102 // say: "It is expected to be a comma separated list of
103 // personal data where the first item is the full name of the
104 // user."
105 if i := strings.Index(u.Name, ","); i >= 0 {
106 u.Name = u.Name[:i]
108 return u, nil