internals_linux.go 2.8 KB

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