Skip to content

Commit

Permalink
Merge pull request #134 from thaJeztah/integrate_libcontainer_user_take2
Browse files Browse the repository at this point in the history
integrate github.com/opencontainers/runc/libcontainer/user (alternative)
  • Loading branch information
tianon committed Sep 18, 2023
2 parents 5b99ac2 + 0123f32 commit c0711cd
Show file tree
Hide file tree
Showing 7 changed files with 1,343 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Makefile
@@ -1,4 +1,4 @@
PACKAGES ?= mountinfo mount sequential signal symlink
PACKAGES ?= mountinfo mount sequential signal symlink user
BINDIR ?= _build/bin
CROSS ?= linux/arm linux/arm64 linux/ppc64le linux/s390x \
freebsd/amd64 openbsd/amd64 darwin/amd64 darwin/arm64 windows/amd64
Expand Down
5 changes: 5 additions & 0 deletions user/go.mod
@@ -0,0 +1,5 @@
module github.com/moby/sys/user

go 1.17

require golang.org/x/sys v0.1.0
2 changes: 2 additions & 0 deletions user/go.sum
@@ -0,0 +1,2 @@
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
157 changes: 157 additions & 0 deletions user/lookup_unix.go
@@ -0,0 +1,157 @@
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris

package user

import (
"io"
"os"
"strconv"

"golang.org/x/sys/unix"
)

// Unix-specific path to the passwd and group formatted files.
const (
unixPasswdPath = "/etc/passwd"
unixGroupPath = "/etc/group"
)

// LookupUser looks up a user by their username in /etc/passwd. If the user
// cannot be found (or there is no /etc/passwd file on the filesystem), then
// LookupUser returns an error.
func LookupUser(username string) (User, error) {
return lookupUserFunc(func(u User) bool {
return u.Name == username
})
}

// LookupUid looks up a user by their user id in /etc/passwd. If the user cannot
// be found (or there is no /etc/passwd file on the filesystem), then LookupId
// returns an error.
func LookupUid(uid int) (User, error) {
return lookupUserFunc(func(u User) bool {
return u.Uid == uid
})
}

func lookupUserFunc(filter func(u User) bool) (User, error) {
// Get operating system-specific passwd reader-closer.
passwd, err := GetPasswd()
if err != nil {
return User{}, err
}
defer passwd.Close()

// Get the users.
users, err := ParsePasswdFilter(passwd, filter)
if err != nil {
return User{}, err
}

// No user entries found.
if len(users) == 0 {
return User{}, ErrNoPasswdEntries
}

// Assume the first entry is the "correct" one.
return users[0], nil
}

// LookupGroup looks up a group by its name in /etc/group. If the group cannot
// be found (or there is no /etc/group file on the filesystem), then LookupGroup
// returns an error.
func LookupGroup(groupname string) (Group, error) {
return lookupGroupFunc(func(g Group) bool {
return g.Name == groupname
})
}

// LookupGid looks up a group by its group id in /etc/group. If the group cannot
// be found (or there is no /etc/group file on the filesystem), then LookupGid
// returns an error.
func LookupGid(gid int) (Group, error) {
return lookupGroupFunc(func(g Group) bool {
return g.Gid == gid
})
}

func lookupGroupFunc(filter func(g Group) bool) (Group, error) {
// Get operating system-specific group reader-closer.
group, err := GetGroup()
if err != nil {
return Group{}, err
}
defer group.Close()

// Get the users.
groups, err := ParseGroupFilter(group, filter)
if err != nil {
return Group{}, err
}

// No user entries found.
if len(groups) == 0 {
return Group{}, ErrNoGroupEntries
}

// Assume the first entry is the "correct" one.
return groups[0], nil
}

func GetPasswdPath() (string, error) {
return unixPasswdPath, nil
}

func GetPasswd() (io.ReadCloser, error) {
return os.Open(unixPasswdPath)
}

func GetGroupPath() (string, error) {
return unixGroupPath, nil
}

func GetGroup() (io.ReadCloser, error) {
return os.Open(unixGroupPath)
}

// CurrentUser looks up the current user by their user id in /etc/passwd. If the
// user cannot be found (or there is no /etc/passwd file on the filesystem),
// then CurrentUser returns an error.
func CurrentUser() (User, error) {
return LookupUid(unix.Getuid())
}

// CurrentGroup looks up the current user's group by their primary group id's
// entry in /etc/passwd. If the group cannot be found (or there is no
// /etc/group file on the filesystem), then CurrentGroup returns an error.
func CurrentGroup() (Group, error) {
return LookupGid(unix.Getgid())
}

func currentUserSubIDs(fileName string) ([]SubID, error) {
u, err := CurrentUser()
if err != nil {
return nil, err
}
filter := func(entry SubID) bool {
return entry.Name == u.Name || entry.Name == strconv.Itoa(u.Uid)
}
return ParseSubIDFileFilter(fileName, filter)
}

func CurrentUserSubUIDs() ([]SubID, error) {
return currentUserSubIDs("/etc/subuid")
}

func CurrentUserSubGIDs() ([]SubID, error) {
return currentUserSubIDs("/etc/subgid")
}

func CurrentProcessUIDMap() ([]IDMap, error) {
return ParseIDMapFile("/proc/self/uid_map")
}

func CurrentProcessGIDMap() ([]IDMap, error) {
return ParseIDMapFile("/proc/self/gid_map")
}

0 comments on commit c0711cd

Please sign in to comment.