github.com/portworx/docker@v1.12.1/daemon/archive_unix.go (about)

     1  // +build !windows
     2  
     3  package daemon
     4  
     5  import (
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/docker/docker/container"
    10  )
    11  
    12  // checkIfPathIsInAVolume checks if the path is in a volume. If it is, it
    13  // cannot be in a read-only volume. If it  is not in a volume, the container
    14  // cannot be configured with a read-only rootfs.
    15  func checkIfPathIsInAVolume(container *container.Container, absPath string) (bool, error) {
    16  	var toVolume bool
    17  	for _, mnt := range container.MountPoints {
    18  		if toVolume = mnt.HasResource(absPath); toVolume {
    19  			if mnt.RW {
    20  				break
    21  			}
    22  			return false, ErrVolumeReadonly
    23  		}
    24  	}
    25  	return toVolume, nil
    26  }
    27  
    28  func fixPermissions(source, destination string, uid, gid int, destExisted bool) error {
    29  	// If the destination didn't already exist, or the destination isn't a
    30  	// directory, then we should Lchown the destination. Otherwise, we shouldn't
    31  	// Lchown the destination.
    32  	destStat, err := os.Stat(destination)
    33  	if err != nil {
    34  		// This should *never* be reached, because the destination must've already
    35  		// been created while untar-ing the context.
    36  		return err
    37  	}
    38  	doChownDestination := !destExisted || !destStat.IsDir()
    39  
    40  	// We Walk on the source rather than on the destination because we don't
    41  	// want to change permissions on things we haven't created or modified.
    42  	return filepath.Walk(source, func(fullpath string, info os.FileInfo, err error) error {
    43  		// Do not alter the walk root iff. it existed before, as it doesn't fall under
    44  		// the domain of "things we should chown".
    45  		if !doChownDestination && (source == fullpath) {
    46  			return nil
    47  		}
    48  
    49  		// Path is prefixed by source: substitute with destination instead.
    50  		cleaned, err := filepath.Rel(source, fullpath)
    51  		if err != nil {
    52  			return err
    53  		}
    54  
    55  		fullpath = filepath.Join(destination, cleaned)
    56  		return os.Lchown(fullpath, uid, gid)
    57  	})
    58  }