/
lookup_unix.go
85 lines (75 loc) · 2 KB
/
lookup_unix.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !cgo
package caps
import (
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"os/user"
"strings"
)
const (
fieldUsername = iota
fieldPassword
fieldUid
fieldGid
fieldGecos
fieldHomeDir
fieldShell
)
// EtcPasswdLookup looks up a user by username. If the user cannot be
// found, the returned error is of type user.UnknownUserError. This
// differs from os/user.Lookup by parsing /etc/password directly, so
// it doesn't need cgo support.
func EtcPasswdLookup(username string) (*user.User, error) {
usernamePrefix := []byte(username)
usernamePrefix = append(usernamePrefix, ':')
etcPasswd, err := ioutil.ReadFile("/etc/passwd")
if err != nil {
return nil, err
}
passwdReader := bufio.NewReader(bytes.NewReader(etcPasswd))
for {
l, isPrefix, err := passwdReader.ReadLine()
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
if isPrefix {
return nil, fmt.Errorf("passwd: line too long: '%s'", l)
}
if !bytes.HasPrefix(l, usernamePrefix) {
continue
}
fields := strings.Split(string(l), ":")
if len(fields) != 7 {
log.Printf("/etc/passwd: wrong num fields (%d): %s\n",
len(fields), string(l))
continue
}
// The pw_gecos field isn't standardized. Some docs
// say: "It is expected to be a comma separated list
// of personal data where the first item is the full
// name of the user."
fullName := strings.SplitN(fields[fieldGecos], ",", 2)[0]
return &user.User{
Uid: fields[fieldUid],
Gid: fields[fieldGid],
Username: fields[fieldUsername],
Name: fullName,
HomeDir: fields[fieldHomeDir],
}, nil
}
return nil, user.UnknownUserError(username)
}
// os/user.Lookup depends on cgo. When cgo is disabled (for static
// linking purposes), caps falls back to parsing /etc/passwd directly.
// Override this behavior as desired.
var Lookup = EtcPasswdLookup