-
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lookupGroupId: add implementation for go1.6
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
- Loading branch information
Showing
4 changed files
with
113 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// +build go1.7 | ||
|
||
package mtree | ||
|
||
import ( | ||
"os/user" | ||
) | ||
|
||
var lookupGroupID = user.LookupGroupId |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// +build !go1.7 | ||
|
||
package mtree | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"io" | ||
"os" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
const groupFile = "/etc/group" | ||
|
||
var colon = []byte{':'} | ||
|
||
// Group represents a grouping of users. | ||
// | ||
// On POSIX systems Gid contains a decimal number representing the group ID. | ||
type Group struct { | ||
Gid string // group ID | ||
Name string // group name | ||
} | ||
|
||
func lookupGroupID(id string) (*Group, error) { | ||
f, err := os.Open(groupFile) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer f.Close() | ||
return findGroupID(id, f) | ||
} | ||
|
||
func findGroupID(id string, r io.Reader) (*Group, error) { | ||
if v, err := readColonFile(r, matchGroupIndexValue(id, 2)); err != nil { | ||
return nil, err | ||
} else if v != nil { | ||
return v.(*Group), nil | ||
} | ||
return nil, UnknownGroupIDError(id) | ||
} | ||
|
||
// lineFunc returns a value, an error, or (nil, nil) to skip the row. | ||
type lineFunc func(line []byte) (v interface{}, err error) | ||
|
||
// readColonFile parses r as an /etc/group or /etc/passwd style file, running | ||
// fn for each row. readColonFile returns a value, an error, or (nil, nil) if | ||
// the end of the file is reached without a match. | ||
func readColonFile(r io.Reader, fn lineFunc) (v interface{}, err error) { | ||
bs := bufio.NewScanner(r) | ||
for bs.Scan() { | ||
line := bs.Bytes() | ||
// There's no spec for /etc/passwd or /etc/group, but we try to follow | ||
// the same rules as the glibc parser, which allows comments and blank | ||
// space at the beginning of a line. | ||
line = bytes.TrimSpace(line) | ||
if len(line) == 0 || line[0] == '#' { | ||
continue | ||
} | ||
v, err = fn(line) | ||
if v != nil || err != nil { | ||
return | ||
} | ||
} | ||
return nil, bs.Err() | ||
} | ||
|
||
func matchGroupIndexValue(value string, idx int) lineFunc { | ||
var leadColon string | ||
if idx > 0 { | ||
leadColon = ":" | ||
} | ||
substr := []byte(leadColon + value + ":") | ||
return func(line []byte) (v interface{}, err error) { | ||
if !bytes.Contains(line, substr) || bytes.Count(line, colon) < 3 { | ||
return | ||
} | ||
// wheel:*:0:root | ||
parts := strings.SplitN(string(line), ":", 4) | ||
if len(parts) < 4 || parts[0] == "" || parts[idx] != value || | ||
// If the file contains +foo and you search for "foo", glibc | ||
// returns an "invalid argument" error. Similarly, if you search | ||
// for a gid for a row where the group name starts with "+" or "-", | ||
// glibc fails to find the record. | ||
parts[0][0] == '+' || parts[0][0] == '-' { | ||
return | ||
} | ||
if _, err := strconv.Atoi(parts[2]); err != nil { | ||
return nil, nil | ||
} | ||
return &Group{Name: parts[0], Gid: parts[2]}, nil | ||
} | ||
} | ||
|
||
// UnknownGroupIDError is returned by LookupGroupId when | ||
// a group cannot be found. | ||
type UnknownGroupIDError string | ||
|
||
func (e UnknownGroupIDError) Error() string { | ||
return "group: unknown groupid " + string(e) | ||
} |