github.com/OpenFlowLabs/storage@v1.12.13/drivers/chown_unix.go (about) 1 // +build !windows 2 3 package graphdriver 4 5 import ( 6 "fmt" 7 "os" 8 "syscall" 9 10 "github.com/containers/storage/pkg/idtools" 11 "github.com/containers/storage/pkg/system" 12 ) 13 14 func platformLChown(path string, info os.FileInfo, toHost, toContainer *idtools.IDMappings) error { 15 sysinfo := info.Sys() 16 if st, ok := sysinfo.(*syscall.Stat_t); ok { 17 // Map an on-disk UID/GID pair from host to container 18 // using the first map, then back to the host using the 19 // second map. Skip that first step if they're 0, to 20 // compensate for cases where a parent layer should 21 // have had a mapped value, but didn't. 22 uid, gid := int(st.Uid), int(st.Gid) 23 if toContainer != nil { 24 pair := idtools.IDPair{ 25 UID: uid, 26 GID: gid, 27 } 28 mappedUid, mappedGid, err := toContainer.ToContainer(pair) 29 if err != nil { 30 if (uid != 0) || (gid != 0) { 31 return fmt.Errorf("error mapping host ID pair %#v for %q to container: %v", pair, path, err) 32 } 33 mappedUid, mappedGid = uid, gid 34 } 35 uid, gid = mappedUid, mappedGid 36 } 37 if toHost != nil { 38 pair := idtools.IDPair{ 39 UID: uid, 40 GID: gid, 41 } 42 mappedPair, err := toHost.ToHost(pair) 43 if err != nil { 44 return fmt.Errorf("error mapping container ID pair %#v for %q to host: %v", pair, path, err) 45 } 46 uid, gid = mappedPair.UID, mappedPair.GID 47 } 48 if uid != int(st.Uid) || gid != int(st.Gid) { 49 stat, err := os.Lstat(path) 50 if err != nil { 51 return fmt.Errorf("%s: lstat(%q): %v", os.Args[0], path, err) 52 } 53 cap, err := system.Lgetxattr(path, "security.capability") 54 if err != nil && err != system.ErrNotSupportedPlatform { 55 return fmt.Errorf("%s: Lgetxattr(%q): %v", os.Args[0], path, err) 56 } 57 58 // Make the change. 59 if err := syscall.Lchown(path, uid, gid); err != nil { 60 return fmt.Errorf("%s: chown(%q): %v", os.Args[0], path, err) 61 } 62 // Restore the SUID and SGID bits if they were originally set. 63 if (stat.Mode()&os.ModeSymlink == 0) && stat.Mode()&(os.ModeSetuid|os.ModeSetgid) != 0 { 64 if err := os.Chmod(path, stat.Mode()); err != nil { 65 return fmt.Errorf("%s: chmod(%q): %v", os.Args[0], path, err) 66 } 67 } 68 if cap != nil { 69 if err := system.Lsetxattr(path, "security.capability", cap, 0); err != nil { 70 return fmt.Errorf("%s: Lsetxattr(%q): %v", os.Args[0], path, err) 71 } 72 } 73 74 } 75 } 76 return nil 77 }