groups_unix.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package continuity
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. // TODO(stevvooe): This needs a lot of work before we can call it useful.
  11. type groupIndex struct {
  12. byName map[string]*group
  13. byGID map[int]*group
  14. }
  15. func getGroupIndex() (*groupIndex, error) {
  16. f, err := os.Open("/etc/group")
  17. if err != nil {
  18. return nil, err
  19. }
  20. defer f.Close()
  21. groups, err := parseGroups(f)
  22. if err != nil {
  23. return nil, err
  24. }
  25. return newGroupIndex(groups), nil
  26. }
  27. func newGroupIndex(groups []group) *groupIndex {
  28. gi := &groupIndex{
  29. byName: make(map[string]*group),
  30. byGID: make(map[int]*group),
  31. }
  32. for i, group := range groups {
  33. gi.byGID[group.gid] = &groups[i]
  34. gi.byName[group.name] = &groups[i]
  35. }
  36. return gi
  37. }
  38. type group struct {
  39. name string
  40. gid int
  41. members []string
  42. }
  43. func getGroupName(gid int) (string, error) {
  44. f, err := os.Open("/etc/group")
  45. if err != nil {
  46. return "", err
  47. }
  48. defer f.Close()
  49. groups, err := parseGroups(f)
  50. if err != nil {
  51. return "", err
  52. }
  53. for _, group := range groups {
  54. if group.gid == gid {
  55. return group.name, nil
  56. }
  57. }
  58. return "", fmt.Errorf("no group for gid")
  59. }
  60. // parseGroups parses an /etc/group file for group names, ids and membership.
  61. // This is unix specific.
  62. func parseGroups(rd io.Reader) ([]group, error) {
  63. var groups []group
  64. scanner := bufio.NewScanner(rd)
  65. for scanner.Scan() {
  66. if strings.HasPrefix(scanner.Text(), "#") {
  67. continue // skip comment
  68. }
  69. parts := strings.SplitN(scanner.Text(), ":", 4)
  70. if len(parts) != 4 {
  71. return nil, fmt.Errorf("bad entry: %q", scanner.Text())
  72. }
  73. name, _, sgid, smembers := parts[0], parts[1], parts[2], parts[3]
  74. gid, err := strconv.Atoi(sgid)
  75. if err != nil {
  76. return nil, fmt.Errorf("bad gid: %q", gid)
  77. }
  78. members := strings.Split(smembers, ",")
  79. groups = append(groups, group{
  80. name: name,
  81. gid: gid,
  82. members: members,
  83. })
  84. }
  85. if scanner.Err() != nil {
  86. return nil, scanner.Err()
  87. }
  88. return groups, nil
  89. }