lookup_unix.go 3.1 KB

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