Fixing Tar functions to support Windows long paths.

Signed-off-by: Stefan J. Wernli <swernli@microsoft.com>
This commit is contained in:
Stefan J. Wernli 2015-08-10 15:21:30 -07:00 committed by John Howard
parent 732af35366
commit 1c1d0c5f6f
4 changed files with 43 additions and 3 deletions

View file

@ -405,6 +405,10 @@ func Tar(path string, compression Compression) (io.ReadCloser, error) {
// paths are included in `options.IncludeFiles` (if non-nil) or not in `options.ExcludePatterns`. // paths are included in `options.IncludeFiles` (if non-nil) or not in `options.ExcludePatterns`.
func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) { func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) {
// Fix the source path to work with long path names. This is a no-op
// on platforms other than Windows.
srcPath = fixVolumePathPrefix(srcPath)
patterns, patDirs, exceptions, err := fileutils.CleanPatterns(options.ExcludePatterns) patterns, patDirs, exceptions, err := fileutils.CleanPatterns(options.ExcludePatterns)
if err != nil { if err != nil {
@ -474,9 +478,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
for _, include := range options.IncludeFiles { for _, include := range options.IncludeFiles {
rebaseName := options.RebaseNames[include] rebaseName := options.RebaseNames[include]
// We can't use filepath.Join(srcPath, include) because this will walkRoot := getWalkRoot(srcPath, include)
// clean away a trailing "." or "/" which may be important.
walkRoot := strings.Join([]string{srcPath, include}, string(filepath.Separator))
filepath.Walk(walkRoot, func(filePath string, f os.FileInfo, err error) error { filepath.Walk(walkRoot, func(filePath string, f os.FileInfo, err error) error {
if err != nil { if err != nil {
logrus.Debugf("Tar: Can't stat file %s to tar: %s", srcPath, err) logrus.Debugf("Tar: Can't stat file %s to tar: %s", srcPath, err)

View file

@ -6,11 +6,26 @@ import (
"archive/tar" "archive/tar"
"errors" "errors"
"os" "os"
"path/filepath"
"syscall" "syscall"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
) )
// fixVolumePathPrefix does platform specific processing to ensure that if
// the path being passed in is not in a volume path format, convert it to one.
func fixVolumePathPrefix(srcPath string) string {
return srcPath
}
// getWalkRoot calculates the root path when performing a TarWithOptions.
// We use a seperate function as this is platform specific. On Linux, we
// can't use filepath.Join(srcPath,include) because this will clean away
// a trailing "." or "/" which may be important.
func getWalkRoot(srcPath string, include string) string {
return srcPath + string(filepath.Separator) + include
}
// CanonicalTarNameForPath returns platform-specific filepath // CanonicalTarNameForPath returns platform-specific filepath
// to canonical posix-style path for tar archival. p is relative // to canonical posix-style path for tar archival. p is relative
// path. // path.

View file

@ -6,9 +6,25 @@ import (
"archive/tar" "archive/tar"
"fmt" "fmt"
"os" "os"
"path/filepath"
"strings" "strings"
) )
// fixVolumePathPrefix does platform specific processing to ensure that if
// the path being passed in is not in a volume path format, convert it to one.
func fixVolumePathPrefix(srcPath string) string {
if !strings.HasPrefix(srcPath, `\\?\`) {
srcPath = `\\?\` + srcPath
}
return srcPath
}
// getWalkRoot calculates the root path when performing a TarWithOptions.
// We use a seperate function as this is platform specific.
func getWalkRoot(srcPath string, include string) string {
return filepath.Join(srcPath, include)
}
// canonicalTarNameForPath returns platform-specific filepath // canonicalTarNameForPath returns platform-specific filepath
// to canonical posix-style path for tar archival. p is relative // to canonical posix-style path for tar archival. p is relative
// path. // path.

View file

@ -5,6 +5,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
) )
@ -14,6 +15,12 @@ import (
// contents of the layer. // contents of the layer.
func applyLayerHandler(dest string, layer archive.Reader, decompress bool) (size int64, err error) { func applyLayerHandler(dest string, layer archive.Reader, decompress bool) (size int64, err error) {
dest = filepath.Clean(dest) dest = filepath.Clean(dest)
// Ensure it is a Windows-style volume path
if !strings.HasPrefix(dest, `\\?\`) {
dest = `\\?\` + dest
}
if decompress { if decompress {
decompressed, err := archive.DecompressStream(layer) decompressed, err := archive.DecompressStream(layer)
if err != nil { if err != nil {