Skip to content

Commit c0711cd

Browse files
authored
Merge pull request #134 from thaJeztah/integrate_libcontainer_user_take2
integrate github.com/opencontainers/runc/libcontainer/user (alternative)
2 parents 5b99ac2 + 0123f32 commit c0711cd

File tree

7 files changed

+1343
-1
lines changed

7 files changed

+1343
-1
lines changed

Diff for: Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
PACKAGES ?= mountinfo mount sequential signal symlink
1+
PACKAGES ?= mountinfo mount sequential signal symlink user
22
BINDIR ?= _build/bin
33
CROSS ?= linux/arm linux/arm64 linux/ppc64le linux/s390x \
44
freebsd/amd64 openbsd/amd64 darwin/amd64 darwin/arm64 windows/amd64

Diff for: user/go.mod

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/moby/sys/user
2+
3+
go 1.17
4+
5+
require golang.org/x/sys v0.1.0

Diff for: user/go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
2+
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

Diff for: user/lookup_unix.go

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

0 commit comments

Comments
 (0)