lookup_unix.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // +build darwin dragonfly freebsd linux netbsd openbsd solaris
  2. package user
  3. import (
  4. "io"
  5. "os"
  6. "strconv"
  7. "golang.org/x/sys/unix"
  8. )
  9. // Unix-specific path to the passwd and group formatted files.
  10. const (
  11. unixPasswdPath = "/etc/passwd"
  12. unixGroupPath = "/etc/group"
  13. )
  14. func lookupUser(username string) (User, error) {
  15. return lookupUserFunc(func(u User) bool {
  16. return u.Name == username
  17. })
  18. }
  19. func lookupUid(uid int) (User, error) {
  20. return lookupUserFunc(func(u User) bool {
  21. return u.Uid == uid
  22. })
  23. }
  24. func lookupUserFunc(filter func(u User) bool) (User, error) {
  25. // Get operating system-specific passwd reader-closer.
  26. passwd, err := GetPasswd()
  27. if err != nil {
  28. return User{}, err
  29. }
  30. defer passwd.Close()
  31. // Get the users.
  32. users, err := ParsePasswdFilter(passwd, filter)
  33. if err != nil {
  34. return User{}, err
  35. }
  36. // No user entries found.
  37. if len(users) == 0 {
  38. return User{}, ErrNoPasswdEntries
  39. }
  40. // Assume the first entry is the "correct" one.
  41. return users[0], nil
  42. }
  43. func lookupGroup(groupname string) (Group, error) {
  44. return lookupGroupFunc(func(g Group) bool {
  45. return g.Name == groupname
  46. })
  47. }
  48. func lookupGid(gid int) (Group, error) {
  49. return lookupGroupFunc(func(g Group) bool {
  50. return g.Gid == gid
  51. })
  52. }
  53. func lookupGroupFunc(filter func(g Group) bool) (Group, error) {
  54. // Get operating system-specific group reader-closer.
  55. group, err := GetGroup()
  56. if err != nil {
  57. return Group{}, err
  58. }
  59. defer group.Close()
  60. // Get the users.
  61. groups, err := ParseGroupFilter(group, filter)
  62. if err != nil {
  63. return Group{}, err
  64. }
  65. // No user entries found.
  66. if len(groups) == 0 {
  67. return Group{}, ErrNoGroupEntries
  68. }
  69. // Assume the first entry is the "correct" one.
  70. return groups[0], nil
  71. }
  72. func GetPasswdPath() (string, error) {
  73. return unixPasswdPath, nil
  74. }
  75. func GetPasswd() (io.ReadCloser, error) {
  76. return os.Open(unixPasswdPath)
  77. }
  78. func GetGroupPath() (string, error) {
  79. return unixGroupPath, nil
  80. }
  81. func GetGroup() (io.ReadCloser, error) {
  82. return os.Open(unixGroupPath)
  83. }
  84. // CurrentUser looks up the current user by their user id in /etc/passwd. If the
  85. // user cannot be found (or there is no /etc/passwd file on the filesystem),
  86. // then CurrentUser returns an error.
  87. func CurrentUser() (User, error) {
  88. return LookupUid(unix.Getuid())
  89. }
  90. // CurrentGroup looks up the current user's group by their primary group id's
  91. // entry in /etc/passwd. If the group cannot be found (or there is no
  92. // /etc/group file on the filesystem), then CurrentGroup returns an error.
  93. func CurrentGroup() (Group, error) {
  94. return LookupGid(unix.Getgid())
  95. }
  96. func currentUserSubIDs(fileName string) ([]SubID, error) {
  97. u, err := CurrentUser()
  98. if err != nil {
  99. return nil, err
  100. }
  101. filter := func(entry SubID) bool {
  102. return entry.Name == u.Name || entry.Name == strconv.Itoa(u.Uid)
  103. }
  104. return ParseSubIDFileFilter(fileName, filter)
  105. }
  106. func CurrentUserSubUIDs() ([]SubID, error) {
  107. return currentUserSubIDs("/etc/subuid")
  108. }
  109. func CurrentUserSubGIDs() ([]SubID, error) {
  110. return currentUserSubIDs("/etc/subgid")
  111. }
  112. func CurrentProcessUIDMap() ([]IDMap, error) {
  113. return ParseIDMapFile("/proc/self/uid_map")
  114. }
  115. func CurrentProcessGIDMap() ([]IDMap, error) {
  116. return ParseIDMapFile("/proc/self/gid_map")
  117. }