github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/go/os/user/lookup_unix.go (about) 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 // +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris 6 // +build cgo 7 8 package user 9 10 import ( 11 "fmt" 12 "strconv" 13 "strings" 14 "syscall" 15 "unsafe" 16 ) 17 18 /* 19 #cgo solaris CFLAGS: -D_POSIX_PTHREAD_SEMANTICS 20 #include <unistd.h> 21 #include <sys/types.h> 22 #include <pwd.h> 23 #include <stdlib.h> 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); 28 } 29 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 } 34 */ 35 36 // bytePtrToString takes a NUL-terminated array of bytes and convert 37 // it to a Go string. 38 func bytePtrToString(p *byte) string { 39 a := (*[10000]byte)(unsafe.Pointer(p)) 40 i := 0 41 for a[i] != 0 { 42 i++ 43 } 44 return string(a[:i]) 45 } 46 47 func current() (*User, error) { 48 return lookupUnix(syscall.Getuid(), "", false) 49 } 50 51 func lookup(username string) (*User, error) { 52 return lookupUnix(-1, username, true) 53 } 54 55 func lookupId(uid string) (*User, error) { 56 i, e := strconv.Atoi(uid) 57 if e != nil { 58 return nil, e 59 } 60 return lookupUnix(i, "", false) 61 } 62 63 func lookupUnix(uid int, username string, lookupByName bool) (*User, error) { 64 var pwd syscall.Passwd 65 var result *syscall.Passwd 66 67 // FIXME: Should let buf grow if necessary. 68 const bufSize = 1024 69 buf := make([]byte, bufSize) 70 if lookupByName { 71 nameC := syscall.StringBytePtr(username) 72 syscall.Entersyscall() 73 rv := libc_getpwnam_r(nameC, 74 &pwd, 75 &buf[0], 76 bufSize, 77 &result) 78 syscall.Exitsyscall() 79 if rv != 0 { 80 return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.GetErrno()) 81 } 82 if result == nil { 83 return nil, UnknownUserError(username) 84 } 85 } else { 86 syscall.Entersyscall() 87 rv := libc_getpwuid_r(syscall.Uid_t(uid), 88 &pwd, 89 &buf[0], 90 bufSize, 91 &result) 92 syscall.Exitsyscall() 93 if rv != 0 { 94 return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.GetErrno()) 95 } 96 if result == nil { 97 return nil, UnknownUserIdError(uid) 98 } 99 } 100 u := &User{ 101 Uid: strconv.Itoa(int(pwd.Pw_uid)), 102 Gid: strconv.Itoa(int(pwd.Pw_gid)), 103 Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))), 104 Name: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))), 105 HomeDir: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))), 106 } 107 // The pw_gecos field isn't quite standardized. Some docs 108 // say: "It is expected to be a comma separated list of 109 // personal data where the first item is the full name of the 110 // user." 111 if i := strings.Index(u.Name, ","); i >= 0 { 112 u.Name = u.Name[:i] 113 } 114 return u, nil 115 }