passwd.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Package passwd parsed content and files in form of /etc/passwd
  2. package passwd
  3. import (
  4. "bufio"
  5. "errors"
  6. "io"
  7. "os"
  8. "strings"
  9. )
  10. // An Entry contains all the fields for a specific user
  11. type Entry struct {
  12. Pass string
  13. Uid string
  14. Gid string
  15. Gecos string
  16. Home string
  17. Shell string
  18. }
  19. // Parse opens the '/etc/passwd' file and parses it into a map from usernames
  20. // to Entries
  21. func Parse() (map[string]Entry, error) {
  22. return ParseFile("/etc/passwd")
  23. }
  24. // ParseFile opens the file and parses it into a map from usernames to Entries
  25. func ParseFile(path string) (map[string]Entry, error) {
  26. file, err := os.Open(path)
  27. if err != nil {
  28. return nil, err
  29. }
  30. defer file.Close()
  31. return ParseReader(file)
  32. }
  33. // ParseReader consumes the contents of r and parses it into a map from
  34. // usernames to Entries
  35. func ParseReader(r io.Reader) (map[string]Entry, error) {
  36. lines := bufio.NewReader(r)
  37. entries := make(map[string]Entry)
  38. for {
  39. line, _, err := lines.ReadLine()
  40. if err != nil {
  41. break
  42. }
  43. name, entry, err := parseLine(string(copyBytes(line)))
  44. if err != nil {
  45. return nil, err
  46. }
  47. entries[name] = entry
  48. }
  49. return entries, nil
  50. }
  51. func parseLine(line string) (string, Entry, error) {
  52. fs := strings.Split(line, ":")
  53. if len(fs) != 7 {
  54. return "", Entry{}, errors.New("Unexpected number of fields in /etc/passwd")
  55. }
  56. return fs[0], Entry{fs[1], fs[2], fs[3], fs[4], fs[5], fs[6]}, nil
  57. }
  58. func copyBytes(x []byte) []byte {
  59. y := make([]byte, len(x))
  60. copy(y, x)
  61. return y
  62. }