Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1221)

Delta Between Two Patch Sets: src/pkg/os/user/lookup_unix.go

Issue 4440057: code review 4440057: os/user: new package to look up users (Closed)
Left Patch Set: diff -r c4b835aa75c1 https://go.googlecode.com/hg/ Created 13 years, 11 months ago
Right Patch Set: diff -r 76be0b3eee98 https://go.googlecode.com/hg/ Created 13 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/os/user/lookup_stubs.go ('k') | src/pkg/os/user/user.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package user 5 package user
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "os" 9 "os"
10 "runtime" 10 "runtime"
11 "strings" 11 "strings"
12 "unsafe" 12 "unsafe"
13 ) 13 )
14 14
15 /* 15 /*
16 #include <unistd.h> 16 #include <unistd.h>
17 #include <sys/types.h> 17 #include <sys/types.h>
18 #include <pwd.h> 18 #include <pwd.h>
19 #include <stdlib.h> 19 #include <stdlib.h>
20 20
21 static int mygetpwuid_r(int uid, struct passwd *pwd, 21 static int mygetpwuid_r(int uid, struct passwd *pwd,
22 char *buf, size_t buflen, struct passwd **result) { 22 char *buf, size_t buflen, struct passwd **result) {
23 return getpwuid_r(uid, pwd, buf, buflen, result); 23 return getpwuid_r(uid, pwd, buf, buflen, result);
24 } 24 }
25 */ 25 */
26 import "C" 26 import "C"
27 27
28 // LookupId looks up a user by username. If the user isn't found, 28 // Lookup looks up a user by username. If the user cannot be found,
r 2011/04/21 20:39:32 s/isn't/cannot be/ here and below
29 // os.ENOENT is returned. 29 // the returned error is of type UnknownUserError.
r 2011/04/21 20:39:32 is this overspecifying the error return? we usual
30 func Lookup(username string) (*User, os.Error) { 30 func Lookup(username string) (*User, os.Error) {
31 return lookup(-1, username, true) 31 return lookup(-1, username, true)
32 } 32 }
33 33
34 // LookupId looks up a user by userid. If the user isn't found, 34 // LookupId looks up a user by userid. If the user cannot be found,
35 // os.ENOENT is returned. 35 // the returned error is of type UnknownUserIdError.
36 func LookupId(uid int) (*User, os.Error) { 36 func LookupId(uid int) (*User, os.Error) {
37 return lookup(uid, "", false) 37 return lookup(uid, "", false)
38 } 38 }
39 39
40 func lookup(uid int, username string, lookupByName bool) (*User, os.Error) { 40 func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
41 var pwd C.struct_passwd 41 var pwd C.struct_passwd
42 var result *C.struct_passwd 42 var result *C.struct_passwd
43 43
44 var bufSize C.long 44 var bufSize C.long
45 if runtime.GOOS == "freebsd" { 45 if runtime.GOOS == "freebsd" {
46 // FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX 46 // FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX
47 // and just returns -1. So just use the same 47 // and just returns -1. So just use the same
48 // size that Linux returns 48 // size that Linux returns
49 bufSize = 1024 49 bufSize = 1024
50 } else { 50 } else {
51 bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX) 51 bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
52 » } 52 » » if bufSize <= 0 || bufSize > 1<<20 {
53 » if bufSize <= 0 || bufSize > 1<<20 { 53 » » » return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_S IZE_MAX of %d", bufSize)
r 2011/04/21 20:39:32 this test can go up a line
54 » » return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize) 54 » » }
55 } 55 }
56 buf := C.malloc(C.size_t(bufSize)) 56 buf := C.malloc(C.size_t(bufSize))
57 defer C.free(buf) 57 defer C.free(buf)
58 var rv C.int 58 var rv C.int
59 if lookupByName { 59 if lookupByName {
60 nameC := C.CString(username) 60 nameC := C.CString(username)
61 defer C.free(unsafe.Pointer(nameC)) 61 defer C.free(unsafe.Pointer(nameC))
62 rv = C.getpwnam_r(nameC, 62 rv = C.getpwnam_r(nameC,
63 &pwd, 63 &pwd,
64 (*C.char)(buf), 64 (*C.char)(buf),
65 C.size_t(bufSize), 65 C.size_t(bufSize),
66 &result) 66 &result)
67 if rv != 0 {
68 return nil, fmt.Errorf("user: lookup username %s: %s", u sername, os.Errno(rv))
69 }
70 if result == nil {
71 return nil, UnknownUserError(username)
72 }
67 } else { 73 } else {
68 // mygetpwuid_r is a wrapper around getpwuid_r to 74 // mygetpwuid_r is a wrapper around getpwuid_r to
69 // to avoid using uid_t because C.uid_t(uid) for 75 // to avoid using uid_t because C.uid_t(uid) for
70 // unknown reasons doesn't work on linux. 76 // unknown reasons doesn't work on linux.
71 rv = C.mygetpwuid_r(C.int(uid), 77 rv = C.mygetpwuid_r(C.int(uid),
72 &pwd, 78 &pwd,
73 (*C.char)(buf), 79 (*C.char)(buf),
74 C.size_t(bufSize), 80 C.size_t(bufSize),
75 &result) 81 &result)
76 » } 82 » » if rv != 0 {
77 » if rv != 0 { 83 » » » return nil, fmt.Errorf("user: lookup userid %d: %s", uid , os.Errno(rv))
78 » » return nil, fmt.Errorf("user: getpwuid_r returned %d", rv) 84 » » }
79 » } 85 » » if result == nil {
80 » if result == nil { 86 » » » return nil, UnknownUserIdError(uid)
81 » » return nil, os.ENOENT 87 » » }
82 } 88 }
83 u := &User{ 89 u := &User{
84 » » Uid: int(pwd.pw_uid), 90 » » Uid: int(pwd.pw_uid),
85 » » Gid: int(pwd.pw_gid), 91 » » Gid: int(pwd.pw_gid),
86 » » Username: C.GoString(pwd.pw_name), 92 » » Username: C.GoString(pwd.pw_name),
87 » » Name: C.GoString(pwd.pw_gecos), 93 » » Name: C.GoString(pwd.pw_gecos),
88 » » HomeDirectory: C.GoString(pwd.pw_dir), 94 » » HomeDir: C.GoString(pwd.pw_dir),
89 } 95 }
90 // The pw_gecos field isn't quite standardized. Some docs 96 // The pw_gecos field isn't quite standardized. Some docs
91 » // says: "It is expected to be a comma separated list of 97 » // say: "It is expected to be a comma separated list of
92 // personal data where the first item is the full name of the 98 // personal data where the first item is the full name of the
93 // user." 99 // user."
94 » if strings.Contains(u.Name, ",") { 100 » if i := strings.Index(u.Name, ","); i >= 0 {
95 » » sp := strings.Split(u.Name, ",", 2) 101 » » u.Name = u.Name[:i]
96 » » u.Name = sp[0]
97 } 102 }
98 return u, nil 103 return u, nil
99 } 104 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b