github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/builder/dockerfile/internals_linux.go (about) 1 package dockerfile // import "github.com/Prakhar-Agarwal-byte/moby/builder/dockerfile" 2 3 import ( 4 "context" 5 "path/filepath" 6 "strconv" 7 "strings" 8 9 "github.com/Prakhar-Agarwal-byte/moby/pkg/idtools" 10 "github.com/moby/sys/symlink" 11 "github.com/moby/sys/user" 12 "github.com/pkg/errors" 13 ) 14 15 func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) { 16 var userStr, grpStr string 17 parts := strings.Split(chown, ":") 18 if len(parts) > 2 { 19 return idtools.Identity{}, errors.New("invalid chown string format: " + chown) 20 } 21 if len(parts) == 1 { 22 // if no group specified, use the user spec as group as well 23 userStr, grpStr = parts[0], parts[0] 24 } else { 25 userStr, grpStr = parts[0], parts[1] 26 } 27 28 passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath) 29 if err != nil { 30 return idtools.Identity{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs") 31 } 32 groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath) 33 if err != nil { 34 return idtools.Identity{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs") 35 } 36 uid, err := lookupUser(userStr, passwdPath) 37 if err != nil { 38 return idtools.Identity{}, errors.Wrapf(err, "can't find uid for user "+userStr) 39 } 40 gid, err := lookupGroup(grpStr, groupPath) 41 if err != nil { 42 return idtools.Identity{}, errors.Wrapf(err, "can't find gid for group "+grpStr) 43 } 44 45 // convert as necessary because of user namespaces 46 chownPair, err := identityMapping.ToHost(idtools.Identity{UID: uid, GID: gid}) 47 if err != nil { 48 return idtools.Identity{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping") 49 } 50 return chownPair, nil 51 } 52 53 func lookupUser(userStr, filepath string) (int, error) { 54 // if the string is actually a uid integer, parse to int and return 55 // as we don't need to translate with the help of files 56 uid, err := strconv.Atoi(userStr) 57 if err == nil { 58 return uid, nil 59 } 60 users, err := user.ParsePasswdFileFilter(filepath, func(u user.User) bool { 61 return u.Name == userStr 62 }) 63 if err != nil { 64 return 0, err 65 } 66 if len(users) == 0 { 67 return 0, errors.New("no such user: " + userStr) 68 } 69 return users[0].Uid, nil 70 } 71 72 func lookupGroup(groupStr, filepath string) (int, error) { 73 // if the string is actually a gid integer, parse to int and return 74 // as we don't need to translate with the help of files 75 gid, err := strconv.Atoi(groupStr) 76 if err == nil { 77 return gid, nil 78 } 79 groups, err := user.ParseGroupFileFilter(filepath, func(g user.Group) bool { 80 return g.Name == groupStr 81 }) 82 if err != nil { 83 return 0, err 84 } 85 if len(groups) == 0 { 86 return 0, errors.New("no such group: " + groupStr) 87 } 88 return groups[0].Gid, nil 89 }