github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/builder/dockerfile/internals_windows.go (about)

     1  package dockerfile
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/docker/docker/pkg/system"
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  // normaliseDest normalises the destination of a COPY/ADD command in a
    14  // platform semantically consistent way.
    15  func normaliseDest(cmdName, workingDir, requested string) (string, error) {
    16  	dest := filepath.FromSlash(requested)
    17  	endsInSlash := strings.HasSuffix(dest, string(os.PathSeparator))
    18  
    19  	// We are guaranteed that the working directory is already consistent,
    20  	// However, Windows also has, for now, the limitation that ADD/COPY can
    21  	// only be done to the system drive, not any drives that might be present
    22  	// as a result of a bind mount.
    23  	//
    24  	// So... if the path requested is Linux-style absolute (/foo or \\foo),
    25  	// we assume it is the system drive. If it is a Windows-style absolute
    26  	// (DRIVE:\\foo), error if DRIVE is not C. And finally, ensure we
    27  	// strip any configured working directories drive letter so that it
    28  	// can be subsequently legitimately converted to a Windows volume-style
    29  	// pathname.
    30  
    31  	// Not a typo - filepath.IsAbs, not system.IsAbs on this next check as
    32  	// we only want to validate where the DriveColon part has been supplied.
    33  	if filepath.IsAbs(dest) {
    34  		if strings.ToUpper(string(dest[0])) != "C" {
    35  			return "", fmt.Errorf("Windows does not support %s with a destinations not on the system drive (C:)", cmdName)
    36  		}
    37  		dest = dest[2:] // Strip the drive letter
    38  	}
    39  
    40  	// Cannot handle relative where WorkingDir is not the system drive.
    41  	if len(workingDir) > 0 {
    42  		if ((len(workingDir) > 1) && !system.IsAbs(workingDir[2:])) || (len(workingDir) == 1) {
    43  			return "", fmt.Errorf("Current WorkingDir %s is not platform consistent", workingDir)
    44  		}
    45  		if !system.IsAbs(dest) {
    46  			if string(workingDir[0]) != "C" {
    47  				return "", fmt.Errorf("Windows does not support %s with relative paths when WORKDIR is not the system drive", cmdName)
    48  			}
    49  			dest = filepath.Join(string(os.PathSeparator), workingDir[2:], dest)
    50  			// Make sure we preserve any trailing slash
    51  			if endsInSlash {
    52  				dest += string(os.PathSeparator)
    53  			}
    54  		}
    55  	}
    56  	return dest, nil
    57  }
    58  
    59  func containsWildcards(name string) bool {
    60  	for i := 0; i < len(name); i++ {
    61  		ch := name[i]
    62  		if ch == '*' || ch == '?' || ch == '[' {
    63  			return true
    64  		}
    65  	}
    66  	return false
    67  }
    68  
    69  var pathBlacklist = map[string]bool{
    70  	"c:\\":        true,
    71  	"c:\\windows": true,
    72  }
    73  
    74  func validateCopySourcePath(imageSource *imageMount, origPath string) error {
    75  	// validate windows paths from other images
    76  	if imageSource == nil {
    77  		return nil
    78  	}
    79  	origPath = filepath.FromSlash(origPath)
    80  	p := strings.ToLower(filepath.Clean(origPath))
    81  	if !filepath.IsAbs(p) {
    82  		if filepath.VolumeName(p) != "" {
    83  			if p[len(p)-2:] == ":." { // case where clean returns weird c:. paths
    84  				p = p[:len(p)-1]
    85  			}
    86  			p += "\\"
    87  		} else {
    88  			p = filepath.Join("c:\\", p)
    89  		}
    90  	}
    91  	if _, blacklisted := pathBlacklist[p]; blacklisted {
    92  		return errors.New("copy from c:\\ or c:\\windows is not allowed on windows")
    93  	}
    94  	return nil
    95  }