File: user_linux.go

package info (click to toggle)
singularity-container 4.1.5%2Bds4-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 43,876 kB
  • sloc: asm: 14,840; sh: 3,190; ansic: 1,751; awk: 414; makefile: 413; python: 99
file content (126 lines) | stat: -rw-r--r-- 2,707 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package ops

import (
	"os"
	"syscall"

	"github.com/containerd/continuity/fs"
	"github.com/moby/buildkit/snapshot"
	"github.com/moby/buildkit/solver/pb"
	"github.com/moby/buildkit/worker"
	"github.com/moby/sys/user"
	"github.com/pkg/errors"
	copy "github.com/tonistiigi/fsutil/copy"
)

func getReadUserFn(_ worker.Worker) func(chopt *pb.ChownOpt, mu, mg snapshot.Mountable) (*copy.User, error) {
	return readUser
}

func readUser(chopt *pb.ChownOpt, mu, mg snapshot.Mountable) (*copy.User, error) {
	if chopt == nil {
		return nil, nil
	}
	var us copy.User
	if chopt.User != nil {
		switch u := chopt.User.User.(type) {
		case *pb.UserOpt_ByName:
			if mu == nil {
				return nil, errors.Errorf("invalid missing user mount")
			}

			lm := snapshot.LocalMounter(mu)
			dir, err := lm.Mount()
			if err != nil {
				return nil, err
			}
			defer lm.Unmount()

			passwdPath, err := user.GetPasswdPath()
			if err != nil {
				return nil, err
			}

			passwdPath, err = fs.RootPath(dir, passwdPath)
			if err != nil {
				return nil, err
			}

			ufile, err := os.Open(passwdPath)
			if errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) {
				// Couldn't open the file. Considering this case as not finding the user in the file.
				break
			}
			if err != nil {
				return nil, err
			}
			defer ufile.Close()

			users, err := user.ParsePasswdFilter(ufile, func(uu user.User) bool {
				return uu.Name == u.ByName.Name
			})
			if err != nil {
				return nil, err
			}

			if len(users) > 0 {
				us.UID = users[0].Uid
				us.GID = users[0].Gid
			}
		case *pb.UserOpt_ByID:
			us.UID = int(u.ByID)
			us.GID = int(u.ByID)
		}
	}

	if chopt.Group != nil {
		switch u := chopt.Group.User.(type) {
		case *pb.UserOpt_ByName:
			if mg == nil {
				return nil, errors.Errorf("invalid missing group mount")
			}

			lm := snapshot.LocalMounter(mg)
			dir, err := lm.Mount()
			if err != nil {
				return nil, err
			}
			defer lm.Unmount()

			groupPath, err := user.GetGroupPath()
			if err != nil {
				return nil, err
			}

			groupPath, err = fs.RootPath(dir, groupPath)
			if err != nil {
				return nil, err
			}

			gfile, err := os.Open(groupPath)
			if errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) {
				// Couldn't open the file. Considering this case as not finding the group in the file.
				break
			}
			if err != nil {
				return nil, err
			}
			defer gfile.Close()

			groups, err := user.ParseGroupFilter(gfile, func(g user.Group) bool {
				return g.Name == u.ByName.Name
			})
			if err != nil {
				return nil, err
			}

			if len(groups) > 0 {
				us.GID = groups[0].Gid
			}
		case *pb.UserOpt_ByID:
			us.GID = int(u.ByID)
		}
	}

	return &us, nil
}