mirror of
https://github.com/vbatts/go-mtree.git
synced 2024-11-25 17:45:39 +00:00
Merge pull request #129 from vbatts/fix_gname
keyword: add missing `gname` keyword functions
This commit is contained in:
commit
abdee6fe11
6 changed files with 142 additions and 0 deletions
|
@ -34,6 +34,7 @@ var (
|
||||||
"gid": gidKeywordFunc, // The file group as a numeric value
|
"gid": gidKeywordFunc, // The file group as a numeric value
|
||||||
"nlink": nlinkKeywordFunc, // The number of hard links the file is expected to have
|
"nlink": nlinkKeywordFunc, // The number of hard links the file is expected to have
|
||||||
"uname": unameKeywordFunc, // The file owner as a symbolic name
|
"uname": unameKeywordFunc, // The file owner as a symbolic name
|
||||||
|
"gname": gnameKeywordFunc, // The file group as a symbolic name
|
||||||
"mode": modeKeywordFunc, // The current file's permissions as a numeric (octal) or symbolic value
|
"mode": modeKeywordFunc, // The current file's permissions as a numeric (octal) or symbolic value
|
||||||
"cksum": cksumKeywordFunc, // The checksum of the file using the default algorithm specified by the cksum(1) utility
|
"cksum": cksumKeywordFunc, // The checksum of the file using the default algorithm specified by the cksum(1) utility
|
||||||
"md5": hasherKeywordFunc("md5digest", md5.New), // The MD5 message digest of the file
|
"md5": hasherKeywordFunc("md5digest", md5.New), // The MD5 message digest of the file
|
||||||
|
|
|
@ -29,6 +29,18 @@ var (
|
||||||
}
|
}
|
||||||
return KeyVal(fmt.Sprintf("uname=%s", u.Username)), nil
|
return KeyVal(fmt.Sprintf("uname=%s", u.Username)), nil
|
||||||
}
|
}
|
||||||
|
gnameKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (KeyVal, error) {
|
||||||
|
if hdr, ok := info.Sys().(*tar.Header); ok {
|
||||||
|
return KeyVal(fmt.Sprintf("gname=%s", hdr.Gname)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
stat := info.Sys().(*syscall.Stat_t)
|
||||||
|
g, err := lookupGroupID(fmt.Sprintf("%d", stat.Gid))
|
||||||
|
if err != nil {
|
||||||
|
return emptyKV, err
|
||||||
|
}
|
||||||
|
return KeyVal(fmt.Sprintf("gname=%s", g.Name)), nil
|
||||||
|
}
|
||||||
uidKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (KeyVal, error) {
|
uidKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (KeyVal, error) {
|
||||||
if hdr, ok := info.Sys().(*tar.Header); ok {
|
if hdr, ok := info.Sys().(*tar.Header); ok {
|
||||||
return KeyVal(fmt.Sprintf("uid=%d", hdr.Uid)), nil
|
return KeyVal(fmt.Sprintf("uid=%d", hdr.Uid)), nil
|
|
@ -34,6 +34,18 @@ var (
|
||||||
}
|
}
|
||||||
return KeyVal(fmt.Sprintf("uname=%s", u.Username)), nil
|
return KeyVal(fmt.Sprintf("uname=%s", u.Username)), nil
|
||||||
}
|
}
|
||||||
|
gnameKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (KeyVal, error) {
|
||||||
|
if hdr, ok := info.Sys().(*tar.Header); ok {
|
||||||
|
return KeyVal(fmt.Sprintf("gname=%s", hdr.Gname)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
stat := info.Sys().(*syscall.Stat_t)
|
||||||
|
g, err := lookupGroupID(fmt.Sprintf("%d", stat.Gid))
|
||||||
|
if err != nil {
|
||||||
|
return emptyKV, err
|
||||||
|
}
|
||||||
|
return KeyVal(fmt.Sprintf("gname=%s", g.Name)), nil
|
||||||
|
}
|
||||||
uidKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (KeyVal, error) {
|
uidKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (KeyVal, error) {
|
||||||
if hdr, ok := info.Sys().(*tar.Header); ok {
|
if hdr, ok := info.Sys().(*tar.Header); ok {
|
||||||
return KeyVal(fmt.Sprintf("uid=%d", hdr.Uid)), nil
|
return KeyVal(fmt.Sprintf("uid=%d", hdr.Uid)), nil
|
||||||
|
|
|
@ -20,6 +20,12 @@ var (
|
||||||
}
|
}
|
||||||
return emptyKV, nil
|
return emptyKV, nil
|
||||||
}
|
}
|
||||||
|
gnameKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (KeyVal, error) {
|
||||||
|
if hdr, ok := info.Sys().(*tar.Header); ok {
|
||||||
|
return KeyVal(fmt.Sprintf("gname=%s", hdr.Gname)), nil
|
||||||
|
}
|
||||||
|
return emptyKV, nil
|
||||||
|
}
|
||||||
uidKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (KeyVal, error) {
|
uidKeywordFunc = func(path string, info os.FileInfo, r io.Reader) (KeyVal, error) {
|
||||||
if hdr, ok := info.Sys().(*tar.Header); ok {
|
if hdr, ok := info.Sys().(*tar.Header); ok {
|
||||||
return KeyVal(fmt.Sprintf("uid=%d", hdr.Uid)), nil
|
return KeyVal(fmt.Sprintf("uid=%d", hdr.Uid)), nil
|
||||||
|
|
9
lookup_new.go
Normal file
9
lookup_new.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package mtree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
var lookupGroupID = user.LookupGroupId
|
102
lookup_old.go
Normal file
102
lookup_old.go
Normal file
|
@ -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)
|
||||||
|
}
|
Loading…
Reference in a new issue